Merge branch 'playback' into dev

This commit is contained in:
Alexander Capehart 2024-07-29 21:38:36 -06:00
commit f0bf7af7b4
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
5 changed files with 76 additions and 24 deletions

View file

@ -43,24 +43,25 @@ class AuxioService : MediaLibraryService(), ForegroundListener {
}
override fun onBind(intent: Intent?): IBinder? {
handleIntent(intent)
start(intent)
return super.onBind(intent)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// TODO: Start command occurring from a foreign service basically implies a detached
// service, we might need more handling here.
handleIntent(intent)
start(intent)
return super.onStartCommand(intent, flags, startId)
}
private fun handleIntent(intent: Intent?) {
private fun start(intent: Intent?) {
val nativeStart = intent?.getBooleanExtra(INTENT_KEY_NATIVE_START, false) ?: false
if (!nativeStart) {
// Some foreign code started us, no guarantees about foreground stability. Figure
// out what to do.
mediaSessionFragment.handleNonNativeStart()
}
indexingFragment.start()
}
override fun onTaskRemoved(rootIntent: Intent?) {

View file

@ -280,9 +280,6 @@ constructor(
}
logD("Registering worker $worker")
indexingWorker = worker
if (indexingState == null) {
worker.requestIndex(true)
}
}
@Synchronized

View file

@ -21,13 +21,13 @@ package org.oxycblt.auxio.music.external
import android.content.Context
import android.net.Uri
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.fs.Components
import org.oxycblt.auxio.music.fs.DocumentPathFactory
import org.oxycblt.auxio.music.fs.Path
import org.oxycblt.auxio.music.fs.contentResolverSafe
import org.oxycblt.auxio.util.logE
import javax.inject.Inject
/**
* Generic playlist file importing abstraction.
@ -92,7 +92,20 @@ constructor(
return try {
context.contentResolverSafe.openInputStream(uri)?.use {
return m3u.read(it, filePath.directory)
val imported = m3u.read(it, filePath.directory) ?: return null
val name = imported.name
if (name != null) {
return imported
}
// Strip extension
val fileName = filePath.name ?: return imported
val split = fileName.split(".")
var newName = split[0]
// Replace delimiters with space
newName = newName.replace(Regex("[_-]"), " ")
// Replace long stretches of whitespace with one space
newName = newName.replace(Regex("\\s+"), " ")
return ImportedPlaylist(newName, imported.paths)
}
} catch (e: Exception) {
logE("Failed to import playlist: $e")

View file

@ -72,13 +72,19 @@ constructor(
fun release() {
contentObserver.release()
musicSettings.registerListener(this)
musicRepository.addIndexingListener(this)
musicRepository.addUpdateListener(this)
musicRepository.unregisterWorker(this)
musicRepository.removeIndexingListener(this)
musicRepository.removeUpdateListener(this)
musicSettings.unregisterListener(this)
foregroundListener = null
}
fun start() {
if (musicRepository.indexingState == null) {
requestIndex(true)
}
}
fun createNotification(post: (IndexerNotification?) -> Unit) {
val state = musicRepository.indexingState
if (state is IndexingState.Indexing) {

View file

@ -101,18 +101,52 @@ class WidgetProvider : AppWidgetProvider() {
SizeF(180f, 272f) to newThinPaneLayout(context, uiSettings, state),
SizeF(304f, 272f) to newWidePaneLayout(context, uiSettings, state))
// This is the order in which we will disable cover art layouts if they exceed the
// maximum bitmap memory usage. (See the comment in the loop below for more info.)
val victims =
mutableSetOf(
R.layout.widget_wafer_thin,
R.layout.widget_wafer_wide,
R.layout.widget_pane_thin,
R.layout.widget_pane_wide,
R.layout.widget_docked_thin,
R.layout.widget_docked_wide,
)
// Manually update AppWidgetManager with the new views.
val awm = AppWidgetManager.getInstance(context)
val component = ComponentName(context, this::class.java)
while (victims.size > 0) {
try {
awm.updateAppWidgetCompat(context, component, views)
logD("Successfully updated RemoteViews layout")
return
} catch (e: IllegalArgumentException) {
val msg = e.message ?: return
if (!msg.startsWith(
"RemoteViews for widget update exceeds maximum bitmap memory usage")) {
throw e
}
// Some android devices on Android 12-14 suffer from a bug where the maximum bitmap
// size calculation does not factor in bitmaps shared across multiple RemoteView
// forms.
// To mitigate an outright crash, progressively disable layouts that contain cover
// art
// in order of least to most commonly used until it actually works.
val victim = victims.first()
val view = views.entries.find { it.value.layoutId == victim } ?: continue
view.value.discardCover(context)
victims.remove(victim)
} catch (e: Exception) {
// Layout update failed, gracefully degrade to the default widget.
logW("Unable to update widget: $e")
reset(context, uiSettings)
}
}
// We flat-out cannot fit the bitmap into the widget. Weird.
logW("Unable to update widget: Bitmap too large")
reset(context, uiSettings)
}
/**
* Revert to the default layout that displays "No music playing".
@ -288,16 +322,17 @@ class WidgetProvider : AppWidgetProvider() {
context.getString(
R.string.desc_album_cover, state.song.album.name.resolve(context)))
} else {
// We are unable to use the typical placeholder cover with the song item due to
// limitations with the corner radius. Instead use a custom-made album icon as the
// placeholder.
setImageViewResource(R.id.widget_cover, R.drawable.ic_remote_default_cover_24)
setContentDescription(R.id.widget_cover, context.getString(R.string.desc_no_cover))
discardCover(context)
}
return this
}
private fun RemoteViews.discardCover(context: Context) {
setImageViewResource(R.id.widget_cover, R.drawable.ic_remote_default_cover_24)
setContentDescription(R.id.widget_cover, context.getString(R.string.desc_no_cover))
}
private fun RemoteViews.setupFillingCover(uiSettings: UISettings): RemoteViews {
// Below API 31, enable a rounded background only if round mode is enabled.
// On API 31+, the background should always be round in order to fit in with other