commit
7b01e59519
49 changed files with 389 additions and 83 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -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
|
||||
|
||||
|
|
25
README.md
25
README.md
|
@ -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">
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
[](http://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
|
|
|
@ -21,8 +21,8 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
applicationId namespace
|
||||
versionName "3.3.0"
|
||||
versionCode 37
|
||||
versionName "3.3.1"
|
||||
versionCode 38
|
||||
|
||||
minSdk 24
|
||||
targetSdk 34
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -519,4 +533,9 @@ class MainFragment :
|
|||
isEnabled = open
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val SPEED_DIAL_OVERLAY_ANIMATION_DURATION_FIELD: Field by
|
||||
lazyReflectedField(SpeedDialOverlayLayout::class, "mAnimationDuration")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 ?"
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
@ -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}")
|
||||
}
|
||||
|
|
|
@ -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() }
|
||||
|
||||
|
@ -130,6 +133,7 @@ class PlaybackPanelFragment :
|
|||
override fun onDestroyBinding(binding: FragmentPlaybackPanelBinding) {
|
||||
equalizerLauncher = null
|
||||
coverAdapter = null
|
||||
binding.playbackSong.isSelected = false
|
||||
binding.playbackToolbar.setOnMenuItemClickListener(null)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,10 @@
|
|||
|
||||
package org.oxycblt.auxio.playback.replaygain
|
||||
|
||||
import android.content.Context
|
||||
import kotlin.math.abs
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.R
|
||||
|
||||
/**
|
||||
* The current ReplayGain configuration.
|
||||
|
@ -67,3 +70,16 @@ data class ReplayGainAdjustment(val track: Float?, val album: Float?)
|
|||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
data class ReplayGainPreAmp(val with: Float, val without: Float)
|
||||
|
||||
/**
|
||||
* Format a decibel value in a human-readable format.
|
||||
*
|
||||
* @param context The context to resolve resources from.
|
||||
* @return A formatted decibel value. Will be prefixed by a + or - sign.
|
||||
*/
|
||||
fun Float.formatDb(context: Context) =
|
||||
if (this >= 0) {
|
||||
context.getString(R.string.fmt_db_pos, this)
|
||||
} else {
|
||||
context.getString(R.string.fmt_db_neg, abs(this))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Auxio Project
|
||||
* BetterShuffleOrder.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.playback.system
|
||||
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.exoplayer.source.ShuffleOrder
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* A ShuffleOrder that fixes the poorly defined default implementation of cloneAndInsert. Whereas
|
||||
* the default implementation will randomly spread out added media items, this implementation will
|
||||
* insert them in the order they are added contiguously.
|
||||
*
|
||||
* @author media3 team, Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class BetterShuffleOrder
|
||||
private constructor(private val shuffled: IntArray, private val random: Random) : ShuffleOrder {
|
||||
private val indexInShuffled: IntArray = IntArray(shuffled.size)
|
||||
|
||||
/**
|
||||
* Creates an instance with a specified length.
|
||||
*
|
||||
* @param length The length of the shuffle order.
|
||||
*/
|
||||
constructor(length: Int) : this(length, Random())
|
||||
|
||||
constructor(length: Int, random: Random) : this(createShuffledList(length, random), random)
|
||||
|
||||
init {
|
||||
for (i in shuffled.indices) {
|
||||
indexInShuffled[shuffled[i]] = i
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLength(): Int {
|
||||
return shuffled.size
|
||||
}
|
||||
|
||||
override fun getNextIndex(index: Int): Int {
|
||||
var shuffledIndex = indexInShuffled[index]
|
||||
return if (++shuffledIndex < shuffled.size) shuffled[shuffledIndex] else C.INDEX_UNSET
|
||||
}
|
||||
|
||||
override fun getPreviousIndex(index: Int): Int {
|
||||
var shuffledIndex = indexInShuffled[index]
|
||||
return if (--shuffledIndex >= 0) shuffled[shuffledIndex] else C.INDEX_UNSET
|
||||
}
|
||||
|
||||
override fun getLastIndex(): Int {
|
||||
return if (shuffled.isNotEmpty()) shuffled[shuffled.size - 1] else C.INDEX_UNSET
|
||||
}
|
||||
|
||||
override fun getFirstIndex(): Int {
|
||||
return if (shuffled.isNotEmpty()) shuffled[0] else C.INDEX_UNSET
|
||||
}
|
||||
|
||||
override fun cloneAndInsert(insertionIndex: Int, insertionCount: Int): ShuffleOrder {
|
||||
val newShuffled = IntArray(shuffled.size + insertionCount)
|
||||
val pivot = indexInShuffled[insertionIndex]
|
||||
for (i in shuffled.indices) {
|
||||
var currentIndex = shuffled[i]
|
||||
if (currentIndex > insertionIndex) {
|
||||
currentIndex += insertionCount
|
||||
}
|
||||
|
||||
if (i <= pivot) {
|
||||
newShuffled[i] = currentIndex
|
||||
} else if (i > pivot) {
|
||||
newShuffled[i + insertionCount] = currentIndex
|
||||
}
|
||||
}
|
||||
for (i in 0 until insertionCount) {
|
||||
newShuffled[pivot + i + 1] = insertionIndex + i + 1
|
||||
}
|
||||
return BetterShuffleOrder(newShuffled, Random(random.nextLong()))
|
||||
}
|
||||
|
||||
override fun cloneAndRemove(indexFrom: Int, indexToExclusive: Int): ShuffleOrder {
|
||||
val numberOfElementsToRemove = indexToExclusive - indexFrom
|
||||
val newShuffled = IntArray(shuffled.size - numberOfElementsToRemove)
|
||||
var foundElementsCount = 0
|
||||
for (i in shuffled.indices) {
|
||||
if (shuffled[i] in indexFrom until indexToExclusive) {
|
||||
foundElementsCount++
|
||||
} else {
|
||||
newShuffled[i - foundElementsCount] =
|
||||
if (shuffled[i] >= indexFrom) shuffled[i] - numberOfElementsToRemove
|
||||
else shuffled[i]
|
||||
}
|
||||
}
|
||||
return BetterShuffleOrder(newShuffled, Random(random.nextLong()))
|
||||
}
|
||||
|
||||
override fun cloneAndClear(): ShuffleOrder {
|
||||
return BetterShuffleOrder(0, Random(random.nextLong()))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun createShuffledList(length: Int, random: Random): IntArray {
|
||||
val shuffled = IntArray(length)
|
||||
for (i in 0 until length) {
|
||||
val swapIndex = random.nextInt(i + 1)
|
||||
shuffled[i] = shuffled[swapIndex]
|
||||
shuffled[swapIndex] = i
|
||||
}
|
||||
return shuffled
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,7 +66,11 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
|
|||
binding.aboutCode.setOnClickListener { requireContext().openInBrowser(LINK_SOURCE) }
|
||||
binding.aboutWiki.setOnClickListener { requireContext().openInBrowser(LINK_WIKI) }
|
||||
binding.aboutLicenses.setOnClickListener { requireContext().openInBrowser(LINK_LICENSES) }
|
||||
binding.aboutAuthor.setOnClickListener { requireContext().openInBrowser(LINK_AUTHOR) }
|
||||
binding.aboutProfile.setOnClickListener { requireContext().openInBrowser(LINK_PROFILE) }
|
||||
binding.aboutDonate.setOnClickListener { requireContext().openInBrowser(LINK_DONATE) }
|
||||
binding.aboutSupportersPromo.setOnClickListener {
|
||||
requireContext().openInBrowser(LINK_DONATE)
|
||||
}
|
||||
|
||||
// VIEWMODEL SETUP
|
||||
collectImmediately(musicModel.statistics, ::updateStatistics)
|
||||
|
@ -88,13 +92,10 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
|
|||
}
|
||||
|
||||
private companion object {
|
||||
/** The URL to the source code. */
|
||||
const val LINK_SOURCE = "https://github.com/OxygenCobalt/Auxio"
|
||||
/** The URL to the app wiki. */
|
||||
const val LINK_WIKI = "$LINK_SOURCE/wiki"
|
||||
/** The URL to the licenses wiki page. */
|
||||
const val LINK_LICENSES = "$LINK_WIKI/Licenses"
|
||||
/** The URL to the app author. */
|
||||
const val LINK_AUTHOR = "https://github.com/OxygenCobalt"
|
||||
const val LINK_PROFILE = "https://github.com/OxygenCobalt"
|
||||
const val LINK_DONATE = "https://github.com/sponsors/OxygenCobalt"
|
||||
}
|
||||
}
|
||||
|
|
10
app/src/main/res/drawable/ic_donate_24.xml
Normal file
10
app/src/main/res/drawable/ic_donate_24.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,840L422,788Q321,697 255,631Q189,565 150,512.5Q111,460 95.5,416Q80,372 80,326Q80,232 143,169Q206,106 300,106Q352,106 399,128Q446,150 480,190Q514,150 561,128Q608,106 660,106Q754,106 817,169Q880,232 880,326Q880,372 864.5,416Q849,460 810,512.5Q771,565 705,631Q639,697 538,788L480,840ZM480,732Q576,646 638,584.5Q700,523 736,477.5Q772,432 786,396.5Q800,361 800,326Q800,266 760,226Q720,186 660,186Q613,186 573,212.5Q533,239 518,280L518,280L442,280L442,280Q427,239 387,212.5Q347,186 300,186Q240,186 200,226Q160,266 160,326Q160,361 174,396.5Q188,432 224,477.5Q260,523 322,584.5Q384,646 480,732ZM480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459L480,459L480,459L480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Z"/>
|
||||
</vector>
|
|
@ -152,19 +152,92 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_wiki" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_medium">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/spacing_tiny">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_author"
|
||||
style="@style/Widget.Auxio.TextView.Header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lbl_author"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_profile"
|
||||
style="@style/Widget.Auxio.TextView.Icon.Clickable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lng_author"
|
||||
android:text="@string/lbl_author_name"
|
||||
app:drawableStartCompat="@drawable/ic_author_24"
|
||||
app:drawableTint="?attr/colorControlNormal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_licenses" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<TextView
|
||||
android:id="@+id/about_donate"
|
||||
style="@style/Widget.Auxio.TextView.Icon.Clickable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lbl_donate"
|
||||
app:drawableStartCompat="@drawable/ic_donate_24"
|
||||
app:drawableTint="?attr/colorControlNormal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_licenses" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_medium">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/spacing_tiny">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_supporters"
|
||||
style="@style/Widget.Auxio.TextView.Header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lbl_supporters"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_supporters_promo"
|
||||
style="@style/Widget.Auxio.TextView.Icon.Clickable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lng_supporters_promo"
|
||||
android:textStyle="italic"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_licenses" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<string name="lbl_version">الإصدار</string>
|
||||
<string name="lbl_code">عرض على الكود في Github</string>
|
||||
<string name="lbl_licenses">التراخيص</string>
|
||||
<string name="lng_author">تمت برمجة التطبيق من قبل الكساندر كابيهارت</string>
|
||||
<string name="lbl_author_name">تمت برمجة التطبيق من قبل الكساندر كابيهارت</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">الإعدادات</string>
|
||||
<string name="set_ui">المظهر</string>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<string name="set_personalize">Персаналізаваць</string>
|
||||
<string name="lng_observing">Адсочванне змяненняў у вашай музычнай бібліятэцы…</string>
|
||||
<string name="lng_queue_added">Дададзены ў чаргу</string>
|
||||
<string name="lng_author">Распрацавана Аляксандрам Кейпхартам</string>
|
||||
<string name="lbl_author_name">Распрацавана Аляксандрам Кейпхартам</string>
|
||||
<string name="set_bar_action">Карыстальніцкае дзеянне панэлі прайгравання</string>
|
||||
<string name="set_play_song_from_album">Прайграць з альбома</string>
|
||||
<string name="set_separators_comma">Коска (,)</string>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<string name="lbl_version">Verze</string>
|
||||
<string name="lbl_code">Zdrojový kód</string>
|
||||
<string name="lbl_licenses">Licence</string>
|
||||
<string name="lng_author">Vytvořil Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Vytvořil Alexander Capehart</string>
|
||||
<string name="lbl_library_counts">Statistiky knihovny</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Nastavení</string>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<string name="lbl_version">Version</string>
|
||||
<string name="lbl_code">Quellcode</string>
|
||||
<string name="lbl_licenses">Lizenzen</string>
|
||||
<string name="lng_author">Entwickelt von Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Entwickelt von Alexander Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Einstellungen</string>
|
||||
<string name="set_ui">Erscheinungsbild</string>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<string name="lbl_version">Versión</string>
|
||||
<string name="lbl_code">Código fuente</string>
|
||||
<string name="lbl_licenses">Licencias</string>
|
||||
<string name="lng_author">Desarrollado por Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Desarrollado por Alexander Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Ajustes</string>
|
||||
<string name="set_ui">Aspecto y Comportamiento</string>
|
||||
|
|
|
@ -155,7 +155,7 @@
|
|||
</plurals>
|
||||
<string name="lbl_observing">Tarkkaillaan musiikkikirjastoa</string>
|
||||
<string name="lbl_code">Lähdekoodi</string>
|
||||
<string name="lng_author">Kehittänyt Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Kehittänyt Alexander Capehart</string>
|
||||
<string name="fmt_lib_total_duration">Kesto yhteensä: %s</string>
|
||||
<string name="lbl_album_live">Live-albumi</string>
|
||||
<string name="lbl_album_remix">Remix-albumi</string>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<string name="lbl_version">Ulat</string>
|
||||
<string name="lbl_code">Tignan sa GitHub</string>
|
||||
<string name="lbl_licenses">Mga Lisensya</string>
|
||||
<string name="lng_author">Binuo ni OxygenCobalt</string>
|
||||
<string name="lbl_author_name">Binuo ni OxygenCobalt</string>
|
||||
<string name="lbl_library_counts">Istatistika ng library</string>
|
||||
<string name="set_root_title">Mga Setting</string>
|
||||
<string name="set_ui">Hitsura</string>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<string name="lbl_version">Version</string>
|
||||
<string name="lbl_code">Code source</string>
|
||||
<string name="lbl_licenses">Licences</string>
|
||||
<string name="lng_author">Développé par Alexandre Capehart</string>
|
||||
<string name="lbl_author_name">Développé par Alexandre Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Paramètres</string>
|
||||
<string name="set_ui">Apparence</string>
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
<string name="lbl_sample_rate">Frecuencia de mostraxe</string>
|
||||
<string name="lbl_about">Acerca de</string>
|
||||
<string name="lng_observing">Monitorizando cambios na túa biblioteca…</string>
|
||||
<string name="lng_author">Desenvolvido por Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Desenvolvido por Alexander Capehart</string>
|
||||
<string name="set_ui">Aspecto e sensación</string>
|
||||
<string name="set_round_mode">Modo redondo</string>
|
||||
<string name="set_round_mode_desc">Habilita as esquinas redondeadas en elementos adicionais da interface de usuario (require que as portadas dos álbums estean redondeadas)</string>
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
<string name="lbl_shuffle_shortcut_short">शफल करें</string>
|
||||
<string name="lbl_state_restored">स्थिति बहाल</string>
|
||||
<string name="lng_playlist_renamed">प्लेलिस्ट का नाम बदला गया</string>
|
||||
<string name="lng_author">अलेक्जेंडर कैपहार्ट द्वारा विकसित</string>
|
||||
<string name="lbl_author_name">अलेक्जेंडर कैपहार्ट द्वारा विकसित</string>
|
||||
<string name="set_separators_desc">एकाधिक टैग मानों को निरूपित करने वाले वर्ण कॉन्फ़िगर करें</string>
|
||||
<string name="set_separators_comma">अल्पविराम (,)</string>
|
||||
<string name="set_separators_slash">स्लैश (/)</string>
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<string name="lbl_version">Inačica</string>
|
||||
<string name="lbl_code">Izvorni kod</string>
|
||||
<string name="lbl_licenses">Licencije</string>
|
||||
<string name="lng_author">Programer: Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Programer: Alexander Capehart</string>
|
||||
<string name="lbl_library_counts">Statistika zbirke</string>
|
||||
<string name="set_ui">Izgled</string>
|
||||
<string name="set_theme_day">Svjetla</string>
|
||||
|
|
|
@ -170,7 +170,7 @@
|
|||
<string name="lbl_save">Ment</string>
|
||||
<string name="lbl_reset">Alaphelyzet</string>
|
||||
<string name="lbl_state_wiped">Állapot törölve</string>
|
||||
<string name="lng_author">Fejlesztő Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Fejlesztő Alexander Capehart</string>
|
||||
<string name="set_play_song_from_all">Lejátszás az összes dalból</string>
|
||||
<string name="set_play_song_from_genre">Lejátszás műfajból</string>
|
||||
<string name="set_content">Tartalom</string>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
<string name="lbl_disc">Disk</string>
|
||||
<string name="lbl_song_detail">Lihat properti</string>
|
||||
<string name="lbl_format">Format</string>
|
||||
<string name="lng_author">Dikembangkan oleh Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Dikembangkan oleh Alexander Capehart</string>
|
||||
<string name="lbl_library_counts">Statistik pustaka</string>
|
||||
<string name="set_notif_action">Tindakan notifikasi khusus</string>
|
||||
<string name="lbl_shuffle_shortcut_short">Acak</string>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<string name="lbl_version">Versione</string>
|
||||
<string name="lbl_code">Codice sorgente</string>
|
||||
<string name="lbl_licenses">Licenze</string>
|
||||
<string name="lng_author">Sviluppato da Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Sviluppato da Alexander Capehart</string>
|
||||
<string name="lbl_library_counts">Statistiche libreria</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Opzioni</string>
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
<string name="lng_indexing">ספריית המוזיקה שלך נטענת…</string>
|
||||
<string name="lng_observing">ספריית המוזיקה שלך נסרקת לאיתור שינויים…</string>
|
||||
<string name="lng_queue_added">התווסף לתור</string>
|
||||
<string name="lng_author">מפותח על ידי אלכסנדר קייפהארט</string>
|
||||
<string name="lbl_author_name">מפותח על ידי אלכסנדר קייפהארט</string>
|
||||
<string name="lng_search_library">חיפוש בספרייה שלך…</string>
|
||||
<string name="set_ui">מראה ותחושה</string>
|
||||
<string name="set_ui_desc">שינוי ערכת הנושא והצבעים של היישום</string>
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
<string name="lbl_album_details">アルバムに移動</string>
|
||||
<string name="lbl_props">曲のプロパティ</string>
|
||||
<string name="lng_queue_added">再生待ちに追加</string>
|
||||
<string name="lng_author">開発者 アレクサンダー・ケイプハート (Alexander Capehart)</string>
|
||||
<string name="lbl_author_name">開発者 アレクサンダー・ケイプハート (Alexander Capehart)</string>
|
||||
<string name="desc_artist_image">%s のアーティスト画像</string>
|
||||
<string name="lbl_compilations">オムニバス</string>
|
||||
<string name="lbl_compilation">オムニバス</string>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<string name="lbl_version">버전</string>
|
||||
<string name="lbl_code">소스 코드</string>
|
||||
<string name="lbl_licenses">라이선스</string>
|
||||
<string name="lng_author">Alexander Capehart가 개발</string>
|
||||
<string name="lbl_author_name">Alexander Capehart가 개발</string>
|
||||
<string name="lbl_library_counts">라이브러리 통계</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">설정</string>
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
<string name="lbl_live_group">Gyvai</string>
|
||||
<string name="set_headset_autoplay_desc">Visada pradėti groti, kai ausinės yra prijungtos (gali neveikti visuose įrenginiuose)</string>
|
||||
<string name="cdc_ogg">Ogg garsas</string>
|
||||
<string name="lng_author">Sukūrė Alexanderis Capehartas (angl. Alexander Capehart)</string>
|
||||
<string name="lbl_author_name">Sukūrė Alexanderis Capehartas (angl. Alexander Capehart)</string>
|
||||
<string name="set_replay_gain_mode_track">Pageidauti takelį</string>
|
||||
<string name="err_no_dirs">Jokių aplankų</string>
|
||||
<string name="err_bad_dir">Šis aplankas nepalaikomas</string>
|
||||
|
|
|
@ -202,7 +202,7 @@
|
|||
<string name="lbl_track">Spor</string>
|
||||
<string name="lbl_date_added">Dato tillagt</string>
|
||||
<string name="lbl_sort">Sorter</string>
|
||||
<string name="lng_author">Utviklet av Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Utviklet av Alexander Capehart</string>
|
||||
<string name="lng_search_library">Søk i biblioteket ditt …</string>
|
||||
<string name="set_root_title">Innstillinger</string>
|
||||
<string name="lng_playlist_created">Spilleliste opprettet</string>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<string name="lbl_version">Versie</string>
|
||||
<string name="lbl_code">Broncode</string>
|
||||
<string name="lbl_licenses">Licenties</string>
|
||||
<string name="lng_author">Ontwikkeld door Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Ontwikkeld door Alexander Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Instellingen</string>
|
||||
<string name="set_ui">Uiterlijk en gevoel</string>
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
<string name="lng_widget">ਸੰਗੀਤ ਪਲੇਬੈਕ ਵੇਖੋ ਅਤੇ ਕੰਟਰੋਲ ਕਰੋ</string>
|
||||
<string name="lng_indexing">ਤੁਹਾਡੀ ਸੰਗੀਤ ਲਾਇਬ੍ਰੇਰੀ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…</string>
|
||||
<string name="lng_queue_added">ਕਤਾਰ ਵਿੱਚ ਸ਼ਾਮਿਲ ਕੀਤਾ</string>
|
||||
<string name="lng_author">ਅਲੈਗਜ਼ੈਂਡਰ ਕੇਪਹਾਰਟ ਦੁਆਰਾ ਵਿਕਸਿਤ</string>
|
||||
<string name="lbl_author_name">ਅਲੈਗਜ਼ੈਂਡਰ ਕੇਪਹਾਰਟ ਦੁਆਰਾ ਵਿਕਸਿਤ</string>
|
||||
<string name="lng_search_library">ਆਪਣੀ ਲਾਇਬ੍ਰੇਰੀ ਖੋਜੋ…</string>
|
||||
<string name="set_root_title">ਸੈਟਿੰਗਾਂ</string>
|
||||
<string name="set_ui">ਦਿੱਖ ਅਤੇ ਛੋਹ</string>
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
<string name="lbl_mix">DJ Mix</string>
|
||||
<string name="desc_skip_prev">Przejdź do ostatniego utworu</string>
|
||||
<string name="desc_skip_next">Przejdź do następnego utworu</string>
|
||||
<string name="lng_author">Autorstwa Alexandra Capeharta</string>
|
||||
<string name="lbl_author_name">Autorstwa Alexandra Capeharta</string>
|
||||
<string name="set_round_mode">Zaokrąglone krawędzie</string>
|
||||
<string name="set_round_mode_desc">Włącz zaokrąglone rogi na dodatkowych elementach interfejsu (wymaga zaokrąglenia okładek albumów)</string>
|
||||
<string name="set_bar_action">Akcja na pasku odtwarzania</string>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<string name="lbl_version">Versão</string>
|
||||
<string name="lbl_code">Código-fonte</string>
|
||||
<string name="lbl_licenses">Licenças</string>
|
||||
<string name="lng_author">Desenvolvido por Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Desenvolvido por Alexander Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Configurações</string>
|
||||
<string name="set_ui">Visualização e Aparência</string>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<string name="lbl_version">Versão</string>
|
||||
<string name="lbl_code">Código fonte</string>
|
||||
<string name="lbl_licenses">Licenças</string>
|
||||
<string name="lng_author">Desenvolvido por Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Desenvolvido por Alexander Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Definições</string>
|
||||
<string name="set_ui">Aparência</string>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<string name="lbl_version">Versiune</string>
|
||||
<string name="lbl_code">Cod sursă</string>
|
||||
<string name="lbl_licenses">Licențe</string>
|
||||
<string name="lng_author">Dezvoltat de Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Dezvoltat de Alexander Capehart</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Setări</string>
|
||||
<string name="set_ui">Aspect și caracteristici</string>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<string name="lbl_version">Версия</string>
|
||||
<string name="lbl_code">Исходный код</string>
|
||||
<string name="lbl_licenses">Лицензии</string>
|
||||
<string name="lng_author">Разработано Александром Кейпхартом</string>
|
||||
<string name="lbl_author_name">Разработано Александром Кейпхартом</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">Настройки</string>
|
||||
<string name="set_ui">Внешний вид</string>
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
<string name="set_music">Glasba</string>
|
||||
<string name="err_bad_dir">Ta mapa ni podprta</string>
|
||||
<string name="set_restore_desc">Obnovi prej shranjeno stanje predvajanja (če obstaja)</string>
|
||||
<string name="lng_author">Razvil Alexander Capehart</string>
|
||||
<string name="lbl_author_name">Razvil Alexander Capehart</string>
|
||||
<string name="desc_music_dir_delete">Odstrani mapo</string>
|
||||
<string name="lbl_copied">Kopirano</string>
|
||||
<string name="err_index_failed">Nalaganje glasbe ni uspelo</string>
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
<string name="lbl_library_counts">Statistik över beroende</string>
|
||||
<string name="lng_playlist_renamed">Byt namn av spellista</string>
|
||||
<string name="lng_playlist_deleted">Spellista tog bort</string>
|
||||
<string name="lng_author">Utvecklad av Alexander Capeheart</string>
|
||||
<string name="lbl_author_name">Utvecklad av Alexander Capeheart</string>
|
||||
<string name="set_theme">Tema</string>
|
||||
<string name="set_theme_night">Mörkt</string>
|
||||
<string name="set_accent">Färgschema</string>
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
<string name="lbl_date">Yıl</string>
|
||||
<string name="lbl_duration">Süre</string>
|
||||
<string name="lbl_state_saved">Durum kaydedildi</string>
|
||||
<string name="lng_author">Alexander Capehart tarafından geliştirildi</string>
|
||||
<string name="lbl_author_name">Alexander Capehart tarafından geliştirildi</string>
|
||||
<string name="set_black_mode">Siyah tema</string>
|
||||
<string name="lbl_library_counts">Kitaplık istatistikleri</string>
|
||||
<string name="set_black_mode_desc">Kapkara koyu tema kullan</string>
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
<string name="lbl_ep_live">Концертний мініальбом</string>
|
||||
<string name="lbl_library_counts">Статистика бібліотеки</string>
|
||||
<string name="lng_indexing">Завантаження музичної бібліотеки…</string>
|
||||
<string name="lng_author">Розроблено Олександром Кейпхартом</string>
|
||||
<string name="lbl_author_name">Розроблено Олександром Кейпхартом</string>
|
||||
<string name="fmt_lib_artist_count">Завантажено виконавців: %d</string>
|
||||
<string name="set_theme_auto">Автоматично</string>
|
||||
<string name="set_accent">Кольоровий акцент</string>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<string name="lbl_version">版本</string>
|
||||
<string name="lbl_code">源代码</string>
|
||||
<string name="lbl_licenses">许可证</string>
|
||||
<string name="lng_author">由 Alexander Capehart 开发</string>
|
||||
<string name="lbl_author_name">由 Alexander Capehart 开发</string>
|
||||
<!-- Settings namespace | Settings-related labels -->
|
||||
<string name="set_root_title">设置</string>
|
||||
<string name="set_ui">外观和感觉</string>
|
||||
|
|
|
@ -146,6 +146,8 @@
|
|||
<string name="lbl_size">Size</string>
|
||||
<string name="lbl_bitrate">Bit rate</string>
|
||||
<string name="lbl_sample_rate">Sample rate</string>
|
||||
<string name="lbl_replaygain_track">ReplayGain Track Adjustment</string>
|
||||
<string name="lbl_replaygain_album">ReplayGain Album Adjustment</string>
|
||||
|
||||
<!-- Limit to 10 characters -->
|
||||
<string name="lbl_shuffle_shortcut_short">Shuffle</string>
|
||||
|
@ -189,6 +191,11 @@
|
|||
<!-- As in to report an error -->
|
||||
<string name="lbl_report">Report</string>
|
||||
|
||||
<string name="lbl_author">Author</string>
|
||||
<string name="lbl_author_name">Alexander Capehart</string>
|
||||
<string name="lbl_donate">Donate</string>
|
||||
<string name="lbl_supporters">Supporters</string>
|
||||
|
||||
<!-- Long Namespace | Longer Descriptions -->
|
||||
<eat-comment />
|
||||
|
||||
|
@ -202,7 +209,7 @@
|
|||
<string name="lng_playlist_exported">Playlist exported</string>
|
||||
<string name="lng_playlist_deleted">Playlist deleted</string>
|
||||
<string name="lng_playlist_added">Added to playlist</string>
|
||||
<string name="lng_author">Developed by Alexander Capehart</string>
|
||||
<string name="lng_supporters_promo">Donate to the project to get your name added here!</string>
|
||||
<!-- As in music library -->
|
||||
<string name="lng_search_library">Search your library…</string>
|
||||
|
||||
|
|
3
fastlane/metadata/android/en-US/changelogs/38.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/38.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Auxio 3.3.1 adds the ability to import and export playlists, skip gestures, and fixes/improvements to the music loader.
|
||||
This release fixes a critical bug with the music loader, among other issues.
|
||||
For more information, see https://github.com/OxygenCobalt/Auxio/releases/tag/v3.3.1
|
Loading…
Reference in a new issue