Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 3.3.1 #669

Merged
merged 18 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# Changelog

## dev
## 3.3.1

#### What's Improved
- The OPUS base volume adjustment field is now parsed and used as a ReplayGain adjustment
- Added ReplayGain adjustment values to Song Properties dialog

#### What's Changed
- Added donation links to the about page

#### What's Fixed
- Fixed a crash occuring if you navigated to the settings page from the playlist view
and then back
- Fixed music loading failing with an SQL error with certain music folder configurations
- Fixed issue where song title on playback screen would not scroll

## 3.3.0

Expand Down
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<h1 align="center"><b>Auxio</b></h1>
<h4 align="center">A simple, rational music player for android.</h4>
<p align="center">
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v3.3.0">
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v3.3.0&color=64B5F6&style=flat">
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v3.3.1">
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v3.3.1&color=64B5F6&style=flat">
</a>
<a href="https://github.com/oxygencobalt/Auxio/releases/">
<img alt="Releases" src="https://img.shields.io/github/downloads/OxygenCobalt/Auxio/total.svg?color=4B95DE&style=flat">
Expand All @@ -13,10 +13,10 @@
</a>
<img alt="Minimum SDK Version" src="https://img.shields.io/badge/API-24%2B-1450A8?style=flat">
</p>
<h4 align="center"><a href="/CHANGELOG.md">Changelog</a> | <a href="https://github.com/OxygenCobalt/Auxio/wiki">Wiki</a></h4>
<h4 align="center"><a href="/CHANGELOG.md">Changelog</a> | <a href="https://github.com/OxygenCobalt/Auxio/wiki">Wiki</a> | <a href="https://github.com/OxygenCobalt/Auxio#Donate">Donate</a></h4>
<p align="center">
<a href="https://f-droid.org/app/org.oxycblt.auxio"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" width="170"></a>
<a href="https://hosted.weblate.org/engage/auxio/"><img src="https://hosted.weblate.org/widgets/auxio/-/strings/287x66-grey.png" alt="Translation status" /></a>
<a href="https://hosted.weblate.org/engage/auxio/"><img height=64 src="https://hosted.weblate.org/widgets/auxio/-/strings/287x66-grey.png" alt="Translation status" /></a>
</p>

## About
Expand All @@ -38,6 +38,7 @@ Auxio is a local music player with a fast, reliable UI/UX without the many usele
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot7.png" width=200>
</p>


## Features

