Merge remote-tracking branch 'origin/main'

This commit is contained in:
CappielloAntonio 2024-05-25 17:26:08 +02:00
commit a3d8b75d07
7 changed files with 152 additions and 1 deletions

View file

@ -30,6 +30,7 @@ import com.cappielloantonio.tempo.ui.activity.MainActivity;
import com.cappielloantonio.tempo.ui.dialog.DeleteDownloadStorageDialog;
import com.cappielloantonio.tempo.ui.dialog.DownloadStorageDialog;
import com.cappielloantonio.tempo.ui.dialog.StarredSyncDialog;
import com.cappielloantonio.tempo.util.DownloadUtil;
import com.cappielloantonio.tempo.util.Preferences;
import com.cappielloantonio.tempo.util.UIUtil;
import com.cappielloantonio.tempo.viewmodel.SettingViewModel;
@ -113,6 +114,22 @@ public class SettingsFragment extends PreferenceFragmentCompat {
return true;
});
}
ListPreference streamingCachePreference = findPreference("streaming_cache_size");
if (streamingCachePreference != null) {
streamingCachePreference.setSummaryProvider(new Preference.SummaryProvider<ListPreference>() {
@Nullable
@Override
public CharSequence provideSummary(@NonNull ListPreference preference) {
CharSequence entry = preference.getEntry();
if (entry == null) {
return null;
}
long currentSizeMb = DownloadUtil.getStreamingCacheSize(requireActivity()) / (1024 * 1024);
return entry + "\nCurrently in use: " + + currentSizeMb + " MiB\nRestarting is required if changed.";
}
});
}
}
private void checkEqualizer() {

View file

@ -8,10 +8,13 @@ import androidx.media3.common.util.UnstableApi;
import androidx.media3.database.DatabaseProvider;
import androidx.media3.database.StandaloneDatabaseProvider;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.datasource.ResolvingDataSource;
import androidx.media3.datasource.cache.Cache;
import androidx.media3.datasource.cache.CacheDataSource;
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor;
import androidx.media3.datasource.cache.NoOpCacheEvictor;
import androidx.media3.datasource.cache.SimpleCache;
import androidx.media3.exoplayer.DefaultRenderersFactory;
@ -42,6 +45,7 @@ public final class DownloadUtil {
private static DatabaseProvider databaseProvider;
private static File downloadDirectory;
private static Cache downloadCache;
private static SimpleCache streamingCache;
private static DownloadManager downloadManager;
private static DownloaderManager downloaderManager;
private static DownloadNotificationHelper downloadNotificationHelper;
@ -75,7 +79,27 @@ public final class DownloadUtil {
if (dataSourceFactory == null) {
context = context.getApplicationContext();
DefaultDataSource.Factory upstreamFactory = new DefaultDataSource.Factory(context, getHttpDataSourceFactory());
dataSourceFactory = buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache(context));
if (Preferences.getStreamingCacheSize() > 0) {
// Cache enabled
CacheDataSource.Factory streamCacheFactory = new CacheDataSource.Factory()
.setCache(getStreamingCache(context))
.setUpstreamDataSourceFactory(upstreamFactory);
ResolvingDataSource.Factory resolvingFactory = new ResolvingDataSource.Factory(
new StreamingCacheDataSource.Factory(streamCacheFactory),
dataSpec -> {
DataSpec.Builder builder = dataSpec.buildUpon();
builder.setFlags(dataSpec.flags & ~DataSpec.FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN);
return builder.build();
}
);
dataSourceFactory = buildReadOnlyCacheDataSource(resolvingFactory, getDownloadCache(context));
} else {
// Cache disabled
dataSourceFactory = buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache(context));
}
}
return dataSourceFactory;
@ -108,6 +132,18 @@ public final class DownloadUtil {
return downloadCache;
}
private static synchronized SimpleCache getStreamingCache(Context context) {
if (streamingCache == null) {
File streamingCacheDirectory = new File(context.getCacheDir(), "streamingCache");
streamingCache = new SimpleCache(
streamingCacheDirectory,
new LeastRecentlyUsedCacheEvictor(Preferences.getStreamingCacheSize() * 1024 * 1024),
getDatabaseProvider(context)
);
}
return streamingCache;
}
private static synchronized void ensureDownloadManagerInitialized(Context context) {
if (downloadManager == null) {
downloadManager = new DownloadManager(
@ -187,6 +223,10 @@ public final class DownloadUtil {
return files;
}
public static synchronized long getStreamingCacheSize(Context context) {
return getStreamingCache(context).getCacheSpace();
}
public static Notification buildGroupSummaryNotification(Context context, String channelId, String groupId, int icon, String title) {
return new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)

View file

@ -23,6 +23,7 @@ object Preferences {
private const val PLAYBACK_SPEED = "playback_speed"
private const val SKIP_SILENCE = "skip_silence"
private const val IMAGE_CACHE_SIZE = "image_cache_size"
private const val STREAMING_CACHE_SIZE = "streaming_cache_size"
private const val IMAGE_SIZE = "image_size"
private const val MAX_BITRATE_WIFI = "max_bitrate_wifi"
private const val MAX_BITRATE_MOBILE = "max_bitrate_mobile"
@ -189,6 +190,14 @@ object Preferences {
return App.getInstance().preferences.getString(IMAGE_SIZE, "-1")!!.toInt()
}
/**
* Size of streaming cache in MiB.
*/
@JvmStatic
fun getStreamingCacheSize(): Long {
return App.getInstance().preferences.getString(STREAMING_CACHE_SIZE, "256")!!.toLong()
}
@JvmStatic
fun getMaxBitrateWifi(): String {
return App.getInstance().preferences.getString(MAX_BITRATE_WIFI, "0")!!

View file

@ -0,0 +1,61 @@
package com.cappielloantonio.tempo.util
import android.net.Uri
import android.util.Log
import androidx.media3.common.C
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DataSpec
import androidx.media3.datasource.TransferListener
import androidx.media3.datasource.cache.CacheDataSource
import androidx.media3.datasource.cache.ContentMetadata
@UnstableApi
class StreamingCacheDataSource private constructor(
private val cacheDataSource: CacheDataSource,
): DataSource {
private val TAG = "StreamingCacheDataSource"
private var currentDataSpec: DataSpec? = null
class Factory(private val cacheDatasourceFactory: CacheDataSource.Factory): DataSource.Factory {
override fun createDataSource(): DataSource {
return StreamingCacheDataSource(cacheDatasourceFactory.createDataSource())
}
}
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
return cacheDataSource.read(buffer, offset, length)
}
override fun addTransferListener(transferListener: TransferListener) {
return cacheDataSource.addTransferListener(transferListener)
}
override fun open(dataSpec: DataSpec): Long {
val ret = cacheDataSource.open(dataSpec)
currentDataSpec = dataSpec
Log.d(TAG, "Opened $currentDataSpec")
return ret
}
override fun getUri(): Uri? {
return cacheDataSource.uri
}
override fun close() {
cacheDataSource.close()
Log.d(TAG, "Closed $currentDataSpec")
val dataSpec = currentDataSpec
if (dataSpec != null) {
val cacheKey = cacheDataSource.cacheKeyFactory.buildCacheKey(dataSpec)
val contentLength = ContentMetadata.getContentLength(cacheDataSource.cache.getContentMetadata(cacheKey));
if (contentLength == C.LENGTH_UNSET.toLong()) {
Log.d(TAG, "Removing partial cache for $cacheKey")
cacheDataSource.cache.removeResource(cacheKey)
} else {
Log.d(TAG, "Key $cacheKey has been fully cached")
}
}
}
}

View file

@ -32,6 +32,21 @@
<item>300</item>
</string-array>
<string-array name="streaming_cache_size_titles">
<item>Disabled</item>
<item>128 MiB</item>
<item>256 MiB</item>
<item>512 MiB</item>
<item>1024 MiB</item>
</string-array>
<string-array name="streaming_cache_size_values">
<item>0</item>
<item>128</item>
<item>256</item>
<item>512</item>
<item>1024</item>
</string-array>
<string-array name="max_bitrate_wifi_list_titles">
<item>Original</item>
<item>32 kbps</item>

View file

@ -377,4 +377,5 @@
<string name="undraw_page">unDraw</string>
<string name="undraw_thanks">A special thanks goes to unDraw without whose illustrations we could not have made this application more beautiful.</string>
<string name="undraw_url">https://undraw.co/</string>
<string name="settings_streaming_cache_size">Size of streaming cache</string>
</resources>

View file

@ -101,6 +101,14 @@
app:title="@string/settings_image_size"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:defaultValue="256"
app:dialogTitle="@string/settings_streaming_cache_size"
app:entries="@array/streaming_cache_size_titles"
app:entryValues="@array/streaming_cache_size_values"
app:key="streaming_cache_size"
app:title="@string/settings_streaming_cache_size" />
<SwitchPreference
android:title="@string/settings_wifi_only_title"
android:defaultValue="false"