all: fully use timber for logging

This commit is contained in:
Alexander Capehart 2024-10-17 20:15:30 -06:00
parent a9a35c8055
commit 6d72240336
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
118 changed files with 749 additions and 836 deletions

View file

@ -36,7 +36,7 @@ import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import org.oxycblt.auxio.music.service.MusicServiceFragment
import org.oxycblt.auxio.playback.service.PlaybackServiceFragment
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
@AndroidEntryPoint
class AuxioService :
@ -150,7 +150,7 @@ class AuxioService :
}
override fun invalidateMusic(mediaId: String) {
logD(mediaId)
T.d(mediaId)
notifyChildrenChanged(mediaId)
}

View file

@ -33,9 +33,8 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.state.DeferredPlayback
import org.oxycblt.auxio.ui.UISettings
import org.oxycblt.auxio.util.isNight
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.systemBarInsetsCompat
import timber.log.Timber as T
/**
* Auxio's single [AppCompatActivity].
@ -63,7 +62,7 @@ class MainActivity : AppCompatActivity() {
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupEdgeToEdge(binding.root)
logD("Activity created")
T.d("Activity created")
}
override fun onResume() {
@ -91,10 +90,10 @@ class MainActivity : AppCompatActivity() {
// Apply the color scheme. The black theme requires it's own set of themes since
// it's not possible to modify the themes at run-time.
if (isNight && uiSettings.useBlackTheme) {
logD("Applying black theme [accent ${uiSettings.accent}]")
T.d("Applying black theme [accent ${uiSettings.accent}]")
setTheme(uiSettings.accent.blackTheme)
} else {
logD("Applying normal theme [accent ${uiSettings.accent}]")
T.d("Applying normal theme [accent ${uiSettings.accent}]")
setTheme(uiSettings.accent.theme)
}
}
@ -121,7 +120,7 @@ class MainActivity : AppCompatActivity() {
private fun startIntentAction(intent: Intent?): Boolean {
if (intent == null) {
// Nothing to do.
logD("No intent to handle")
T.d("No intent to handle")
return false
}
@ -130,7 +129,7 @@ class MainActivity : AppCompatActivity() {
// This is because onStart can run multiple times, and thus we really don't
// want to return false and override the original delayed action with a
// RestoreState action.
logD("Already used this intent")
T.d("Already used this intent")
return true
}
intent.putExtra(KEY_INTENT_USED, true)
@ -140,11 +139,11 @@ class MainActivity : AppCompatActivity() {
Intent.ACTION_VIEW -> DeferredPlayback.Open(intent.data ?: return false)
Auxio.INTENT_KEY_SHORTCUT_SHUFFLE -> DeferredPlayback.ShuffleAll
else -> {
logW("Unexpected intent ${intent.action}")
T.w("Unexpected intent ${intent.action}")
return false
}
}
logD("Translated intent to $action")
T.d("Translated intent to $action")
playbackModel.playDeferred(action)
return true
}

View file

@ -66,9 +66,9 @@ import org.oxycblt.auxio.util.coordinatorLayoutBehavior
import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.getDimen
import org.oxycblt.auxio.util.lazyReflectedMethod
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A wrapper around the home fragment that shows the playback fragment and high-level navigation.
@ -145,13 +145,13 @@ class MainFragment :
if (queueSheetBehavior != null) {
// In portrait mode, set up click listeners on the stacked sheets.
logD("Configuring stacked bottom sheets")
T.d("Configuring stacked bottom sheets")
unlikelyToBeNull(binding.queueHandleWrapper).setOnClickListener {
playbackModel.openQueue()
}
} else {
// Dual-pane mode, manually style the static queue sheet.
logD("Configuring dual-pane bottom sheet")
T.d("Configuring dual-pane bottom sheet")
binding.queueSheet.apply {
// Emulate the elevated bottom sheet style.
background =
@ -367,11 +367,11 @@ class MainFragment :
override fun onActionSelected(actionItem: SpeedDialActionItem): Boolean {
when (actionItem.id) {
R.id.action_new_playlist -> {
logD("Creating playlist")
T.d("Creating playlist")
musicModel.createPlaylist()
}
R.id.action_import_playlist -> {
logD("Importing playlist")
T.d("Importing playlist")
musicModel.importPlaylist()
}
else -> {}
@ -402,7 +402,7 @@ class MainFragment :
// 1. Loading placeholder for item lists
// 2. Rework the "No Music" case to not be an error and instead result in a placeholder
if (state is IndexingState.Completed && state.error == null) {
logD("Received ok response")
T.d("Received ok response")
val binding = requireBinding()
updateFabVisibility(
binding,
@ -427,7 +427,7 @@ class MainFragment :
// displaying the shuffle FAB makes no sense. We also don't want the fast scroll
// popup to overlap with the FAB, so we hide the FAB when fast scrolling too.
if (shouldHideAllFabs(binding, songs, isFastScrolling)) {
logD("Hiding fab: [empty: ${songs.isEmpty()} scrolling: $isFastScrolling]")
T.d("Hiding fab: [empty: ${songs.isEmpty()} scrolling: $isFastScrolling]")
forceHideAllFabs()
} else {
if (tabType != MusicType.PLAYLISTS) {
@ -436,7 +436,7 @@ class MainFragment :
}
if (binding.homeNewPlaylistFab.mainFab.isOrWillBeShown) {
logD("Animating transition")
T.d("Animating transition")
binding.homeNewPlaylistFab.hide(
object : FloatingActionButton.OnVisibilityChangedListener() {
override fun onHidden(fab: FloatingActionButton) {
@ -451,17 +451,17 @@ class MainFragment :
}
})
} else {
logD("Showing immediately")
T.d("Showing immediately")
binding.homeShuffleFab.show()
}
} else {
logD("Showing playlist button")
T.d("Showing playlist button")
if (binding.homeNewPlaylistFab.mainFab.isOrWillBeShown) {
return
}
if (binding.homeShuffleFab.isOrWillBeShown) {
logD("Animating transition")
T.d("Animating transition")
binding.homeShuffleFab.hide(
object : FloatingActionButton.OnVisibilityChangedListener() {
override fun onHidden(fab: FloatingActionButton) {
@ -476,7 +476,7 @@ class MainFragment :
}
})
} else {
logD("Showing immediately")
T.d("Showing immediately")
binding.homeNewPlaylistFab.show()
}
}
@ -551,7 +551,7 @@ class MainFragment :
private fun handlePanel(panel: OpenPanel?) {
if (panel == null) return
logD("Trying to update panel to $panel")
T.d("Trying to update panel to $panel")
when (panel) {
OpenPanel.MAIN -> tryClosePlaybackPanel()
OpenPanel.PLAYBACK -> tryOpenPlaybackPanel()
@ -567,7 +567,7 @@ class MainFragment :
if (playbackSheetBehavior.targetState == BackportBottomSheetBehavior.STATE_COLLAPSED) {
// Playback sheet is not expanded and not hidden, we can expand it.
logD("Expanding playback sheet")
T.d("Expanding playback sheet")
playbackSheetBehavior.state = BackportBottomSheetBehavior.STATE_EXPANDED
return
}
@ -578,7 +578,7 @@ class MainFragment :
queueSheetBehavior.targetState == BackportBottomSheetBehavior.STATE_EXPANDED) {
// Queue sheet and playback sheet is expanded, close the queue sheet so the
// playback panel can shown.
logD("Collapsing queue sheet")
T.d("Collapsing queue sheet")
queueSheetBehavior.state = BackportBottomSheetBehavior.STATE_COLLAPSED
}
}
@ -589,7 +589,7 @@ class MainFragment :
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackBottomSheetBehavior
if (playbackSheetBehavior.targetState == BackportBottomSheetBehavior.STATE_EXPANDED) {
// Playback sheet (and possibly queue) needs to be collapsed.
logD("Collapsing playback and queue sheets")
T.d("Collapsing playback and queue sheets")
val queueSheetBehavior =
binding.queueSheet.coordinatorLayoutBehavior as QueueBottomSheetBehavior?
playbackSheetBehavior.state = BackportBottomSheetBehavior.STATE_COLLAPSED
@ -615,7 +615,7 @@ class MainFragment :
val playbackSheetBehavior =
binding.playbackSheet.coordinatorLayoutBehavior as PlaybackBottomSheetBehavior
if (playbackSheetBehavior.targetState == BackportBottomSheetBehavior.STATE_HIDDEN) {
logD("Unhiding and enabling playback sheet")
T.d("Unhiding and enabling playback sheet")
val queueSheetBehavior =
binding.queueSheet.coordinatorLayoutBehavior as QueueBottomSheetBehavior?
// Queue sheet behavior is either collapsed or expanded, no hiding needed
@ -636,7 +636,7 @@ class MainFragment :
val queueSheetBehavior =
binding.queueSheet.coordinatorLayoutBehavior as QueueBottomSheetBehavior?
logD("Hiding and disabling playback and queue sheets")
T.d("Hiding and disabling playback and queue sheets")
// Make both bottom sheets non-draggable so the user can't halt the hiding event.
queueSheetBehavior?.apply {
@ -720,7 +720,7 @@ class MainFragment :
OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
if (detailModel.dropPlaylistEdit()) {
logD("Dropped playlist edits")
T.d("Dropped playlist edits")
}
}
@ -733,7 +733,7 @@ class MainFragment :
OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
if (listModel.dropSelection()) {
logD("Dropped selection")
T.d("Dropped selection")
}
}

View file

@ -41,10 +41,10 @@ import org.oxycblt.auxio.playback.formatDurationMs
import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.getPlural
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A [ListFragment] that shows information about an [Album].
@ -103,7 +103,7 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
private fun updateAlbum(album: Album?) {
if (album == null) {
logD("No album to show, navigating away")
T.d("No album to show, navigating away")
findNavController().navigateUp()
return
}
@ -153,7 +153,7 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
val binding = requireBinding()
when (show) {
is Show.SongDetails -> {
logD("Navigating to ${show.song}")
T.d("Navigating to ${show.song}")
findNavController()
.navigateSafe(AlbumDetailFragmentDirections.showSong(show.song.uid))
}
@ -162,11 +162,11 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
// fragment should be launched otherwise.
is Show.SongAlbumDetails -> {
if (unlikelyToBeNull(detailModel.currentAlbum.value) == show.song.album) {
logD("Navigating to a ${show.song} in this album")
T.d("Navigating to a ${show.song} in this album")
scrollToAlbumSong(show.song)
detailModel.toShow.consume()
} else {
logD("Navigating to the album of ${show.song}")
T.d("Navigating to the album of ${show.song}")
findNavController()
.navigateSafe(AlbumDetailFragmentDirections.showAlbum(show.song.album.uid))
}
@ -176,27 +176,27 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
// detail fragment.
is Show.AlbumDetails -> {
if (unlikelyToBeNull(detailModel.currentAlbum.value) == show.album) {
logD("Navigating to the top of this album")
T.d("Navigating to the top of this album")
binding.detailRecycler.scrollToPosition(0)
detailModel.toShow.consume()
} else {
logD("Navigating to ${show.album}")
T.d("Navigating to ${show.album}")
findNavController()
.navigateSafe(AlbumDetailFragmentDirections.showAlbum(show.album.uid))
}
}
is Show.ArtistDetails -> {
logD("Navigating to ${show.artist}")
T.d("Navigating to ${show.artist}")
findNavController()
.navigateSafe(AlbumDetailFragmentDirections.showArtist(show.artist.uid))
}
is Show.SongArtistDecision -> {
logD("Navigating to artist choices for ${show.song}")
T.d("Navigating to artist choices for ${show.song}")
findNavController()
.navigateSafe(AlbumDetailFragmentDirections.showArtistChoices(show.song.uid))
}
is Show.AlbumArtistDecision -> {
logD("Navigating to artist choices for ${show.album}")
T.d("Navigating to artist choices for ${show.album}")
findNavController()
.navigateSafe(AlbumDetailFragmentDirections.showArtistChoices(show.album.uid))
}
@ -239,7 +239,7 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
val directions =
when (decision) {
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} songs to a playlist")
T.d("Adding ${decision.songs.size} songs to a playlist")
AlbumDetailFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
@ -268,11 +268,11 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
val directions =
when (decision) {
is PlaybackDecision.PlayFromArtist -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
AlbumDetailFragmentDirections.playFromArtist(decision.song.uid)
}
is PlaybackDecision.PlayFromGenre -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
AlbumDetailFragmentDirections.playFromGenre(decision.song.uid)
}
}

View file

@ -42,10 +42,10 @@ import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getPlural
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A [ListFragment] that shows information about an [Artist].
@ -112,7 +112,7 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
private fun updateArtist(artist: Artist?) {
if (artist == null) {
logD("No artist to show, navigating away")
T.d("No artist to show, navigating away")
findNavController().navigateUp()
return
}
@ -155,7 +155,7 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
// The artist does not have any songs, so hide functionality that makes no sense.
// ex. Play and Shuffle, Song Counts, and Genre Information.
// Artists are always guaranteed to have albums however, so continue to show those.
logD("Artist is empty, disabling genres and playback")
T.d("Artist is empty, disabling genres and playback")
binding.detailSubhead.isVisible = false
binding.detailPlayButton?.isEnabled = false
binding.detailShuffleButton?.isEnabled = false
@ -177,14 +177,14 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
val binding = requireBinding()
when (show) {
is Show.SongDetails -> {
logD("Navigating to ${show.song}")
T.d("Navigating to ${show.song}")
findNavController()
.navigateSafe(ArtistDetailFragmentDirections.showSong(show.song.uid))
}
// Songs should be shown in their album, not in their artist.
is Show.SongAlbumDetails -> {
logD("Navigating to the album of ${show.song}")
T.d("Navigating to the album of ${show.song}")
findNavController()
.navigateSafe(ArtistDetailFragmentDirections.showAlbum(show.song.album.uid))
}
@ -192,7 +192,7 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
// Launch a new detail view for an album, even if it is part of
// this artist.
is Show.AlbumDetails -> {
logD("Navigating to ${show.album}")
T.d("Navigating to ${show.album}")
findNavController()
.navigateSafe(ArtistDetailFragmentDirections.showAlbum(show.album.uid))
}
@ -201,22 +201,22 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
// scroll back to the top. Otherwise launch a new detail view.
is Show.ArtistDetails -> {
if (show.artist == detailModel.currentArtist.value) {
logD("Navigating to the top of this artist")
T.d("Navigating to the top of this artist")
binding.detailRecycler.scrollToPosition(0)
detailModel.toShow.consume()
} else {
logD("Navigating to ${show.artist}")
T.d("Navigating to ${show.artist}")
findNavController()
.navigateSafe(ArtistDetailFragmentDirections.showArtist(show.artist.uid))
}
}
is Show.SongArtistDecision -> {
logD("Navigating to artist choices for ${show.song}")
T.d("Navigating to artist choices for ${show.song}")
findNavController()
.navigateSafe(ArtistDetailFragmentDirections.showArtistChoices(show.song.uid))
}
is Show.AlbumArtistDecision -> {
logD("Navigating to artist choices for ${show.album}")
T.d("Navigating to artist choices for ${show.album}")
findNavController()
.navigateSafe(ArtistDetailFragmentDirections.showArtistChoices(show.album.uid))
}
@ -260,7 +260,7 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
val directions =
when (decision) {
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} songs to a playlist")
T.d("Adding ${decision.songs.size} songs to a playlist")
ArtistDetailFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
@ -301,7 +301,7 @@ class ArtistDetailFragment : DetailFragment<Artist, Music>() {
is PlaybackDecision.PlayFromArtist ->
error("Unexpected playback decision $decision")
is PlaybackDecision.PlayFromGenre -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
ArtistDetailFragmentDirections.playFromGenre(decision.song.uid)
}
}

View file

@ -34,7 +34,7 @@ import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.info.Disc
import org.oxycblt.auxio.music.info.ReleaseType
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
interface DetailGenerator {
fun any(uid: Music.UID): Detail<out MusicParent>?
@ -159,7 +159,7 @@ private class DetailGeneratorImpl(
// groupByTo normally returns a mapping to a MutableList mapping. Since MutableList
// inherits list, we can cast upwards and save a copy by directly inserting the
// implicit album list into the mapping.
logD("Implicit albums present, adding to list")
T.d("Implicit albums present, adding to list")
@Suppress("UNCHECKED_CAST")
(grouping as MutableMap<DetailSection.Albums.Category, Collection<Album>>)[
DetailSection.Albums.Category.APPEARANCES] = artist.implicitAlbums

View file

@ -54,9 +54,8 @@ import org.oxycblt.auxio.playback.PlaySong
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* [ViewModel] that manages the Song, Album, Artist, and Genre detail views. Keeps track of the
@ -302,7 +301,7 @@ constructor(
private fun showImpl(show: Show) {
val existing = toShow.flow.value
if (existing != null) {
logD("Already have pending show command $existing, ignoring $show")
T.d("Already have pending show command $existing, ignoring $show")
return
}
_toShow.put(show)
@ -315,10 +314,10 @@ constructor(
* @param uid The UID of the [Song] to load. Must be valid.
*/
fun setSong(uid: Music.UID) {
logD("Opening song $uid")
T.d("Opening song $uid")
_currentSong.value = musicRepository.deviceLibrary?.findSong(uid)?.also(::refreshAudioInfo)
if (_currentSong.value == null) {
logW("Given song UID was invalid")
T.w("Given song UID was invalid")
}
}
@ -329,14 +328,14 @@ constructor(
* @param uid The [Music.UID] of the [Album] to update [currentAlbum] to. Must be valid.
*/
fun setAlbum(uid: Music.UID) {
logD("Opening album $uid")
T.d("Opening album $uid")
if (uid === _currentAlbum.value?.uid) {
return
}
val album = detailGenerator.album(uid)
refreshDetail(album, _currentAlbum, _albumSongList, _albumSongInstructions, null)
if (_currentAlbum.value == null) {
logW("Given album UID was invalid")
T.w("Given album UID was invalid")
}
}
@ -356,7 +355,7 @@ constructor(
* @param uid The [Music.UID] of the [Artist] to update [currentArtist] to. Must be valid.
*/
fun setArtist(uid: Music.UID) {
logD("Opening artist $uid")
T.d("Opening artist $uid")
if (uid === _currentArtist.value?.uid) {
return
}
@ -380,7 +379,7 @@ constructor(
* @param uid The [Music.UID] of the [Genre] to update [currentGenre] to. Must be valid.
*/
fun setGenre(uid: Music.UID) {
logD("Opening genre $uid")
T.d("Opening genre $uid")
if (uid === _currentGenre.value?.uid) {
return
}
@ -404,7 +403,7 @@ constructor(
* @param uid The [Music.UID] of the [Playlist] to update [currentPlaylist] to. Must be valid.
*/
fun setPlaylist(uid: Music.UID) {
logD("Opening playlist $uid")
T.d("Opening playlist $uid")
if (uid === _currentPlaylist.value?.uid) {
return
}
@ -414,7 +413,7 @@ constructor(
/** Start a playlist editing session. Does nothing if a playlist is not being shown. */
fun startPlaylistEdit() {
val playlist = _currentPlaylist.value ?: return
logD("Starting playlist edit")
T.d("Starting playlist edit")
_editedPlaylist.value = playlist.songs
refreshPlaylist(playlist.uid)
}
@ -426,7 +425,7 @@ constructor(
fun savePlaylistEdit() {
val playlist = _currentPlaylist.value ?: return
val editedPlaylist = _editedPlaylist.value ?: return
logD("Committing playlist edits")
T.d("Committing playlist edits")
viewModelScope.launch {
musicRepository.rewritePlaylist(playlist, editedPlaylist)
// TODO: The user could probably press some kind of button if they were fast enough.
@ -479,7 +478,7 @@ constructor(
if (realFrom !in editedPlaylist.indices || realTo !in editedPlaylist.indices) {
return false
}
logD("Moving playlist song from $realFrom [$from] to $realTo [$to]")
T.d("Moving playlist song from $realFrom [$from] to $realTo [$to]")
editedPlaylist.add(realFrom, editedPlaylist.removeAt(realTo))
_editedPlaylist.value = editedPlaylist
refreshPlaylist(playlist.uid, UpdateInstructions.Move(from, to))
@ -498,7 +497,7 @@ constructor(
if (realAt !in editedPlaylist.indices) {
return
}
logD("Removing playlist song at $realAt [$at]")
T.d("Removing playlist song at $realAt [$at]")
editedPlaylist.removeAt(realAt)
_editedPlaylist.value = editedPlaylist
refreshPlaylist(
@ -506,13 +505,13 @@ constructor(
if (editedPlaylist.isNotEmpty()) {
UpdateInstructions.Remove(at, 1)
} else {
logD("Playlist will be empty after removal, removing header")
T.d("Playlist will be empty after removal, removing header")
UpdateInstructions.Remove(at - 1, 3)
})
}
private fun refreshAudioInfo(song: Song) {
logD("Refreshing audio info")
T.d("Refreshing audio info")
// Clear any previous job in order to avoid stale data from appearing in the UI.
currentSongJob?.cancel()
_songAudioProperties.value = null
@ -520,7 +519,7 @@ constructor(
viewModelScope.launch(Dispatchers.IO) {
val info = audioPropertiesFactory.extract(song)
yield()
logD("Updating audio info to $info")
T.d("Updating audio info to $info")
_songAudioProperties.value = info
}
}
@ -587,7 +586,7 @@ constructor(
uid: Music.UID,
instructions: UpdateInstructions = UpdateInstructions.Diff
) {
logD("Refreshing playlist list")
T.d("Refreshing playlist list")
val edited = editedPlaylist.value
if (edited == null) {
val playlist = detailGenerator.playlist(uid)

View file

@ -40,10 +40,10 @@ import org.oxycblt.auxio.playback.PlaybackDecision
import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.getPlural
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A [ListFragment] that shows information for a particular [Genre].
@ -110,7 +110,7 @@ class GenreDetailFragment : DetailFragment<Genre, Music>() {
private fun updateGenre(genre: Genre?) {
if (genre == null) {
logD("No genre to show, navigating away")
T.d("No genre to show, navigating away")
findNavController().navigateUp()
return
}
@ -144,7 +144,7 @@ class GenreDetailFragment : DetailFragment<Genre, Music>() {
private fun handleShow(show: Show?) {
when (show) {
is Show.SongDetails -> {
logD("Navigating to ${show.song}")
T.d("Navigating to ${show.song}")
findNavController()
.navigateSafe(GenreDetailFragmentDirections.showSong(show.song.uid))
}
@ -152,7 +152,7 @@ class GenreDetailFragment : DetailFragment<Genre, Music>() {
// Songs should be scrolled to if the album matches, or a new detail
// fragment should be launched otherwise.
is Show.SongAlbumDetails -> {
logD("Navigating to the album of ${show.song}")
T.d("Navigating to the album of ${show.song}")
findNavController()
.navigateSafe(GenreDetailFragmentDirections.showAlbum(show.song.album.uid))
}
@ -160,29 +160,29 @@ class GenreDetailFragment : DetailFragment<Genre, Music>() {
// If the album matches, no need to do anything. Otherwise launch a new
// detail fragment.
is Show.AlbumDetails -> {
logD("Navigating to ${show.album}")
T.d("Navigating to ${show.album}")
findNavController()
.navigateSafe(GenreDetailFragmentDirections.showAlbum(show.album.uid))
}
// Always launch a new ArtistDetailFragment.
is Show.ArtistDetails -> {
logD("Navigating to ${show.artist}")
T.d("Navigating to ${show.artist}")
findNavController()
.navigateSafe(GenreDetailFragmentDirections.showArtist(show.artist.uid))
}
is Show.SongArtistDecision -> {
logD("Navigating to artist choices for ${show.song}")
T.d("Navigating to artist choices for ${show.song}")
findNavController()
.navigateSafe(GenreDetailFragmentDirections.showArtistChoices(show.song.uid))
}
is Show.AlbumArtistDecision -> {
logD("Navigating to artist choices for ${show.album}")
T.d("Navigating to artist choices for ${show.album}")
findNavController()
.navigateSafe(GenreDetailFragmentDirections.showArtistChoices(show.album.uid))
}
is Show.GenreDetails -> {
logD("Navigated to this genre")
T.d("Navigated to this genre")
detailModel.toShow.consume()
}
is Show.PlaylistDetails -> {
@ -223,7 +223,7 @@ class GenreDetailFragment : DetailFragment<Genre, Music>() {
val directions =
when (decision) {
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} songs to a playlist")
T.d("Adding ${decision.songs.size} songs to a playlist")
GenreDetailFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
@ -262,7 +262,7 @@ class GenreDetailFragment : DetailFragment<Genre, Music>() {
val directions =
when (decision) {
is PlaybackDecision.PlayFromArtist -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
GenreDetailFragmentDirections.playFromArtist(decision.song.uid)
}
is PlaybackDecision.PlayFromGenre -> error("Unexpected playback decision $decision")

View file

@ -49,11 +49,10 @@ import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getPlural
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A [ListFragment] that shows information for a particular [Playlist].
@ -82,11 +81,11 @@ class PlaylistDetailFragment :
getContentLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri == null) {
logW("No URI returned from file picker")
T.w("No URI returned from file picker")
return@registerForActivityResult
}
logD("Received playlist URI $uri")
T.d("Received playlist URI $uri")
musicModel.importPlaylist(uri, pendingImportTarget)
}
@ -194,7 +193,7 @@ class PlaylistDetailFragment :
getString(R.string.fmt_editing, playlist.name.resolve(requireContext()))
if (editedPlaylist != null) {
logD("Binding edited playlist image")
T.d("Binding edited playlist image")
binding.detailCover.bind(
editedPlaylist,
binding.context.getString(R.string.desc_playlist_image, playlist.name),
@ -223,7 +222,7 @@ class PlaylistDetailFragment :
val playable = playlist.songs.isNotEmpty() && editedPlaylist == null
if (!playable) {
logD("Playlist is being edited or is empty, disabling playback options")
T.d("Playlist is being edited or is empty, disabling playback options")
}
binding.detailPlayButton?.apply {
@ -249,7 +248,7 @@ class PlaylistDetailFragment :
listModel.dropSelection()
if (editedPlaylist != null) {
logD("Updating save button state")
T.d("Updating save button state")
requireBinding().detailEditToolbar.menu.findItem(R.id.action_save).apply {
isEnabled = editedPlaylist != detailModel.currentPlaylist.value?.songs
}
@ -261,38 +260,38 @@ class PlaylistDetailFragment :
private fun handleShow(show: Show?) {
when (show) {
is Show.SongDetails -> {
logD("Navigating to ${show.song}")
T.d("Navigating to ${show.song}")
findNavController()
.navigateSafe(PlaylistDetailFragmentDirections.showSong(show.song.uid))
}
is Show.SongAlbumDetails -> {
logD("Navigating to the album of ${show.song}")
T.d("Navigating to the album of ${show.song}")
findNavController()
.navigateSafe(PlaylistDetailFragmentDirections.showAlbum(show.song.album.uid))
}
is Show.AlbumDetails -> {
logD("Navigating to ${show.album}")
T.d("Navigating to ${show.album}")
findNavController()
.navigateSafe(PlaylistDetailFragmentDirections.showAlbum(show.album.uid))
}
is Show.ArtistDetails -> {
logD("Navigating to ${show.artist}")
T.d("Navigating to ${show.artist}")
findNavController()
.navigateSafe(PlaylistDetailFragmentDirections.showArtist(show.artist.uid))
}
is Show.SongArtistDecision -> {
logD("Navigating to artist choices for ${show.song}")
T.d("Navigating to artist choices for ${show.song}")
findNavController()
.navigateSafe(PlaylistDetailFragmentDirections.showArtistChoices(show.song.uid))
}
is Show.AlbumArtistDecision -> {
logD("Navigating to artist choices for ${show.album}")
T.d("Navigating to artist choices for ${show.album}")
findNavController()
.navigateSafe(
PlaylistDetailFragmentDirections.showArtistChoices(show.album.uid))
}
is Show.PlaylistDetails -> {
logD("Navigated to this playlist")
T.d("Navigated to this playlist")
detailModel.toShow.consume()
}
is Show.GenreDetails -> {
@ -333,7 +332,7 @@ class PlaylistDetailFragment :
val directions =
when (decision) {
is PlaylistDecision.Import -> {
logD("Importing playlist")
T.d("Importing playlist")
pendingImportTarget = decision.target
requireNotNull(getContentLauncher) {
"Content picker launcher was not available"
@ -343,7 +342,7 @@ class PlaylistDetailFragment :
return
}
is PlaylistDecision.Rename -> {
logD("Renaming ${decision.playlist}")
T.d("Renaming ${decision.playlist}")
PlaylistDetailFragmentDirections.renamePlaylist(
decision.playlist.uid,
decision.template,
@ -351,15 +350,15 @@ class PlaylistDetailFragment :
decision.reason)
}
is PlaylistDecision.Export -> {
logD("Exporting ${decision.playlist}")
T.d("Exporting ${decision.playlist}")
PlaylistDetailFragmentDirections.exportPlaylist(decision.playlist.uid)
}
is PlaylistDecision.Delete -> {
logD("Deleting ${decision.playlist}")
T.d("Deleting ${decision.playlist}")
PlaylistDetailFragmentDirections.deletePlaylist(decision.playlist.uid)
}
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} songs to a playlist")
T.d("Adding ${decision.songs.size} songs to a playlist")
PlaylistDetailFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
@ -385,11 +384,11 @@ class PlaylistDetailFragment :
val directions =
when (decision) {
is PlaybackDecision.PlayFromArtist -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
PlaylistDetailFragmentDirections.playFromArtist(decision.song.uid)
}
is PlaybackDecision.PlayFromGenre -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
PlaylistDetailFragmentDirections.playFromGenre(decision.song.uid)
}
}
@ -400,15 +399,15 @@ class PlaylistDetailFragment :
val id =
when {
detailModel.editedPlaylist.value != null -> {
logD("Currently editing playlist, showing edit toolbar")
T.d("Currently editing playlist, showing edit toolbar")
R.id.detail_edit_toolbar
}
listModel.selected.value.isNotEmpty() -> {
logD("Currently selecting, showing selection toolbar")
T.d("Currently selecting, showing selection toolbar")
R.id.detail_selection_toolbar
}
else -> {
logD("Using normal toolbar")
T.d("Using normal toolbar")
R.id.detail_normal_toolbar
}
}

View file

@ -42,7 +42,7 @@ import org.oxycblt.auxio.playback.replaygain.formatDb
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.concatLocalized
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ViewBindingMaterialDialogFragment] that shows information about a Song.
@ -76,7 +76,7 @@ class SongDetailDialog : ViewBindingMaterialDialogFragment<DialogSongDetailBindi
private fun updateSong(song: Song?, info: AudioProperties?) {
if (song == null) {
logD("No song to show, navigating away")
T.d("No song to show, navigating away")
findNavController().navigateUp()
return
}

View file

@ -29,8 +29,7 @@ import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.device.DeviceLibrary
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A [ViewModel] that stores choice information for [ShowArtistDialog], and possibly others in the
@ -60,7 +59,7 @@ class DetailPickerViewModel @Inject constructor(private val musicRepository: Mus
val deviceLibrary = musicRepository.deviceLibrary ?: return
// Need to sanitize different items depending on the current set of choices.
_artistChoices.value = _artistChoices.value?.sanitize(deviceLibrary)
logD("Updated artist choices: ${_artistChoices.value}")
T.d("Updated artist choices: ${_artistChoices.value}")
}
/**
@ -69,20 +68,20 @@ class DetailPickerViewModel @Inject constructor(private val musicRepository: Mus
* @param itemUid The [Music.UID] of the item to show. Must be a [Song] or [Album].
*/
fun setArtistChoiceUid(itemUid: Music.UID) {
logD("Opening navigation choices for $itemUid")
T.d("Opening navigation choices for $itemUid")
// Support Songs and Albums, which have parent artists.
_artistChoices.value =
when (val music = musicRepository.find(itemUid)) {
is Song -> {
logD("Creating navigation choices for song")
T.d("Creating navigation choices for song")
ArtistShowChoices.FromSong(music)
}
is Album -> {
logD("Creating navigation choices for album")
T.d("Creating navigation choices for album")
ArtistShowChoices.FromAlbum(music)
}
else -> {
logW("Given song/album UID was invalid")
T.w("Given song/album UID was invalid")
null
}
}

View file

@ -35,7 +35,7 @@ import org.oxycblt.auxio.list.adapter.UpdateInstructions
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A picker [ViewBindingMaterialDialogFragment] intended for when the [Artist] to show is ambiguous.
@ -85,7 +85,7 @@ class ShowArtistDialog :
private fun updateChoices(choices: ArtistShowChoices?) {
if (choices == null) {
logD("No choices to show, navigating away")
T.d("No choices to show, navigating away")
findNavController().navigateUp()
return
}

View file

@ -38,6 +38,7 @@ import org.oxycblt.auxio.list.recycler.DividerViewHolder
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.inflater
import timber.log.Timber as T
/**
* A [RecyclerView.Adapter] that implements shared behavior between lists of child items in the

View file

@ -46,7 +46,7 @@ import org.oxycblt.auxio.music.resolveNames
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [DetailListAdapter] implementing the header, sub-items, and editing state for the [Playlist]
@ -97,7 +97,7 @@ class PlaylistDetailListAdapter(private val listener: Listener) :
// Nothing to do.
return
}
logD("Updating editing state [old: $isEditing new: $editing]")
T.d("Updating editing state [old: $isEditing new: $editing]")
this.isEditing = editing
notifyItemRangeChanged(0, currentList.size, PAYLOAD_EDITING_CHANGED)
}

View file

@ -28,7 +28,7 @@ import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.list.sort.SortDialog
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [SortDialog] that controls the [Sort] of [DetailViewModel.albumSongSort].
@ -56,7 +56,7 @@ class AlbumSongSortDialog : SortDialog() {
private fun updateAlbum(album: Album?) {
if (album == null) {
logD("No album to sort, navigating away")
T.d("No album to sort, navigating away")
findNavController().navigateUp()
}
}

View file

@ -28,7 +28,7 @@ import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.list.sort.SortDialog
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [SortDialog] that controls the [Sort] of [DetailViewModel.artistSongSort].
@ -57,7 +57,7 @@ class ArtistSongSortDialog : SortDialog() {
private fun updateArtist(artist: Artist?) {
if (artist == null) {
logD("No artist to sort, navigating away")
T.d("No artist to sort, navigating away")
findNavController().navigateUp()
}
}

View file

@ -28,7 +28,7 @@ import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.list.sort.SortDialog
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [SortDialog] that controls the [Sort] of [DetailViewModel.genreSongSort].
@ -62,7 +62,7 @@ class GenreSongSortDialog : SortDialog() {
private fun updateGenre(genre: Genre?) {
if (genre == null) {
logD("No genre to sort, navigating away")
T.d("No genre to sort, navigating away")
findNavController().navigateUp()
}
}

View file

@ -28,7 +28,7 @@ import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.list.sort.SortDialog
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [SortDialog] that controls the [Sort] of [DetailViewModel.genreSongSort].
@ -62,7 +62,7 @@ class PlaylistSongSortDialog : SortDialog() {
private fun updatePlaylist(genre: Playlist?) {
if (genre == null) {
logD("No genre to sort, navigating away")
T.d("No genre to sort, navigating away")
findNavController().navigateUp()
}
}

View file

@ -77,10 +77,9 @@ import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.getColorCompat
import org.oxycblt.auxio.util.lazyReflectedField
import org.oxycblt.auxio.util.lazyReflectedMethod
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.showToast
import timber.log.Timber as T
/**
* The starting [SelectionFragment] of Auxio. Shows the user's music library and enables navigation
@ -126,11 +125,11 @@ class HomeFragment :
getContentLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri == null) {
logW("No URI returned from file picker")
T.w("No URI returned from file picker")
return@registerForActivityResult
}
logD("Received playlist URI $uri")
T.d("Received playlist URI $uri")
musicModel.importPlaylist(uri, pendingImportTarget)
}
@ -221,17 +220,17 @@ class HomeFragment :
return when (item.itemId) {
// Handle main actions (Search, Settings, About)
R.id.action_search -> {
logD("Navigating to search")
T.d("Navigating to search")
findNavController().navigateSafe(HomeFragmentDirections.search())
true
}
R.id.action_settings -> {
logD("Navigating to preferences")
T.d("Navigating to preferences")
homeModel.showSettings()
true
}
R.id.action_about -> {
logD("Navigating to about")
T.d("Navigating to about")
homeModel.showAbout()
true
}
@ -251,7 +250,7 @@ class HomeFragment :
true
}
else -> {
logW("Unexpected menu item selected")
T.w("Unexpected menu item selected")
false
}
}
@ -265,7 +264,7 @@ class HomeFragment :
if (homeModel.currentTabTypes.size == 1) {
// A single tab makes the tab layout redundant, hide it and disable the collapsing
// behavior.
logD("Single tab shown, disabling TabLayout")
T.d("Single tab shown, disabling TabLayout")
binding.homeTabs.isVisible = false
binding.homeAppbar.setExpanded(true, false)
toolbarParams.scrollFlags = 0
@ -303,7 +302,7 @@ class HomeFragment :
private fun handleRecreate(recreate: Unit?) {
if (recreate == null) return
val binding = requireBinding()
logD("Recreating ViewPager")
T.d("Recreating ViewPager")
// Move back to position zero, as there must be a tab there.
binding.homePager.currentItem = 0
// Make sure tabs are set up to also follow the new ViewPager configuration.
@ -320,7 +319,7 @@ class HomeFragment :
is IndexingState.Completed -> setupCompleteState(binding, state.error)
is IndexingState.Indexing -> setupIndexingState(binding, state.progress)
null -> {
logD("Indexer is in indeterminate state")
T.d("Indexer is in indeterminate state")
binding.homeIndexingContainer.visibility = View.INVISIBLE
}
}
@ -328,19 +327,19 @@ class HomeFragment :
private fun setupCompleteState(binding: FragmentHomeBinding, error: Exception?) {
if (error == null) {
logD("Received ok response")
T.d("Received ok response")
binding.homeIndexingContainer.visibility = View.INVISIBLE
return
}
logD("Received non-ok response")
T.d("Received non-ok response")
val context = requireContext()
binding.homeIndexingContainer.visibility = View.VISIBLE
binding.homeIndexingProgress.visibility = View.INVISIBLE
binding.homeIndexingActions.visibility = View.VISIBLE
when (error) {
is NoAudioPermissionException -> {
logD("Showing permission prompt")
T.d("Showing permission prompt")
binding.homeIndexingStatus.setText(R.string.err_no_perms)
// Configure the action to act as a permission launcher.
binding.homeIndexingTry.apply {
@ -355,7 +354,7 @@ class HomeFragment :
binding.homeIndexingMore.visibility = View.GONE
}
is NoMusicException -> {
logD("Showing no music error")
T.d("Showing no music error")
binding.homeIndexingStatus.setText(R.string.err_no_music)
// Configure the action to act as a reload trigger.
binding.homeIndexingTry.apply {
@ -366,7 +365,7 @@ class HomeFragment :
binding.homeIndexingMore.visibility = View.GONE
}
else -> {
logD("Showing generic error")
T.d("Showing generic error")
binding.homeIndexingStatus.setText(R.string.err_index_failed)
// Configure the action to act as a reload trigger.
binding.homeIndexingTry.apply {
@ -412,14 +411,14 @@ class HomeFragment :
val directions =
when (decision) {
is PlaylistDecision.New -> {
logD("Creating new playlist")
T.d("Creating new playlist")
HomeFragmentDirections.newPlaylist(
decision.songs.map { it.uid }.toTypedArray(),
decision.template,
decision.reason)
}
is PlaylistDecision.Import -> {
logD("Importing playlist")
T.d("Importing playlist")
pendingImportTarget = decision.target
requireNotNull(getContentLauncher) {
"Content picker launcher was not available"
@ -429,7 +428,7 @@ class HomeFragment :
return
}
is PlaylistDecision.Rename -> {
logD("Renaming ${decision.playlist}")
T.d("Renaming ${decision.playlist}")
HomeFragmentDirections.renamePlaylist(
decision.playlist.uid,
decision.template,
@ -437,15 +436,15 @@ class HomeFragment :
decision.reason)
}
is PlaylistDecision.Export -> {
logD("Exporting ${decision.playlist}")
T.d("Exporting ${decision.playlist}")
HomeFragmentDirections.exportPlaylist(decision.playlist.uid)
}
is PlaylistDecision.Delete -> {
logD("Deleting ${decision.playlist}")
T.d("Deleting ${decision.playlist}")
HomeFragmentDirections.deletePlaylist(decision.playlist.uid)
}
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} to a playlist")
T.d("Adding ${decision.songs.size} to a playlist")
HomeFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
@ -476,38 +475,38 @@ class HomeFragment :
private fun handleShow(show: Show?) {
when (show) {
is Show.SongDetails -> {
logD("Navigating to ${show.song}")
T.d("Navigating to ${show.song}")
findNavController().navigateSafe(HomeFragmentDirections.showSong(show.song.uid))
}
is Show.SongAlbumDetails -> {
logD("Navigating to the album of ${show.song}")
T.d("Navigating to the album of ${show.song}")
findNavController()
.navigateSafe(HomeFragmentDirections.showAlbum(show.song.album.uid))
}
is Show.AlbumDetails -> {
logD("Navigating to ${show.album}")
T.d("Navigating to ${show.album}")
findNavController().navigateSafe(HomeFragmentDirections.showAlbum(show.album.uid))
}
is Show.ArtistDetails -> {
logD("Navigating to ${show.artist}")
T.d("Navigating to ${show.artist}")
findNavController().navigateSafe(HomeFragmentDirections.showArtist(show.artist.uid))
}
is Show.SongArtistDecision -> {
logD("Navigating to artist choices for ${show.song}")
T.d("Navigating to artist choices for ${show.song}")
findNavController()
.navigateSafe(HomeFragmentDirections.showArtistChoices(show.song.uid))
}
is Show.AlbumArtistDecision -> {
logD("Navigating to artist choices for ${show.album}")
T.d("Navigating to artist choices for ${show.album}")
findNavController()
.navigateSafe(HomeFragmentDirections.showArtistChoices(show.album.uid))
}
is Show.GenreDetails -> {
logD("Navigating to ${show.genre}")
T.d("Navigating to ${show.genre}")
findNavController().navigateSafe(HomeFragmentDirections.showGenre(show.genre.uid))
}
is Show.PlaylistDetails -> {
logD("Navigating to ${show.playlist}")
T.d("Navigating to ${show.playlist}")
findNavController()
.navigateSafe(HomeFragmentDirections.showPlaylist(show.playlist.uid))
}
@ -535,7 +534,7 @@ class HomeFragment :
binding.homeSelectionToolbar.title = getString(R.string.fmt_selected, selected.size)
if (binding.homeToolbar.setVisible(R.id.home_selection_toolbar)) {
// New selection started, show the AppBarLayout to indicate the new state.
logD("Significant selection occurred, expanding AppBar")
T.d("Significant selection occurred, expanding AppBar")
binding.homeAppbar.expandWithScrollingRecycler()
}
} else {

View file

@ -29,7 +29,7 @@ import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.MusicType
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
interface HomeGenerator {
fun attach()
@ -89,7 +89,7 @@ private class HomeGeneratorImpl(
override fun onHideCollaboratorsChanged() {
// Changes in the hide collaborator setting will change the artist contents
// of the library, consider it a library update.
logD("Collaborator setting changed, forwarding update")
T.d("Collaborator setting changed, forwarding update")
onMusicChanges(MusicRepository.Changes(deviceLibrary = true, userLibrary = false))
}
@ -121,7 +121,7 @@ private class HomeGeneratorImpl(
override fun onMusicChanges(changes: MusicRepository.Changes) {
val deviceLibrary = musicRepository.deviceLibrary
if (changes.deviceLibrary && deviceLibrary != null) {
logD("Refreshing library")
T.d("Refreshing library")
// Get the each list of items in the library to use as our list data.
// Applying the preferred sorting to them.
invalidator.invalidateMusic(MusicType.SONGS, UpdateInstructions.Diff)
@ -132,7 +132,7 @@ private class HomeGeneratorImpl(
val userLibrary = musicRepository.userLibrary
if (changes.userLibrary && userLibrary != null) {
logD("Refreshing playlists")
T.d("Refreshing playlists")
invalidator.invalidateMusic(MusicType.PLAYLISTS, UpdateInstructions.Diff)
}
}

View file

@ -26,8 +26,8 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.home.tabs.Tab
import org.oxycblt.auxio.music.MusicType
import org.oxycblt.auxio.settings.Settings
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* User configuration specific to the home UI.
@ -68,17 +68,17 @@ class HomeSettingsImpl @Inject constructor(@ApplicationContext context: Context)
override fun migrate() {
if (sharedPreferences.contains(OLD_KEY_LIB_TABS)) {
logD("Migrating tab setting")
T.d("Migrating tab setting")
val oldTabs =
Tab.fromIntCode(sharedPreferences.getInt(OLD_KEY_LIB_TABS, Tab.SEQUENCE_DEFAULT))
?: unlikelyToBeNull(Tab.fromIntCode(Tab.SEQUENCE_DEFAULT))
logD("Old tabs: $oldTabs")
T.d("Old tabs: $oldTabs")
// The playlist tab is now parsed, but it needs to be made visible.
val playlistIndex = oldTabs.indexOfFirst { it.type == MusicType.PLAYLISTS }
check(playlistIndex > -1) // This should exist, otherwise we are in big trouble
oldTabs[playlistIndex] = Tab.Visible(MusicType.PLAYLISTS)
logD("New tabs: $oldTabs")
T.d("New tabs: $oldTabs")
sharedPreferences.edit {
putInt(getString(R.string.set_key_home_tabs), Tab.toIntCode(oldTabs))
@ -90,11 +90,11 @@ class HomeSettingsImpl @Inject constructor(@ApplicationContext context: Context)
override fun onSettingChanged(key: String, listener: HomeSettings.Listener) {
when (key) {
getString(R.string.set_key_home_tabs) -> {
logD("Dispatching tab setting change")
T.d("Dispatching tab setting change")
listener.onTabsChanged()
}
getString(R.string.set_key_hide_collaborators) -> {
logD("Dispatching collaborator setting change")
T.d("Dispatching collaborator setting change")
listener.onHideCollaboratorsChanged()
}
}

View file

@ -37,7 +37,7 @@ import org.oxycblt.auxio.playback.PlaySong
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* The ViewModel for managing the tab data and lists of the home view.
@ -249,7 +249,7 @@ constructor(
* @param pagerPos The new position of the ViewPager2 instance.
*/
fun synchronizeTabPosition(pagerPos: Int) {
logD("Updating current tab to ${currentTabTypes[pagerPos]}")
T.d("Updating current tab to ${currentTabTypes[pagerPos]}")
_currentTabType.value = currentTabTypes[pagerPos]
}
@ -259,7 +259,7 @@ constructor(
* @param isFastScrolling true if the user is currently fast scrolling, false otherwise.
*/
fun setFastScrolling(isFastScrolling: Boolean) {
logD("Updating fast scrolling state: $isFastScrolling")
T.d("Updating fast scrolling state: $isFastScrolling")
_isFastScrolling.value = isFastScrolling
}

View file

@ -19,8 +19,7 @@
package org.oxycblt.auxio.home.tabs
import org.oxycblt.auxio.music.MusicType
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A representation of a library tab suitable for configuration.
@ -86,7 +85,7 @@ sealed class Tab(open val type: MusicType) {
// Like when deserializing, make sure there are no duplicate tabs for whatever reason.
val distinct = tabs.distinctBy { it.type }
if (tabs.size != distinct.size) {
logW(
T.w(
"Tab sequences should not have duplicates [old: ${tabs.size} new: ${distinct.size}]")
}
@ -133,13 +132,13 @@ sealed class Tab(open val type: MusicType) {
// Make sure there are no duplicate tabs
val distinct = tabs.distinctBy { it.type }
if (tabs.size != distinct.size) {
logW(
T.w(
"Tab sequences should not have duplicates [old: ${tabs.size} new: ${distinct.size}]")
}
// For safety, return null if we have an empty or larger-than-expected tab array.
if (distinct.isEmpty() || distinct.size < MAX_SEQUENCE_IDX) {
logE("Sequence size was ${distinct.size}, which is invalid")
T.e("Sequence size was ${distinct.size}, which is invalid")
return null
}

View file

@ -28,7 +28,7 @@ import org.oxycblt.auxio.list.EditClickListListener
import org.oxycblt.auxio.list.recycler.DialogRecyclerView
import org.oxycblt.auxio.music.MusicType
import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [RecyclerView.Adapter] that displays an array of [Tab]s open for configuration.
@ -55,7 +55,7 @@ class TabAdapter(private val listener: EditClickListListener<Tab>) :
* @param newTabs The new array of tabs to show.
*/
fun submitTabs(newTabs: Array<Tab>) {
logD("Force-updating tab information")
T.d("Force-updating tab information")
tabs = newTabs
@Suppress("NotifyDatasetChanged") notifyDataSetChanged()
}
@ -67,7 +67,7 @@ class TabAdapter(private val listener: EditClickListListener<Tab>) :
* @param tab The new tab.
*/
fun setTab(at: Int, tab: Tab) {
logD("Updating tab [at: $at, tab: $tab]")
T.d("Updating tab [at: $at, tab: $tab]")
tabs[at] = tab
// Use a payload to avoid an item change animation.
notifyItemChanged(at, PAYLOAD_TAB_CHANGED)
@ -80,7 +80,7 @@ class TabAdapter(private val listener: EditClickListListener<Tab>) :
* @param b The position of the second tab to swap.
*/
fun swapTabs(a: Int, b: Int) {
logD("Swapping tabs [a: $a, b: $b]")
T.d("Swapping tabs [a: $a, b: $b]")
val tmp = tabs[b]
tabs[b] = tabs[a]
tabs[a] = tmp

View file

@ -31,7 +31,7 @@ import org.oxycblt.auxio.databinding.DialogTabsBinding
import org.oxycblt.auxio.home.HomeSettings
import org.oxycblt.auxio.list.EditClickListListener
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ViewBindingMaterialDialogFragment] that allows the user to modify the home [Tab]
@ -52,7 +52,7 @@ class TabCustomizeDialog :
builder
.setTitle(R.string.set_lib_tabs)
.setPositiveButton(R.string.lbl_ok) { _, _ ->
logD("Committing tab changes")
T.d("Committing tab changes")
homeSettings.homeTabs = tabAdapter.tabs
}
.setNegativeButton(R.string.lbl_cancel, null)
@ -99,7 +99,7 @@ class TabCustomizeDialog :
is Tab.Visible -> Tab.Invisible(old.type)
is Tab.Invisible -> Tab.Visible(old.type)
}
logD("Flipping tab visibility [from: $old to: $new]")
T.d("Flipping tab visibility [from: $old to: $new]")
tabAdapter.setTab(index, new)
// Prevent the user from saving if all the tabs are Invisible, as that's an invalid state.

View file

@ -24,7 +24,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.oxycblt.auxio.R
import org.oxycblt.auxio.settings.Settings
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* User configuration specific to image loading.
@ -58,7 +58,7 @@ class ImageSettingsImpl @Inject constructor(@ApplicationContext context: Context
// Show album covers and Ignore MediaStore covers were unified in 3.0.0
if (sharedPreferences.contains(OLD_KEY_SHOW_COVERS) ||
sharedPreferences.contains(OLD_KEY_QUALITY_COVERS)) {
logD("Migrating cover settings")
T.d("Migrating cover settings")
val mode =
when {
@ -79,7 +79,7 @@ class ImageSettingsImpl @Inject constructor(@ApplicationContext context: Context
override fun onSettingChanged(key: String, listener: ImageSettings.Listener) {
if (key == getString(R.string.set_key_cover_mode) ||
key == getString(R.string.set_key_square_covers)) {
logD("Dispatching image setting change")
T.d("Dispatching image setting change")
listener.onImageSettingsChanged()
}
}

View file

@ -53,7 +53,7 @@ import okio.source
import org.oxycblt.auxio.image.CoverMode
import org.oxycblt.auxio.image.ImageSettings
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
/**
* Provides functionality for extracting album cover information. Meant for internal use only.
@ -153,7 +153,7 @@ constructor(
}
}
} catch (e: Exception) {
logE("Unable to extract album cover due to an error: $e")
T.e("Unable to extract album cover due to an error: $e")
null
}

View file

@ -19,6 +19,7 @@
package org.oxycblt.auxio.list
import androidx.annotation.StringRes
import timber.log.Timber as T
// TODO: Consider breaking this up into sealed classes for individual adapters
/** A marker for something that is a RecyclerView item. Has no functionality on it's own. */

View file

@ -21,6 +21,7 @@ package org.oxycblt.auxio.list
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import org.oxycblt.auxio.music.Music
import timber.log.Timber as T
/**
* A Fragment containing a selectable list.

View file

@ -36,8 +36,7 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaySong
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A [ViewModel] that orchestrates menu dialogs and selection state.
@ -94,16 +93,16 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
*/
fun select(music: Music) {
if (music is MusicParent && music.songs.isEmpty()) {
logD("Cannot select empty parent, ignoring operation")
T.d("Cannot select empty parent, ignoring operation")
return
}
val selected = _selected.value.toMutableList()
if (!selected.remove(music)) {
logD("Adding $music to selection")
T.d("Adding $music to selection")
selected.add(music)
} else {
logD("Removed $music from selection")
T.d("Removed $music from selection")
}
_selected.value = selected
@ -131,7 +130,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @return A list of [Song]s collated from each item selected.
*/
fun takeSelection(): List<Song> {
logD("Taking selection")
T.d("Taking selection")
return peekSelection().also { _selected.value = listOf() }
}
@ -141,7 +140,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @return true if the prior selection was non-empty, false otherwise.
*/
fun dropSelection(): Boolean {
logD("Dropping selection [empty=${_selected.value.isEmpty()}]")
T.d("Dropping selection [empty=${_selected.value.isEmpty()}]")
return _selected.value.isNotEmpty().also { _selected.value = listOf() }
}
@ -155,7 +154,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* should do.
*/
fun openMenu(@MenuRes menuRes: Int, song: Song, playWith: PlaySong) {
logD("Opening menu for $song")
T.d("Opening menu for $song")
openImpl(Menu.ForSong(menuRes, song, playWith))
}
@ -167,7 +166,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @param album The [Album] to show.
*/
fun openMenu(@MenuRes menuRes: Int, album: Album) {
logD("Opening menu for $album")
T.d("Opening menu for $album")
openImpl(Menu.ForAlbum(menuRes, album))
}
@ -179,7 +178,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @param artist The [Artist] to show.
*/
fun openMenu(@MenuRes menuRes: Int, artist: Artist) {
logD("Opening menu for $artist")
T.d("Opening menu for $artist")
openImpl(Menu.ForArtist(menuRes, artist))
}
@ -191,7 +190,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @param genre The [Genre] to show.
*/
fun openMenu(@MenuRes menuRes: Int, genre: Genre) {
logD("Opening menu for $genre")
T.d("Opening menu for $genre")
openImpl(Menu.ForGenre(menuRes, genre))
}
@ -203,7 +202,7 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @param playlist The [Playlist] to show.
*/
fun openMenu(@MenuRes menuRes: Int, playlist: Playlist) {
logD("Opening menu for $playlist")
T.d("Opening menu for $playlist")
openImpl(Menu.ForPlaylist(menuRes, playlist))
}
@ -215,14 +214,14 @@ constructor(private val listSettings: ListSettings, private val musicRepository:
* @param songs The [Song] selection to show.
*/
fun openMenu(@MenuRes menuRes: Int, songs: List<Song>) {
logD("Opening menu for ${songs.size} songs")
T.d("Opening menu for ${songs.size} songs")
openImpl(Menu.ForSelection(menuRes, songs))
}
private fun openImpl(menu: Menu) {
val existing = _menu.flow.value
if (existing != null) {
logW("Already opening $existing, ignoring $menu")
T.w("Already opening $existing, ignoring $menu")
return
}
_menu.put(menu)

View file

@ -21,6 +21,7 @@ package org.oxycblt.auxio.list
import android.view.MotionEvent
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import timber.log.Timber as T
/**
* A basic listener for list interactions.

View file

@ -25,7 +25,7 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import java.util.concurrent.Executor
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A variant of ListDiffer with more flexible updates.
@ -57,7 +57,7 @@ abstract class FlexibleListAdapter<T, VH : RecyclerView.ViewHolder>(
instructions: UpdateInstructions?,
callback: (() -> Unit)? = null
) {
logD("Updating list to ${newList.size} items with $instructions")
T.d("Updating list to ${newList.size} items with $instructions")
differ.update(newList, instructions, callback)
}
}
@ -171,7 +171,7 @@ private class FlexibleListDiffer<T>(
) {
// fast simple remove all
if (newList.isEmpty()) {
logD("Short-circuiting diff to remove all")
T.d("Short-circuiting diff to remove all")
val countRemoved = oldList.size
currentList = emptyList()
// notify last, after list is updated
@ -182,7 +182,7 @@ private class FlexibleListDiffer<T>(
// fast simple first insert
if (oldList.isEmpty()) {
logD("Short-circuiting diff to insert all")
T.d("Short-circuiting diff to insert all")
currentList = newList
// notify last, after list is updated
updateCallback.onInserted(0, newList.size)
@ -244,7 +244,7 @@ private class FlexibleListDiffer<T>(
mainThreadExecutor.execute {
if (maxScheduledGeneration == runGeneration) {
logD("Applying calculated diff")
T.d("Applying calculated diff")
currentList = newList
result.dispatchUpdatesTo(updateCallback)
callback?.invoke()

View file

@ -21,8 +21,7 @@ package org.oxycblt.auxio.list.adapter
import android.view.View
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A [RecyclerView.Adapter] that supports indicating the playback status of a particular item.
@ -59,7 +58,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
* @param isPlaying Whether playback is ongoing or paused.
*/
fun setPlaying(item: T?, isPlaying: Boolean) {
logD("Updating playing item [old: $currentItem new: $item]")
T.d("Updating playing item [old: $currentItem new: $item]")
var updatedItem = false
if (currentItem != item) {
@ -72,7 +71,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
if (pos > -1) {
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
} else {
logW("oldItem was not in adapter data")
T.w("oldItem was not in adapter data")
}
}
@ -82,7 +81,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
if (pos > -1) {
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
} else {
logW("newItem was not in adapter data")
T.w("newItem was not in adapter data")
}
}
@ -100,7 +99,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
if (pos > -1) {
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
} else {
logW("newItem was not in adapter data")
T.w("newItem was not in adapter data")
}
}
}

View file

@ -22,7 +22,7 @@ import android.view.View
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [PlayingIndicatorAdapter] that also supports indicating the selection status of a group of
@ -55,7 +55,7 @@ abstract class SelectionIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
// Nothing to do.
return
}
logD("Updating selection [old=${oldSelectedItems.size} new=${newSelectedItems.size}")
T.d("Updating selection [old=${oldSelectedItems.size} new=${newSelectedItems.size}")
selectedItems = newSelectedItems
for (i in currentList.indices) {

View file

@ -20,6 +20,7 @@ package org.oxycblt.auxio.list.adapter
import androidx.recyclerview.widget.DiffUtil
import org.oxycblt.auxio.list.Item
import timber.log.Timber as T
/**
* A [DiffUtil.ItemCallback] that automatically implements the [areItemsTheSame] method. Use this

View file

@ -33,7 +33,7 @@ import org.oxycblt.auxio.list.ListViewModel
import org.oxycblt.auxio.list.adapter.UpdateInstructions
import org.oxycblt.auxio.ui.ViewBindingBottomSheetDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ViewBindingBottomSheetDialogFragment] that displays basic music information and a series of
@ -102,7 +102,7 @@ abstract class MenuDialogFragment<M : Menu> :
private fun updateMenu(menu: Menu?) {
if (menu == null) {
logD("No menu to show, navigating away")
T.d("No menu to show, navigating away")
findNavController().navigateUp()
return
}

View file

@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.StateFlow
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.playback.PlaySong
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* Manages the state information for [MenuDialogFragment] implementations.
@ -55,7 +55,7 @@ class MenuViewModel @Inject constructor(private val musicRepository: MusicReposi
fun setMenu(parcel: Menu.Parcel) {
_currentMenu.value = unpackParcel(parcel)
if (_currentMenu.value == null) {
logW("Given menu parcel $parcel was invalid")
T.w("Given menu parcel $parcel was invalid")
}
}

View file

@ -34,7 +34,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.list.recycler.MaterialDragCallback.ViewHolder
import org.oxycblt.auxio.util.getDimen
import org.oxycblt.auxio.util.getInteger
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A highly customized [ItemTouchHelper.Callback] that enables some extra eye candy in editable UIs,
@ -94,7 +94,7 @@ abstract class MaterialDragCallback : ItemTouchHelper.Callback() {
// this is only done once when the item is initially picked up.
// TODO: I think this is possible to improve with a raw ValueAnimator.
if (shouldLift && isCurrentlyActive && actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
logD("Lifting ViewHolder")
T.d("Lifting ViewHolder")
val bg = holder.background
val elevation = recyclerView.context.getDimen(MR.dimen.m3_sys_elevation_level4)
@ -136,7 +136,7 @@ abstract class MaterialDragCallback : ItemTouchHelper.Callback() {
// This function can be called multiple times, so only start the animation when the view's
// translationZ is already non-zero.
if (holder.root.translationZ != 0f) {
logD("Lifting ViewHolder")
T.d("Lifting ViewHolder")
val bg = holder.background
val elevation = recyclerView.context.getDimen(MR.dimen.m3_sys_elevation_level4)

View file

@ -39,6 +39,7 @@ import org.oxycblt.auxio.music.info.ReleaseType
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
import org.oxycblt.auxio.util.concatLocalized
import org.oxycblt.auxio.util.toUuidOrNull
import timber.log.Timber as T
/**
* Abstract music data. This contains universal information about all concrete music

View file

@ -44,9 +44,7 @@ import org.oxycblt.auxio.music.user.MutableUserLibrary
import org.oxycblt.auxio.music.user.UserLibrary
import org.oxycblt.auxio.util.DEFAULT_TIMEOUT
import org.oxycblt.auxio.util.forEachWithTimeout
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* Primary manager of music information and loading.
@ -244,51 +242,51 @@ constructor(
@Synchronized
override fun addUpdateListener(listener: MusicRepository.UpdateListener) {
logD("Adding $listener to update listeners")
T.d("Adding $listener to update listeners")
updateListeners.add(listener)
listener.onMusicChanges(MusicRepository.Changes(deviceLibrary = true, userLibrary = true))
}
@Synchronized
override fun removeUpdateListener(listener: MusicRepository.UpdateListener) {
logD("Removing $listener to update listeners")
T.d("Removing $listener to update listeners")
if (!updateListeners.remove(listener)) {
logW("Update listener $listener was not added prior, cannot remove")
T.w("Update listener $listener was not added prior, cannot remove")
}
}
@Synchronized
override fun addIndexingListener(listener: MusicRepository.IndexingListener) {
logD("Adding $listener to indexing listeners")
T.d("Adding $listener to indexing listeners")
indexingListeners.add(listener)
listener.onIndexingStateChanged()
}
@Synchronized
override fun removeIndexingListener(listener: MusicRepository.IndexingListener) {
logD("Removing $listener from indexing listeners")
T.d("Removing $listener from indexing listeners")
if (!indexingListeners.remove(listener)) {
logW("Indexing listener $listener was not added prior, cannot remove")
T.w("Indexing listener $listener was not added prior, cannot remove")
}
}
@Synchronized
override fun registerWorker(worker: MusicRepository.IndexingWorker) {
if (indexingWorker != null) {
logW("Worker is already registered")
T.w("Worker is already registered")
return
}
logD("Registering worker $worker")
T.d("Registering worker $worker")
indexingWorker = worker
}
@Synchronized
override fun unregisterWorker(worker: MusicRepository.IndexingWorker) {
if (indexingWorker !== worker) {
logW("Given worker did not match current worker")
T.w("Given worker did not match current worker")
return
}
logD("Unregistering worker $worker")
T.d("Unregistering worker $worker")
indexingWorker = null
currentIndexingState = null
}
@ -300,42 +298,42 @@ constructor(
override suspend fun createPlaylist(name: String, songs: List<Song>) {
val userLibrary = synchronized(this) { userLibrary ?: return }
logD("Creating playlist $name with ${songs.size} songs")
T.d("Creating playlist $name with ${songs.size} songs")
userLibrary.createPlaylist(name, songs)
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
}
override suspend fun renamePlaylist(playlist: Playlist, name: String) {
val userLibrary = synchronized(this) { userLibrary ?: return }
logD("Renaming $playlist to $name")
T.d("Renaming $playlist to $name")
userLibrary.renamePlaylist(playlist, name)
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
}
override suspend fun deletePlaylist(playlist: Playlist) {
val userLibrary = synchronized(this) { userLibrary ?: return }
logD("Deleting $playlist")
T.d("Deleting $playlist")
userLibrary.deletePlaylist(playlist)
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
}
override suspend fun addToPlaylist(songs: List<Song>, playlist: Playlist) {
val userLibrary = synchronized(this) { userLibrary ?: return }
logD("Adding ${songs.size} songs to $playlist")
T.d("Adding ${songs.size} songs to $playlist")
userLibrary.addToPlaylist(playlist, songs)
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
}
override suspend fun rewritePlaylist(playlist: Playlist, songs: List<Song>) {
val userLibrary = synchronized(this) { userLibrary ?: return }
logD("Rewriting $playlist with ${songs.size} songs")
T.d("Rewriting $playlist with ${songs.size} songs")
userLibrary.rewritePlaylist(playlist, songs)
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
}
@Synchronized
override fun requestIndex(withCache: Boolean) {
logD("Requesting index operation [cache=$withCache]")
T.d("Requesting index operation [cache=$withCache]")
indexingWorker?.requestIndex(withCache)
}
@ -347,13 +345,13 @@ constructor(
indexImpl(context, scope, withCache)
} catch (e: CancellationException) {
// Got cancelled, propagate upwards to top-level co-routine.
logD("Loading routine was cancelled")
T.d("Loading routine was cancelled")
throw e
} catch (e: Exception) {
// Music loading process failed due to something we have not handled.
// TODO: Still want to display this error eventually
logE("Music indexing failed")
logE(e.stackTraceToString())
T.e("Music indexing failed")
T.e(e.stackTraceToString())
emitIndexingCompletion(e)
}
}
@ -366,7 +364,7 @@ constructor(
// done at the UI level, but that intertwines logic and display too much.
if (ContextCompat.checkSelfPermission(context, PERMISSION_READ_AUDIO) ==
PackageManager.PERMISSION_DENIED) {
logE("Permissions were not granted")
T.e("Permissions were not granted")
throw NoAudioPermissionException()
}
@ -385,7 +383,7 @@ constructor(
// to figure out what songs are (probably) on the device, and the latter will be needed
// for discovery (described later). These have no shared state, so they are done in
// parallel.
logD("Starting MediaStore query")
T.d("Starting MediaStore query")
emitIndexingProgress(IndexingProgress.Indeterminate)
val mediaStoreQueryJob =
@ -406,18 +404,18 @@ constructor(
// identical to calling async.
val cache =
if (withCache) {
logD("Reading cache")
T.d("Reading cache")
cacheRepository.readCache()
} else {
null
}
logD("Awaiting MediaStore query")
T.d("Awaiting MediaStore query")
val query = mediaStoreQueryJob.await().getOrThrow()
// We now have all the information required to start the "discovery" process. This
// is the point at which Auxio starts scanning each file given from MediaStore and
// transforming it into a music library. MediaStore normally
logD("Starting discovery")
T.d("Starting discovery")
val incompleteSongs = Channel<RawSong>(Channel.UNLIMITED) // Not fully populated w/metadata
val completeSongs = Channel<RawSong>(Channel.UNLIMITED) // Populated with quality metadata
val processedSongs = Channel<RawSong>(Channel.UNLIMITED) // Transformed into SongImpl
@ -425,7 +423,7 @@ constructor(
// MediaStoreExtractor discovers all music on the device, and forwards them to either
// DeviceLibrary if cached metadata exists for it, or TagExtractor if cached metadata
// does not exist. In the latter situation, it also applies it's own (inferior) metadata.
logD("Starting MediaStore discovery")
T.d("Starting MediaStore discovery")
val mediaStoreJob =
scope.async {
try {
@ -434,7 +432,7 @@ constructor(
// To prevent a deadlock, we want to close the channel with an exception
// to cascade to and cancel all other routines before finally bubbling up
// to the main extractor loop.
logE("MediaStore extraction failed: $e")
T.e("MediaStore extraction failed: $e")
incompleteSongs.close(
Exception("MediaStore extraction failed: ${e.stackTraceToString()}"))
return@async
@ -444,13 +442,13 @@ constructor(
// TagExtractor takes the incomplete songs from MediaStoreExtractor, parses up-to-date
// metadata for them, and then forwards it to DeviceLibrary.
logD("Starting tag extraction")
T.d("Starting tag extraction")
val tagJob =
scope.async {
try {
tagExtractor.consume(incompleteSongs, completeSongs)
} catch (e: Exception) {
logE("Tag extraction failed: $e")
T.e("Tag extraction failed: $e")
completeSongs.close(
Exception("Tag extraction failed: ${e.stackTraceToString()}"))
return@async
@ -460,7 +458,7 @@ constructor(
// DeviceLibrary constructs music parent instances as song information is provided,
// and then forwards them to the primary loading loop.
logD("Starting DeviceLibrary creation")
T.d("Starting DeviceLibrary creation")
val deviceLibraryJob =
scope.async(Dispatchers.Default) {
val deviceLibrary =
@ -468,7 +466,7 @@ constructor(
deviceLibraryFactory.create(
completeSongs, processedSongs, separators, nameFactory)
} catch (e: Exception) {
logE("DeviceLibrary creation failed: $e")
T.e("DeviceLibrary creation failed: $e")
processedSongs.close(
Exception("DeviceLibrary creation failed: ${e.stackTraceToString()}"))
return@async Result.failure(e)
@ -499,14 +497,14 @@ constructor(
// that the short-circuit occurs so quickly as to break the UI.
// TODO: Do not error, instead just wipe the entire library.
if (rawSongs.isEmpty()) {
logE("Music library was empty")
T.e("Music library was empty")
throw NoMusicException()
}
// Now that the library is effectively loaded, we can start the finalization step, which
// involves writing new cache information and creating more music data that is derived
// from the library (e.g playlists)
logD("Discovered ${rawSongs.size} songs, starting finalization")
T.d("Discovered ${rawSongs.size} songs, starting finalization")
// We have no idea how long the cache will take, and the playlist construction
// will be too fast to indicate, so switch back to an indeterminate state.
@ -515,7 +513,7 @@ constructor(
// The UserLibrary job is split into a query and construction step, a la MediaStore.
// This way, we can start working on playlists even as DeviceLibrary might still be
// working on parent information.
logD("Starting UserLibrary query")
T.d("Starting UserLibrary query")
val userLibraryQueryJob =
scope.async {
val rawPlaylists =
@ -532,20 +530,20 @@ constructor(
// since the playlist read will probably take some time.
// TODO: Read/write from the cache incrementally instead of in bulk?
if (cache == null || cache.invalidated) {
logD("Writing cache [why=${cache?.invalidated}]")
T.d("Writing cache [why=${cache?.invalidated}]")
cacheRepository.writeCache(rawSongs)
}
// Create UserLibrary once we finally get the required components for it.
logD("Awaiting UserLibrary query")
T.d("Awaiting UserLibrary query")
val rawPlaylists = userLibraryQueryJob.await().getOrThrow()
logD("Awaiting DeviceLibrary creation")
T.d("Awaiting DeviceLibrary creation")
val deviceLibrary = deviceLibraryJob.await().getOrThrow()
logD("Starting UserLibrary creation")
T.d("Starting UserLibrary creation")
val userLibrary = userLibraryFactory.create(rawPlaylists, deviceLibrary, nameFactory)
// Loading process is functionally done, indicate such
logD(
T.d(
"Successfully indexed music library [device=$deviceLibrary " +
"user=$userLibrary time=${System.currentTimeMillis() - start}]")
emitIndexingCompletion(null)
@ -561,7 +559,7 @@ constructor(
deviceLibraryChanged = this.deviceLibrary != deviceLibrary
userLibraryChanged = this.userLibrary != userLibrary
if (!deviceLibraryChanged && !userLibraryChanged) {
logD("Library has not changed, skipping update")
T.d("Library has not changed, skipping update")
return
}
@ -591,7 +589,7 @@ constructor(
synchronized(this) {
previousCompletedState = IndexingState.Completed(error)
currentIndexingState = null
logD("Dispatching completion state [error=$error]")
T.d("Dispatching completion state [error=$error]")
for (listener in indexingListeners) {
listener.onIndexingStateChanged()
}
@ -601,7 +599,7 @@ constructor(
@Synchronized
private fun dispatchLibraryChange(device: Boolean, user: Boolean) {
val changes = MusicRepository.Changes(device, user)
logD("Dispatching library change [changes=$changes]")
T.d("Dispatching library change [changes=$changes]")
for (listener in updateListeners) {
listener.onMusicChanges(changes)
}

View file

@ -26,7 +26,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.dirs.MusicDirectories
import org.oxycblt.auxio.music.fs.DocumentPathFactory
import org.oxycblt.auxio.settings.Settings
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* User configuration specific to music system.
@ -108,11 +108,11 @@ constructor(
getString(R.string.set_key_music_dirs_include),
getString(R.string.set_key_separators),
getString(R.string.set_key_auto_sort_names) -> {
logD("Dispatching indexing setting change for $key")
T.d("Dispatching indexing setting change for $key")
listener.onIndexingSettingChanged()
}
getString(R.string.set_key_observing) -> {
logD("Dispatching observing setting change")
T.d("Dispatching observing setting change")
listener.onObservingChanged()
}
}

View file

@ -33,8 +33,7 @@ import org.oxycblt.auxio.music.external.ExportConfig
import org.oxycblt.auxio.music.external.ExternalPlaylistManager
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
/**
* A [ViewModel] providing data specific to the music loading process.
@ -94,7 +93,7 @@ constructor(
deviceLibrary.artists.size,
deviceLibrary.genres.size,
deviceLibrary.songs.sumOf { it.durationMs })
logD("Updated statistics: ${_statistics.value}")
T.d("Updated statistics: ${_statistics.value}")
}
override fun onIndexingStateChanged() {
@ -103,13 +102,13 @@ constructor(
/** Requests that the music library should be re-loaded while leveraging the cache. */
fun refresh() {
logD("Refreshing library")
T.d("Refreshing library")
musicRepository.requestIndex(true)
}
/** Requests that the music library be re-loaded without the cache. */
fun rescan() {
logD("Rescanning library")
T.d("Rescanning library")
musicRepository.requestIndex(false)
}
@ -127,7 +126,7 @@ constructor(
reason: PlaylistDecision.New.Reason = PlaylistDecision.New.Reason.NEW
) {
if (name != null) {
logD("Creating $name with ${songs.size} songs]")
T.d("Creating $name with ${songs.size} songs]")
viewModelScope.launch(Dispatchers.IO) {
musicRepository.createPlaylist(name, songs)
val message =
@ -139,7 +138,7 @@ constructor(
_playlistMessage.put(message)
}
} else {
logD("Launching creation dialog for ${songs.size} songs")
T.d("Launching creation dialog for ${songs.size} songs")
_playlistDecision.put(PlaylistDecision.New(songs, null, reason))
}
}
@ -158,7 +157,7 @@ constructor(
viewModelScope.launch(Dispatchers.IO) {
val importedPlaylist = externalPlaylistManager.import(uri)
if (importedPlaylist == null) {
logE("Could not import playlist")
T.e("Could not import playlist")
_playlistMessage.put(PlaylistMessage.ImportFailed)
return@launch
}
@ -170,7 +169,7 @@ constructor(
}
if (songs.isEmpty()) {
logE("No songs found")
T.e("No songs found")
_playlistMessage.put(PlaylistMessage.ImportFailed)
return@launch
}
@ -194,7 +193,7 @@ constructor(
}
}
} else {
logD("Launching import picker")
T.d("Launching import picker")
_playlistDecision.put(PlaylistDecision.Import(target))
}
}
@ -207,7 +206,7 @@ constructor(
*/
fun exportPlaylist(playlist: Playlist, uri: Uri? = null, config: ExportConfig? = null) {
if (uri != null && config != null) {
logD("Exporting playlist to $uri")
T.d("Exporting playlist to $uri")
viewModelScope.launch(Dispatchers.IO) {
if (externalPlaylistManager.export(playlist, uri, config)) {
_playlistMessage.put(PlaylistMessage.ExportSuccess)
@ -216,7 +215,7 @@ constructor(
}
}
} else {
logD("Launching export dialog")
T.d("Launching export dialog")
_playlistDecision.put(PlaylistDecision.Export(playlist))
}
}
@ -238,7 +237,7 @@ constructor(
reason: PlaylistDecision.Rename.Reason = PlaylistDecision.Rename.Reason.ACTION
) {
if (name != null) {
logD("Renaming $playlist to $name")
T.d("Renaming $playlist to $name")
viewModelScope.launch(Dispatchers.IO) {
musicRepository.renamePlaylist(playlist, name)
if (applySongs.isNotEmpty()) {
@ -252,7 +251,7 @@ constructor(
_playlistMessage.put(message)
}
} else {
logD("Launching rename dialog for $playlist")
T.d("Launching rename dialog for $playlist")
_playlistDecision.put(PlaylistDecision.Rename(playlist, null, applySongs, reason))
}
}
@ -267,13 +266,13 @@ constructor(
*/
fun deletePlaylist(playlist: Playlist, rude: Boolean = false) {
if (rude) {
logD("Deleting $playlist")
T.d("Deleting $playlist")
viewModelScope.launch(Dispatchers.IO) {
musicRepository.deletePlaylist(playlist)
_playlistMessage.put(PlaylistMessage.DeleteSuccess)
}
} else {
logD("Launching deletion dialog for $playlist")
T.d("Launching deletion dialog for $playlist")
_playlistDecision.put(PlaylistDecision.Delete(playlist))
}
}
@ -285,7 +284,7 @@ constructor(
* @param playlist The [Playlist] to add to. If null, the user will be prompted for one.
*/
fun addToPlaylist(song: Song, playlist: Playlist? = null) {
logD("Adding $song to playlist")
T.d("Adding $song to playlist")
addToPlaylist(listOf(song), playlist)
}
@ -296,7 +295,7 @@ constructor(
* @param playlist The [Playlist] to add to. If null, the user will be prompted for one.
*/
fun addToPlaylist(album: Album, playlist: Playlist? = null) {
logD("Adding $album to playlist")
T.d("Adding $album to playlist")
addToPlaylist(listSettings.albumSongSort.songs(album.songs), playlist)
}
@ -307,7 +306,7 @@ constructor(
* @param playlist The [Playlist] to add to. If null, the user will be prompted for one.
*/
fun addToPlaylist(artist: Artist, playlist: Playlist? = null) {
logD("Adding $artist to playlist")
T.d("Adding $artist to playlist")
addToPlaylist(listSettings.artistSongSort.songs(artist.songs), playlist)
}
@ -318,7 +317,7 @@ constructor(
* @param playlist The [Playlist] to add to. If null, the user will be prompted for one.
*/
fun addToPlaylist(genre: Genre, playlist: Playlist? = null) {
logD("Adding $genre to playlist")
T.d("Adding $genre to playlist")
addToPlaylist(listSettings.genreSongSort.songs(genre.songs), playlist)
}
@ -330,13 +329,13 @@ constructor(
*/
fun addToPlaylist(songs: List<Song>, playlist: Playlist? = null) {
if (playlist != null) {
logD("Adding ${songs.size} songs to $playlist")
T.d("Adding ${songs.size} songs to $playlist")
viewModelScope.launch(Dispatchers.IO) {
musicRepository.addToPlaylist(songs, playlist)
_playlistMessage.put(PlaylistMessage.AddSuccess)
}
} else {
logD("Launching addition dialog for songs=${songs.size}")
T.d("Launching addition dialog for songs=${songs.size}")
_playlistDecision.put(PlaylistDecision.Add(songs))
}
}

View file

@ -20,8 +20,7 @@ package org.oxycblt.auxio.music.cache
import javax.inject.Inject
import org.oxycblt.auxio.music.device.RawSong
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
/**
* A repository allowing access to cached metadata obtained in prior music loading operations.
@ -51,11 +50,11 @@ class CacheRepositoryImpl @Inject constructor(private val cachedSongsDao: Cached
// Faster to load the whole database into memory than do a query on each
// populate call.
val songs = cachedSongsDao.readSongs()
logD("Successfully read ${songs.size} songs from cache")
T.d("Successfully read ${songs.size} songs from cache")
CacheImpl(songs)
} catch (e: Exception) {
logE("Unable to load cache database.")
logE(e.stackTraceToString())
T.e("Unable to load cache database.")
T.e(e.stackTraceToString())
null
}
@ -63,12 +62,12 @@ class CacheRepositoryImpl @Inject constructor(private val cachedSongsDao: Cached
try {
// Still write out whatever data was extracted.
cachedSongsDao.nukeSongs()
logD("Successfully deleted old cache")
T.d("Successfully deleted old cache")
cachedSongsDao.insertSongs(rawSongs.map(CachedSong::fromRaw))
logD("Successfully wrote ${rawSongs.size} songs to cache")
T.d("Successfully wrote ${rawSongs.size} songs to cache")
} catch (e: Exception) {
logE("Unable to save cache database.")
logE(e.stackTraceToString())
T.e("Unable to save cache database.")
T.e(e.stackTraceToString())
}
}
}

View file

@ -36,8 +36,8 @@ import org.oxycblt.auxio.music.PlaylistDecision
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import timber.log.Timber as T
/**
* A dialog that allows the user to pick a specific playlist to add song(s) to.
@ -105,7 +105,7 @@ class AddToPlaylistDialog :
private fun updatePendingSongs(songs: List<Song>?) {
if (songs == null) {
logD("No songs to show choices for, navigating away")
T.d("No songs to show choices for, navigating away")
findNavController().navigateUp()
}
}

View file

@ -32,8 +32,8 @@ import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A [ViewBindingMaterialDialogFragment] that asks the user to confirm the deletion of a [Playlist].
@ -76,7 +76,7 @@ class DeletePlaylistDialog : ViewBindingMaterialDialogFragment<DialogDeletePlayl
private fun updatePlaylistToDelete(playlist: Playlist?) {
if (playlist == null) {
logD("No playlist to delete, navigating away")
T.d("No playlist to delete, navigating away")
findNavController().navigateUp()
return
}

View file

@ -36,9 +36,8 @@ import org.oxycblt.auxio.music.external.ExportConfig
import org.oxycblt.auxio.music.external.M3U
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A dialog that allows the user to configure how a playlist will be exported to a file.
@ -73,18 +72,18 @@ class ExportPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistExp
registerForActivityResult(ActivityResultContracts.CreateDocument(M3U.MIME_TYPE)) { uri
->
if (uri == null) {
logW("No URI returned from file picker")
T.w("No URI returned from file picker")
return@registerForActivityResult
}
val playlist = pickerModel.currentPlaylistToExport.value
if (playlist == null) {
logW("No playlist to export")
T.w("No playlist to export")
findNavController().navigateUp()
return@registerForActivityResult
}
logD("Received playlist URI $uri")
T.d("Received playlist URI $uri")
musicModel.exportPlaylist(playlist, uri, pickerModel.currentExportConfig.value)
findNavController().navigateUp()
}
@ -129,7 +128,7 @@ class ExportPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistExp
private fun updatePlaylistToExport(playlist: Playlist?) {
if (playlist == null) {
logD("No playlist to export, leaving")
T.d("No playlist to export, leaving")
findNavController().navigateUp()
return
}

View file

@ -34,8 +34,8 @@ import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.PlaylistDecision
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A dialog allowing the name of a new playlist to be chosen before committing it to the database.
@ -98,7 +98,7 @@ class NewPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBi
private fun updatePendingPlaylist(pendingNewPlaylist: PendingNewPlaylist?) {
if (pendingNewPlaylist == null) {
logD("No playlist to create, leaving")
T.d("No playlist to create, leaving")
findNavController().navigateUp()
return
}

View file

@ -33,9 +33,7 @@ import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.PlaylistDecision
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.external.ExportConfig
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A [ViewModel] managing the state of the playlist picker dialogs.
@ -101,7 +99,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
pendingPlaylist.template,
pendingPlaylist.reason)
}
logD("Updated pending playlist: ${_currentPendingNewPlaylist.value?.preferredName}")
T.d("Updated pending playlist: ${_currentPendingNewPlaylist.value?.preferredName}")
_currentSongsToAdd.value =
_currentSongsToAdd.value?.let { pendingSongs ->
@ -110,7 +108,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
.ifEmpty { null }
.also { refreshChoicesWith = it }
}
logD("Updated songs to add: ${_currentSongsToAdd.value?.size} songs")
T.d("Updated songs to add: ${_currentSongsToAdd.value?.size} songs")
}
val chosenName = _chosenName.value
@ -122,7 +120,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
// Nothing to do.
}
}
logD("Updated chosen name to $chosenName")
T.d("Updated chosen name to $chosenName")
refreshChoicesWith = refreshChoicesWith ?: _currentSongsToAdd.value
// TODO: Add music syncing for other playlist states here
@ -131,7 +129,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
_currentPlaylistToExport.value?.let { playlist ->
musicRepository.userLibrary?.findPlaylist(playlist.uid)
}
logD("Updated playlist to export to ${_currentPlaylistToExport.value}")
T.d("Updated playlist to export to ${_currentPlaylistToExport.value}")
}
refreshChoicesWith?.let(::refreshPlaylistChoices)
@ -154,7 +152,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
template: String?,
reason: PlaylistDecision.New.Reason
) {
logD("Opening ${songUids.size} songs to create a playlist from")
T.d("Opening ${songUids.size} songs to create a playlist from")
val userLibrary = musicRepository.userLibrary ?: return
val songs =
musicRepository.deviceLibrary
@ -168,10 +166,10 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
var possibleName: String
do {
possibleName = context.getString(R.string.fmt_def_playlist, i)
logD("Trying $possibleName as a playlist name")
T.d("Trying $possibleName as a playlist name")
++i
} while (userLibrary.playlists.any { it.name.resolve(context) == possibleName })
logD("$possibleName is unique, using it as the playlist name")
T.d("$possibleName is unique, using it as the playlist name")
possibleName
}
@ -179,7 +177,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
if (possibleName != null && songs != null) {
PendingNewPlaylist(possibleName, songs, template, reason)
} else {
logW("Given song UIDs to create were invalid")
T.w("Given song UIDs to create were invalid")
null
}
}
@ -195,7 +193,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
template: String?,
reason: PlaylistDecision.Rename.Reason
) {
logD("Opening playlist $playlistUid to rename")
T.d("Opening playlist $playlistUid to rename")
val playlist = musicRepository.userLibrary?.findPlaylist(playlistUid)
val applySongs =
musicRepository.deviceLibrary?.let { applySongUids.mapNotNull(it::findSong) }
@ -204,7 +202,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
if (playlist != null && applySongs != null) {
PendingRenamePlaylist(playlist, applySongs, template, reason)
} else {
logW("Given playlist UID to rename was invalid")
T.w("Given playlist UID to rename was invalid")
null
}
}
@ -215,12 +213,12 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
* @param playlistUid The [Music.UID] of the [Playlist] to export.
*/
fun setPlaylistToExport(playlistUid: Music.UID) {
logD("Opening playlist $playlistUid to export")
T.d("Opening playlist $playlistUid to export")
// TODO: Add this guard to the rest of the methods here
if (_currentPlaylistToExport.value?.uid == playlistUid) return
_currentPlaylistToExport.value = musicRepository.userLibrary?.findPlaylist(playlistUid)
if (_currentPlaylistToExport.value == null) {
logW("Given playlist UID to export was invalid")
T.w("Given playlist UID to export was invalid")
} else {
_currentExportConfig.value = DEFAULT_EXPORT_CONFIG
}
@ -232,7 +230,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
* @param exportConfig The new [ExportConfig] to use.
*/
fun setExportConfig(exportConfig: ExportConfig) {
logD("Setting export config to $exportConfig")
T.d("Setting export config to $exportConfig")
_currentExportConfig.value = exportConfig
}
@ -242,10 +240,10 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
* @param playlistUid The [Music.UID] of the [Playlist] to delete.
*/
fun setPlaylistToDelete(playlistUid: Music.UID) {
logD("Opening playlist $playlistUid to delete")
T.d("Opening playlist $playlistUid to delete")
_currentPlaylistToDelete.value = musicRepository.userLibrary?.findPlaylist(playlistUid)
if (_currentPlaylistToDelete.value == null) {
logW("Given playlist UID to delete was invalid")
T.w("Given playlist UID to delete was invalid")
}
}
@ -255,25 +253,25 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
* @param name The new user-inputted name, or null if not present.
*/
fun updateChosenName(name: String?) {
logD("Updating chosen name to $name")
T.d("Updating chosen name to $name")
_chosenName.value =
when {
name.isNullOrEmpty() -> {
logE("Chosen name is empty")
T.e("Chosen name is empty")
ChosenName.Empty
}
name.isBlank() -> {
logE("Chosen name is blank")
T.e("Chosen name is blank")
ChosenName.Blank
}
else -> {
val trimmed = name.trim()
val userLibrary = musicRepository.userLibrary
if (userLibrary != null && userLibrary.findPlaylist(trimmed) == null) {
logD("Chosen name is valid")
T.d("Chosen name is valid")
ChosenName.Valid(trimmed)
} else {
logD("Chosen name already exists in library")
T.d("Chosen name already exists in library")
ChosenName.AlreadyExists(trimmed)
}
}
@ -286,19 +284,19 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
* @param songUids The [Music.UID]s of songs to add to a playlist.
*/
fun setSongsToAdd(songUids: Array<Music.UID>) {
logD("Opening ${songUids.size} songs to add to a playlist")
T.d("Opening ${songUids.size} songs to add to a playlist")
_currentSongsToAdd.value =
musicRepository.deviceLibrary
?.let { songUids.mapNotNull(it::findSong).ifEmpty { null } }
?.also(::refreshPlaylistChoices)
if (_currentSongsToAdd.value == null || songUids.size != _currentSongsToAdd.value?.size) {
logW("Given song UIDs to add were (partially) invalid")
T.w("Given song UIDs to add were (partially) invalid")
}
}
private fun refreshPlaylistChoices(songs: List<Song>) {
val userLibrary = musicRepository.userLibrary ?: return
logD("Refreshing playlist choices")
T.d("Refreshing playlist choices")
_playlistAddChoices.value =
Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).playlists(userLibrary.playlists).map {
val songSet = it.songs.toSet()

View file

@ -32,8 +32,8 @@ import org.oxycblt.auxio.databinding.DialogPlaylistNameBinding
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A dialog allowing the name of a new playlist to be chosen before committing it to the database.
@ -94,7 +94,7 @@ class RenamePlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNam
val default =
pendingRenamePlaylist.template
?: pendingRenamePlaylist.playlist.name.resolve(requireContext())
logD("Name input is not initialized, setting to $default")
T.d("Name input is not initialized, setting to $default")
requireBinding().playlistName.setText(default)
initializedField = true
}

View file

@ -35,9 +35,9 @@ import org.oxycblt.auxio.music.fs.useQuery
import org.oxycblt.auxio.music.info.Name
import org.oxycblt.auxio.music.metadata.Separators
import org.oxycblt.auxio.util.forEachWithTimeout
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.sendWithTimeout
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* Organized music library information obtained from device storage.
@ -147,7 +147,7 @@ class DeviceLibraryFactoryImpl @Inject constructor() : DeviceLibrary.Factory {
// UID is sufficient for something like this, and also prevents collisions from
// causing severe issues elsewhere.
if (songGrouping.containsKey(song.uid)) {
logW(
T.w(
"Duplicate song found: ${song.path} " +
"collides with ${unlikelyToBeNull(songGrouping[song.uid]).path}")
// We still want to say that we "processed" the song so that the user doesn't

View file

@ -26,7 +26,7 @@ import org.oxycblt.auxio.list.recycler.DialogRecyclerView
import org.oxycblt.auxio.music.fs.Path
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* [RecyclerView.Adapter] that manages a list of [Path] music directory instances.
@ -55,7 +55,7 @@ class DirectoryAdapter(private val listener: Listener) :
*/
fun add(path: Path) {
if (_dirs.contains(path)) return
logD("Adding $path")
T.d("Adding $path")
_dirs.add(path)
notifyItemInserted(_dirs.lastIndex)
}
@ -66,7 +66,7 @@ class DirectoryAdapter(private val listener: Listener) :
* @param path The [Path] instances to add.
*/
fun addAll(path: List<Path>) {
logD("Adding ${path.size} directories")
T.d("Adding ${path.size} directories")
val oldLastIndex = path.lastIndex
_dirs.addAll(path)
notifyItemRangeInserted(oldLastIndex, path.size)
@ -78,7 +78,7 @@ class DirectoryAdapter(private val listener: Listener) :
* @param path The [Path] to remove. Must exist in the list.
*/
fun remove(path: Path) {
logD("Removing $path")
T.d("Removing $path")
val idx = _dirs.indexOf(path)
_dirs.removeAt(idx)
notifyItemRemoved(idx)

View file

@ -36,8 +36,8 @@ import org.oxycblt.auxio.music.MusicSettings
import org.oxycblt.auxio.music.fs.DocumentPathFactory
import org.oxycblt.auxio.music.fs.Path
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.showToast
import timber.log.Timber as T
/**
* Dialog that manages the music dirs setting.
@ -62,7 +62,7 @@ class MusicDirsDialog :
.setPositiveButton(R.string.lbl_save) { _, _ ->
val newDirs = MusicDirectories(dirAdapter.dirs, isUiModeInclude(requireBinding()))
if (musicSettings.musicDirs != newDirs) {
logD("Committing changes")
T.d("Committing changes")
musicSettings.musicDirs = newDirs
}
}
@ -76,7 +76,7 @@ class MusicDirsDialog :
binding.dirsAdd.apply {
ViewCompat.setTooltipText(this, contentDescription)
setOnClickListener {
logD("Opening launcher")
T.d("Opening launcher")
val launcher =
requireNotNull(openDocumentTreeLauncher) {
"Document tree launcher was not available"
@ -150,7 +150,7 @@ class MusicDirsDialog :
private fun addDocumentTreeUriToDirs(uri: Uri?) {
if (uri == null) {
// A null URI means that the user left the file picker without picking a directory
logD("No URI given (user closed the dialog)")
T.d("No URI given (user closed the dialog)")
return
}

View file

@ -27,7 +27,7 @@ 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 timber.log.Timber as T
/**
* Generic playlist file importing abstraction.
@ -108,7 +108,7 @@ constructor(
return ImportedPlaylist(newName, imported.paths)
}
} catch (e: Exception) {
logE("Failed to import playlist: $e")
T.e("Failed to import playlist: $e")
null
}
}
@ -124,7 +124,7 @@ constructor(
return try {
val outputStream = context.contentResolverSafe.openOutputStream(uri)
if (outputStream == null) {
logE("Failed to export playlist: Could not open output stream")
T.e("Failed to export playlist: Could not open output stream")
return false
}
outputStream.use {
@ -132,7 +132,7 @@ constructor(
true
}
} catch (e: Exception) {
logE("Failed to export playlist: $e")
T.e("Failed to export playlist: $e")
false
}
}

View file

@ -33,8 +33,8 @@ import org.oxycblt.auxio.music.fs.Volume
import org.oxycblt.auxio.music.fs.VolumeManager
import org.oxycblt.auxio.music.metadata.correctWhitespace
import org.oxycblt.auxio.music.resolveNames
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* Minimal M3U file format implementation.
@ -116,7 +116,7 @@ constructor(
}
if (path == null) {
logE("Expected a path, instead got an EOF")
T.e("Expected a path, instead got an EOF")
break@consumeFile
}

View file

@ -32,8 +32,8 @@ import org.oxycblt.auxio.music.dirs.MusicDirectories
import org.oxycblt.auxio.music.info.Date
import org.oxycblt.auxio.music.metadata.parseId3v2PositionField
import org.oxycblt.auxio.music.metadata.transformPositionField
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.sendWithTimeout
import timber.log.Timber as T
/**
* The layer that loads music from the [MediaStore] database. This is an intermediate step in the
@ -127,7 +127,7 @@ private class MediaStoreExtractorImpl(
// Filter out audio that is not music, if enabled.
if (constraints.excludeNonMusic) {
logD("Excluding non-music")
T.d("Excluding non-music")
uniSelector += " AND ${MediaStore.Audio.AudioColumns.IS_MUSIC}=1"
}
@ -136,10 +136,10 @@ private class MediaStoreExtractorImpl(
val pathSelector =
mediaStorePathInterpreterFactory.createSelector(constraints.musicDirs.dirs)
if (pathSelector != null) {
logD("Must select for directories")
T.d("Must select for directories")
uniSelector += " AND "
if (!constraints.musicDirs.shouldInclude) {
logD("Excluding directories in selector")
T.d("Excluding directories in selector")
// Without a NOT, the query will be restricted to the specified paths, resulting
// in the "Include" mode. With a NOT, the specified paths will not be included,
// resulting in the "Exclude" mode.
@ -151,7 +151,7 @@ private class MediaStoreExtractorImpl(
}
// Now we can actually query MediaStore.
logD(
T.d(
"Starting song query [proj=${projection.toList()}, selector=$uniSelector, args=$uniArgs]")
val cursor =
context.contentResolverSafe.safeQuery(
@ -159,7 +159,7 @@ private class MediaStoreExtractorImpl(
projection,
uniSelector,
uniArgs.toTypedArray())
logD("Successfully queried for ${cursor.count} songs")
T.d("Successfully queried for ${cursor.count} songs")
val genreNamesMap = mutableMapOf<Long, String>()
@ -194,8 +194,8 @@ private class MediaStoreExtractorImpl(
}
}
logD("Read ${genreNamesMap.values.distinct().size} genres from MediaStore")
logD("Finished initialization in ${System.currentTimeMillis() - start}ms")
T.d("Read ${genreNamesMap.values.distinct().size} genres from MediaStore")
T.d("Finished initialization in ${System.currentTimeMillis() - start}ms")
return QueryImpl(
cursor,
mediaStorePathInterpreterFactory.wrap(cursor),

View file

@ -21,7 +21,7 @@ package org.oxycblt.auxio.music.fs
import android.database.Cursor
import android.os.Build
import android.provider.MediaStore
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
/**
* Wrapper around a [Cursor] that interprets path information on a per-API/manufacturer basis.
@ -112,7 +112,7 @@ private constructor(private val cursor: Cursor, volumeManager: VolumeManager) :
}
}
logE("Could not find volume for $data [tried: ${volumes.map { it.components }}]")
T.e("Could not find volume for $data [tried: ${volumes.map { it.components }}]")
return null
}
@ -181,7 +181,7 @@ private constructor(private val cursor: Cursor, volumeManager: VolumeManager) :
val displayName = cursor.getString(displayNameIndex)
val volume = volumes.find { it.mediaStoreName == volumeName }
if (volume == null) {
logE(
T.e(
"Could not find volume for $volumeName:$relativePath/$displayName [tried: ${volumes.map { it.mediaStoreName }}]")
return null
}

View file

@ -24,8 +24,8 @@ import java.text.SimpleDateFormat
import kotlin.math.max
import org.oxycblt.auxio.R
import org.oxycblt.auxio.util.inRangeOrNull
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.positiveOrNull
import timber.log.Timber as T
/**
* An ISO-8601/RFC 3339 Date.
@ -64,7 +64,7 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
try {
format.parse("$year-$month")
} catch (e: ParseException) {
logE("Unable to parse fine-grained date: $e")
T.e("Unable to parse fine-grained date: $e")
return null
}

View file

@ -25,9 +25,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.fs.MimeType
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* The properties of a [Song]'s file.
@ -75,8 +73,8 @@ constructor(@ApplicationContext private val context: Context) : AudioProperties.
// Can feasibly fail with invalid file formats. Note that this isn't considered
// an error condition in the UI, as there is still plenty of other song information
// that we can show.
logW("Unable to extract song attributes.")
logW(e.stackTraceToString())
T.w("Unable to extract song attributes.")
T.w(e.stackTraceToString())
return AudioProperties(null, null, song.mimeType)
}
@ -92,7 +90,7 @@ constructor(@ApplicationContext private val context: Context) : AudioProperties.
// Convert bytes-per-second to kilobytes-per-second.
format.getInteger(MediaFormat.KEY_BIT_RATE) / 1000
} catch (e: NullPointerException) {
logD("Unable to extract bit rate field")
T.d("Unable to extract bit rate field")
null
}
@ -100,7 +98,7 @@ constructor(@ApplicationContext private val context: Context) : AudioProperties.
try {
format.getInteger(MediaFormat.KEY_SAMPLE_RATE)
} catch (e: NullPointerException) {
logE("Unable to extract sample rate field")
T.e("Unable to extract sample rate field")
null
}
@ -110,13 +108,13 @@ constructor(@ApplicationContext private val context: Context) : AudioProperties.
try {
format.getString(MediaFormat.KEY_MIME)
} catch (e: NullPointerException) {
logE("Unable to extract mime type field")
T.e("Unable to extract mime type field")
null
}
extractor.release()
logD("Finished extracting audio properties")
T.d("Finished extracting audio properties")
return AudioProperties(
bitrate,

View file

@ -30,7 +30,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.DialogSeparatorsBinding
import org.oxycblt.auxio.music.MusicSettings
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A [ViewBindingMaterialDialogFragment] that allows the user to configure the separator characters
@ -76,7 +76,7 @@ class SeparatorsDialog : ViewBindingMaterialDialogFragment<DialogSeparatorsBindi
Separators.SLASH -> binding.separatorSlash.isChecked = true
Separators.PLUS -> binding.separatorPlus.isChecked = true
Separators.AND -> binding.separatorAnd.isChecked = true
else -> logW("Unexpected separator in settings data")
else -> T.w("Unexpected separator in settings data")
}
}
}

View file

@ -41,9 +41,8 @@ import kotlinx.coroutines.yield
import org.oxycblt.auxio.music.device.RawSong
import org.oxycblt.auxio.music.fs.toAudioUri
import org.oxycblt.auxio.util.forEachWithTimeout
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.sendWithTimeout
import timber.log.Timber as T
class TagExtractor
@Inject
@ -67,7 +66,7 @@ constructor(private val mediaSourceFactory: Factory, private val tagInterpreter:
songsIn++
}
logD("All incomplete songs exhausted, starting cleanup loop")
T.d("All incomplete songs exhausted, starting cleanup loop")
while (!worker.idle()) {
val completeRawSong = worker.pull()
if (completeRawSong != null) {
@ -153,8 +152,8 @@ private class MetadataWorker(
try {
tagInterpreter.interpret(job.rawSong, job.future.get())
} catch (e: Exception) {
logE("Failed to extract metadata")
logE(e.stackTraceToString())
T.e("Failed to extract metadata")
T.e(e.stackTraceToString())
}
jobs[i] = null
return job.rawSong
@ -177,7 +176,7 @@ private class MetadataWorker(
mediaSource = currentMediaSource
mediaSourceCaller = currentMediaSourceCaller
} else {
logD("new media source yahoo")
T.d("new media source yahoo")
mediaSource = mediaSourceFactory.createMediaSource(job.mediaItem)
mediaSourceCaller = MediaSourceCaller(job)
mediaSource.prepareSource(
@ -194,8 +193,8 @@ private class MetadataWorker(
mediaPeriod.maybeThrowPrepareError()
}
} catch (e: Exception) {
logE("Failed to extract MediaSource")
logE(e.stackTraceToString())
T.e("Failed to extract MediaSource")
T.e(e.stackTraceToString())
job.mediaPeriod?.let(mediaSource::releasePeriod)
mediaSource.releaseSource(mediaSourceCaller)
job.future.setException(e)
@ -248,7 +247,7 @@ private class MetadataWorker(
// Ignore dynamic updates.
return
}
logD("yay source created")
T.d("yay source created")
mediaPeriodCreated = true
val mediaPeriod =
source.createPeriod(

View file

@ -26,8 +26,8 @@ import kotlin.math.min
import org.oxycblt.auxio.image.extractor.CoverExtractor
import org.oxycblt.auxio.music.device.RawSong
import org.oxycblt.auxio.music.info.Date
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.nonZeroOrNull
import timber.log.Timber as T
/**
* An processing abstraction over the [MetadataRetriever] and [TextTags] workflow that operates on
@ -82,25 +82,25 @@ class TagInterpreterImpl @Inject constructor(private val coverExtractor: CoverEx
// val gain =
// (((header[16]).toInt() and 0xFF) or ((header[17].toInt() shl 8)))
// .R128ToLUFS18()
// logD("Obtained opus base gain: $gain dB")
// T.d("Obtained opus base gain: $gain dB")
// if (gain != 0f) {
// logD("Applying opus base gain")
// T.d("Applying opus base gain")
// rawSong.replayGainTrackAdjustment =
// (rawSong.replayGainTrackAdjustment ?: 0f) + gain
// rawSong.replayGainAlbumAdjustment =
// (rawSong.replayGainAlbumAdjustment ?: 0f) + gain
// } else {
// logD("Ignoring opus base gain")
// T.d("Ignoring opus base gain")
// }
// }
} else {
logD("No metadata could be extracted for ${rawSong.name}")
T.d("No metadata could be extracted for ${rawSong.name}")
}
}
private fun populateWithId3v2(rawSong: RawSong, textFrames: Map<String, List<String>>) {
// Song
logD(textFrames)
T.d(textFrames)
(textFrames["TXXX:musicbrainz release track id"]
?: textFrames["TXXX:musicbrainz_releasetrackid"])
?.let { rawSong.musicBrainzId = it.first() }

View file

@ -33,7 +33,7 @@ import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.MusicSettings
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.util.getSystemServiceCompat
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
class Indexer
private constructor(
@ -117,7 +117,7 @@ private constructor(
}
} else if (musicSettings.shouldBeObserving) {
// Not observing and done loading, exit foreground.
logD("Exiting foreground")
T.d("Exiting foreground")
post(observingNotification)
} else {
post(null)
@ -125,7 +125,7 @@ private constructor(
}
override fun requestIndex(withCache: Boolean) {
logD("Starting new indexing job (previous=${currentIndexJob?.hashCode()})")
T.d("Starting new indexing job (previous=${currentIndexJob?.hashCode()})")
// Cancel the previous music loading job.
currentIndexJob?.cancel()
// Start a new music loading job on a co-routine.
@ -146,7 +146,7 @@ private constructor(
override fun onMusicChanges(changes: MusicRepository.Changes) {
val deviceLibrary = musicRepository.deviceLibrary ?: return
logD("Music changed, updating shared objects")
T.d("Music changed, updating shared objects")
// Wipe possibly-invalidated outdated covers
imageLoader.memoryCache?.clear()
// Clear invalid models from PlaybackStateManager. This is not connected
@ -175,7 +175,7 @@ private constructor(
// setting changed. In such a case, the state will still be updated when
// the music loading process ends.
if (musicRepository.indexingState == null) {
logD("Not loading, updating idle session")
T.d("Not loading, updating idle session")
foregroundListener.updateForeground(ForegroundListener.Change.INDEXER)
}
}
@ -184,7 +184,7 @@ private constructor(
private fun PowerManager.WakeLock.acquireSafe() {
// Avoid unnecessary acquire calls.
if (!wakeLock.isHeld) {
logD("Acquiring wake lock")
T.d("Acquiring wake lock")
// Time out after a minute, which is the average music loading time for a medium-sized
// library. If this runs out, we will re-request the lock, and if music loading is
// shorter than the timeout, it will be released early.
@ -196,7 +196,7 @@ private constructor(
private fun PowerManager.WakeLock.releaseSafe() {
// Avoid unnecessary release calls.
if (wakeLock.isHeld) {
logD("Releasing wake lock")
T.d("Releasing wake lock")
release()
}
}

View file

@ -26,8 +26,8 @@ import org.oxycblt.auxio.ForegroundServiceNotification
import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.IndexingProgress
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.newMainPendingIntent
import timber.log.Timber as T
/**
* A dynamic [ForegroundServiceNotification] that shows the current music loading state.
@ -66,7 +66,7 @@ class IndexingNotification(private val context: Context) :
// Indeterminate state, use a vaguer description and in-determinate progress.
// These events are not very frequent, and thus we don't need to safeguard
// against rate limiting.
logD("Updating state to $progress")
T.d("Updating state to $progress")
lastUpdateTime = -1
setContentText(context.getString(R.string.lng_indexing))
setProgress(0, 0, true)
@ -81,7 +81,7 @@ class IndexingNotification(private val context: Context) :
return false
}
lastUpdateTime = SystemClock.elapsedRealtime()
logD("Updating state to $progress")
T.d("Updating state to $progress")
setContentText(
context.getString(R.string.fmt_indexing, progress.current, progress.total))
setProgress(progress.total, progress.current, false)

View file

@ -31,8 +31,7 @@ import kotlinx.coroutines.launch
import org.oxycblt.auxio.ForegroundListener
import org.oxycblt.auxio.ForegroundServiceNotification
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
class MusicServiceFragment
@Inject
@ -124,11 +123,11 @@ constructor(
try {
val result = body()
if (result == null) {
logW("Result is null")
T.w("Result is null")
}
sendResult(result)
} catch (e: Exception) {
logD("Error while dispatching: $e")
T.d("Error while dispatching: $e")
sendResult(null)
}
}
@ -139,11 +138,11 @@ constructor(
try {
val result = body()
if (result == null) {
logW("Result is null")
T.w("Result is null")
}
sendResult(result)
} catch (e: Exception) {
logD("Error while dispatching: $e")
T.d("Error while dispatching: $e")
sendResult(null)
}
}

View file

@ -28,7 +28,7 @@ import javax.inject.Inject
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.MusicSettings
import org.oxycblt.auxio.music.fs.contentResolverSafe
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ContentObserver] that observes the [MediaStore] music database for changes, a behavior known
@ -68,7 +68,7 @@ constructor(
// Check here if we should even start a reindex. This is much less bug-prone than
// registering and de-registering this component as this setting changes.
if (musicSettings.shouldBeObserving) {
logD("MediaStore changed, starting re-index")
T.d("MediaStore changed, starting re-index")
musicRepository.requestIndex(true)
}
}

View file

@ -26,8 +26,7 @@ import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.device.DeviceLibrary
import org.oxycblt.auxio.music.info.Name
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
/**
* Organized library information controlled by the user.
@ -144,10 +143,10 @@ class UserLibraryFactoryImpl @Inject constructor(private val playlistDao: Playli
override suspend fun query() =
try {
val rawPlaylists = playlistDao.readRawPlaylists()
logD("Successfully read ${rawPlaylists.size} playlists")
T.d("Successfully read ${rawPlaylists.size} playlists")
rawPlaylists
} catch (e: Exception) {
logE("Unable to read playlists: $e")
T.e("Unable to read playlists: $e")
listOf()
}
@ -193,11 +192,11 @@ private class UserLibraryImpl(
return try {
playlistDao.insertPlaylist(rawPlaylist)
logD("Successfully created playlist $name with ${songs.size} songs")
T.d("Successfully created playlist $name with ${songs.size} songs")
playlistImpl
} catch (e: Exception) {
logE("Unable to create playlist $name with ${songs.size} songs")
logE(e.stackTraceToString())
T.e("Unable to create playlist $name with ${songs.size} songs")
T.e(e.stackTraceToString())
synchronized(this) { playlistMap.remove(playlistImpl.uid) }
null
}
@ -212,11 +211,11 @@ private class UserLibraryImpl(
return try {
playlistDao.replacePlaylistInfo(PlaylistInfo(playlist.uid, name))
logD("Successfully renamed $playlist to $name")
T.d("Successfully renamed $playlist to $name")
true
} catch (e: Exception) {
logE("Unable to rename $playlist to $name: $e")
logE(e.stackTraceToString())
T.e("Unable to rename $playlist to $name: $e")
T.e(e.stackTraceToString())
synchronized(this) { playlistMap[playlistImpl.uid] = playlistImpl }
false
}
@ -231,11 +230,11 @@ private class UserLibraryImpl(
return try {
playlistDao.deletePlaylist(playlist.uid)
logD("Successfully deleted $playlist")
T.d("Successfully deleted $playlist")
true
} catch (e: Exception) {
logE("Unable to delete $playlist: $e")
logE(e.stackTraceToString())
T.e("Unable to delete $playlist: $e")
T.e(e.stackTraceToString())
synchronized(this) { playlistMap[playlistImpl.uid] = playlistImpl }
false
}
@ -250,11 +249,11 @@ private class UserLibraryImpl(
return try {
playlistDao.insertPlaylistSongs(playlist.uid, songs.map { PlaylistSong(it.uid) })
logD("Successfully added ${songs.size} songs to $playlist")
T.d("Successfully added ${songs.size} songs to $playlist")
true
} catch (e: Exception) {
logE("Unable to add ${songs.size} songs to $playlist: $e")
logE(e.stackTraceToString())
T.e("Unable to add ${songs.size} songs to $playlist: $e")
T.e(e.stackTraceToString())
synchronized(this) { playlistMap[playlistImpl.uid] = playlistImpl }
false
}
@ -269,11 +268,11 @@ private class UserLibraryImpl(
return try {
playlistDao.replacePlaylistSongs(playlist.uid, songs.map { PlaylistSong(it.uid) })
logD("Successfully rewrote $playlist with ${songs.size} songs")
T.d("Successfully rewrote $playlist with ${songs.size} songs")
true
} catch (e: Exception) {
logE("Unable to rewrite $playlist with ${songs.size} songs: $e")
logE(e.stackTraceToString())
T.e("Unable to rewrite $playlist with ${songs.size} songs: $e")
T.e(e.stackTraceToString())
synchronized(this) { playlistMap[playlistImpl.uid] = playlistImpl }
false
}

View file

@ -33,7 +33,7 @@ import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.getColorCompat
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ViewBindingFragment] that shows the current playback state in a compact manner.
@ -128,7 +128,7 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
val binding = requireBinding()
when (actionMode) {
ActionMode.NEXT -> {
logD("Using skip next action")
T.d("Using skip next action")
binding.playbackSecondaryAction.apply {
if (tag != actionMode) {
setIconResource(R.drawable.ic_skip_next_24)
@ -140,7 +140,7 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
}
}
ActionMode.REPEAT -> {
logD("Using repeat mode action")
T.d("Using repeat mode action")
binding.playbackSecondaryAction.apply {
if (tag != actionMode) {
contentDescription = getString(R.string.desc_change_repeat)
@ -153,7 +153,7 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
}
}
ActionMode.SHUFFLE -> {
logD("Using shuffle action")
T.d("Using shuffle action")
binding.playbackSecondaryAction.apply {
if (tag != actionMode) {
setIconResource(R.drawable.sel_shuffle_state_24)

View file

@ -43,9 +43,9 @@ import org.oxycblt.auxio.playback.ui.StyledSeekBar
import org.oxycblt.auxio.playback.ui.SwipeCoverView
import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.systemBarInsetsCompat
import timber.log.Timber as T
/**
* A [ViewBindingFragment] more information about the currently playing song, alongside all
@ -136,7 +136,7 @@ class PlaybackPanelFragment :
override fun onStart() {
super.onStart()
logD(requireBinding().playbackCover.width)
T.d(requireBinding().playbackCover.width)
playbackModel.song.value?.let { requireBinding().playbackCover.bind(it) }
requireBinding().root.viewTreeObserver.addOnGlobalLayoutListener(this)
}
@ -180,7 +180,7 @@ class PlaybackPanelFragment :
override fun onMenuItemClick(item: MenuItem): Boolean {
if (item.itemId == R.id.action_open_equalizer) {
// Launch the system equalizer app, if possible.
logD("Launching equalizer")
T.d("Launching equalizer")
val equalizerIntent =
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL)
// Provide audio session ID so the equalizer can show options for this app
@ -221,7 +221,7 @@ class PlaybackPanelFragment :
val binding = requireBinding()
val context = requireContext()
logD("Updating song display: $song")
T.d("Updating song display: $song")
binding.playbackCover.bind(song)
binding.playbackSong.text = song.name.resolve(context)
binding.playbackArtist.text = song.artists.resolveNames(context)

View file

@ -27,7 +27,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.playback.replaygain.ReplayGainMode
import org.oxycblt.auxio.playback.replaygain.ReplayGainPreAmp
import org.oxycblt.auxio.settings.Settings
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* User configuration specific to the playback system.
@ -146,7 +146,7 @@ class PlaybackSettingsImpl @Inject constructor(@ApplicationContext context: Cont
}
if (sharedPreferences.contains(OLD_KEY_LIB_MUSIC_PLAYBACK_MODE)) {
logD("Migrating $OLD_KEY_LIB_MUSIC_PLAYBACK_MODE")
T.d("Migrating $OLD_KEY_LIB_MUSIC_PLAYBACK_MODE")
val mode =
sharedPreferences
@ -162,7 +162,7 @@ class PlaybackSettingsImpl @Inject constructor(@ApplicationContext context: Cont
}
if (sharedPreferences.contains(OLD_KEY_DETAIL_MUSIC_PLAYBACK_MODE)) {
logD("Migrating $OLD_KEY_DETAIL_MUSIC_PLAYBACK_MODE")
T.d("Migrating $OLD_KEY_DETAIL_MUSIC_PLAYBACK_MODE")
val mode =
sharedPreferences
@ -183,19 +183,19 @@ class PlaybackSettingsImpl @Inject constructor(@ApplicationContext context: Cont
getString(R.string.set_key_replay_gain),
getString(R.string.set_key_pre_amp_with),
getString(R.string.set_key_pre_amp_without) -> {
logD("Dispatching ReplayGain setting change")
T.d("Dispatching ReplayGain setting change")
listener.onReplayGainSettingsChanged()
}
getString(R.string.set_key_notif_action) -> {
logD("Dispatching notification setting change")
T.d("Dispatching notification setting change")
listener.onNotificationActionChanged()
}
getString(R.string.set_key_bar_action) -> {
logD("Dispatching bar action change")
T.d("Dispatching bar action change")
listener.onBarActionChanged()
}
getString(R.string.set_key_repeat_pause) -> {
logD("Dispatching pause on repeat change")
T.d("Dispatching pause on repeat change")
listener.onPauseOnRepeatChanged()
}
}

View file

@ -43,7 +43,7 @@ import org.oxycblt.auxio.playback.state.RepeatMode
import org.oxycblt.auxio.playback.state.ShuffleMode
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* An [ViewModel] that provides a safe UI frontend for the current playback state.
@ -129,20 +129,20 @@ constructor(
}
override fun onIndexMoved(index: Int) {
logD("Index moved, updating current song")
T.d("Index moved, updating current song")
_song.value = playbackManager.currentSong
}
override fun onQueueChanged(queue: List<Song>, index: Int, change: QueueChange) {
// Other types of queue changes preserve the current song.
if (change.type == QueueChange.Type.SONG) {
logD("Queue changed, updating current song")
T.d("Queue changed, updating current song")
_song.value = playbackManager.currentSong
}
}
override fun onQueueReordered(queue: List<Song>, index: Int, isShuffled: Boolean) {
logD("Queue completely changed, updating current song")
T.d("Queue completely changed, updating current song")
_isShuffled.value = isShuffled
}
@ -152,14 +152,14 @@ constructor(
index: Int,
isShuffled: Boolean
) {
logD("New playback started, updating playback information")
T.d("New playback started, updating playback information")
_song.value = playbackManager.currentSong
_parent.value = parent
_isShuffled.value = isShuffled
}
override fun onProgressionChanged(progression: Progression) {
logD("Player state changed, starting new position polling")
T.d("Player state changed, starting new position polling")
_isPlaying.value = progression.isPlaying
// Still need to update the position now due to co-routine launch delays
_positionDs.value = progression.calculateElapsedPositionMs().msToDs()
@ -187,7 +187,7 @@ constructor(
// --- PLAYING FUNCTIONS ---
fun play(song: Song, with: PlaySong) {
logD("Playing $song with $with")
T.d("Playing $song with $with")
playWithImpl(song, with, ShuffleMode.IMPLICIT)
}
@ -201,7 +201,7 @@ constructor(
/** Shuffle all songs in the music library. */
fun shuffleAll() {
logD("Shuffling all songs")
T.d("Shuffling all songs")
playFromAllImpl(null, ShuffleMode.ON)
}
@ -257,7 +257,7 @@ constructor(
}
private fun playFromAlbumImpl(song: Song, shuffle: ShuffleMode) {
logD("Playing $song from album")
T.d("Playing $song from album")
playImpl(commandFactory.songFromAlbum(song, shuffle))
}
@ -267,7 +267,7 @@ constructor(
playbackManager.play(params)
return
}
logD(
T.d(
"Cannot use given artist parameter for $song [$artist from ${song.artists}], showing choice dialog")
startPlaybackDecision(PlaybackDecision.PlayFromArtist(song))
}
@ -278,20 +278,20 @@ constructor(
playbackManager.play(params)
return
}
logD(
T.d(
"Cannot use given genre parameter for $song [$genre from ${song.genres}], showing choice dialog")
startPlaybackDecision(PlaybackDecision.PlayFromArtist(song))
}
private fun playFromPlaylistImpl(song: Song, playlist: Playlist, shuffle: ShuffleMode) {
logD("Playing $song from $playlist")
T.d("Playing $song from $playlist")
playImpl(commandFactory.songFromPlaylist(song, playlist, shuffle))
}
private fun startPlaybackDecision(decision: PlaybackDecision) {
val existing = _playbackDecision.flow.value
if (existing != null) {
logD("Already handling decision $existing, ignoring $decision")
T.d("Already handling decision $existing, ignoring $decision")
return
}
_playbackDecision.put(decision)
@ -303,7 +303,7 @@ constructor(
* @param album The [Album] to play.
*/
fun play(album: Album) {
logD("Playing $album")
T.d("Playing $album")
playImpl(commandFactory.album(album, ShuffleMode.OFF))
}
@ -313,7 +313,7 @@ constructor(
* @param album The [Album] to shuffle.
*/
fun shuffle(album: Album) {
logD("Shuffling $album")
T.d("Shuffling $album")
playImpl(commandFactory.album(album, ShuffleMode.ON))
}
@ -323,7 +323,7 @@ constructor(
* @param artist The [Artist] to play.
*/
fun play(artist: Artist) {
logD("Playing $artist")
T.d("Playing $artist")
playImpl(commandFactory.artist(artist, ShuffleMode.OFF))
}
@ -333,7 +333,7 @@ constructor(
* @param artist The [Artist] to shuffle.
*/
fun shuffle(artist: Artist) {
logD("Shuffling $artist")
T.d("Shuffling $artist")
playImpl(commandFactory.artist(artist, ShuffleMode.ON))
}
@ -343,7 +343,7 @@ constructor(
* @param genre The [Genre] to play.
*/
fun play(genre: Genre) {
logD("Playing $genre")
T.d("Playing $genre")
playImpl(commandFactory.genre(genre, ShuffleMode.OFF))
}
@ -353,7 +353,7 @@ constructor(
* @param genre The [Genre] to shuffle.
*/
fun shuffle(genre: Genre) {
logD("Shuffling $genre")
T.d("Shuffling $genre")
playImpl(commandFactory.genre(genre, ShuffleMode.ON))
}
@ -363,7 +363,7 @@ constructor(
* @param playlist The [Playlist] to play.
*/
fun play(playlist: Playlist) {
logD("Playing $playlist")
T.d("Playing $playlist")
playImpl(commandFactory.playlist(playlist, ShuffleMode.OFF))
}
@ -373,7 +373,7 @@ constructor(
* @param playlist The [Playlist] to shuffle.
*/
fun shuffle(playlist: Playlist) {
logD("Shuffling $playlist")
T.d("Shuffling $playlist")
playImpl(commandFactory.playlist(playlist, ShuffleMode.ON))
}
@ -383,7 +383,7 @@ constructor(
* @param songs The [Song]s to play.
*/
fun play(songs: List<Song>) {
logD("Playing ${songs.size} songs")
T.d("Playing ${songs.size} songs")
playImpl(commandFactory.songs(songs, ShuffleMode.OFF))
}
@ -393,7 +393,7 @@ constructor(
* @param songs The [Song]s to shuffle.
*/
fun shuffle(songs: List<Song>) {
logD("Shuffling ${songs.size} songs")
T.d("Shuffling ${songs.size} songs")
playImpl(commandFactory.songs(songs, ShuffleMode.ON))
}
@ -408,7 +408,7 @@ constructor(
* @param action The [DeferredPlayback] to perform eventually.
*/
fun playDeferred(action: DeferredPlayback) {
logD("Starting action $action")
T.d("Starting action $action")
playbackManager.playDeferred(action)
}
@ -420,7 +420,7 @@ constructor(
* @param positionDs The position to seek to, in deci-seconds (1/10th of a second).
*/
fun seekTo(positionDs: Long) {
logD("Seeking to ${positionDs}ds")
T.d("Seeking to ${positionDs}ds")
playbackManager.seekTo(positionDs.dsToMs())
}
@ -428,13 +428,13 @@ constructor(
/** Skip to the next [Song]. */
fun next() {
logD("Skipping to next song")
T.d("Skipping to next song")
playbackManager.next()
}
/** Skip to the previous [Song]. */
fun prev() {
logD("Skipping to previous song")
T.d("Skipping to previous song")
playbackManager.prev()
}
@ -444,7 +444,7 @@ constructor(
* @param song The [Song] to add.
*/
fun playNext(song: Song) {
logD("Playing $song next")
T.d("Playing $song next")
playbackManager.playNext(song)
}
@ -454,7 +454,7 @@ constructor(
* @param album The [Album] to add.
*/
fun playNext(album: Album) {
logD("Playing $album next")
T.d("Playing $album next")
playbackManager.playNext(listSettings.albumSongSort.songs(album.songs))
}
@ -464,7 +464,7 @@ constructor(
* @param artist The [Artist] to add.
*/
fun playNext(artist: Artist) {
logD("Playing $artist next")
T.d("Playing $artist next")
playbackManager.playNext(listSettings.artistSongSort.songs(artist.songs))
}
@ -474,7 +474,7 @@ constructor(
* @param genre The [Genre] to add.
*/
fun playNext(genre: Genre) {
logD("Playing $genre next")
T.d("Playing $genre next")
playbackManager.playNext(listSettings.genreSongSort.songs(genre.songs))
}
@ -484,7 +484,7 @@ constructor(
* @param playlist The [Playlist] to add.
*/
fun playNext(playlist: Playlist) {
logD("Playing $playlist next")
T.d("Playing $playlist next")
playbackManager.playNext(playlist.songs)
}
@ -494,7 +494,7 @@ constructor(
* @param songs The [Song]s to add.
*/
fun playNext(songs: List<Song>) {
logD("Playing ${songs.size} songs next")
T.d("Playing ${songs.size} songs next")
playbackManager.playNext(songs)
}
@ -504,7 +504,7 @@ constructor(
* @param song The [Song] to add.
*/
fun addToQueue(song: Song) {
logD("Adding $song to queue")
T.d("Adding $song to queue")
playbackManager.addToQueue(song)
}
@ -514,7 +514,7 @@ constructor(
* @param album The [Album] to add.
*/
fun addToQueue(album: Album) {
logD("Adding $album to queue")
T.d("Adding $album to queue")
playbackManager.addToQueue(listSettings.albumSongSort.songs(album.songs))
}
@ -524,7 +524,7 @@ constructor(
* @param artist The [Artist] to add.
*/
fun addToQueue(artist: Artist) {
logD("Adding $artist to queue")
T.d("Adding $artist to queue")
playbackManager.addToQueue(listSettings.artistSongSort.songs(artist.songs))
}
@ -534,7 +534,7 @@ constructor(
* @param genre The [Genre] to add.
*/
fun addToQueue(genre: Genre) {
logD("Adding $genre to queue")
T.d("Adding $genre to queue")
playbackManager.addToQueue(listSettings.genreSongSort.songs(genre.songs))
}
@ -544,7 +544,7 @@ constructor(
* @param playlist The [Playlist] to add.
*/
fun addToQueue(playlist: Playlist) {
logD("Adding $playlist to queue")
T.d("Adding $playlist to queue")
playbackManager.addToQueue(playlist.songs)
}
@ -554,7 +554,7 @@ constructor(
* @param songs The [Song]s to add.
*/
fun addToQueue(songs: List<Song>) {
logD("Adding ${songs.size} songs to queue")
T.d("Adding ${songs.size} songs to queue")
playbackManager.addToQueue(songs)
}
@ -562,13 +562,13 @@ constructor(
/** Toggle [isPlaying] (i.e from playing to paused) */
fun togglePlaying() {
logD("Toggling playing state")
T.d("Toggling playing state")
playbackManager.playing(!playbackManager.progression.isPlaying)
}
/** Toggle [isShuffled] (ex. from on to off) */
fun toggleShuffled() {
logD("Toggling shuffled state")
T.d("Toggling shuffled state")
playbackManager.shuffled(!playbackManager.isShuffled)
}
@ -578,7 +578,7 @@ constructor(
* @see RepeatMode.increment
*/
fun toggleRepeatMode() {
logD("Toggling repeat mode")
T.d("Toggling repeat mode")
playbackManager.repeatMode(playbackManager.repeatMode.increment())
}
@ -599,7 +599,7 @@ constructor(
private fun openImpl(panel: OpenPanel) {
val existing = openPanel.flow.value
if (existing != null) {
logD("Already opening $existing, ignoring opening $panel")
T.d("Already opening $existing, ignoring opening $panel")
return
}
_openPanel.put(panel)

View file

@ -36,8 +36,8 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A picker [ViewBindingMaterialDialogFragment] intended for when [Artist] playback is ambiguous.
@ -88,7 +88,7 @@ class PlayFromArtistDialog :
private fun updateSong(song: Song?) {
if (song == null) {
logD("No song to show choices for, navigating away")
T.d("No song to show choices for, navigating away")
findNavController().navigateUp()
return
}

View file

@ -36,8 +36,8 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* A picker [ViewBindingMaterialDialogFragment] intended for when [Genre] playback is ambiguous.
@ -88,7 +88,7 @@ class PlayFromGenreDialog :
private fun updateSong(song: Song?) {
if (song == null) {
logD("No song to show choices for, navigating away")
T.d("No song to show choices for, navigating away")
findNavController().navigateUp()
return
}

View file

@ -27,8 +27,7 @@ import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* A [ViewModel] that stores the choices shown in the playback picker dialogs.
@ -64,10 +63,10 @@ class PlaybackPickerViewModel @Inject constructor(private val musicRepository: M
* @param uid The [Music.UID] of the item to show. Must be a [Song].
*/
fun setPickerSongUid(uid: Music.UID) {
logD("Opening picker for song $uid")
T.d("Opening picker for song $uid")
_currentPickerSong.value = musicRepository.deviceLibrary?.findSong(uid)
if (_currentPickerSong.value != null) {
logW("Given song UID was invalid")
T.w("Given song UID was invalid")
}
}
}

View file

@ -22,8 +22,7 @@ import javax.inject.Inject
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
/**
* Manages the persisted playback state in a structured manner.
@ -60,8 +59,8 @@ constructor(
heapItems = queueDao.getHeap()
mappingItems = queueDao.getShuffledMapping()
} catch (e: Exception) {
logE("Unable read playback state")
logE(e.stackTraceToString())
T.e("Unable read playback state")
T.e(e.stackTraceToString())
return null
}
@ -85,12 +84,12 @@ constructor(
queueDao.nukeHeap()
queueDao.nukeShuffledMapping()
} catch (e: Exception) {
logE("Unable to clear previous state")
logE(e.stackTraceToString())
T.e("Unable to clear previous state")
T.e(e.stackTraceToString())
return false
}
logD("Successfully cleared previous state")
T.d("Successfully cleared previous state")
if (state != null) {
// Transform saved state into raw state, which can then be written to the database.
val playbackState =
@ -114,12 +113,12 @@ constructor(
queueDao.insertHeap(heap)
queueDao.insertShuffledMapping(shuffledMapping)
} catch (e: Exception) {
logE("Unable to write new state")
logE(e.stackTraceToString())
T.e("Unable to write new state")
T.e(e.stackTraceToString())
return false
}
logD("Successfully wrote new state")
T.d("Successfully wrote new state")
}
return true

View file

@ -37,7 +37,7 @@ import org.oxycblt.auxio.music.resolveNames
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [RecyclerView.Adapter] that shows an editable list of queue items.
@ -80,7 +80,7 @@ class QueueAdapter(private val listener: EditClickListListener<Song>) :
* @param isPlaying Whether playback is ongoing or paused.
*/
fun setPosition(index: Int, isPlaying: Boolean) {
logD("Updating index")
T.d("Updating index")
val lastIndex = currentIndex
currentIndex = index
@ -89,10 +89,10 @@ class QueueAdapter(private val listener: EditClickListListener<Song>) :
// TODO: Optimize this by only updating the range between old and new indices?
// TODO: Don't update when the index has not moved.
if (currentIndex < lastIndex) {
logD("Moved backwards, must update items above last index")
T.d("Moved backwards, must update items above last index")
notifyItemRangeChanged(0, lastIndex + 1, PAYLOAD_UPDATE_POSITION)
} else {
logD("Moved forwards, update items after index")
T.d("Moved forwards, update items after index")
notifyItemRangeChanged(0, currentIndex + 1, PAYLOAD_UPDATE_POSITION)
}

View file

@ -34,7 +34,7 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ViewBindingFragment] that displays an editable queue.
@ -122,14 +122,14 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), EditClickList
// dependent on where we have to scroll to get to the currently playing song.
if (notInitialized || scrollTo < start) {
// We need to scroll upwards, or initialize the scroll, no need to offset
logD("Not scrolling downwards, no offset needed")
T.d("Not scrolling downwards, no offset needed")
binding.queueRecycler.scrollToPosition(scrollTo)
} else if (scrollTo > end) {
// We need to scroll downwards, we need to offset by a screen of songs.
// This does have some error due to how many completely visible items on-screen
// can vary. This is considered okay.
val offset = scrollTo + (end - start)
logD("Scrolling downwards, offsetting by $offset")
T.d("Scrolling downwards, offsetting by $offset")
binding.queueRecycler.scrollToPosition(min(queue.lastIndex, offset))
}
}

View file

@ -30,7 +30,7 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.playback.state.QueueChange
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [ViewModel] that manages the current queue state and allows navigation through the queue.
@ -62,26 +62,26 @@ class QueueViewModel @Inject constructor(private val playbackManager: PlaybackSt
}
override fun onIndexMoved(index: Int) {
logD("Index moved, synchronizing and scrolling to new position")
T.d("Index moved, synchronizing and scrolling to new position")
_scrollTo.put(index)
_index.value = index
}
override fun onQueueChanged(queue: List<Song>, index: Int, change: QueueChange) {
// Queue changed trivially due to item mo -> Diff queue, stay at current index.
logD("Updating queue display")
T.d("Updating queue display")
_queueInstructions.put(change.instructions)
_queue.value = queue
if (change.type != QueueChange.Type.MAPPING) {
// Index changed, make sure it remains updated without actually scrolling to it.
logD("Index changed with queue, synchronizing new position")
T.d("Index changed with queue, synchronizing new position")
_index.value = index
}
}
override fun onQueueReordered(queue: List<Song>, index: Int, isShuffled: Boolean) {
// Queue changed completely -> Replace queue, update index
logD("Queue changed completely, replacing queue and position")
T.d("Queue changed completely, replacing queue and position")
_queueInstructions.put(UpdateInstructions.Replace(0))
_scrollTo.put(index)
_queue.value = queue
@ -95,7 +95,7 @@ class QueueViewModel @Inject constructor(private val playbackManager: PlaybackSt
isShuffled: Boolean
) {
// Entirely new queue -> Replace queue, update index
logD("New playback, replacing queue and position")
T.d("New playback, replacing queue and position")
_queueInstructions.put(UpdateInstructions.Replace(0))
_scrollTo.put(index)
_queue.value = queue
@ -117,7 +117,7 @@ class QueueViewModel @Inject constructor(private val playbackManager: PlaybackSt
if (adapterIndex !in queue.value.indices) {
return
}
logD("Going to position $adapterIndex in queue")
T.d("Going to position $adapterIndex in queue")
playbackManager.goto(adapterIndex)
}
@ -131,7 +131,7 @@ class QueueViewModel @Inject constructor(private val playbackManager: PlaybackSt
if (adapterIndex !in queue.value.indices) {
return
}
logD("Removing item $adapterIndex in queue")
T.d("Removing item $adapterIndex in queue")
playbackManager.removeQueueItem(adapterIndex)
}
@ -146,7 +146,7 @@ class QueueViewModel @Inject constructor(private val playbackManager: PlaybackSt
if (adapterFrom !in queue.value.indices || adapterTo !in queue.value.indices) {
return false
}
logD("Moving $adapterFrom to $adapterFrom in queue")
T.d("Moving $adapterFrom to $adapterFrom in queue")
playbackManager.moveQueueItem(adapterFrom, adapterTo)
return true
}

View file

@ -28,7 +28,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.DialogPreAmpBinding
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* aa [ViewBindingMaterialDialogFragment] that allows user configuration of the current
@ -62,7 +62,7 @@ class PreAmpCustomizeDialog : ViewBindingMaterialDialogFragment<DialogPreAmpBind
// settings. After this, the sliders save their own state, so we do not need to
// do any restore behavior.
val preAmp = playbackSettings.replayGainPreAmp
logD("Initializing from $preAmp")
T.d("Initializing from $preAmp")
binding.withTagsSlider.value = preAmp.with
binding.withoutTagsSlider.value = preAmp.without
}

View file

@ -32,7 +32,7 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.playback.state.QueueChange
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* An [AudioProcessor] that handles ReplayGain values and their amplification of the audio stream.
@ -71,7 +71,7 @@ constructor(
// --- OVERRIDES ---
override fun onIndexMoved(index: Int) {
logD("Index moved, updating current song")
T.d("Index moved, updating current song")
applyReplayGain(playbackManager.currentSong)
}
@ -88,7 +88,7 @@ constructor(
index: Int,
isShuffled: Boolean
) {
logD("New playback started, updating playback information")
T.d("New playback started, updating playback information")
applyReplayGain(playbackManager.currentSong)
}
@ -106,12 +106,12 @@ constructor(
*/
private fun applyReplayGain(song: Song?) {
if (song == null) {
logD("Nothing playing, disabling adjustment")
T.d("Nothing playing, disabling adjustment")
volume = 1f
return
}
logD("Applying ReplayGain adjustment for $song")
T.d("Applying ReplayGain adjustment for $song")
val gain = song.replayGainAdjustment
val preAmp = playbackSettings.replayGainPreAmp
@ -121,24 +121,24 @@ constructor(
when (playbackSettings.replayGainMode) {
// User wants no adjustment.
ReplayGainMode.OFF -> {
logD("ReplayGain is off")
T.d("ReplayGain is off")
null
}
// User wants track gain to be preferred. Default to album gain only if
// there is no track gain.
ReplayGainMode.TRACK -> {
logD("Using track strategy")
T.d("Using track strategy")
gain.track ?: gain.album
}
// User wants album gain to be preferred. Default to track gain only if
// here is no album gain.
ReplayGainMode.ALBUM -> {
logD("Using album strategy")
T.d("Using album strategy")
gain.album ?: gain.track
}
// User wants album gain to be used when in an album, track gain otherwise.
ReplayGainMode.DYNAMIC -> {
logD("Using dynamic strategy")
T.d("Using dynamic strategy")
gain.album?.takeIf {
playbackManager.parent is Album &&
playbackManager.currentSong?.album == playbackManager.parent
@ -150,15 +150,15 @@ constructor(
val amplifiedAdjustment =
if (resolvedAdjustment != null) {
// Successfully resolved an adjustment, apply the corresponding pre-amp
logD("Applying with pre-amp")
T.d("Applying with pre-amp")
resolvedAdjustment + preAmp.with
} else {
// No adjustment found, use the corresponding user-defined pre-amp
logD("Applying without pre-amp")
T.d("Applying without pre-amp")
preAmp.without
}
logD("Applying ReplayGain adjustment ${amplifiedAdjustment}db")
T.d("Applying ReplayGain adjustment ${amplifiedAdjustment}db")
// Final adjustment along the volume curve.
volume = 10f.pow(amplifiedAdjustment / 20f)

View file

@ -59,8 +59,7 @@ import org.oxycblt.auxio.playback.state.RawQueue
import org.oxycblt.auxio.playback.state.RepeatMode
import org.oxycblt.auxio.playback.state.ShuffleMode
import org.oxycblt.auxio.playback.state.StateAck
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import timber.log.Timber as T
class ExoPlaybackStateHolder(
private val context: Context,
@ -152,7 +151,7 @@ class ExoPlaybackStateHolder(
when (action) {
// Restore state -> Start a new restoreState job
is DeferredPlayback.RestoreState -> {
logD("Restoring playback state")
T.d("Restoring playback state")
restoreScope.launch {
val state = persistenceRepository.readState()
withContext(Dispatchers.Main) {
@ -171,7 +170,7 @@ class ExoPlaybackStateHolder(
}
// Shuffle all -> Start new playback from all songs
is DeferredPlayback.ShuffleAll -> {
logD("Shuffling all tracks")
T.d("Shuffling all tracks")
playbackManager.play(
requireNotNull(commandFactory.all(ShuffleMode.ON)) {
"Invalid playback parameters"
@ -179,7 +178,7 @@ class ExoPlaybackStateHolder(
}
// Open -> Try to find the Song for the given file and then play it from all songs
is DeferredPlayback.Open -> {
logD("Opening specified file")
T.d("Opening specified file")
deviceLibrary.findSongForUri(context, action.uri)?.let { song ->
playbackManager.play(
requireNotNull(commandFactory.song(song, ShuffleMode.IMPLICIT)) {
@ -428,18 +427,18 @@ class ExoPlaybackStateHolder(
if (player.playWhenReady) {
// Mark that we have started playing so that the notification can now be posted.
logD("Player has started playing")
T.d("Player has started playing")
sessionOngoing = true
if (!openAudioEffectSession) {
// Convention to start an audioeffect session on play/pause rather than
// start/stop
logD("Opening audio effect session")
T.d("Opening audio effect session")
broadcastAudioEffectAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)
openAudioEffectSession = true
}
} else if (openAudioEffectSession) {
// Make sure to close the audio session when we stop playback.
logD("Closing audio effect session")
T.d("Closing audio effect session")
broadcastAudioEffectAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)
openAudioEffectSession = false
}
@ -471,7 +470,7 @@ class ExoPlaybackStateHolder(
Player.EVENT_PLAY_WHEN_READY_CHANGED,
Player.EVENT_IS_PLAYING_CHANGED,
Player.EVENT_POSITION_DISCONTINUITY)) {
logD("Player state changed, must synchronize state")
T.d("Player state changed, must synchronize state")
playbackManager.ack(this, StateAck.ProgressionChanged)
}
}
@ -479,13 +478,13 @@ class ExoPlaybackStateHolder(
override fun onPlayerError(error: PlaybackException) {
// TODO: Replace with no skipping and a notification instead
// If there's any issue, just go to the next song.
logE("Player error occurred")
logE(error.stackTraceToString())
T.e("Player error occurred")
T.e(error.stackTraceToString())
playbackManager.next()
}
private fun broadcastAudioEffectAction(event: String) {
logD("Broadcasting AudioEffect event: $event")
T.d("Broadcasting AudioEffect event: $event")
context.sendBroadcast(
Intent(event)
.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName)
@ -498,7 +497,7 @@ class ExoPlaybackStateHolder(
override fun onMusicChanges(changes: MusicRepository.Changes) {
if (changes.deviceLibrary && musicRepository.deviceLibrary != null) {
// We now have a library, see if we have anything we need to do.
logD("Library obtained, requesting action")
T.d("Library obtained, requesting action")
playbackManager.requestAction(this)
}
}
@ -524,17 +523,17 @@ class ExoPlaybackStateHolder(
private fun deferSave() {
saveJob {
logD("Waiting for save buffer")
T.d("Waiting for save buffer")
delay(SAVE_BUFFER)
yield()
logD("Committing saved state")
T.d("Committing saved state")
persistenceRepository.saveState(playbackManager.toSavedState())
}
}
private fun saveJob(block: suspend () -> Unit) {
currentSaveJob?.let {
logD("Discarding prior save job")
T.d("Discarding prior save job")
it.cancel()
}
currentSaveJob = saveScope.launch { block() }

View file

@ -27,7 +27,7 @@ import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import org.oxycblt.auxio.AuxioService
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [BroadcastReceiver] that forwards [Intent.ACTION_MEDIA_BUTTON] [Intent]s to
@ -47,7 +47,7 @@ class MediaButtonReceiver : BroadcastReceiver() {
// stupid this is with the state of foreground services on modern android. One
// wrong action at the wrong time will result in the app crashing, and there is
// nothing I can do about it.
logD("Delivering media button intent $intent")
T.d("Delivering media button intent $intent")
intent.component = ComponentName(context, AuxioService::class.java)
ContextCompat.startForegroundService(context, intent)
}

View file

@ -47,9 +47,9 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.playback.state.Progression
import org.oxycblt.auxio.playback.state.QueueChange
import org.oxycblt.auxio.playback.state.RepeatMode
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.newBroadcastPendingIntent
import org.oxycblt.auxio.util.newMainPendingIntent
import timber.log.Timber as T
/**
* A component that mirrors the current playback state into the [MediaSessionCompat] and
@ -210,10 +210,10 @@ private constructor(
* playback is currently occuring from all songs.
*/
private fun updateMediaMetadata(song: Song?, parent: MusicParent?) {
logD("Updating media metadata to $song with $parent")
T.d("Updating media metadata to $song with $parent")
if (song == null) {
// Nothing playing, reset the MediaSession and close the notification.
logD("Nothing playing, resetting media session")
T.d("Nothing playing, resetting media session")
mediaSession.setMetadata(emptyMetadata)
return
}
@ -252,15 +252,15 @@ private constructor(
MediaSessionUID.SingleItem(song.album.uid).toString())
// These fields are nullable and so we must check first before adding them to the fields.
song.track?.let {
logD("Adding track information")
T.d("Adding track information")
builder.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, it.toLong())
}
song.disc?.let {
logD("Adding disc information")
T.d("Adding disc information")
builder.putLong(MediaMetadataCompat.METADATA_KEY_DISC_NUMBER, it.number.toLong())
}
song.date?.let {
logD("Adding date information")
T.d("Adding date information")
builder.putString(MediaMetadataCompat.METADATA_KEY_DATE, it.toString())
builder.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, it.year.toLong())
}
@ -272,7 +272,7 @@ private constructor(
song,
object : BitmapProvider.Target {
override fun onCompleted(bitmap: Bitmap?) {
logD("Bitmap loaded, applying media session and posting notification")
T.d("Bitmap loaded, applying media session and posting notification")
if (bitmap != null) {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmap)
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)
@ -300,13 +300,13 @@ private constructor(
// playback state.
MediaSessionCompat.QueueItem(description, i.toLong())
}
logD("Uploading ${queueItems.size} songs to MediaSession queue")
T.d("Uploading ${queueItems.size} songs to MediaSession queue")
mediaSession.setQueue(queueItems)
}
/** Invalidate the current [MediaSessionCompat]'s [PlaybackStateCompat]. */
private fun invalidateSessionState() {
logD("Updating media session playback state")
T.d("Updating media session playback state")
val state =
// InternalPlayer.State handles position/state information.
@ -322,7 +322,7 @@ private constructor(
val secondaryAction =
when (playbackSettings.notificationAction) {
ActionMode.SHUFFLE -> {
logD("Using shuffle MediaSession action")
T.d("Using shuffle MediaSession action")
PlaybackStateCompat.CustomAction.Builder(
PlaybackActions.ACTION_INVERT_SHUFFLE,
context.getString(R.string.desc_shuffle),
@ -333,7 +333,7 @@ private constructor(
})
}
else -> {
logD("Using repeat mode MediaSession action")
T.d("Using repeat mode MediaSession action")
PlaybackStateCompat.CustomAction.Builder(
PlaybackActions.ACTION_INC_REPEAT_MODE,
context.getString(R.string.desc_change_repeat),
@ -356,22 +356,22 @@ private constructor(
/** Invalidate the "secondary" action (i.e shuffle/repeat mode). */
private fun invalidateSecondaryAction() {
logD("Invalidating secondary action")
T.d("Invalidating secondary action")
invalidateSessionState()
when (playbackSettings.notificationAction) {
ActionMode.SHUFFLE -> {
logD("Using shuffle notification action")
T.d("Using shuffle notification action")
_notification.updateShuffled(playbackManager.isShuffled)
}
else -> {
logD("Using repeat mode notification action")
T.d("Using repeat mode notification action")
_notification.updateRepeatMode(playbackManager.repeatMode)
}
}
if (!bitmapProvider.isBusy) {
logD("Not loading a bitmap, post the notification")
T.d("Not loading a bitmap, post the notification")
foregroundListener.updateForeground(ForegroundListener.Change.MEDIA_SESSION)
}
}
@ -423,7 +423,7 @@ private class PlaybackNotification(
* @param metadata The [MediaMetadataCompat] to display in this notification.
*/
fun updateMetadata(metadata: MediaMetadataCompat) {
logD("Updating shown metadata")
T.d("Updating shown metadata")
setLargeIcon(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART))
setContentTitle(metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE))
setContentText(metadata.getText(MediaMetadataCompat.METADATA_KEY_ARTIST))
@ -436,7 +436,7 @@ private class PlaybackNotification(
* @param isPlaying Whether playback should be indicated as ongoing or paused.
*/
fun updatePlaying(isPlaying: Boolean) {
logD("Updating playing state: $isPlaying")
T.d("Updating playing state: $isPlaying")
mActions[2] = buildPlayPauseAction(context, isPlaying)
}
@ -446,7 +446,7 @@ private class PlaybackNotification(
* @param repeatMode The current [RepeatMode].
*/
fun updateRepeatMode(repeatMode: RepeatMode) {
logD("Applying repeat mode action: $repeatMode")
T.d("Applying repeat mode action: $repeatMode")
mActions[0] = buildRepeatAction(context, repeatMode)
}
@ -456,7 +456,7 @@ private class PlaybackNotification(
* @param isShuffled Whether the queue is currently shuffled or not.
*/
fun updateShuffled(isShuffled: Boolean) {
logD("Applying shuffle action: $isShuffled")
T.d("Applying shuffle action: $isShuffled")
mActions[0] = buildShuffleAction(context, isShuffled)
}

View file

@ -47,7 +47,7 @@ import org.oxycblt.auxio.playback.state.PlaybackCommand
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.playback.state.RepeatMode
import org.oxycblt.auxio.playback.state.ShuffleMode
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
class MediaSessionInterface
@Inject
@ -85,7 +85,7 @@ constructor(
val parentUid =
extras?.getString(MusicBrowser.KEY_CHILD_OF)?.let { MediaSessionUID.fromString(it) }
val command = expandUidIntoCommand(uid, parentUid)
logD(extras?.getString(MusicBrowser.KEY_CHILD_OF))
T.d(extras?.getString(MusicBrowser.KEY_CHILD_OF))
playbackManager.play(requireNotNull(command) { "Invalid playback configuration" })
}

View file

@ -27,8 +27,8 @@ import org.oxycblt.auxio.ForegroundServiceNotification
import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.playback.state.DeferredPlayback
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.widgets.WidgetComponent
import timber.log.Timber as T
class PlaybackServiceFragment
private constructor(
@ -86,7 +86,7 @@ private constructor(
fun start(startedBy: Int) {
// At minimum we want to ensure an active playback state.
// TODO: Possibly also force to go foreground?
logD("Handling non-native start.")
T.d("Handling non-native start.")
val action =
when (startedBy) {
IntegerTable.START_ID_ACTIVITY -> null
@ -97,7 +97,7 @@ private constructor(
else -> DeferredPlayback.RestoreState(play = false)
}
if (action != null) {
logD("Initing service fragment using action $action")
T.d("Initing service fragment using action $action")
playbackManager.playDeferred(action)
}
}

View file

@ -27,9 +27,9 @@ import androidx.core.content.ContextCompat
import javax.inject.Inject
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.widgets.WidgetComponent
import org.oxycblt.auxio.widgets.WidgetProvider
import timber.log.Timber as T
/**
* A [BroadcastReceiver] for receiving playback-specific [Intent]s from the system that require an
@ -75,7 +75,7 @@ private constructor(
// 3. Some internal framework thing that also handles bluetooth headsets
// Just use ACTION_HEADSET_PLUG.
AudioManager.ACTION_HEADSET_PLUG -> {
logD("Received headset plug event")
T.d("Received headset plug event")
when (intent.getIntExtra("state", -1)) {
0 -> pauseFromHeadsetPlug()
1 -> playFromHeadsetPlug()
@ -84,37 +84,37 @@ private constructor(
initialHeadsetPlugEventHandled = true
}
AudioManager.ACTION_AUDIO_BECOMING_NOISY -> {
logD("Received Headset noise event")
T.d("Received Headset noise event")
pauseFromHeadsetPlug()
}
// --- AUXIO EVENTS ---
PlaybackActions.ACTION_PLAY_PAUSE -> {
logD("Received play event")
T.d("Received play event")
playbackManager.playing(!playbackManager.progression.isPlaying)
}
PlaybackActions.ACTION_INC_REPEAT_MODE -> {
logD("Received repeat mode event")
T.d("Received repeat mode event")
playbackManager.repeatMode(playbackManager.repeatMode.increment())
}
PlaybackActions.ACTION_INVERT_SHUFFLE -> {
logD("Received shuffle event")
T.d("Received shuffle event")
playbackManager.shuffled(!playbackManager.isShuffled)
}
PlaybackActions.ACTION_SKIP_PREV -> {
logD("Received skip previous event")
T.d("Received skip previous event")
playbackManager.prev()
}
PlaybackActions.ACTION_SKIP_NEXT -> {
logD("Received skip next event")
T.d("Received skip next event")
playbackManager.next()
}
PlaybackActions.ACTION_EXIT -> {
logD("Received exit event")
T.d("Received exit event")
playbackManager.endSession()
}
WidgetProvider.ACTION_WIDGET_UPDATE -> {
logD("Received widget update event")
T.d("Received widget update event")
widgetComponent.update()
}
}
@ -127,14 +127,14 @@ private constructor(
if (playbackSettings.headsetAutoplay &&
playbackManager.currentSong != null &&
initialHeadsetPlugEventHandled) {
logD("Device connected, resuming")
T.d("Device connected, resuming")
playbackManager.playing(true)
}
}
private fun pauseFromHeadsetPlug() {
if (playbackManager.currentSong != null) {
logD("Device disconnected, pausing")
T.d("Device disconnected, pausing")
playbackManager.playing(false)
}
}

View file

@ -29,6 +29,7 @@ import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackSettings
import timber.log.Timber as T
/**
* A playback command that can be passed to [PlaybackStateManager] to start new playback.

View file

@ -25,8 +25,7 @@ import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.state.PlaybackStateManager.Listener
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import timber.log.Timber as T
/**
* Core playback state controller class.
@ -388,11 +387,11 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun addListener(listener: Listener) {
logD("Adding $listener to listeners")
T.d("Adding $listener to listeners")
listeners.add(listener)
if (isInitialized) {
logD("Sending initial state to $listener")
T.d("Sending initial state to $listener")
listener.onNewPlayback(
stateMirror.parent, stateMirror.queue, stateMirror.index, stateMirror.isShuffled)
listener.onProgressionChanged(stateMirror.progression)
@ -402,16 +401,16 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun removeListener(listener: Listener) {
logD("Removing $listener from listeners")
T.d("Removing $listener from listeners")
if (!listeners.remove(listener)) {
logW("Listener $listener was not added prior, cannot remove")
T.w("Listener $listener was not added prior, cannot remove")
}
}
@Synchronized
override fun registerStateHolder(stateHolder: PlaybackStateHolder) {
if (this.stateHolder != null) {
logW("Internal player is already registered")
T.w("Internal player is already registered")
return
}
@ -430,11 +429,11 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun unregisterStateHolder(stateHolder: PlaybackStateHolder) {
if (this.stateHolder !== stateHolder) {
logW("Given internal player did not match current internal player")
T.w("Given internal player did not match current internal player")
return
}
logD("Unregistering internal player $stateHolder")
T.d("Unregistering internal player $stateHolder")
this.stateHolder = null
}
@ -444,7 +443,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun play(command: PlaybackCommand) {
val stateHolder = stateHolder ?: return
logD("Playing $command")
T.d("Playing $command")
// Played something, so we are initialized now
isInitialized = true
stateHolder.newPlayback(command)
@ -455,32 +454,32 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun next() {
val stateHolder = stateHolder ?: return
logD("Going to next song")
T.d("Going to next song")
stateHolder.next()
}
@Synchronized
override fun prev() {
val stateHolder = stateHolder ?: return
logD("Going to previous song")
T.d("Going to previous song")
stateHolder.prev()
}
@Synchronized
override fun goto(index: Int) {
val stateHolder = stateHolder ?: return
logD("Going to index $index")
T.d("Going to index $index")
stateHolder.goto(index)
}
@Synchronized
override fun playNext(songs: List<Song>) {
if (currentSong == null) {
logD("Nothing playing, short-circuiting to new playback")
T.d("Nothing playing, short-circuiting to new playback")
play(QueueCommand(songs))
} else {
val stateHolder = stateHolder ?: return
logD("Adding ${songs.size} songs to start of queue")
T.d("Adding ${songs.size} songs to start of queue")
stateHolder.playNext(songs, StateAck.PlayNext(stateMirror.index + 1, songs.size))
}
}
@ -488,11 +487,11 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun addToQueue(songs: List<Song>) {
if (currentSong == null) {
logD("Nothing playing, short-circuiting to new playback")
T.d("Nothing playing, short-circuiting to new playback")
play(QueueCommand(songs))
} else {
val stateHolder = stateHolder ?: return
logD("Adding ${songs.size} songs to end of queue")
T.d("Adding ${songs.size} songs to end of queue")
stateHolder.addToQueue(songs, StateAck.AddToQueue(queue.size, songs.size))
}
}
@ -506,21 +505,21 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun moveQueueItem(src: Int, dst: Int) {
val stateHolder = stateHolder ?: return
logD("Moving item $src to position $dst")
T.d("Moving item $src to position $dst")
stateHolder.move(src, dst, StateAck.Move(src, dst))
}
@Synchronized
override fun removeQueueItem(at: Int) {
val stateHolder = stateHolder ?: return
logD("Removing item at $at")
T.d("Removing item at $at")
stateHolder.remove(at, StateAck.Remove(at))
}
@Synchronized
override fun shuffled(shuffled: Boolean) {
val stateHolder = stateHolder ?: return
logD("Reordering queue [shuffled=$shuffled]")
T.d("Reordering queue [shuffled=$shuffled]")
stateHolder.shuffled(shuffled)
}
@ -530,7 +529,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
override fun playDeferred(action: DeferredPlayback) {
val stateHolder = stateHolder
if (stateHolder == null || !stateHolder.handleDeferred(action)) {
logD("Internal player not present or did not consume action, waiting")
T.d("Internal player not present or did not consume action, waiting")
pendingDeferredPlayback = action
}
}
@ -538,12 +537,12 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun requestAction(stateHolder: PlaybackStateHolder) {
if (BuildConfig.DEBUG && this.stateHolder !== stateHolder) {
logW("Given internal player did not match current internal player")
T.w("Given internal player did not match current internal player")
return
}
if (pendingDeferredPlayback?.let(stateHolder::handleDeferred) == true) {
logD("Pending action consumed")
T.d("Pending action consumed")
pendingDeferredPlayback = null
}
}
@ -551,35 +550,35 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
@Synchronized
override fun playing(isPlaying: Boolean) {
val stateHolder = stateHolder ?: return
logD("Updating playing state to $isPlaying")
T.d("Updating playing state to $isPlaying")
stateHolder.playing(isPlaying)
}
@Synchronized
override fun repeatMode(repeatMode: RepeatMode) {
val stateHolder = stateHolder ?: return
logD("Updating repeat mode to $repeatMode")
T.d("Updating repeat mode to $repeatMode")
stateHolder.repeatMode(repeatMode)
}
@Synchronized
override fun seekTo(positionMs: Long) {
val stateHolder = stateHolder ?: return
logD("Seeking to ${positionMs}ms")
T.d("Seeking to ${positionMs}ms")
stateHolder.seekTo(positionMs)
}
@Synchronized
override fun endSession() {
val stateHolder = stateHolder ?: return
logD("Ending session")
T.d("Ending session")
stateHolder.endSession()
}
@Synchronized
override fun ack(stateHolder: PlaybackStateHolder, ack: StateAck) {
if (BuildConfig.DEBUG && this.stateHolder !== stateHolder) {
logW("Given internal player did not match current internal player")
T.w("Given internal player did not match current internal player")
return
}
@ -730,7 +729,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
destructive: Boolean
) {
if (isInitialized && !destructive) {
logW("Already initialized, cannot apply saved state")
T.w("Already initialized, cannot apply saved state")
return
}
@ -752,7 +751,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
}
}
logD("Created adjustment mapping [max shift=$currentShift]")
T.d("Created adjustment mapping [max shift=$currentShift]")
val shuffledMapping =
savedState.shuffledMapping.mapNotNullTo(mutableListOf()) { index ->
@ -767,7 +766,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
} else {
heap.getOrNull(index)
}
logD(currentSong)
T.d(currentSong)
return currentSong?.uid == savedState.songUid
}
@ -777,7 +776,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
index--
}
logD("Corrected index: ${savedState.index} -> $index")
T.d("Corrected index: ${savedState.index} -> $index")
check(shuffledMapping.all { it in heap.indices }) {
"Queue inconsistency detected: Shuffled mapping indices out of heap bounds"

View file

@ -26,7 +26,7 @@ import com.google.android.material.R as MR
import com.google.android.material.button.MaterialButton
import com.google.android.material.motion.MotionUtils
import org.oxycblt.auxio.ui.RippleFixMaterialButton
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A [MaterialButton] that automatically morphs from a circle to a squircle shape appearance when
@ -62,12 +62,12 @@ class AnimatedMaterialButton : RippleFixMaterialButton {
val targetRadius = if (activated) 0.3f else 0.5f
if (!isLaidOut) {
// Not laid out, initialize it without animation before drawing.
logD("Not laid out, immediately updating corner radius")
T.d("Not laid out, immediately updating corner radius")
updateCornerRadiusRatio(targetRadius)
return
}
logD("Starting corner radius animation")
T.d("Starting corner radius animation")
animator?.cancel()
animator =
ValueAnimator.ofFloat(currentCornerRadiusRatio, targetRadius).apply {

View file

@ -25,7 +25,7 @@ import kotlin.math.max
import org.oxycblt.auxio.databinding.ViewSeekBarBinding
import org.oxycblt.auxio.playback.formatDurationDs
import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* A wrapper around [Slider] that shows position and duration values and sanitizes input to reduce
@ -81,11 +81,11 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
// zero, use 1 instead and disable the SeekBar.
val to = max(value, 1)
isEnabled = value > 0
logD("Value sanitization finished [to=$to, enabled=$isEnabled]")
T.d("Value sanitization finished [to=$to, enabled=$isEnabled]")
// Sanity check 2: If the current value exceeds the new duration value, clamp it
// down so that we don't crash and instead have an annoying visual flicker.
if (positionDs > to) {
logD("Clamping invalid position [current: $positionDs new max: $to]")
T.d("Clamping invalid position [current: $positionDs new max: $to]")
binding.seekBarSlider.value = to.toFloat()
}
binding.seekBarSlider.valueTo = to.toFloat()
@ -93,14 +93,14 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
}
override fun onStartTrackingTouch(slider: Slider) {
logD("Starting seek mode")
T.d("Starting seek mode")
// User has begun seeking, place the SeekBar into a "Suspended" mode in which no
// position updates are sent and is indicated by the position value turning accented.
isActivated = true
}
override fun onStopTrackingTouch(slider: Slider) {
logD("Confirming seek")
T.d("Confirming seek")
// End of seek event, send off new value to listener.
isActivated = false
listener?.onSeekConfirmed(slider.value.toLong())

View file

@ -39,7 +39,7 @@ import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* An adapter that displays search results.
@ -75,7 +75,7 @@ class SearchAdapter(private val listener: SelectableListListener<Music>) :
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
logD(position)
T.d(position)
when (val item = getItem(position)) {
is Song -> (holder as SongViewHolder).bind(item, listener)
is Album -> (holder as AlbumViewHolder).bind(item, listener)

View file

@ -29,7 +29,7 @@ import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.info.Name
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* Implements the fuzzy-ish searching algorithm used in the search view.
@ -67,7 +67,7 @@ interface SearchEngine {
class SearchEngineImpl @Inject constructor(@ApplicationContext private val context: Context) :
SearchEngine {
override suspend fun search(items: SearchEngine.Items, query: String): SearchEngine.Items {
logD("Launching search for $query")
T.d("Launching search for $query")
return SearchEngine.Items(
songs =
items.songs?.searchListImpl(query) { q, song ->

View file

@ -61,11 +61,10 @@ import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getSystemServiceCompat
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.setFullWidthLookup
import org.oxycblt.auxio.util.showToast
import timber.log.Timber as T
/**
* The [ListFragment] providing search functionality for the music library.
@ -109,11 +108,11 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
getContentLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri == null) {
logW("No URI returned from file picker")
T.w("No URI returned from file picker")
return@registerForActivityResult
}
logD("Received playlist URI $uri")
T.d("Received playlist URI $uri")
musicModel.importPlaylist(uri, pendingImportTarget)
}
@ -140,7 +139,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
if (!launchedKeyboard) {
// Auto-open the keyboard when this view is shown
logD("Keyboard is not shown yet")
T.d("Keyboard is not shown yet")
showKeyboard(this)
launchedKeyboard = true
}
@ -185,7 +184,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
if (item.itemId != R.id.submenu_filtering) {
// Is a change in filter mode and not just a junk submenu click, update
// the filtering within SearchViewModel.
logD("Filter mode selected")
T.d("Filter mode selected")
item.isChecked = true
searchModel.setFilterOptionId(item.itemId)
return true
@ -223,7 +222,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
// I would make it so that the position is only scrolled back to the top when
// the query actually changes instead of once every re-creation event, but sadly
// that doesn't seem possible.
logD("Update finished, scrolling to top")
T.d("Update finished, scrolling to top")
binding.searchRecycler.scrollToPosition(0)
}
}
@ -231,39 +230,39 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
private fun handleShow(show: Show?) {
when (show) {
is Show.SongDetails -> {
logD("Navigating to ${show.song}")
T.d("Navigating to ${show.song}")
findNavController().navigateSafe(SearchFragmentDirections.showSong(show.song.uid))
}
is Show.SongAlbumDetails -> {
logD("Navigating to the album of ${show.song}")
T.d("Navigating to the album of ${show.song}")
findNavController()
.navigateSafe(SearchFragmentDirections.showAlbum(show.song.album.uid))
}
is Show.AlbumDetails -> {
logD("Navigating to ${show.album}")
T.d("Navigating to ${show.album}")
findNavController().navigateSafe(SearchFragmentDirections.showAlbum(show.album.uid))
}
is Show.ArtistDetails -> {
logD("Navigating to ${show.artist}")
T.d("Navigating to ${show.artist}")
findNavController()
.navigateSafe(SearchFragmentDirections.showArtist(show.artist.uid))
}
is Show.SongArtistDecision -> {
logD("Navigating to artist choices for ${show.song}")
T.d("Navigating to artist choices for ${show.song}")
findNavController()
.navigateSafe(SearchFragmentDirections.showArtistChoices(show.song.uid))
}
is Show.AlbumArtistDecision -> {
logD("Navigating to artist choices for ${show.album}")
T.d("Navigating to artist choices for ${show.album}")
findNavController()
.navigateSafe(SearchFragmentDirections.showArtistChoices(show.album.uid))
}
is Show.GenreDetails -> {
logD("Navigating to ${show.genre}")
T.d("Navigating to ${show.genre}")
findNavController().navigateSafe(SearchFragmentDirections.showGenre(show.genre.uid))
}
is Show.PlaylistDetails -> {
logD("Navigating to ${show.playlist}")
T.d("Navigating to ${show.playlist}")
findNavController()
.navigateSafe(SearchFragmentDirections.showPlaylist(show.playlist.uid))
}
@ -297,7 +296,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
binding.searchSelectionToolbar.title = getString(R.string.fmt_selected, selected.size)
if (binding.searchToolbar.setVisible(R.id.search_selection_toolbar)) {
// New selection started, show the keyboard to make selection easier.
logD("Significant selection occurred, hiding keyboard")
T.d("Significant selection occurred, hiding keyboard")
hideKeyboard()
}
} else {
@ -310,7 +309,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
val directions =
when (decision) {
is PlaylistDecision.Import -> {
logD("Importing playlist")
T.d("Importing playlist")
pendingImportTarget = decision.target
requireNotNull(getContentLauncher) {
"Content picker launcher was not available"
@ -320,7 +319,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
return
}
is PlaylistDecision.Rename -> {
logD("Renaming ${decision.playlist}")
T.d("Renaming ${decision.playlist}")
SearchFragmentDirections.renamePlaylist(
decision.playlist.uid,
decision.template,
@ -328,15 +327,15 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
decision.reason)
}
is PlaylistDecision.Delete -> {
logD("Deleting ${decision.playlist}")
T.d("Deleting ${decision.playlist}")
SearchFragmentDirections.deletePlaylist(decision.playlist.uid)
}
is PlaylistDecision.Export -> {
logD("Exporting ${decision.playlist}")
T.d("Exporting ${decision.playlist}")
SearchFragmentDirections.exportPlaylist(decision.playlist.uid)
}
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} to a playlist")
T.d("Adding ${decision.songs.size} to a playlist")
SearchFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
@ -362,11 +361,11 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
val directions =
when (decision) {
is PlaybackDecision.PlayFromArtist -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
SearchFragmentDirections.playFromArtist(decision.song.uid)
}
is PlaybackDecision.PlayFromGenre -> {
logD("Launching play from artist dialog for $decision")
T.d("Launching play from artist dialog for $decision")
SearchFragmentDirections.playFromGenre(decision.song.uid)
}
}
@ -379,7 +378,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
* @param view The [View] to focus the keyboard on.
*/
private fun showKeyboard(view: View) {
logD("Launching keyboard")
T.d("Launching keyboard")
view.apply {
requestFocus()
postDelayed(200) {
@ -391,7 +390,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
/** Safely hide the keyboard from this view. */
private fun hideKeyboard() {
logD("Hiding keyboard")
T.d("Hiding keyboard")
requireNotNull(imm) { "InputMethodManager was not available" }
.hideSoftInputFromWindow(requireView().windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}

View file

@ -40,7 +40,7 @@ import org.oxycblt.auxio.music.device.DeviceLibrary
import org.oxycblt.auxio.music.user.UserLibrary
import org.oxycblt.auxio.playback.PlaySong
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.util.logD
import timber.log.Timber as T
/**
* An [ViewModel] that keeps performs search operations and tracks their results.
@ -79,7 +79,7 @@ constructor(
override fun onMusicChanges(changes: MusicRepository.Changes) {
if (changes.deviceLibrary || changes.userLibrary) {
logD("Music changed, re-searching library")
T.d("Music changed, re-searching library")
search(lastQuery)
}
}
@ -98,13 +98,13 @@ constructor(
val deviceLibrary = musicRepository.deviceLibrary
val userLibrary = musicRepository.userLibrary
if (query.isNullOrEmpty() || deviceLibrary == null || userLibrary == null) {
logD("Cannot search for the current query, aborting")
T.d("Cannot search for the current query, aborting")
_searchResults.value = listOf()
return
}
// Searching is time-consuming, so do it in the background.
logD("Searching music library for $query")
T.d("Searching music library for $query")
currentSearchJob =
viewModelScope.launch {
_searchResults.value =
@ -122,7 +122,7 @@ constructor(
val items =
if (filter == null) {
// A nulled filter type means to not filter anything.
logD("No filter specified, using entire library")
T.d("No filter specified, using entire library")
SearchEngine.Items(
deviceLibrary.songs,
deviceLibrary.albums,
@ -130,7 +130,7 @@ constructor(
deviceLibrary.genres,
userLibrary.playlists)
} else {
logD("Filter specified, reducing library")
T.d("Filter specified, reducing library")
SearchEngine.Items(
songs = if (filter == MusicType.SONGS) deviceLibrary.songs else null,
albums = if (filter == MusicType.ALBUMS) deviceLibrary.albums else null,
@ -143,13 +143,13 @@ constructor(
return buildList {
results.artists?.let {
logD("Adding ${it.size} artists to search results")
T.d("Adding ${it.size} artists to search results")
val header = BasicHeader(R.string.lbl_artists)
add(header)
addAll(SORT.artists(it))
}
results.albums?.let {
logD("Adding ${it.size} albums to search results")
T.d("Adding ${it.size} albums to search results")
val header = BasicHeader(R.string.lbl_albums)
if (isNotEmpty()) {
add(PlainDivider(header))
@ -159,7 +159,7 @@ constructor(
addAll(SORT.albums(it))
}
results.playlists?.let {
logD("Adding ${it.size} playlists to search results")
T.d("Adding ${it.size} playlists to search results")
val header = BasicHeader(R.string.lbl_playlists)
if (isNotEmpty()) {
add(PlainDivider(header))
@ -169,7 +169,7 @@ constructor(
addAll(SORT.playlists(it))
}
results.genres?.let {
logD("Adding ${it.size} genres to search results")
T.d("Adding ${it.size} genres to search results")
val header = BasicHeader(R.string.lbl_genres)
if (isNotEmpty()) {
add(PlainDivider(header))
@ -179,7 +179,7 @@ constructor(
addAll(SORT.genres(it))
}
results.songs?.let {
logD("Adding ${it.size} songs to search results")
T.d("Adding ${it.size} songs to search results")
val header = BasicHeader(R.string.lbl_songs)
if (isNotEmpty()) {
add(PlainDivider(header))
@ -225,7 +225,7 @@ constructor(
R.id.option_filter_all -> null
else -> error("Invalid option ID provided")
}
logD("Updating filter type to $newFilter")
T.d("Updating filter type to $newFilter")
searchSettings.filterTo = newFilter
search(lastQuery)
}

View file

@ -37,8 +37,8 @@ import org.oxycblt.auxio.settings.ui.IntListPreference
import org.oxycblt.auxio.settings.ui.IntListPreferenceDialog
import org.oxycblt.auxio.settings.ui.PreferenceHeaderItemDecoration
import org.oxycblt.auxio.settings.ui.WrappedDialogPreference
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.systemBarInsetsCompat
import timber.log.Timber as T
/**
* Shared [PreferenceFragmentCompat] used across all preference screens.
@ -82,7 +82,7 @@ abstract class BasePreferenceFragment(@XmlRes private val screen: Int) :
preferenceManager.onDisplayPreferenceDialogListener = this
preferenceScreen.children.forEach(::setupPreference)
logD("Fragment created")
T.d("Fragment created")
}
override fun onCreateRecyclerView(

View file

@ -29,8 +29,8 @@ import dagger.hilt.android.AndroidEntryPoint
import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.settings.ui.WrappedDialogPreference
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import timber.log.Timber as T
/**
* The [PreferenceFragmentCompat] that displays the root settings list.
@ -62,21 +62,21 @@ class RootPreferenceFragment : BasePreferenceFragment(R.xml.preferences_root) {
// do one.
when (preference.key) {
getString(R.string.set_key_ui) -> {
logD("Navigating to UI preferences")
T.d("Navigating to UI preferences")
findNavController().navigateSafe(RootPreferenceFragmentDirections.uiPreferences())
}
getString(R.string.set_key_personalize) -> {
logD("Navigating to personalization preferences")
T.d("Navigating to personalization preferences")
findNavController()
.navigateSafe(RootPreferenceFragmentDirections.personalizePreferences())
}
getString(R.string.set_key_music) -> {
logD("Navigating to music preferences")
T.d("Navigating to music preferences")
findNavController()
.navigateSafe(RootPreferenceFragmentDirections.musicPreferences())
}
getString(R.string.set_key_audio) -> {
logD("Navigating to audio preferences")
T.d("Navigating to audio preferences")
findNavController().navigateSafe(RootPreferenceFragmentDirections.audioPeferences())
}
getString(R.string.set_key_reindex) -> musicModel.refresh()

View file

@ -22,9 +22,8 @@ import android.content.Context
import android.content.SharedPreferences
import androidx.annotation.StringRes
import androidx.preference.PreferenceManager
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.unlikelyToBeNull
import timber.log.Timber as T
/**
* Abstract user configuration information. This interface has no functionality whatsoever. Concrete
@ -74,19 +73,19 @@ interface Settings<L> {
override fun registerListener(listener: L) {
if (this.listener == null) {
// Registering a listener when it was null prior, attach the callback.
logD("Registering shared preference listener")
T.d("Registering shared preference listener")
sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}
logD("Registering listener $listener")
T.d("Registering listener $listener")
this.listener = listener
}
override fun unregisterListener(listener: L) {
if (this.listener !== listener) {
logW("Given listener was not the current listener.")
T.w("Given listener was not the current listener.")
return
}
logD("Unregistering listener $listener")
T.d("Unregistering listener $listener")
this.listener = null
// No longer have a listener, detach from the preferences instance.
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
@ -97,7 +96,7 @@ interface Settings<L> {
key: String?
) {
// FIXME: Settings initialization firing the listener.
logD("Dispatching settings change $key")
T.d("Dispatching settings change $key")
onSettingChanged(unlikelyToBeNull(key), unlikelyToBeNull(listener))
}

View file

@ -22,8 +22,8 @@ import androidx.navigation.fragment.findNavController
import org.oxycblt.auxio.R
import org.oxycblt.auxio.settings.BasePreferenceFragment
import org.oxycblt.auxio.settings.ui.WrappedDialogPreference
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import timber.log.Timber as T
/**
* Audio settings interface.
@ -34,7 +34,7 @@ class AudioPreferenceFragment : BasePreferenceFragment(R.xml.preferences_audio)
override fun onOpenDialogPreference(preference: WrappedDialogPreference) {
if (preference.key == getString(R.string.set_key_pre_amp)) {
logD("Navigating to pre-amp dialog")
T.d("Navigating to pre-amp dialog")
findNavController().navigateSafe(AudioPreferenceFragmentDirections.preAmpSettings())
}
}

View file

@ -26,8 +26,8 @@ import javax.inject.Inject
import org.oxycblt.auxio.R
import org.oxycblt.auxio.settings.BasePreferenceFragment
import org.oxycblt.auxio.settings.ui.WrappedDialogPreference
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import timber.log.Timber as T
/**
* "Content" settings.
@ -40,7 +40,7 @@ class MusicPreferenceFragment : BasePreferenceFragment(R.xml.preferences_music)
override fun onOpenDialogPreference(preference: WrappedDialogPreference) {
if (preference.key == getString(R.string.set_key_separators)) {
logD("Navigating to separator dialog")
T.d("Navigating to separator dialog")
findNavController().navigateSafe(MusicPreferenceFragmentDirections.separatorsSettings())
}
}
@ -48,10 +48,10 @@ class MusicPreferenceFragment : BasePreferenceFragment(R.xml.preferences_music)
override fun onSetupPreference(preference: Preference) {
if (preference.key == getString(R.string.set_key_cover_mode) ||
preference.key == getString(R.string.set_key_square_covers)) {
logD("Configuring cover mode setting")
T.d("Configuring cover mode setting")
preference.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, _ ->
logD("Cover mode changed, resetting image memory cache")
T.d("Cover mode changed, resetting image memory cache")
imageLoader.memoryCache?.clear()
true
}

View file

@ -22,8 +22,8 @@ import androidx.navigation.fragment.findNavController
import org.oxycblt.auxio.R
import org.oxycblt.auxio.settings.BasePreferenceFragment
import org.oxycblt.auxio.settings.ui.WrappedDialogPreference
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import timber.log.Timber as T
/**
* Personalization settings interface.
@ -33,7 +33,7 @@ import org.oxycblt.auxio.util.navigateSafe
class PersonalizePreferenceFragment : BasePreferenceFragment(R.xml.preferences_personalize) {
override fun onOpenDialogPreference(preference: WrappedDialogPreference) {
if (preference.key == getString(R.string.set_key_home_tabs)) {
logD("Navigating to home tab dialog")
T.d("Navigating to home tab dialog")
findNavController().navigateSafe(PersonalizePreferenceFragmentDirections.tabSettings())
}
}

View file

@ -28,8 +28,8 @@ import org.oxycblt.auxio.settings.BasePreferenceFragment
import org.oxycblt.auxio.settings.ui.WrappedDialogPreference
import org.oxycblt.auxio.ui.UISettings
import org.oxycblt.auxio.util.isNight
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import timber.log.Timber as T
/**
* Display preferences.
@ -42,7 +42,7 @@ class UIPreferenceFragment : BasePreferenceFragment(R.xml.preferences_ui) {
override fun onOpenDialogPreference(preference: WrappedDialogPreference) {
if (preference.key == getString(R.string.set_key_accent)) {
logD("Navigating to accent dialog")
T.d("Navigating to accent dialog")
findNavController().navigateSafe(UIPreferenceFragmentDirections.accentSettings())
}
}
@ -50,25 +50,25 @@ class UIPreferenceFragment : BasePreferenceFragment(R.xml.preferences_ui) {
override fun onSetupPreference(preference: Preference) {
when (preference.key) {
getString(R.string.set_key_theme) -> {
logD("Configuring theme setting")
T.d("Configuring theme setting")
preference.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, value ->
logD("Theme changed, recreating")
T.d("Theme changed, recreating")
AppCompatDelegate.setDefaultNightMode(value as Int)
true
}
}
getString(R.string.set_key_accent) -> {
logD("Configuring accent setting")
T.d("Configuring accent setting")
preference.summary = getString(uiSettings.accent.name)
}
getString(R.string.set_key_black_theme) -> {
logD("Configuring black theme setting")
T.d("Configuring black theme setting")
preference.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, _ ->
val activity = requireActivity()
if (activity.isNight) {
logD("Black theme changed in night mode, recreating")
T.d("Black theme changed in night mode, recreating")
activity.recreate()
}

Some files were not shown because too many files have changed in this diff Show more