- Playback based on [Media3 ExoPlayer](https://developer.android.com/guide/topics/media/exoplayer)
Expand Down Expand Up @@ -65,6 +66,20 @@ precise/original dates, sort tags, and more
- Storage (`READ_MEDIA_AUDIO`, `READ_EXTERNAL_STORAGE`) to read and play your music files
- Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`) to keep the music playing in the background

## Donate

You can support Auxio's development through [my Github Sponsors page](https://github.com/sponsors/OxygenCobalt). Get the ability to prioritize features and have your profile added to the README, Release Changelogs, and even App Itself!

**$16/month supporters:**

*Be the first to have their profile picture and username added here!*

**$8/month supporters:**

<p align="start">
<a href="https://github.com/alanorth"><img src="https://avatars.githubusercontent.com/u/191754?v=4" width=50 /></a>
</p>

## Building

Auxio relies on a custom version of Media3 that enables some extra features. This adds some caveats to the build process:
Expand All @@ -82,6 +97,8 @@ However, feature additions and major UI changes are less likely to be accepted.
[Why Are These Features Missing?](https://github.com/OxygenCobalt/Auxio/wiki/Why-Are-These-Features-Missing%3F)
for more information.



## License

[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](http://www.gnu.org/licenses/gpl-3.0.en.html)
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ android {

defaultConfig {
applicationId namespace
versionName "3.3.0"
versionCode 37
versionName "3.3.1"
versionCode 38

minSdk 24
targetSdk 34
Expand Down
21 changes: 20 additions & 1 deletion app/src/main/java/org/oxycblt/auxio/MainFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import android.view.WindowInsets
import androidx.activity.OnBackPressedCallback
import androidx.core.view.ViewCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
Expand All @@ -33,7 +34,9 @@ import com.google.android.material.R as MR
import com.google.android.material.bottomsheet.BackportBottomSheetBehavior
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.transition.MaterialFadeThrough
import com.leinardi.android.speeddial.SpeedDialOverlayLayout
import dagger.hilt.android.AndroidEntryPoint
import java.lang.reflect.Field
import kotlin.math.max
import kotlin.math.min
import org.oxycblt.auxio.databinding.FragmentMainBinding
Expand All @@ -56,6 +59,7 @@ import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.coordinatorLayoutBehavior
import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.getDimen
import org.oxycblt.auxio.util.lazyReflectedField
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.systemBarInsetsCompat
Expand Down Expand Up @@ -153,6 +157,9 @@ class MainFragment :
}
}

binding.mainScrim.setOnClickListener { homeModel.setSpeedDialOpen(false) }
binding.sheetScrim.setOnClickListener { homeModel.setSpeedDialOpen(false) }

// --- VIEWMODEL SETUP ---
// This has to be done here instead of the playback panel to make sure that it's prioritized
// by StateFlow over any detail fragment.
Expand All @@ -161,7 +168,7 @@ class MainFragment :
collect(detailModel.toShow.flow, ::handleShow)
collectImmediately(detailModel.editedPlaylist, detailBackCallback::invalidateEnabled)
collectImmediately(homeModel.showOuter.flow, ::handleShowOuter)
collectImmediately(homeModel.speedDialOpen, speedDialBackCallback::invalidateEnabled)
collectImmediately(homeModel.speedDialOpen, ::handleSpeedDialState)
collectImmediately(listModel.selected, selectionBackCallback::invalidateEnabled)
collectImmediately(playbackModel.song, ::updateSong)
collectImmediately(playbackModel.openPanel.flow, ::handlePanel)
Expand Down Expand Up @@ -336,6 +343,13 @@ class MainFragment :
homeModel.showOuter.consume()
}

private fun handleSpeedDialState(open: Boolean) {
requireNotNull(speedDialBackCallback) { "SpeedDialBackPressedCallback was not available" }
.invalidateEnabled(open)
requireBinding().mainScrim.isVisible = open
requireBinding().sheetScrim.isVisible = open
}

private fun updateSong(song: Song?) {
if (song != null) {
tryShowSheets()
Expand Down Expand Up @@ -519,4 +533,9 @@ class MainFragment :
isEnabled = open
}
}

private companion object {
val SPEED_DIAL_OVERLAY_ANIMATION_DURATION_FIELD: Field by
lazyReflectedField(SpeedDialOverlayLayout::class, "mAnimationDuration")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import org.oxycblt.auxio.music.info.Name
import org.oxycblt.auxio.music.metadata.AudioProperties
import org.oxycblt.auxio.music.resolveNames
import org.oxycblt.auxio.playback.formatDurationMs
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
Expand Down Expand Up @@ -118,6 +119,12 @@ class SongDetailDialog : ViewBindingMaterialDialogFragment<DialogSongDetailBindi
SongProperty(
R.string.lbl_sample_rate, getString(R.string.fmt_sample_rate, it)))
}
song.replayGainAdjustment.track?.let {
add(SongProperty(R.string.lbl_replaygain_track, it.formatDb(context)))
}
song.replayGainAdjustment.album?.let {
add(SongProperty(R.string.lbl_replaygain_album, it.formatDb(context)))
}
},
UpdateInstructions.Replace(0))
}
Expand Down
34 changes: 11 additions & 23 deletions app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.oxycblt.auxio.home

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
Expand Down Expand Up @@ -124,6 +125,7 @@ class HomeFragment :

override fun getSelectionToolbar(binding: FragmentHomeBinding) = binding.homeSelectionToolbar

@SuppressLint("ClickableViewAccessibility")
override fun onBindingCreated(binding: FragmentHomeBinding, savedInstanceState: Bundle?) {
super.onBindingCreated(binding, savedInstanceState)

Expand All @@ -146,23 +148,16 @@ class HomeFragment :

// --- UI SETUP ---

// Stock bottom sheet overlay won't work with our nested UI setup, have to replicate
// it ourselves.
binding.root.rootView.apply {
// Stock bottom sheet overlay won't work with our nested UI setup, have to replicate
// it ourselves.
findViewById<View>(R.id.main_scrim).setOnClickListener {
homeModel.setSpeedDialOpen(false)
}

findViewById<View>(R.id.main_scrim).setOnTouchListener { _, event ->
handleSpeedDialBoundaryTouch(event)
}

findViewById<View>(R.id.sheet_scrim).setOnClickListener {
homeModel.setSpeedDialOpen(false)
}

findViewById<View>(R.id.sheet_scrim).setOnTouchListener { _, event ->
handleSpeedDialBoundaryTouch(event)
post {
findViewById<View>(R.id.main_scrim).setOnTouchListener { _, event ->
handleSpeedDialBoundaryTouch(event)
}
findViewById<View>(R.id.sheet_scrim).setOnTouchListener { _, event ->
handleSpeedDialBoundaryTouch(event)
}
}
}

Expand Down Expand Up @@ -616,13 +611,6 @@ class HomeFragment :
private fun updateSpeedDial(open: Boolean) {
val binding = requireBinding()

binding.root.rootView.apply {
// Stock bottom sheet overlay won't work with our nested UI setup, have to replicate
// it ourselves.
findViewById<View>(R.id.main_scrim).isClickable = open
findViewById<View>(R.id.sheet_scrim).isClickable = open
}

if (open) {
binding.homeNewPlaylistFab.open(true)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,13 @@ class ExportPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistExp
} else {
R.id.export_relative_paths
})
logD(config.windowsPaths)
if (config.absolute) {
binding.exportRelativePaths.icon = null
binding.exportAbsolutePaths.setIconResource(R.drawable.ic_check_24)
} else {
binding.exportAbsolutePaths.icon = null
binding.exportRelativePaths.setIconResource(R.drawable.ic_check_24)
}
binding.exportWindowsPaths.isChecked = config.windowsPaths
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +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

/**
* Wrapper around a [Cursor] that interprets path information on a per-API/manufacturer basis.
Expand Down Expand Up @@ -111,6 +112,8 @@ private constructor(private val cursor: Cursor, volumeManager: VolumeManager) :
}
}

logE("Could not find volume for $data [tried: ${volumes.map { it.components }}]")

return null
}

Expand All @@ -134,7 +137,7 @@ private constructor(private val cursor: Cursor, volumeManager: VolumeManager) :
val path = paths[i]
val volume = path.volume.components ?: continue
template +=
if (i == 0) {
if (args.isEmpty()) {
"${MediaStore.Audio.AudioColumns.DATA} LIKE ?"
} else {
" OR ${MediaStore.Audio.AudioColumns.DATA} LIKE ?"
Expand Down Expand Up @@ -172,11 +175,16 @@ private constructor(private val cursor: Cursor, volumeManager: VolumeManager) :
override fun extract(): Path? {
// Find the StorageVolume whose MediaStore name corresponds to it.
val volumeName = cursor.getString(volumeIndex)
val volume = volumes.find { it.mediaStoreName == volumeName } ?: return null
// Relative path does not include file name, must use DISPLAY_NAME and add it
// in manually.
val relativePath = cursor.getString(relativePathIndex)
val displayName = cursor.getString(displayNameIndex)
val volume = volumes.find { it.mediaStoreName == volumeName }
if (volume == null) {
logE(
"Could not find volume for $volumeName:$relativePath/$displayName [tried: ${volumes.map { it.mediaStoreName }}]")
return null
}
val components = Components.parseUnix(relativePath).child(displayName)
return Path(volume, components)
}
Expand Down Expand Up @@ -209,7 +217,7 @@ private constructor(private val cursor: Cursor, volumeManager: VolumeManager) :
for (i in paths.indices) {
val path = paths[i]
template =
if (i == 0) {
if (args.isEmpty()) {
"(${MediaStore.Audio.AudioColumns.VOLUME_NAME} LIKE ? " +
"AND ${MediaStore.Audio.AudioColumns.RELATIVE_PATH} LIKE ?)"
} else {
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package org.oxycblt.auxio.music.metadata

import androidx.core.text.isDigitsOnly
import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes
import androidx.media3.exoplayer.MetadataRetriever
import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.TrackGroupArray
Expand Down Expand Up @@ -97,6 +98,20 @@ private class TagWorkerImpl(
val textTags = TextTags(metadata)
populateWithId3v2(textTags.id3v2)
populateWithVorbis(textTags.vorbis)

// If this metadata is of a vorbis file, we actually need to extract it's base gain
// and divide it by 256 to get the gain in decibels.
if (format.sampleMimeType == MimeTypes.AUDIO_OPUS &&
format.initializationData.isNotEmpty() &&
format.initializationData[0].size >= 18) {
val header = format.initializationData[0]
val gain = header[1].toInt() or ((header[0].toInt() shl 8) and 0xFF)
logD("Obtained opus base gain: ${gain / 256f} dB")
rawSong.replayGainTrackAdjustment =
rawSong.replayGainTrackAdjustment?.plus(gain / 256f)
rawSong.replayGainAlbumAdjustment =
rawSong.replayGainAlbumAdjustment?.plus(gain / 256f)
}
} else {
logD("No metadata could be extracted for ${rawSong.name}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ class PlaybackPanelFragment :
}

binding.playbackCover.onSwipeListener = this
binding.playbackSong.setOnClickListener { navigateToCurrentSong() }
binding.playbackSong.apply {
isSelected = true
setOnClickListener { navigateToCurrentSong() }
}
binding.playbackArtist.setOnClickListener { navigateToCurrentArtist() }
binding.playbackAlbum.setOnClickListener { navigateToCurrentAlbum() }

Expand All @@ -130,6 +133,7 @@ class PlaybackPanelFragment :
override fun onDestroyBinding(binding: FragmentPlaybackPanelBinding) {
equalizerLauncher = null
coverAdapter = null
binding.playbackSong.isSelected = false
binding.playbackToolbar.setOnMenuItemClickListener(null)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlin.math.abs
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.DialogPreAmpBinding
import org.oxycblt.auxio.playback.PlaybackSettings
Expand Down Expand Up @@ -85,11 +84,6 @@ class PreAmpCustomizeDialog : ViewBindingMaterialDialogFragment<DialogPreAmpBind
// It is more clear to prepend a +/- before the pre-amp value to make it easier to
// gauge how much it may be increasing the volume, however android does not add +
// to positive float values when formatting them in a string. Instead, add it ourselves.
ticker.text =
if (valueDb >= 0) {
getString(R.string.fmt_db_pos, valueDb)
} else {
getString(R.string.fmt_db_neg, abs(valueDb))
}
ticker.text = valueDb.formatDb(requireContext())
}
}
Loading