Compare commits
No commits in common. "dev" and "v4.0.0-dev" have entirely different histories.
dev
...
v4.0.0-dev
247 changed files with 6316 additions and 5957 deletions
1
.github/ISSUE_TEMPLATE/bug-crash-report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug-crash-report.yml
vendored
|
@ -34,7 +34,6 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: What android version do you use?
|
label: What android version do you use?
|
||||||
options:
|
options:
|
||||||
- Android 15
|
|
||||||
- Android 14
|
- Android 14
|
||||||
- Android 13
|
- Android 13
|
||||||
- Android 12L
|
- Android 12L
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -14,5 +14,3 @@ captures/
|
||||||
*.iml
|
*.iml
|
||||||
.cxx
|
.cxx
|
||||||
.kotlin
|
.kotlin
|
||||||
.aider*
|
|
||||||
.env
|
|
||||||
|
|
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -5,4 +5,4 @@
|
||||||
[submodule "musikr/src/main/cpp/taglib"]
|
[submodule "musikr/src/main/cpp/taglib"]
|
||||||
path = musikr/src/main/cpp/taglib
|
path = musikr/src/main/cpp/taglib
|
||||||
url = https://github.com/taglib/taglib.git
|
url = https://github.com/taglib/taglib.git
|
||||||
tag = ee1931b
|
tag = v2.0.2
|
||||||
|
|
52
CHANGELOG.md
52
CHANGELOG.md
|
@ -1,52 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 4.0.3
|
|
||||||
|
|
||||||
#### What's Improved
|
|
||||||
- Improved music loader pipeline efficiency
|
|
||||||
- Made cover.png support more flexible
|
|
||||||
- Albums with the same name but different album artists are now split
|
|
||||||
if fully tagged with album artists
|
|
||||||
|
|
||||||
#### What's Fixed
|
|
||||||
- Possibly fixed cache failures on large libraries
|
|
||||||
- Possibly fixed playback state saving failing on some devices
|
|
||||||
- Fixed issue where artists w/o songs would not have a cover
|
|
||||||
- Fixed music not being reloaded when music locations changed
|
|
||||||
- Fixed tasker media control not working
|
|
||||||
- Fixed tasker playback start command never finishing
|
|
||||||
|
|
||||||
#### Dev/Meta
|
|
||||||
- Removed useless storage permissions
|
|
||||||
- Internal cleanup/simplification of musikr API
|
|
||||||
- Removed unused resources
|
|
||||||
|
|
||||||
#### What's Fixed
|
|
||||||
|
|
||||||
## 4.0.2
|
|
||||||
|
|
||||||
#### What's New
|
|
||||||
- Added back in support for cover art from cover.png/cover.jpg
|
|
||||||
- Added "As is" cover art setting
|
|
||||||
- Option to include hidden files or not (off by default)
|
|
||||||
|
|
||||||
#### What's Improved
|
|
||||||
- Reduced elevation contrast in black theme
|
|
||||||
|
|
||||||
#### What's Fixed
|
|
||||||
- Fixed incorrect extension stripping on some files
|
|
||||||
- Fixed various errors in new branding
|
|
||||||
- Fixed MTE segfault from improper string handling
|
|
||||||
|
|
||||||
#### What's Changed
|
|
||||||
- Hidden files no longer loaded by default
|
|
||||||
|
|
||||||
## 4.0.1
|
|
||||||
|
|
||||||
#### What's Fixed
|
|
||||||
- Fixed music loading hanging on files without tags
|
|
||||||
- Fixed playlists being destroyed in poorly tagged libraries
|
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
#### What's New
|
#### What's New
|
||||||
|
@ -70,7 +23,6 @@ if fully tagged with album artists
|
||||||
- M3U playlist file name is now proposed if one cannot be found within the file
|
- M3U playlist file name is now proposed if one cannot be found within the file
|
||||||
- Duration is now parsed from certain files that previously could not be parsed
|
- Duration is now parsed from certain files that previously could not be parsed
|
||||||
- ID3v2 tags are now parsed from WAV files
|
- ID3v2 tags are now parsed from WAV files
|
||||||
- NN/TT tracks/discs are now handled in Vorbis
|
|
||||||
- Music library will is less likely to fail to respond to updates
|
- Music library will is less likely to fail to respond to updates
|
||||||
- Hidden audio files can now be loaded
|
- Hidden audio files can now be loaded
|
||||||
- Sorting songs by date now uses songs date first, before the earliest album date
|
- Sorting songs by date now uses songs date first, before the earliest album date
|
||||||
|
@ -82,15 +34,11 @@ if fully tagged with album artists
|
||||||
- Fixed playback sheet flickering on warm start
|
- Fixed playback sheet flickering on warm start
|
||||||
- No longer possible to save a sort with no direction specified
|
- No longer possible to save a sort with no direction specified
|
||||||
- Fixed inconsistent corner radii in widget
|
- Fixed inconsistent corner radii in widget
|
||||||
- Possibly fixed foreground start music loading failures
|
|
||||||
- Fixed playlist view not exiting on deletion
|
|
||||||
|
|
||||||
#### What's Changed
|
#### What's Changed
|
||||||
- Date added is now local to when the app discovers the file and will not
|
- Date added is now local to when the app discovers the file and will not
|
||||||
persist long-term
|
persist long-term
|
||||||
- Songs with no album are now "Unknown album" rather than folder name
|
- Songs with no album are now "Unknown album" rather than folder name
|
||||||
- Tab layout no longer changes depending on device configuration
|
|
||||||
- Round mode is now on by default
|
|
||||||
|
|
||||||
#### Dev/Meta
|
#### Dev/Meta
|
||||||
- No longer using custom logging setup
|
- No longer using custom logging setup
|
||||||
|
|
41
README.md
41
README.md
|
@ -2,8 +2,8 @@
|
||||||
<h1 align="center"><b>Auxio</b></h1>
|
<h1 align="center"><b>Auxio</b></h1>
|
||||||
<h4 align="center">A simple, rational music player for android.</h4>
|
<h4 align="center">A simple, rational music player for android.</h4>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v4.0.4">
|
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v3.6.3">
|
||||||
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v4.0.4&color=64B5F6&style=flat">
|
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v3.6.3&color=64B5F6&style=flat">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/oxygencobalt/Auxio/releases/">
|
<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">
|
<img alt="Releases" src="https://img.shields.io/github/downloads/OxygenCobalt/Auxio/total.svg?color=4B95DE&style=flat">
|
||||||
|
@ -15,12 +15,7 @@
|
||||||
</p>
|
</p>
|
||||||
<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>
|
<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">
|
<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="250"></a>
|
<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://accrescent.app/app/org.oxycblt.auxio">
|
|
||||||
<img alt="Get it on Accrescent" src="https://accrescent.app/badges/get-it-on.png" width="250">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<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>
|
<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>
|
</p>
|
||||||
|
|
||||||
|
@ -33,12 +28,14 @@ Auxio is a local music player with a fast, reliable UI/UX without the many usele
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot0.png" width=250>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot0.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot1.png" width=250>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot1.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot2.png" width=250>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot2.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot3.png" width=250>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot3.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot4.png" width=250>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot4.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot5.png" width=250>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot5.png" width=200>
|
||||||
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot6.png" width=200>
|
||||||
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot7.png" width=200>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,39 +61,29 @@ precise/original dates, sort tags, and more
|
||||||
- Headset autoplay
|
- Headset autoplay
|
||||||
- Stylish widgets that automatically adapt to their size
|
- Stylish widgets that automatically adapt to their size
|
||||||
- Completely private and offline
|
- Completely private and offline
|
||||||
- No rounded album covers (if you want them)
|
- No rounded album covers (by default)
|
||||||
|
|
||||||
## Permissions
|
## Permissions
|
||||||
|
|
||||||
- Storage (`READ_MEDIA_AUDIO`, `READ_EXTERNAL_STORAGE`) to read and play your music files
|
- 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
|
- Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`) to keep the music playing in the background
|
||||||
- Notifications (`POST_NOTIFICATION`) to indicate ongoing playback and music loading
|
- Notifcations (`POST_NOTIFICATION`) to indicate ongoing playback and music loading
|
||||||
|
|
||||||
## Donate
|
## 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 the app itself!
|
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 the app itself!
|
||||||
|
|
||||||
<p align="center"><b>$16/month supporters:</b></p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://github.com/mark-pitblado"><img src="https://avatars.githubusercontent.com/u/86988982?v=4" width=75 /></a>
|
|
||||||
<br/>
|
|
||||||
<a href="https://github.com/mark-pitblado"><b>Mark Pitblado</b></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center"><b>$8/month supporters:</b></p>
|
<p align="center"><b>$8/month supporters:</b></p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/alanorth"><img src="https://avatars.githubusercontent.com/u/191754?v=4" width=50 /></a>
|
<a href="https://github.com/alanorth"><img src="https://avatars.githubusercontent.com/u/191754?v=4" width=50 /></a>
|
||||||
<a href="https://github.com/dmint789"><img src="https://avatars.githubusercontent.com/u/53250435?v=4" width=50 /></a>
|
<a href="https://github.com/dmint789"><img src="https://avatars.githubusercontent.com/u/53250435?v=4" width=50 /></a>
|
||||||
<a href="https://github.com/adventure-tense"><img src="https://avatars.githubusercontent.com/u/123326084?v=4" width=50 /></a>
|
<a href="https://github.com/adventure-tense"><img src="https://avatars.githubusercontent.com/u/123326084?v=4" width=50 /></a>
|
||||||
<a href="https://github.com/slushspirit"><img src="https://avatars.githubusercontent.com/u/95902378?v=4" width=50 /></a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Auxio relies on a patched version of Media3 that enables some extra playback features, alongside taglib for metadata
|
Auxio relies on a custom version of Media3 that enables some extra features. This adds some caveats to the build process:
|
||||||
parsing. This adds some caveats to the build process:
|
|
||||||
1. `cmake` and `ninja-build` must be installed before building the project.
|
1. `cmake` and `ninja-build` must be installed before building the project.
|
||||||
2. The project uses submodules, so when cloning initially, use `git clone --recurse-submodules` to properly
|
2. The project uses submodules, so when cloning initially, use `git clone --recurse-submodules` to properly
|
||||||
download the external code.
|
download the external code.
|
||||||
|
|
|
@ -18,8 +18,8 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId namespace
|
applicationId namespace
|
||||||
versionName "4.0.4"
|
versionName "4.0.0-dev"
|
||||||
versionCode 63
|
versionCode 54
|
||||||
|
|
||||||
minSdk min_sdk
|
minSdk min_sdk
|
||||||
targetSdk target_sdk
|
targetSdk target_sdk
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<!-- Android 13 uses READ_MEDIA_AUDIO instead of READ_EXTERNAL_STORAGE -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||||
|
|
BIN
app/src/main/ic_launcher-playstore.png
Normal file
BIN
app/src/main/ic_launcher-playstore.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -1309,6 +1309,7 @@ public class BackportBottomSheetBehavior<V extends View> extends CoordinatorLayo
|
||||||
+ " should not be set externally.");
|
+ " should not be set externally.");
|
||||||
}
|
}
|
||||||
if (!hideable && state == STATE_HIDDEN) {
|
if (!hideable && state == STATE_HIDDEN) {
|
||||||
|
Log.w(TAG, "Cannot set state: " + state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int finalState;
|
final int finalState;
|
||||||
|
@ -1632,13 +1633,12 @@ public class BackportBottomSheetBehavior<V extends View> extends CoordinatorLayo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BackEventCompat backEvent = bottomContainerBackHelper.onHandleBackInvoked();
|
BackEventCompat backEvent = bottomContainerBackHelper.onHandleBackInvoked();
|
||||||
boolean canActuallyHide = hideable && isHideableWhenDragging();
|
|
||||||
if (backEvent == null || VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
if (backEvent == null || VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
// If using traditional button system nav or if pre-U, just hide or collapse the bottom sheet.
|
// If using traditional button system nav or if pre-U, just hide or collapse the bottom sheet.
|
||||||
setState(canActuallyHide ? STATE_HIDDEN : STATE_COLLAPSED);
|
setState(hideable ? STATE_HIDDEN : STATE_COLLAPSED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (canActuallyHide) {
|
if (hideable && isHideableWhenDragging()) {
|
||||||
bottomContainerBackHelper.finishBackProgressNotPersistent(
|
bottomContainerBackHelper.finishBackProgressNotPersistent(
|
||||||
backEvent,
|
backEvent,
|
||||||
new AnimatorListenerAdapter() {
|
new AnimatorListenerAdapter() {
|
||||||
|
|
|
@ -36,7 +36,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.music.service.MusicServiceFragment
|
import org.oxycblt.auxio.music.service.MusicServiceFragment
|
||||||
import org.oxycblt.auxio.playback.service.PlaybackServiceFragment
|
import org.oxycblt.auxio.playback.service.PlaybackServiceFragment
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class AuxioService :
|
class AuxioService :
|
||||||
|
@ -54,30 +53,24 @@ class AuxioService :
|
||||||
musicFragment = musicFragmentFactory.create(this, this, this)
|
musicFragment = musicFragmentFactory.create(this, this, this)
|
||||||
sessionToken = playbackFragment.attach()
|
sessionToken = playbackFragment.attach()
|
||||||
musicFragment.attach()
|
musicFragment.attach()
|
||||||
Timber.d("Service Created")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
// TODO: Start command occurring from a foreign service basically implies a detached
|
// TODO: Start command occurring from a foreign service basically implies a detached
|
||||||
// service, we might need more handling here.
|
// service, we might need more handling here.
|
||||||
super.onStartCommand(intent, flags, startId)
|
|
||||||
onHandleForeground(intent)
|
onHandleForeground(intent)
|
||||||
// If we die we want to not restart, we will immediately try to foreground in and just
|
return super.onStartCommand(intent, flags, startId)
|
||||||
// fail to start again since the activity will be dead too. This is not the semantically
|
|
||||||
// "correct" flag (normally you want START_STICKY for playback) but we need this to avoid
|
|
||||||
// weird foreground errors.
|
|
||||||
return START_NOT_STICKY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
val binder = super.onBind(intent)
|
|
||||||
onHandleForeground(intent)
|
onHandleForeground(intent)
|
||||||
return binder
|
return super.onBind(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onHandleForeground(intent: Intent?) {
|
private fun onHandleForeground(intent: Intent?) {
|
||||||
|
val startId = intent?.getIntExtra(INTENT_KEY_START_ID, -1) ?: -1
|
||||||
musicFragment.start()
|
musicFragment.start()
|
||||||
playbackFragment.start(intent)
|
playbackFragment.start(startId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
|
@ -141,7 +134,6 @@ class AuxioService :
|
||||||
}
|
}
|
||||||
// Nothing changed, but don't show anything music related since we can always
|
// Nothing changed, but don't show anything music related since we can always
|
||||||
// index during playback.
|
// index during playback.
|
||||||
isForeground = true
|
|
||||||
} else {
|
} else {
|
||||||
musicFragment.createNotification {
|
musicFragment.createNotification {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
|
|
|
@ -65,8 +65,6 @@ object IntegerTable {
|
||||||
const val START_ID_ACTIVITY = 0xA050
|
const val START_ID_ACTIVITY = 0xA050
|
||||||
/** Tasker AuxioService Start ID */
|
/** Tasker AuxioService Start ID */
|
||||||
const val START_ID_TASKER = 0xA051
|
const val START_ID_TASKER = 0xA051
|
||||||
/** MediaButtonReceiver AuxioService Start ID */
|
|
||||||
const val START_ID_MEDIA_BUTTON = 0xA052
|
|
||||||
/** RepeatMode.NONE */
|
/** RepeatMode.NONE */
|
||||||
const val REPEAT_MODE_NONE = 0xA100
|
const val REPEAT_MODE_NONE = 0xA100
|
||||||
/** RepeatMode.ALL */
|
/** RepeatMode.ALL */
|
||||||
|
@ -143,6 +141,4 @@ object IntegerTable {
|
||||||
const val PLAY_SONG_BY_ITSELF = 0xA124
|
const val PLAY_SONG_BY_ITSELF = 0xA124
|
||||||
/** CoverMode.SaveSpace */
|
/** CoverMode.SaveSpace */
|
||||||
const val COVER_MODE_SAVE_SPACE = 0xA125
|
const val COVER_MODE_SAVE_SPACE = 0xA125
|
||||||
/** CoverMode.AsIs */
|
|
||||||
const val COVER_MODE_AS_IS = 0xA126
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio
|
package org.oxycblt.auxio
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
|
@ -26,7 +27,6 @@ import androidx.activity.BackEventCompat
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.isInvisible
|
import androidx.core.view.isInvisible
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
@ -257,9 +257,9 @@ class MainFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreDraw(): Boolean {
|
override fun onPreDraw(): Boolean {
|
||||||
// This is where I shove literally all the UI logic that won't behave any callback
|
// TODO: Due to draw caching even *this* isn't effective enough to avoid the bottom
|
||||||
// or "normal" method I've tried. Surely running this on every frame will actually cause
|
// sheets continually getting stuck. I need something with even more frequent updates,
|
||||||
// it to work properly!
|
// or otherwise bottom sheets get stuck.
|
||||||
|
|
||||||
// We overload CoordinatorLayout far too much to rely on any of it's typical
|
// We overload CoordinatorLayout far too much to rely on any of it's typical
|
||||||
// listener functionality. Just update all transitions before every draw. Should
|
// listener functionality. Just update all transitions before every draw. Should
|
||||||
|
@ -367,10 +367,6 @@ class MainFragment :
|
||||||
requireNotNull(sheetBackCallback) { "SheetBackPressedCallback was not available" }
|
requireNotNull(sheetBackCallback) { "SheetBackPressedCallback was not available" }
|
||||||
.invalidateEnabled()
|
.invalidateEnabled()
|
||||||
|
|
||||||
// Stop the FrameLayout containing the fabs from eating touch events elsewhere
|
|
||||||
binding.mainFabContainer.isVisible =
|
|
||||||
binding.homeNewPlaylistFab.mainFab.isVisible || binding.homeShuffleFab.isVisible
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,6 +509,8 @@ class MainFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var scrimAnimator: ValueAnimator? = null
|
||||||
|
|
||||||
private fun updateSpeedDial(open: Boolean) {
|
private fun updateSpeedDial(open: Boolean) {
|
||||||
requireNotNull(speedDialBackCallback) { "SpeedDialBackPressedCallback was not available" }
|
requireNotNull(speedDialBackCallback) { "SpeedDialBackPressedCallback was not available" }
|
||||||
.invalidateEnabled(open)
|
.invalidateEnabled(open)
|
||||||
|
|
|
@ -22,7 +22,6 @@ import android.os.Bundle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentDetailBinding
|
import org.oxycblt.auxio.databinding.FragmentDetailBinding
|
||||||
|
@ -299,11 +298,6 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
|
||||||
// RecyclerView will scroll assuming it has the total height of the screen (i.e a
|
// RecyclerView will scroll assuming it has the total height of the screen (i.e a
|
||||||
// collapsed appbar), so we need to collapse the appbar if that's the case.
|
// collapsed appbar), so we need to collapse the appbar if that's the case.
|
||||||
binding.detailAppbar.setExpanded(false)
|
binding.detailAppbar.setExpanded(false)
|
||||||
if (!binding.detailRecycler.canScroll()) {
|
|
||||||
// Don't scroll if the RecyclerView goes off screen. If we go anyway, overscroll
|
|
||||||
// kicks in and creates a weird bounce effect.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
binding.detailRecycler.post {
|
binding.detailRecycler.post {
|
||||||
// Use a custom smooth scroller that will settle the item in the middle of
|
// Use a custom smooth scroller that will settle the item in the middle of
|
||||||
// the screen rather than the end.
|
// the screen rather than the end.
|
||||||
|
@ -329,6 +323,4 @@ class AlbumDetailFragment : DetailFragment<Album, Song>() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RecyclerView.canScroll() = computeVerticalScrollRange() > height
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ sealed interface ArtistShowChoices {
|
||||||
val uid: Music.UID
|
val uid: Music.UID
|
||||||
/** The current [Artist] choices. */
|
/** The current [Artist] choices. */
|
||||||
val choices: List<Artist>
|
val choices: List<Artist>
|
||||||
/** Sanitize this instance with a [Library]. */
|
/** Sanitize this instance with a [DeviceLibrary]. */
|
||||||
fun sanitize(newLibrary: Library): ArtistShowChoices?
|
fun sanitize(newLibrary: Library): ArtistShowChoices?
|
||||||
|
|
||||||
/** Backing implementation of [ArtistShowChoices] that is based on a [Song]. */
|
/** Backing implementation of [ArtistShowChoices] that is based on a [Song]. */
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.oxycblt.auxio.ui
|
package org.oxycblt.auxio.home
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
@ -40,6 +40,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||||
|
// Prevent excessive layouts by using translation instead of padding.
|
||||||
updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
|
updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
|
||||||
return insets
|
return insets
|
||||||
}
|
}
|
|
@ -24,11 +24,9 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.viewModels
|
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.DialogErrorDetailsBinding
|
import org.oxycblt.auxio.databinding.DialogErrorDetailsBinding
|
||||||
import org.oxycblt.auxio.music.MusicViewModel
|
|
||||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||||
import org.oxycblt.auxio.util.getSystemServiceCompat
|
import org.oxycblt.auxio.util.getSystemServiceCompat
|
||||||
import org.oxycblt.auxio.util.openInBrowser
|
import org.oxycblt.auxio.util.openInBrowser
|
||||||
|
@ -44,12 +42,10 @@ import org.oxycblt.auxio.util.showToast
|
||||||
class ErrorDetailsDialog : ViewBindingMaterialDialogFragment<DialogErrorDetailsBinding>() {
|
class ErrorDetailsDialog : ViewBindingMaterialDialogFragment<DialogErrorDetailsBinding>() {
|
||||||
private val args: ErrorDetailsDialogArgs by navArgs()
|
private val args: ErrorDetailsDialogArgs by navArgs()
|
||||||
private var clipboardManager: ClipboardManager? = null
|
private var clipboardManager: ClipboardManager? = null
|
||||||
private val musicModel: MusicViewModel by viewModels()
|
|
||||||
|
|
||||||
override fun onConfigDialog(builder: AlertDialog.Builder) {
|
override fun onConfigDialog(builder: AlertDialog.Builder) {
|
||||||
builder
|
builder
|
||||||
.setTitle(R.string.lbl_error_info)
|
.setTitle(R.string.lbl_error_info)
|
||||||
.setNeutralButton(R.string.lbl_retry) { _, _ -> musicModel.refresh() }
|
|
||||||
.setPositiveButton(R.string.lbl_report) { _, _ ->
|
.setPositiveButton(R.string.lbl_report) { _, _ ->
|
||||||
requireContext().openInBrowser(LINK_ISSUES)
|
requireContext().openInBrowser(LINK_ISSUES)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,12 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Method
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentHomeBinding
|
import org.oxycblt.auxio.databinding.FragmentHomeBinding
|
||||||
|
@ -51,7 +53,7 @@ import org.oxycblt.auxio.home.list.ArtistListFragment
|
||||||
import org.oxycblt.auxio.home.list.GenreListFragment
|
import org.oxycblt.auxio.home.list.GenreListFragment
|
||||||
import org.oxycblt.auxio.home.list.PlaylistListFragment
|
import org.oxycblt.auxio.home.list.PlaylistListFragment
|
||||||
import org.oxycblt.auxio.home.list.SongListFragment
|
import org.oxycblt.auxio.home.list.SongListFragment
|
||||||
import org.oxycblt.auxio.home.tabs.NamedTabStrategy
|
import org.oxycblt.auxio.home.tabs.AdaptiveTabStrategy
|
||||||
import org.oxycblt.auxio.home.tabs.Tab
|
import org.oxycblt.auxio.home.tabs.Tab
|
||||||
import org.oxycblt.auxio.list.ListViewModel
|
import org.oxycblt.auxio.list.ListViewModel
|
||||||
import org.oxycblt.auxio.list.SelectionFragment
|
import org.oxycblt.auxio.list.SelectionFragment
|
||||||
|
@ -66,6 +68,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.util.collect
|
import org.oxycblt.auxio.util.collect
|
||||||
import org.oxycblt.auxio.util.collectImmediately
|
import org.oxycblt.auxio.util.collectImmediately
|
||||||
import org.oxycblt.auxio.util.lazyReflectedField
|
import org.oxycblt.auxio.util.lazyReflectedField
|
||||||
|
import org.oxycblt.auxio.util.lazyReflectedMethod
|
||||||
import org.oxycblt.auxio.util.navigateSafe
|
import org.oxycblt.auxio.util.navigateSafe
|
||||||
import org.oxycblt.auxio.util.showToast
|
import org.oxycblt.auxio.util.showToast
|
||||||
import org.oxycblt.musikr.IndexingProgress
|
import org.oxycblt.musikr.IndexingProgress
|
||||||
|
@ -91,6 +94,7 @@ class HomeFragment :
|
||||||
private var storagePermissionLauncher: ActivityResultLauncher<String>? = null
|
private var storagePermissionLauncher: ActivityResultLauncher<String>? = null
|
||||||
private var getContentLauncher: ActivityResultLauncher<String>? = null
|
private var getContentLauncher: ActivityResultLauncher<String>? = null
|
||||||
private var pendingImportTarget: Playlist? = null
|
private var pendingImportTarget: Playlist? = null
|
||||||
|
private var lastUpdateTime = -1L
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -266,7 +270,9 @@ class HomeFragment :
|
||||||
|
|
||||||
// Set up the mapping between the ViewPager and TabLayout.
|
// Set up the mapping between the ViewPager and TabLayout.
|
||||||
TabLayoutMediator(
|
TabLayoutMediator(
|
||||||
binding.homeTabs, binding.homePager, NamedTabStrategy(homeModel.currentTabTypes))
|
binding.homeTabs,
|
||||||
|
binding.homePager,
|
||||||
|
AdaptiveTabStrategy(requireContext(), homeModel.currentTabTypes))
|
||||||
.attach()
|
.attach()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,5 +514,11 @@ class HomeFragment :
|
||||||
private companion object {
|
private companion object {
|
||||||
val VP_RECYCLER_FIELD: Field by lazyReflectedField(ViewPager2::class, "mRecyclerView")
|
val VP_RECYCLER_FIELD: Field by lazyReflectedField(ViewPager2::class, "mRecyclerView")
|
||||||
val RV_TOUCH_SLOP_FIELD: Field by lazyReflectedField(RecyclerView::class, "mTouchSlop")
|
val RV_TOUCH_SLOP_FIELD: Field by lazyReflectedField(RecyclerView::class, "mTouchSlop")
|
||||||
|
val FAB_HIDE_FROM_USER_FIELD: Method by
|
||||||
|
lazyReflectedMethod(
|
||||||
|
FloatingActionButton::class,
|
||||||
|
"hide",
|
||||||
|
FloatingActionButton.OnVisibilityChangedListener::class,
|
||||||
|
Boolean::class)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,8 +190,6 @@ class ThemedSpeedDialView : SpeedDialView {
|
||||||
val overlayColor = surfaceColor.defaultColor.withModulatedAlpha(0.87f)
|
val overlayColor = surfaceColor.defaultColor.withModulatedAlpha(0.87f)
|
||||||
overlayLayout.setBackgroundColor(overlayColor)
|
overlayLayout.setBackgroundColor(overlayColor)
|
||||||
}
|
}
|
||||||
// Fix default margins added by library
|
|
||||||
(mainFab.layoutParams as LayoutParams).setMargins(0, 0, 0, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Int.withModulatedAlpha(
|
private fun Int.withModulatedAlpha(
|
||||||
|
@ -232,24 +230,13 @@ class ThemedSpeedDialView : SpeedDialView {
|
||||||
return super.addActionItem(actionItem, position, animate)?.apply {
|
return super.addActionItem(actionItem, position, animate)?.apply {
|
||||||
fab.apply {
|
fab.apply {
|
||||||
updateLayoutParams<MarginLayoutParams> {
|
updateLayoutParams<MarginLayoutParams> {
|
||||||
val rightMargin = context.getDimenPixels(R.dimen.spacing_tiny)
|
val horizontalMargin = context.getDimenPixels(R.dimen.spacing_mid_large)
|
||||||
if (position == actionItems.lastIndex) {
|
setMargins(horizontalMargin, 0, horizontalMargin, 0)
|
||||||
val bottomMargin = context.getDimenPixels(R.dimen.spacing_small)
|
|
||||||
setMargins(0, 0, rightMargin, bottomMargin)
|
|
||||||
} else {
|
|
||||||
setMargins(0, 0, rightMargin, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
useCompatPadding = false
|
useCompatPadding = false
|
||||||
}
|
}
|
||||||
|
|
||||||
labelBackground.apply {
|
labelBackground.apply {
|
||||||
updateLayoutParams<MarginLayoutParams> {
|
|
||||||
if (position == actionItems.lastIndex) {
|
|
||||||
val bottomMargin = context.getDimenPixels(R.dimen.spacing_small)
|
|
||||||
setMargins(0, 0, rightMargin, bottomMargin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
useCompatPadding = false
|
useCompatPadding = false
|
||||||
setContentPadding(spacingSmall, spacingSmall, spacingSmall, spacingSmall)
|
setContentPadding(spacingSmall, spacingSmall, spacingSmall, spacingSmall)
|
||||||
background =
|
background =
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.oxycblt.auxio.music.MusicViewModel
|
||||||
import org.oxycblt.auxio.music.resolve
|
import org.oxycblt.auxio.music.resolve
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
|
import org.oxycblt.auxio.playback.secsToMs
|
||||||
import org.oxycblt.auxio.util.collectImmediately
|
import org.oxycblt.auxio.util.collectImmediately
|
||||||
import org.oxycblt.musikr.Album
|
import org.oxycblt.musikr.Album
|
||||||
import org.oxycblt.musikr.Music
|
import org.oxycblt.musikr.Music
|
||||||
|
@ -127,7 +128,7 @@ class AlbumListFragment :
|
||||||
|
|
||||||
// Last added -> Format as date
|
// Last added -> Format as date
|
||||||
is Sort.Mode.ByDateAdded -> {
|
is Sort.Mode.ByDateAdded -> {
|
||||||
val dateAddedMillis = album.addedMs
|
val dateAddedMillis = album.dateAdded.secsToMs()
|
||||||
formatterSb.setLength(0)
|
formatterSb.setLength(0)
|
||||||
DateUtils.formatDateRange(
|
DateUtils.formatDateRange(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.oxycblt.auxio.music.MusicViewModel
|
||||||
import org.oxycblt.auxio.music.resolve
|
import org.oxycblt.auxio.music.resolve
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.formatDurationMs
|
import org.oxycblt.auxio.playback.formatDurationMs
|
||||||
|
import org.oxycblt.auxio.playback.secsToMs
|
||||||
import org.oxycblt.auxio.util.collectImmediately
|
import org.oxycblt.auxio.util.collectImmediately
|
||||||
import org.oxycblt.musikr.Music
|
import org.oxycblt.musikr.Music
|
||||||
import org.oxycblt.musikr.MusicParent
|
import org.oxycblt.musikr.MusicParent
|
||||||
|
@ -127,7 +128,7 @@ class SongListFragment :
|
||||||
|
|
||||||
// Last added -> Format as date
|
// Last added -> Format as date
|
||||||
is Sort.Mode.ByDateAdded -> {
|
is Sort.Mode.ByDateAdded -> {
|
||||||
val dateAddedMillis = song.addedMs
|
val dateAddedMillis = song.dateAdded.secsToMs()
|
||||||
formatterSb.setLength(0)
|
formatterSb.setLength(0)
|
||||||
DateUtils.formatDateRange(
|
DateUtils.formatDateRange(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Auxio Project
|
||||||
|
* AdaptiveTabStrategy.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.home.tabs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.music.MusicType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [TabLayoutMediator.TabConfigurationStrategy] that uses larger/smaller tab configurations
|
||||||
|
* depending on the screen configuration.
|
||||||
|
*
|
||||||
|
* @param context [Context] required to obtain window information
|
||||||
|
* @param tabs Current tab configuration from settings
|
||||||
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
|
*/
|
||||||
|
class AdaptiveTabStrategy(context: Context, private val tabs: List<MusicType>) :
|
||||||
|
TabLayoutMediator.TabConfigurationStrategy {
|
||||||
|
private val width = context.resources.configuration.smallestScreenWidthDp
|
||||||
|
|
||||||
|
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
|
||||||
|
val homeTab = tabs[position]
|
||||||
|
val icon =
|
||||||
|
when (homeTab) {
|
||||||
|
MusicType.SONGS -> R.drawable.ic_song_24
|
||||||
|
MusicType.ALBUMS -> R.drawable.ic_album_24
|
||||||
|
MusicType.ARTISTS -> R.drawable.ic_artist_24
|
||||||
|
MusicType.GENRES -> R.drawable.ic_genre_24
|
||||||
|
MusicType.PLAYLISTS -> R.drawable.ic_playlist_24
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use expected sw* size thresholds when choosing a configuration.
|
||||||
|
when {
|
||||||
|
// On small screens, only display an icon.
|
||||||
|
width < 370 -> tab.setIcon(icon).setContentDescription(homeTab.nameRes)
|
||||||
|
// On large screens, display an icon and text.
|
||||||
|
width < 600 -> tab.setText(homeTab.nameRes)
|
||||||
|
// On medium-size screens, display text.
|
||||||
|
else -> tab.setIcon(icon).setText(homeTab.nameRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,8 +29,7 @@ enum class CoverMode {
|
||||||
OFF,
|
OFF,
|
||||||
SAVE_SPACE,
|
SAVE_SPACE,
|
||||||
BALANCED,
|
BALANCED,
|
||||||
HIGH_QUALITY,
|
HIGH_QUALITY;
|
||||||
AS_IS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The integer representation of this instance.
|
* The integer representation of this instance.
|
||||||
|
@ -44,7 +43,6 @@ enum class CoverMode {
|
||||||
SAVE_SPACE -> IntegerTable.COVER_MODE_SAVE_SPACE
|
SAVE_SPACE -> IntegerTable.COVER_MODE_SAVE_SPACE
|
||||||
BALANCED -> IntegerTable.COVER_MODE_BALANCED
|
BALANCED -> IntegerTable.COVER_MODE_BALANCED
|
||||||
HIGH_QUALITY -> IntegerTable.COVER_MODE_HIGH_QUALITY
|
HIGH_QUALITY -> IntegerTable.COVER_MODE_HIGH_QUALITY
|
||||||
AS_IS -> IntegerTable.COVER_MODE_AS_IS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -61,7 +59,6 @@ enum class CoverMode {
|
||||||
IntegerTable.COVER_MODE_SAVE_SPACE -> SAVE_SPACE
|
IntegerTable.COVER_MODE_SAVE_SPACE -> SAVE_SPACE
|
||||||
IntegerTable.COVER_MODE_BALANCED -> BALANCED
|
IntegerTable.COVER_MODE_BALANCED -> BALANCED
|
||||||
IntegerTable.COVER_MODE_HIGH_QUALITY -> HIGH_QUALITY
|
IntegerTable.COVER_MODE_HIGH_QUALITY -> HIGH_QUALITY
|
||||||
IntegerTable.COVER_MODE_AS_IS -> AS_IS
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,9 @@ import android.net.Uri
|
||||||
import android.os.ParcelFileDescriptor
|
import android.os.ParcelFileDescriptor
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.image.covers.SettingCovers
|
import org.oxycblt.auxio.image.covers.SiloedCoverId
|
||||||
import org.oxycblt.musikr.covers.CoverResult
|
import org.oxycblt.auxio.image.covers.SiloedCovers
|
||||||
|
import org.oxycblt.musikr.cover.ObtainResult
|
||||||
|
|
||||||
class CoverProvider : ContentProvider() {
|
class CoverProvider : ContentProvider() {
|
||||||
override fun onCreate(): Boolean = true
|
override fun onCreate(): Boolean = true
|
||||||
|
@ -38,10 +39,12 @@ class CoverProvider : ContentProvider() {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val id = uri.lastPathSegment ?: return null
|
val id = uri.lastPathSegment ?: return null
|
||||||
|
val coverId = SiloedCoverId.parse(id) ?: return null
|
||||||
return runBlocking {
|
return runBlocking {
|
||||||
when (val result = SettingCovers.immutable(requireNotNull(context)).obtain(id)) {
|
val siloedCovers = SiloedCovers.from(requireNotNull(context), coverId.silo)
|
||||||
is CoverResult.Hit -> result.cover.fd()
|
when (val res = siloedCovers.obtain(id)) {
|
||||||
else -> null
|
is ObtainResult.Hit -> res.cover.fd()
|
||||||
|
is ObtainResult.Miss -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.Px
|
import androidx.annotation.Px
|
||||||
import androidx.core.graphics.drawable.DrawableCompat
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.view.isEmpty
|
|
||||||
import androidx.core.view.updateMarginsRelative
|
import androidx.core.view.updateMarginsRelative
|
||||||
import androidx.core.widget.ImageViewCompat
|
import androidx.core.widget.ImageViewCompat
|
||||||
import coil3.ImageLoader
|
import coil3.ImageLoader
|
||||||
|
@ -65,7 +64,7 @@ import org.oxycblt.musikr.Artist
|
||||||
import org.oxycblt.musikr.Genre
|
import org.oxycblt.musikr.Genre
|
||||||
import org.oxycblt.musikr.Playlist
|
import org.oxycblt.musikr.Playlist
|
||||||
import org.oxycblt.musikr.Song
|
import org.oxycblt.musikr.Song
|
||||||
import org.oxycblt.musikr.covers.CoverCollection
|
import org.oxycblt.musikr.cover.CoverCollection
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auxio's extension of [ImageView] that enables cover art loading and playing indicator and
|
* Auxio's extension of [ImageView] that enables cover art loading and playing indicator and
|
||||||
|
@ -173,7 +172,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
super.onFinishInflate()
|
super.onFinishInflate()
|
||||||
|
|
||||||
// The image isn't added if other children have populated the body. This is by design.
|
// The image isn't added if other children have populated the body. This is by design.
|
||||||
if (isEmpty()) {
|
if (childCount == 0) {
|
||||||
addView(image)
|
addView(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +409,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
@Px val iconSize: Int?
|
@Px val iconSize: Int?
|
||||||
) : Drawable() {
|
) : Drawable() {
|
||||||
init {
|
init {
|
||||||
// Re-tint the drawable to use the analogous "on surface" color for
|
// Re-tint the drawable to use the analogous "on surfaceg" color for
|
||||||
// StyledImageView.
|
// StyledImageView.
|
||||||
DrawableCompat.setTintList(inner, context.getColorCompat(R.color.sel_on_cover_bg))
|
DrawableCompat.setTintList(inner, context.getColorCompat(R.color.sel_on_cover_bg))
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
package org.oxycblt.auxio.image.coil
|
package org.oxycblt.auxio.image.coil
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import androidx.core.graphics.createBitmap
|
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import coil3.ImageLoader
|
import coil3.ImageLoader
|
||||||
import coil3.asImage
|
import coil3.asImage
|
||||||
|
@ -46,7 +46,7 @@ import kotlinx.coroutines.withContext
|
||||||
import okio.FileSystem
|
import okio.FileSystem
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.source
|
import okio.source
|
||||||
import org.oxycblt.musikr.covers.CoverCollection
|
import org.oxycblt.musikr.cover.CoverCollection
|
||||||
|
|
||||||
class CoverCollectionFetcher
|
class CoverCollectionFetcher
|
||||||
private constructor(
|
private constructor(
|
||||||
|
@ -90,7 +90,8 @@ private constructor(
|
||||||
val mosaicFrameSize =
|
val mosaicFrameSize =
|
||||||
Size(Dimension(mosaicSize.width / 2), Dimension(mosaicSize.height / 2))
|
Size(Dimension(mosaicSize.width / 2), Dimension(mosaicSize.height / 2))
|
||||||
|
|
||||||
val mosaicBitmap = createBitmap(mosaicSize.width, mosaicSize.height)
|
val mosaicBitmap =
|
||||||
|
Bitmap.createBitmap(mosaicSize.width, mosaicSize.height, Bitmap.Config.ARGB_8888)
|
||||||
val canvas = Canvas(mosaicBitmap)
|
val canvas = Canvas(mosaicBitmap)
|
||||||
|
|
||||||
var x = 0
|
var x = 0
|
||||||
|
|
|
@ -18,20 +18,32 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.image.coil
|
package org.oxycblt.auxio.image.coil
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import coil3.ImageLoader
|
import coil3.ImageLoader
|
||||||
|
import coil3.asImage
|
||||||
import coil3.decode.DataSource
|
import coil3.decode.DataSource
|
||||||
import coil3.decode.ImageSource
|
import coil3.decode.ImageSource
|
||||||
import coil3.fetch.FetchResult
|
import coil3.fetch.FetchResult
|
||||||
import coil3.fetch.Fetcher
|
import coil3.fetch.Fetcher
|
||||||
|
import coil3.fetch.ImageFetchResult
|
||||||
import coil3.fetch.SourceFetchResult
|
import coil3.fetch.SourceFetchResult
|
||||||
import coil3.request.Options
|
import coil3.request.Options
|
||||||
|
import coil3.size.Dimension
|
||||||
|
import coil3.size.Size
|
||||||
|
import coil3.size.pxOrElse
|
||||||
|
import java.io.InputStream
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import okio.FileSystem
|
import okio.FileSystem
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.source
|
import okio.source
|
||||||
import org.oxycblt.musikr.covers.Cover
|
import org.oxycblt.musikr.cover.Cover
|
||||||
|
|
||||||
class CoverFetcher private constructor(private val cover: Cover) : Fetcher {
|
class CoverFetcher private constructor(private val context: Context, private val cover: Cover) :
|
||||||
|
Fetcher {
|
||||||
override suspend fun fetch(): FetchResult? {
|
override suspend fun fetch(): FetchResult? {
|
||||||
val stream = cover.open() ?: return null
|
val stream = cover.open() ?: return null
|
||||||
return SourceFetchResult(
|
return SourceFetchResult(
|
||||||
|
@ -40,8 +52,59 @@ class CoverFetcher private constructor(private val cover: Cover) : Fetcher {
|
||||||
dataSource = DataSource.DISK)
|
dataSource = DataSource.DISK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Derived from phonograph: https://github.com/kabouzeid/Phonograph */
|
||||||
|
private suspend fun createMosaic(streams: List<InputStream>, size: Size): FetchResult {
|
||||||
|
// Use whatever size coil gives us to create the mosaic.
|
||||||
|
val mosaicSize = android.util.Size(size.width.mosaicSize(), size.height.mosaicSize())
|
||||||
|
val mosaicFrameSize =
|
||||||
|
Size(Dimension(mosaicSize.width / 2), Dimension(mosaicSize.height / 2))
|
||||||
|
|
||||||
|
val mosaicBitmap =
|
||||||
|
Bitmap.createBitmap(mosaicSize.width, mosaicSize.height, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(mosaicBitmap)
|
||||||
|
|
||||||
|
var x = 0
|
||||||
|
var y = 0
|
||||||
|
|
||||||
|
// For each stream, create a bitmap scaled to 1/4th of the mosaics combined size
|
||||||
|
// and place it on a corner of the canvas.
|
||||||
|
for (stream in streams) {
|
||||||
|
if (y == mosaicSize.height) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crop the bitmap down to a square so it leaves no empty space
|
||||||
|
// TODO: Work around this
|
||||||
|
val bitmap =
|
||||||
|
SquareCropTransformation.INSTANCE.transform(
|
||||||
|
BitmapFactory.decodeStream(stream), mosaicFrameSize)
|
||||||
|
canvas.drawBitmap(bitmap, x.toFloat(), y.toFloat(), null)
|
||||||
|
|
||||||
|
x += bitmap.width
|
||||||
|
if (x == mosaicSize.width) {
|
||||||
|
x = 0
|
||||||
|
y += bitmap.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's way easier to map this into a drawable then try to serialize it into an
|
||||||
|
// BufferedSource. Just make sure we mark it as "sampled" so Coil doesn't try to
|
||||||
|
// load low-res mosaics into high-res ImageViews.
|
||||||
|
return ImageFetchResult(
|
||||||
|
image = mosaicBitmap.toDrawable(context.resources).asImage(),
|
||||||
|
isSampled = true,
|
||||||
|
dataSource = DataSource.DISK)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Dimension.mosaicSize(): Int {
|
||||||
|
// Since we want the mosaic to be perfectly divisible into two, we need to round any
|
||||||
|
// odd image sizes upwards to prevent the mosaic creation from failing.
|
||||||
|
val size = pxOrElse { 512 }
|
||||||
|
return if (size.mod(2) > 0) size + 1 else size
|
||||||
|
}
|
||||||
|
|
||||||
class Factory @Inject constructor() : Fetcher.Factory<Cover> {
|
class Factory @Inject constructor() : Fetcher.Factory<Cover> {
|
||||||
override fun create(data: Cover, options: Options, imageLoader: ImageLoader) =
|
override fun create(data: Cover, options: Options, imageLoader: ImageLoader) =
|
||||||
CoverFetcher(data)
|
CoverFetcher(options.context, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ package org.oxycblt.auxio.image.coil
|
||||||
import coil3.key.Keyer
|
import coil3.key.Keyer
|
||||||
import coil3.request.Options
|
import coil3.request.Options
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import org.oxycblt.musikr.covers.Cover
|
import org.oxycblt.musikr.cover.Cover
|
||||||
import org.oxycblt.musikr.covers.CoverCollection
|
import org.oxycblt.musikr.cover.CoverCollection
|
||||||
|
|
||||||
class CoverKeyer @Inject constructor() : Keyer<Cover> {
|
class CoverKeyer @Inject constructor() : Keyer<Cover> {
|
||||||
override fun key(data: Cover, options: Options) = "${data.id}&${options.size}"
|
override fun key(data: Cover, options: Options) = "${data.id}&${options.size}"
|
||||||
|
|
|
@ -38,8 +38,8 @@ import coil3.transform.Transformation
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vendoring of coil's RoundedCornersTransformation that can handle non-1:1 aspect ratio images
|
* A vendoring of [coil.transform.RoundedCornersTransformation] that can handle non-1:1 aspect ratio
|
||||||
* without cropping them.
|
* images without cropping them.
|
||||||
*
|
*
|
||||||
* @author Coil Team, Alexander Capehart (OxygenCobalt)
|
* @author Coil Team, Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.oxycblt.auxio.image.coil
|
package org.oxycblt.auxio.image.coil
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import androidx.core.graphics.scale
|
|
||||||
import coil3.size.Size
|
import coil3.size.Size
|
||||||
import coil3.size.pxOrElse
|
import coil3.size.pxOrElse
|
||||||
import coil3.transform.Transformation
|
import coil3.transform.Transformation
|
||||||
|
@ -47,7 +46,7 @@ class SquareCropTransformation : Transformation() {
|
||||||
val desiredHeight = size.height.pxOrElse { dstSize }
|
val desiredHeight = size.height.pxOrElse { dstSize }
|
||||||
if (dstSize != desiredWidth || dstSize != desiredHeight) {
|
if (dstSize != desiredWidth || dstSize != desiredHeight) {
|
||||||
// Image is not the desired size, upscale it.
|
// Image is not the desired size, upscale it.
|
||||||
return dst.scale(desiredWidth, desiredHeight)
|
return Bitmap.createScaledBitmap(dst, desiredWidth, desiredHeight, true)
|
||||||
}
|
}
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 Auxio Project
|
* Copyright (c) 2024 Auxio Project
|
||||||
* CoversModule.kt is part of Auxio.
|
* CoverModule.kt is part of Auxio.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,11 +20,19 @@ package org.oxycblt.auxio.image.covers
|
||||||
|
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import org.oxycblt.musikr.cover.CoverIdentifier
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
interface CoilModule {
|
interface CoverModule {
|
||||||
@Binds fun settingCovers(imageSettings: SettingCoversImpl): SettingCovers
|
@Binds fun configCovers(impl: SettingCoversImpl): SettingCovers
|
||||||
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
class CoverProvidesModule {
|
||||||
|
@Provides fun identifier(): CoverIdentifier = CoverIdentifier.md5()
|
||||||
}
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Auxio Project
|
||||||
|
* CoverSilo.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.image.covers
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
import org.oxycblt.musikr.cover.CoverParams
|
||||||
|
|
||||||
|
data class CoverSilo(val revision: UUID, val params: CoverParams) {
|
||||||
|
override fun toString() = "${revision}.${params.resolution}.${params.quality}"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun parse(silo: String): CoverSilo? {
|
||||||
|
val parts = silo.split('.')
|
||||||
|
if (parts.size != 3) return null
|
||||||
|
val revision = parts[0].toUuidOrNull() ?: return null
|
||||||
|
val resolution = parts[1].toIntOrNull() ?: return null
|
||||||
|
val quality = parts[2].toIntOrNull() ?: return null
|
||||||
|
return CoverSilo(revision, CoverParams.of(resolution, quality))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.toUuidOrNull(): UUID? =
|
||||||
|
try {
|
||||||
|
UUID.fromString(this)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
null
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2025 Auxio Project
|
* Copyright (c) 2024 Auxio Project
|
||||||
* RevisionedTranscoding.kt is part of Auxio.
|
* CoverUtil.kt is part of Auxio.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,9 +18,9 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.image.covers
|
package org.oxycblt.auxio.image.covers
|
||||||
|
|
||||||
import java.util.UUID
|
import android.content.Context
|
||||||
import org.oxycblt.musikr.covers.stored.Transcoding
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class RevisionedTranscoding(revision: UUID, private val inner: Transcoding) : Transcoding by inner {
|
suspend fun Context.coversDir() =
|
||||||
override val tag = "_$revision${inner.tag}"
|
withContext(Dispatchers.IO) { filesDir.resolve("covers").apply { mkdirs() } }
|
||||||
}
|
|
|
@ -18,20 +18,18 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.image.covers
|
package org.oxycblt.auxio.image.covers
|
||||||
|
|
||||||
import org.oxycblt.musikr.covers.Cover
|
import android.content.Context
|
||||||
import org.oxycblt.musikr.covers.CoverResult
|
import org.oxycblt.musikr.cover.Cover
|
||||||
import org.oxycblt.musikr.covers.MutableCovers
|
import org.oxycblt.musikr.cover.MutableCovers
|
||||||
import org.oxycblt.musikr.covers.stored.CoverStorage
|
import org.oxycblt.musikr.cover.ObtainResult
|
||||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
|
||||||
import org.oxycblt.musikr.metadata.Metadata
|
|
||||||
|
|
||||||
class NullCovers(private val storage: CoverStorage) : MutableCovers<NullCover> {
|
class NullCovers(private val context: Context) : MutableCovers {
|
||||||
override suspend fun obtain(id: String) = CoverResult.Hit(NullCover)
|
override suspend fun obtain(id: String) = ObtainResult.Hit(NullCover)
|
||||||
|
|
||||||
override suspend fun create(file: DeviceFile, metadata: Metadata) = CoverResult.Hit(NullCover)
|
override suspend fun write(data: ByteArray): Cover = NullCover
|
||||||
|
|
||||||
override suspend fun cleanup(excluding: Collection<Cover>) {
|
override suspend fun cleanup(excluding: Collection<Cover>) {
|
||||||
storage.ls(setOf()).map { storage.rm(it) }
|
context.coversDir().listFiles()?.forEach { it.deleteRecursively() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,55 +19,30 @@
|
||||||
package org.oxycblt.auxio.image.covers
|
package org.oxycblt.auxio.image.covers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.image.CoverMode
|
import org.oxycblt.auxio.image.CoverMode
|
||||||
import org.oxycblt.auxio.image.ImageSettings
|
import org.oxycblt.auxio.image.ImageSettings
|
||||||
import org.oxycblt.musikr.covers.Cover
|
import org.oxycblt.musikr.cover.CoverIdentifier
|
||||||
import org.oxycblt.musikr.covers.Covers
|
import org.oxycblt.musikr.cover.CoverParams
|
||||||
import org.oxycblt.musikr.covers.FDCover
|
import org.oxycblt.musikr.cover.MutableCovers
|
||||||
import org.oxycblt.musikr.covers.MutableCovers
|
|
||||||
import org.oxycblt.musikr.covers.chained.ChainedCovers
|
|
||||||
import org.oxycblt.musikr.covers.chained.MutableChainedCovers
|
|
||||||
import org.oxycblt.musikr.covers.embedded.CoverIdentifier
|
|
||||||
import org.oxycblt.musikr.covers.embedded.EmbeddedCovers
|
|
||||||
import org.oxycblt.musikr.covers.fs.FSCovers
|
|
||||||
import org.oxycblt.musikr.covers.fs.MutableFSCovers
|
|
||||||
import org.oxycblt.musikr.covers.stored.Compress
|
|
||||||
import org.oxycblt.musikr.covers.stored.CoverStorage
|
|
||||||
import org.oxycblt.musikr.covers.stored.MutableStoredCovers
|
|
||||||
import org.oxycblt.musikr.covers.stored.NoTranscoding
|
|
||||||
import org.oxycblt.musikr.covers.stored.StoredCovers
|
|
||||||
|
|
||||||
interface SettingCovers {
|
interface SettingCovers {
|
||||||
suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover>
|
suspend fun create(context: Context, revision: UUID): MutableCovers
|
||||||
|
|
||||||
companion object {
|
|
||||||
suspend fun immutable(context: Context): Covers<FDCover> =
|
|
||||||
ChainedCovers(StoredCovers(CoverStorage.at(context.coversDir())), FSCovers(context))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingCoversImpl @Inject constructor(private val imageSettings: ImageSettings) :
|
class SettingCoversImpl
|
||||||
|
@Inject
|
||||||
|
constructor(private val imageSettings: ImageSettings, private val identifier: CoverIdentifier) :
|
||||||
SettingCovers {
|
SettingCovers {
|
||||||
override suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover> {
|
override suspend fun create(context: Context, revision: UUID): MutableCovers =
|
||||||
val coverStorage = CoverStorage.at(context.coversDir())
|
when (imageSettings.coverMode) {
|
||||||
val transcoding =
|
CoverMode.OFF -> NullCovers(context)
|
||||||
when (imageSettings.coverMode) {
|
CoverMode.SAVE_SPACE -> siloedCovers(context, revision, CoverParams.of(500, 70))
|
||||||
CoverMode.OFF -> return NullCovers(coverStorage)
|
CoverMode.BALANCED -> siloedCovers(context, revision, CoverParams.of(750, 85))
|
||||||
CoverMode.SAVE_SPACE -> Compress(Bitmap.CompressFormat.JPEG, 500, 70)
|
CoverMode.HIGH_QUALITY -> siloedCovers(context, revision, CoverParams.of(1000, 100))
|
||||||
CoverMode.BALANCED -> Compress(Bitmap.CompressFormat.JPEG, 750, 85)
|
}
|
||||||
CoverMode.HIGH_QUALITY -> Compress(Bitmap.CompressFormat.JPEG, 1000, 100)
|
|
||||||
CoverMode.AS_IS -> NoTranscoding
|
|
||||||
}
|
|
||||||
val revisionedTranscoding = RevisionedTranscoding(revision, transcoding)
|
|
||||||
val storedCovers =
|
|
||||||
MutableStoredCovers(
|
|
||||||
EmbeddedCovers(CoverIdentifier.md5()), coverStorage, revisionedTranscoding)
|
|
||||||
val fsCovers = MutableFSCovers(context)
|
|
||||||
return MutableChainedCovers(storedCovers, fsCovers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Context.coversDir() = filesDir.resolve("covers").apply { mkdirs() }
|
private suspend fun siloedCovers(context: Context, revision: UUID, with: CoverParams) =
|
||||||
|
MutableSiloedCovers.from(context, CoverSilo(revision, with), identifier)
|
||||||
|
}
|
||||||
|
|
118
app/src/main/java/org/oxycblt/auxio/image/covers/SiloedCovers.kt
Normal file
118
app/src/main/java/org/oxycblt/auxio/image/covers/SiloedCovers.kt
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Auxio Project
|
||||||
|
* SiloedCovers.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.image.covers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import java.io.File
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.oxycblt.musikr.cover.Cover
|
||||||
|
import org.oxycblt.musikr.cover.CoverFormat
|
||||||
|
import org.oxycblt.musikr.cover.CoverIdentifier
|
||||||
|
import org.oxycblt.musikr.cover.Covers
|
||||||
|
import org.oxycblt.musikr.cover.FileCover
|
||||||
|
import org.oxycblt.musikr.cover.FileCovers
|
||||||
|
import org.oxycblt.musikr.cover.MutableCovers
|
||||||
|
import org.oxycblt.musikr.cover.MutableFileCovers
|
||||||
|
import org.oxycblt.musikr.cover.ObtainResult
|
||||||
|
import org.oxycblt.musikr.fs.app.AppFiles
|
||||||
|
|
||||||
|
open class SiloedCovers(private val silo: CoverSilo, private val fileCovers: FileCovers) : Covers {
|
||||||
|
override suspend fun obtain(id: String): ObtainResult<SiloedCover> {
|
||||||
|
val coverId = SiloedCoverId.parse(id) ?: return ObtainResult.Miss()
|
||||||
|
if (coverId.silo != silo) return ObtainResult.Miss()
|
||||||
|
return when (val result = fileCovers.obtain(coverId.id)) {
|
||||||
|
is ObtainResult.Hit -> ObtainResult.Hit(SiloedCover(silo, result.cover))
|
||||||
|
is ObtainResult.Miss -> ObtainResult.Miss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
suspend fun from(context: Context, silo: CoverSilo): SiloedCovers {
|
||||||
|
val core = SiloCore.from(context, silo)
|
||||||
|
return SiloedCovers(silo, FileCovers(core.files, core.format))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutableSiloedCovers
|
||||||
|
private constructor(
|
||||||
|
private val rootDir: File,
|
||||||
|
private val silo: CoverSilo,
|
||||||
|
private val fileCovers: MutableFileCovers
|
||||||
|
) : SiloedCovers(silo, fileCovers), MutableCovers {
|
||||||
|
override suspend fun write(data: ByteArray) = SiloedCover(silo, fileCovers.write(data))
|
||||||
|
|
||||||
|
override suspend fun cleanup(excluding: Collection<Cover>) {
|
||||||
|
fileCovers.cleanup(excluding.filterIsInstance<SiloedCover>().map { it.innerCover })
|
||||||
|
|
||||||
|
// Destroy old revisions no longer being used.
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val exclude = silo.toString()
|
||||||
|
rootDir.listFiles { file -> file.name != exclude }?.forEach { it.deleteRecursively() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
suspend fun from(
|
||||||
|
context: Context,
|
||||||
|
silo: CoverSilo,
|
||||||
|
coverIdentifier: CoverIdentifier
|
||||||
|
): MutableSiloedCovers {
|
||||||
|
val core = SiloCore.from(context, silo)
|
||||||
|
return MutableSiloedCovers(
|
||||||
|
core.rootDir, silo, MutableFileCovers(core.files, core.format, coverIdentifier))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class SiloedCover(private val silo: CoverSilo, val innerCover: FileCover) :
|
||||||
|
FileCover by innerCover {
|
||||||
|
private val innerId = SiloedCoverId(silo, innerCover.id)
|
||||||
|
override val id = innerId.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class SiloedCoverId(val silo: CoverSilo, val id: String) {
|
||||||
|
override fun toString() = "$id@$silo"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun parse(id: String): SiloedCoverId? {
|
||||||
|
val parts = id.split('@')
|
||||||
|
if (parts.size != 2) return null
|
||||||
|
val silo = CoverSilo.parse(parts[1]) ?: return null
|
||||||
|
return SiloedCoverId(silo, parts[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class SiloCore(val rootDir: File, val files: AppFiles, val format: CoverFormat) {
|
||||||
|
companion object {
|
||||||
|
suspend fun from(context: Context, silo: CoverSilo): SiloCore {
|
||||||
|
val rootDir: File
|
||||||
|
val revisionDir: File
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
rootDir = context.coversDir()
|
||||||
|
revisionDir = rootDir.resolve(silo.toString()).apply { mkdirs() }
|
||||||
|
}
|
||||||
|
val files = AppFiles.at(revisionDir)
|
||||||
|
val format = CoverFormat.jpeg(silo.params)
|
||||||
|
return SiloCore(rootDir, files, format)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,6 @@
|
||||||
package org.oxycblt.auxio.list.recycler
|
package org.oxycblt.auxio.list.recycler
|
||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
@ -35,7 +34,6 @@ import android.view.ViewGroup
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.core.view.isEmpty
|
|
||||||
import androidx.core.view.isInvisible
|
import androidx.core.view.isInvisible
|
||||||
import androidx.core.view.updatePaddingRelative
|
import androidx.core.view.updatePaddingRelative
|
||||||
import androidx.core.widget.TextViewCompat
|
import androidx.core.widget.TextViewCompat
|
||||||
|
@ -92,7 +90,6 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
private val thumbSlider = MaterialSlider.small(context, thumbWidth)
|
private val thumbSlider = MaterialSlider.small(context, thumbWidth)
|
||||||
private var thumbAnimator: Animator? = null
|
private var thumbAnimator: Animator? = null
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
|
||||||
private val thumbView =
|
private val thumbView =
|
||||||
context.inflater.inflate(R.layout.view_scroll_thumb, null).apply {
|
context.inflater.inflate(R.layout.view_scroll_thumb, null).apply {
|
||||||
thumbSlider.jumpOut(this)
|
thumbSlider.jumpOut(this)
|
||||||
|
@ -342,7 +339,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
// [proportion of scroll position to scroll range] * [total thumb range]
|
// [proportion of scroll position to scroll range] * [total thumb range]
|
||||||
// This is somewhat adapted from the androidx RecyclerView FastScroller implementation.
|
// This is somewhat adapted from the androidx RecyclerView FastScroller implementation.
|
||||||
val offsetY = computeVerticalScrollOffset()
|
val offsetY = computeVerticalScrollOffset()
|
||||||
if (computeVerticalScrollRange() < height || isEmpty()) {
|
if (computeVerticalScrollRange() < height || childCount == 0) {
|
||||||
fastScrollingPossible = false
|
fastScrollingPossible = false
|
||||||
hideThumb()
|
hideThumb()
|
||||||
hidePopup()
|
hidePopup()
|
||||||
|
|
|
@ -360,16 +360,16 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
||||||
override fun sortSongs(songs: MutableList<Song>, direction: Direction) {
|
override fun sortSongs(songs: MutableList<Song>, direction: Direction) {
|
||||||
songs.sortBy { it.name }
|
songs.sortBy { it.name }
|
||||||
when (direction) {
|
when (direction) {
|
||||||
Direction.ASCENDING -> songs.sortBy { it.addedMs }
|
Direction.ASCENDING -> songs.sortBy { it.dateAdded }
|
||||||
Direction.DESCENDING -> songs.sortByDescending { it.addedMs }
|
Direction.DESCENDING -> songs.sortByDescending { it.dateAdded }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sortAlbums(albums: MutableList<Album>, direction: Direction) {
|
override fun sortAlbums(albums: MutableList<Album>, direction: Direction) {
|
||||||
albums.sortBy { it.name }
|
albums.sortBy { it.name }
|
||||||
when (direction) {
|
when (direction) {
|
||||||
Direction.ASCENDING -> albums.sortBy { it.addedMs }
|
Direction.ASCENDING -> albums.sortBy { it.dateAdded }
|
||||||
Direction.DESCENDING -> albums.sortByDescending { it.addedMs }
|
Direction.DESCENDING -> albums.sortByDescending { it.dateAdded }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import org.oxycblt.auxio.image.covers.SettingCovers
|
import org.oxycblt.auxio.image.covers.SettingCovers
|
||||||
import org.oxycblt.auxio.music.MusicRepository.IndexingWorker
|
import org.oxycblt.auxio.music.MusicRepository.IndexingWorker
|
||||||
import org.oxycblt.auxio.music.shim.WriteOnlyMutableCache
|
|
||||||
import org.oxycblt.musikr.IndexingProgress
|
import org.oxycblt.musikr.IndexingProgress
|
||||||
import org.oxycblt.musikr.Interpretation
|
import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.Library
|
import org.oxycblt.musikr.Library
|
||||||
|
@ -39,7 +38,7 @@ import org.oxycblt.musikr.MutableLibrary
|
||||||
import org.oxycblt.musikr.Playlist
|
import org.oxycblt.musikr.Playlist
|
||||||
import org.oxycblt.musikr.Song
|
import org.oxycblt.musikr.Song
|
||||||
import org.oxycblt.musikr.Storage
|
import org.oxycblt.musikr.Storage
|
||||||
import org.oxycblt.musikr.cache.MutableCache
|
import org.oxycblt.musikr.cache.StoredCache
|
||||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
import org.oxycblt.musikr.tag.interpret.Naming
|
import org.oxycblt.musikr.tag.interpret.Naming
|
||||||
import org.oxycblt.musikr.tag.interpret.Separators
|
import org.oxycblt.musikr.tag.interpret.Separators
|
||||||
|
@ -188,8 +187,8 @@ interface MusicRepository {
|
||||||
/**
|
/**
|
||||||
* Flags indicating which kinds of music information changed.
|
* Flags indicating which kinds of music information changed.
|
||||||
*
|
*
|
||||||
* @param deviceLibrary Whether the current songs/albums/artists/genres has changed.
|
* @param deviceLibrary Whether the current [DeviceLibrary] has changed.
|
||||||
* @param userLibrary Whether the current playlists have changed.
|
* @param library Whether the current [Playlist]s have changed.
|
||||||
*/
|
*/
|
||||||
data class Changes(val deviceLibrary: Boolean, val userLibrary: Boolean)
|
data class Changes(val deviceLibrary: Boolean, val userLibrary: Boolean)
|
||||||
|
|
||||||
|
@ -237,14 +236,14 @@ class MusicRepositoryImpl
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val cache: MutableCache,
|
private val storedCache: StoredCache,
|
||||||
private val storedPlaylists: StoredPlaylists,
|
private val storedPlaylists: StoredPlaylists,
|
||||||
private val settingCovers: SettingCovers,
|
private val settingCovers: SettingCovers,
|
||||||
private val musicSettings: MusicSettings
|
private val musicSettings: MusicSettings
|
||||||
) : MusicRepository {
|
) : MusicRepository {
|
||||||
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
|
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
|
||||||
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
|
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
|
||||||
@Volatile private var indexingWorker: IndexingWorker? = null
|
@Volatile private var indexingWorker: MusicRepository.IndexingWorker? = null
|
||||||
|
|
||||||
@Volatile override var library: MutableLibrary? = null
|
@Volatile override var library: MutableLibrary? = null
|
||||||
@Volatile private var previousCompletedState: IndexingState.Completed? = null
|
@Volatile private var previousCompletedState: IndexingState.Completed? = null
|
||||||
|
@ -283,7 +282,7 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun registerWorker(worker: IndexingWorker) {
|
override fun registerWorker(worker: MusicRepository.IndexingWorker) {
|
||||||
if (indexingWorker != null) {
|
if (indexingWorker != null) {
|
||||||
L.w("Worker is already registered")
|
L.w("Worker is already registered")
|
||||||
return
|
return
|
||||||
|
@ -293,7 +292,7 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun unregisterWorker(worker: IndexingWorker) {
|
override fun unregisterWorker(worker: MusicRepository.IndexingWorker) {
|
||||||
if (indexingWorker !== worker) {
|
if (indexingWorker !== worker) {
|
||||||
L.w("Given worker did not match current worker")
|
L.w("Given worker did not match current worker")
|
||||||
return
|
return
|
||||||
|
@ -348,8 +347,7 @@ constructor(
|
||||||
override suspend fun rewritePlaylist(playlist: Playlist, songs: List<Song>) {
|
override suspend fun rewritePlaylist(playlist: Playlist, songs: List<Song>) {
|
||||||
val library = synchronized(this) { library ?: return }
|
val library = synchronized(this) { library ?: return }
|
||||||
L.d("Rewriting $playlist with ${songs.size} songs")
|
L.d("Rewriting $playlist with ${songs.size} songs")
|
||||||
val newLibrary = library.rewritePlaylist(playlist, songs)
|
library.rewritePlaylist(playlist, songs)
|
||||||
synchronized(this) { this.library = newLibrary }
|
|
||||||
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,14 +383,14 @@ constructor(
|
||||||
Naming.simple()
|
Naming.simple()
|
||||||
}
|
}
|
||||||
val locations = musicSettings.musicLocations
|
val locations = musicSettings.musicLocations
|
||||||
val withHidden = musicSettings.withHidden
|
|
||||||
|
|
||||||
val currentRevision = musicSettings.revision
|
val currentRevision = musicSettings.revision
|
||||||
val newRevision = currentRevision?.takeIf { withCache } ?: UUID.randomUUID()
|
val newRevision = currentRevision?.takeIf { withCache } ?: UUID.randomUUID()
|
||||||
val cache = if (withCache) cache else WriteOnlyMutableCache(cache)
|
val cache = if (withCache) storedCache.visible() else storedCache.invisible()
|
||||||
val covers = settingCovers.mutate(context, newRevision)
|
val covers = settingCovers.create(context, newRevision)
|
||||||
val storage = Storage(cache, covers, storedPlaylists)
|
val storage = Storage(cache, covers, storedPlaylists)
|
||||||
val interpretation = Interpretation(nameFactory, separators, withHidden)
|
val interpretation = Interpretation(nameFactory, separators)
|
||||||
|
|
||||||
val result =
|
val result =
|
||||||
Musikr.new(context, storage, interpretation).run(locations, ::emitIndexingProgress)
|
Musikr.new(context, storage, interpretation).run(locations, ::emitIndexingProgress)
|
||||||
// Music loading completed, update the revision right now so we re-use this work
|
// Music loading completed, update the revision right now so we re-use this work
|
||||||
|
|
|
@ -40,8 +40,6 @@ interface MusicSettings : Settings<MusicSettings.Listener> {
|
||||||
var musicLocations: List<MusicLocation>
|
var musicLocations: List<MusicLocation>
|
||||||
/** Whether to exclude non-music audio files from the music library. */
|
/** Whether to exclude non-music audio files from the music library. */
|
||||||
val excludeNonMusic: Boolean
|
val excludeNonMusic: Boolean
|
||||||
/** Whether to ignore hidden files and directories during music loading. */
|
|
||||||
val withHidden: Boolean
|
|
||||||
/** Whether to be actively watching for changes in the music library. */
|
/** Whether to be actively watching for changes in the music library. */
|
||||||
val shouldBeObserving: Boolean
|
val shouldBeObserving: Boolean
|
||||||
/** A [String] of characters representing the desired characters to denote multi-value tags. */
|
/** A [String] of characters representing the desired characters to denote multi-value tags. */
|
||||||
|
@ -85,19 +83,13 @@ class MusicSettingsImpl @Inject constructor(@ApplicationContext private val cont
|
||||||
sharedPreferences.edit {
|
sharedPreferences.edit {
|
||||||
putString(
|
putString(
|
||||||
getString(R.string.set_key_music_locations), MusicLocation.toString(value))
|
getString(R.string.set_key_music_locations), MusicLocation.toString(value))
|
||||||
commit()
|
this@edit.apply()
|
||||||
// Sometimes changing this setting just won't actually trigger the listener.
|
|
||||||
// Only this one. No idea why.
|
|
||||||
listener?.onMusicLocationsChanged()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val excludeNonMusic: Boolean
|
override val excludeNonMusic: Boolean
|
||||||
get() = sharedPreferences.getBoolean(getString(R.string.set_key_exclude_non_music), true)
|
get() = sharedPreferences.getBoolean(getString(R.string.set_key_exclude_non_music), true)
|
||||||
|
|
||||||
override val withHidden: Boolean
|
|
||||||
get() = sharedPreferences.getBoolean(getString(R.string.set_key_with_hidden), false)
|
|
||||||
|
|
||||||
override val shouldBeObserving: Boolean
|
override val shouldBeObserving: Boolean
|
||||||
get() = sharedPreferences.getBoolean(getString(R.string.set_key_observing), false)
|
get() = sharedPreferences.getBoolean(getString(R.string.set_key_observing), false)
|
||||||
|
|
||||||
|
@ -124,9 +116,7 @@ class MusicSettingsImpl @Inject constructor(@ApplicationContext private val cont
|
||||||
listener.onMusicLocationsChanged()
|
listener.onMusicLocationsChanged()
|
||||||
}
|
}
|
||||||
getString(R.string.set_key_separators),
|
getString(R.string.set_key_separators),
|
||||||
getString(R.string.set_key_auto_sort_names),
|
getString(R.string.set_key_auto_sort_names) -> {
|
||||||
getString(R.string.set_key_with_hidden),
|
|
||||||
getString(R.string.set_key_exclude_non_music) -> {
|
|
||||||
L.d("Dispatching indexing setting change for $key")
|
L.d("Dispatching indexing setting change for $key")
|
||||||
listener.onIndexingSettingChanged()
|
listener.onIndexingSettingChanged()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,15 @@ import org.oxycblt.auxio.R
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
enum class MusicType {
|
enum class MusicType {
|
||||||
|
/** @see Song */
|
||||||
SONGS,
|
SONGS,
|
||||||
|
/** @see Album */
|
||||||
ALBUMS,
|
ALBUMS,
|
||||||
|
/** @see Artist */
|
||||||
ARTISTS,
|
ARTISTS,
|
||||||
|
/** @see Genre */
|
||||||
GENRES,
|
GENRES,
|
||||||
|
/** @see Playlist */
|
||||||
PLAYLISTS;
|
PLAYLISTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -53,9 +53,6 @@ class DeletePlaylistDialog : ViewBindingMaterialDialogFragment<DialogDeletePlayl
|
||||||
builder
|
builder
|
||||||
.setTitle(R.string.lbl_confirm_delete_playlist)
|
.setTitle(R.string.lbl_confirm_delete_playlist)
|
||||||
.setPositiveButton(R.string.lbl_delete) { _, _ ->
|
.setPositiveButton(R.string.lbl_delete) { _, _ ->
|
||||||
// Normally the navigateUp will occur after this, which then collides with the
|
|
||||||
// playlist view's navigation. Forcefully navigate up to stop this.
|
|
||||||
findNavController().navigateUp()
|
|
||||||
// Now we can delete the playlist for-real this time.
|
// Now we can delete the playlist for-real this time.
|
||||||
musicModel.deletePlaylist(
|
musicModel.deletePlaylist(
|
||||||
unlikelyToBeNull(pickerModel.currentPlaylistToDelete.value), rude = true)
|
unlikelyToBeNull(pickerModel.currentPlaylistToDelete.value), rude = true)
|
||||||
|
|
|
@ -25,7 +25,6 @@ import android.view.LayoutInflater
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.net.toUri
|
|
||||||
import androidx.recyclerview.widget.ConcatAdapter
|
import androidx.recyclerview.widget.ConcatAdapter
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -81,7 +80,7 @@ class MusicSourcesDialog :
|
||||||
|
|
||||||
val locations =
|
val locations =
|
||||||
savedInstanceState?.getStringArrayList(KEY_PENDING_LOCATIONS)?.mapNotNull {
|
savedInstanceState?.getStringArrayList(KEY_PENDING_LOCATIONS)?.mapNotNull {
|
||||||
MusicLocation.existing(requireContext(), it.toUri())
|
MusicLocation.existing(requireContext(), Uri.parse(it))
|
||||||
} ?: musicSettings.musicLocations
|
} ?: musicSettings.musicLocations
|
||||||
|
|
||||||
locationAdapter.addAll(locations)
|
locationAdapter.addAll(locations)
|
||||||
|
|
|
@ -51,7 +51,7 @@ class NewLocationFooterAdapter(private val listener: Listener) :
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [RecyclerView.ViewHolder] that displays a "New Playlist" choice in [NewLocationFooterAdapter].
|
* A [RecyclerView.ViewHolder] that displays a "New Playlist" choice in [NewPlaylistFooterAdapter].
|
||||||
* Use [from] to create an instance.
|
* Use [from] to create an instance.
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
|
|
|
@ -92,7 +92,6 @@ constructor(
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
if (musicRepository.indexingState == null) {
|
if (musicRepository.indexingState == null) {
|
||||||
L.d("Requesting index")
|
|
||||||
musicRepository.requestIndex(true)
|
musicRepository.requestIndex(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,7 @@ import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import org.oxycblt.musikr.cache.MutableCache
|
import org.oxycblt.musikr.cache.StoredCache
|
||||||
import org.oxycblt.musikr.cache.db.MutableDBCache
|
|
||||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -34,7 +33,7 @@ import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
class MusikrShimModule {
|
class MusikrShimModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun cache(@ApplicationContext context: Context): MutableCache = MutableDBCache.from(context)
|
fun storedCache(@ApplicationContext context: Context) = StoredCache.from(context)
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2025 Auxio Project
|
|
||||||
* WriteOnlyMutableCache.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.music.shim
|
|
||||||
|
|
||||||
import org.oxycblt.musikr.cache.CacheResult
|
|
||||||
import org.oxycblt.musikr.cache.CachedSong
|
|
||||||
import org.oxycblt.musikr.cache.MutableCache
|
|
||||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
|
||||||
|
|
||||||
class WriteOnlyMutableCache(private val inner: MutableCache) : MutableCache {
|
|
||||||
override suspend fun read(file: DeviceFile): CacheResult {
|
|
||||||
return when (val result = inner.read(file)) {
|
|
||||||
is CacheResult.Hit -> CacheResult.Stale(file, result.song.addedMs)
|
|
||||||
else -> result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun write(cachedSong: CachedSong) {
|
|
||||||
inner.write(cachedSong)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun cleanup(excluding: List<CachedSong>) {
|
|
||||||
inner.cleanup(excluding)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -48,6 +48,13 @@ fun Long.dsToMs() = times(100)
|
||||||
*/
|
*/
|
||||||
fun Long.dsToSecs() = floorDiv(10)
|
fun Long.dsToSecs() = floorDiv(10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert seconds into milliseconds.
|
||||||
|
*
|
||||||
|
* @return A converted millisecond value.
|
||||||
|
*/
|
||||||
|
fun Long.secsToMs() = times(1000)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a millisecond value into a string duration.
|
* Convert a millisecond value into a string duration.
|
||||||
*
|
*
|
||||||
|
|
|
@ -50,7 +50,7 @@ constructor(
|
||||||
) : PersistenceRepository {
|
) : PersistenceRepository {
|
||||||
|
|
||||||
override suspend fun readState(): PlaybackStateManager.SavedState? {
|
override suspend fun readState(): PlaybackStateManager.SavedState? {
|
||||||
val library = musicRepository.library?.takeIf { !it.empty() } ?: return null
|
val library = musicRepository.library ?: return null
|
||||||
val playbackState: PlaybackState
|
val playbackState: PlaybackState
|
||||||
val heapItems: List<QueueHeapItem>
|
val heapItems: List<QueueHeapItem>
|
||||||
val mappingItems: List<QueueShuffledMappingItem>
|
val mappingItems: List<QueueShuffledMappingItem>
|
||||||
|
|
|
@ -18,9 +18,7 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.playback.service
|
package org.oxycblt.auxio.playback.service
|
||||||
|
|
||||||
import androidx.annotation.OptIn
|
|
||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
import androidx.media3.common.util.UnstableApi
|
|
||||||
import androidx.media3.exoplayer.source.ShuffleOrder
|
import androidx.media3.exoplayer.source.ShuffleOrder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +28,6 @@ import androidx.media3.exoplayer.source.ShuffleOrder
|
||||||
*
|
*
|
||||||
* @author media3 team, Alexander Capehart (OxygenCobalt)
|
* @author media3 team, Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
@OptIn(UnstableApi::class)
|
|
||||||
class BetterShuffleOrder(private val shuffled: IntArray) : ShuffleOrder {
|
class BetterShuffleOrder(private val shuffled: IntArray) : ShuffleOrder {
|
||||||
private val indexInShuffled: IntArray = IntArray(shuffled.size)
|
private val indexInShuffled: IntArray = IntArray(shuffled.size)
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,11 @@ package org.oxycblt.auxio.playback.service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.audiofx.AudioEffect
|
import android.media.audiofx.AudioEffect
|
||||||
import android.provider.OpenableColumns
|
|
||||||
import androidx.annotation.OptIn
|
|
||||||
import androidx.media3.common.AudioAttributes
|
import androidx.media3.common.AudioAttributes
|
||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.PlaybackException
|
import androidx.media3.common.PlaybackException
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
|
||||||
import androidx.media3.decoder.ffmpeg.FfmpegAudioRenderer
|
import androidx.media3.decoder.ffmpeg.FfmpegAudioRenderer
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.RenderersFactory
|
import androidx.media3.exoplayer.RenderersFactory
|
||||||
|
@ -38,7 +35,6 @@ import androidx.media3.exoplayer.mediacodec.MediaCodecSelector
|
||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -49,6 +45,7 @@ import kotlinx.coroutines.yield
|
||||||
import org.oxycblt.auxio.image.ImageSettings
|
import org.oxycblt.auxio.image.ImageSettings
|
||||||
import org.oxycblt.auxio.music.MusicRepository
|
import org.oxycblt.auxio.music.MusicRepository
|
||||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||||
|
import org.oxycblt.auxio.playback.msToSecs
|
||||||
import org.oxycblt.auxio.playback.persist.PersistenceRepository
|
import org.oxycblt.auxio.playback.persist.PersistenceRepository
|
||||||
import org.oxycblt.auxio.playback.replaygain.ReplayGainAudioProcessor
|
import org.oxycblt.auxio.playback.replaygain.ReplayGainAudioProcessor
|
||||||
import org.oxycblt.auxio.playback.state.DeferredPlayback
|
import org.oxycblt.auxio.playback.state.DeferredPlayback
|
||||||
|
@ -64,7 +61,6 @@ import org.oxycblt.musikr.MusicParent
|
||||||
import org.oxycblt.musikr.Song
|
import org.oxycblt.musikr.Song
|
||||||
import timber.log.Timber as L
|
import timber.log.Timber as L
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
|
||||||
class ExoPlaybackStateHolder(
|
class ExoPlaybackStateHolder(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val player: ExoPlayer,
|
private val player: ExoPlayer,
|
||||||
|
@ -150,7 +146,7 @@ class ExoPlaybackStateHolder(
|
||||||
|
|
||||||
override fun handleDeferred(action: DeferredPlayback): Boolean {
|
override fun handleDeferred(action: DeferredPlayback): Boolean {
|
||||||
val library =
|
val library =
|
||||||
musicRepository.library?.takeIf { !it.empty() }
|
musicRepository.library
|
||||||
// No library, cannot do anything.
|
// No library, cannot do anything.
|
||||||
?: return false
|
?: return false
|
||||||
|
|
||||||
|
@ -185,34 +181,13 @@ class ExoPlaybackStateHolder(
|
||||||
// Open -> Try to find the Song for the given file and then play it from all songs
|
// Open -> Try to find the Song for the given file and then play it from all songs
|
||||||
is DeferredPlayback.Open -> {
|
is DeferredPlayback.Open -> {
|
||||||
L.d("Opening specified file")
|
L.d("Opening specified file")
|
||||||
context.applicationContext.contentResolver
|
// library.findSongForUri(context, action.uri)?.let { song ->
|
||||||
.query(
|
// playbackManager.play(
|
||||||
action.uri,
|
// requireNotNull(commandFactory.song(song,
|
||||||
arrayOf(OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE),
|
// ShuffleMode.IMPLICIT)) {
|
||||||
null,
|
// "Invalid playback parameters"
|
||||||
null,
|
// })
|
||||||
null)
|
// }
|
||||||
?.use { cursor ->
|
|
||||||
val displayNameIndex =
|
|
||||||
cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
|
|
||||||
val sizeIndex = cursor.getColumnIndexOrThrow(OpenableColumns.SIZE)
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
val displayName = cursor.getString(displayNameIndex)
|
|
||||||
val size = cursor.getLong(sizeIndex)
|
|
||||||
val song =
|
|
||||||
library.songs.find {
|
|
||||||
it.path.name == displayName && it.size == size
|
|
||||||
}
|
|
||||||
if (song != null) {
|
|
||||||
val command =
|
|
||||||
requireNotNull(
|
|
||||||
commandFactory.songFromAll(song, ShuffleMode.IMPLICIT)) {
|
|
||||||
"Invalid playback command"
|
|
||||||
}
|
|
||||||
playbackManager.play(command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,6 +372,7 @@ class ExoPlaybackStateHolder(
|
||||||
) {
|
) {
|
||||||
var sendNewPlaybackEvent = false
|
var sendNewPlaybackEvent = false
|
||||||
var shouldSeek = false
|
var shouldSeek = false
|
||||||
|
L.d("invalidating parent ${this.parent?.songs} ${parent?.songs}")
|
||||||
if (this.parent != parent) {
|
if (this.parent != parent) {
|
||||||
this.parent = parent
|
this.parent = parent
|
||||||
sendNewPlaybackEvent = true
|
sendNewPlaybackEvent = true
|
||||||
|
@ -417,13 +393,9 @@ class ExoPlaybackStateHolder(
|
||||||
}
|
}
|
||||||
|
|
||||||
repeatMode(repeatMode)
|
repeatMode(repeatMode)
|
||||||
// See if we differ by more than a second. This allows us to avoid a meaningless seek
|
// Positions in milliseconds will drift during tight restores (i.e what the music loader
|
||||||
// in the case of a "tight restore" (i.e music was reloaded).
|
// does to sanitize the state), compare by seconds instead.
|
||||||
// In the case that this is a false positive, it's not very percievable (at least compared
|
if (positionMs.msToSecs() != player.currentPosition.msToSecs() || shouldSeek) {
|
||||||
// to skipping when updating the library).
|
|
||||||
// TODO: Introduce a better state management system rather than do something finicky like
|
|
||||||
// this.
|
|
||||||
if (shouldSeek || abs(player.currentPosition - positionMs) > 1000L) {
|
|
||||||
player.seekTo(positionMs)
|
player.seekTo(positionMs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,14 +407,14 @@ class ExoPlaybackStateHolder(
|
||||||
override fun endSession() {
|
override fun endSession() {
|
||||||
// This session has ended, so we need to reset this flag for when the next
|
// This session has ended, so we need to reset this flag for when the next
|
||||||
// session starts.
|
// session starts.
|
||||||
playbackManager.playing(false)
|
|
||||||
save {
|
save {
|
||||||
// User could feasibly start playing again if they were fast enough, so
|
// User could feasibly start playing again if they were fast enough, so
|
||||||
// we need to avoid stopping the foreground state if that's the case.
|
// we need to avoid stopping the foreground state if that's the case.
|
||||||
if (!playbackManager.progression.isPlaying) {
|
if (playbackManager.progression.isPlaying) {
|
||||||
sessionOngoing = false
|
playbackManager.playing(false)
|
||||||
playbackManager.ack(this, StateAck.SessionEnded)
|
|
||||||
}
|
}
|
||||||
|
sessionOngoing = false
|
||||||
|
playbackManager.ack(this, StateAck.SessionEnded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +499,7 @@ class ExoPlaybackStateHolder(
|
||||||
// --- MUSICREPOSITORY METHODS ---
|
// --- MUSICREPOSITORY METHODS ---
|
||||||
|
|
||||||
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
||||||
if (changes.deviceLibrary && musicRepository.library?.takeIf { !it.empty() } != null) {
|
if (changes.deviceLibrary && musicRepository.library != null) {
|
||||||
// We now have a library, see if we have anything we need to do.
|
// We now have a library, see if we have anything we need to do.
|
||||||
L.d("Library obtained, requesting action")
|
L.d("Library obtained, requesting action")
|
||||||
playbackManager.requestAction(this)
|
playbackManager.requestAction(this)
|
||||||
|
@ -548,9 +520,7 @@ class ExoPlaybackStateHolder(
|
||||||
|
|
||||||
private fun save(cb: () -> Unit) {
|
private fun save(cb: () -> Unit) {
|
||||||
saveJob {
|
saveJob {
|
||||||
if (sessionOngoing) {
|
persistenceRepository.saveState(playbackManager.toSavedState())
|
||||||
persistenceRepository.saveState(playbackManager.toSavedState())
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.Main) { cb() }
|
withContext(Dispatchers.Main) { cb() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -561,9 +531,7 @@ class ExoPlaybackStateHolder(
|
||||||
delay(SAVE_BUFFER)
|
delay(SAVE_BUFFER)
|
||||||
yield()
|
yield()
|
||||||
L.d("Committing saved state")
|
L.d("Committing saved state")
|
||||||
if (sessionOngoing) {
|
persistenceRepository.saveState(playbackManager.toSavedState())
|
||||||
persistenceRepository.saveState(playbackManager.toSavedState())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ import androidx.core.content.ContextCompat
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.AuxioService
|
import org.oxycblt.auxio.AuxioService
|
||||||
import org.oxycblt.auxio.IntegerTable
|
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
import timber.log.Timber as L
|
import timber.log.Timber as L
|
||||||
|
|
||||||
|
@ -48,11 +47,8 @@ class MediaButtonReceiver : BroadcastReceiver() {
|
||||||
// stupid this is with the state of foreground services on modern android. One
|
// 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
|
// wrong action at the wrong time will result in the app crashing, and there is
|
||||||
// nothing I can do about it.
|
// nothing I can do about it.
|
||||||
// TODO: Think I finally have an alternative with the changes I made to accomodate
|
|
||||||
// tasker
|
|
||||||
L.d("Delivering media button intent $intent")
|
L.d("Delivering media button intent $intent")
|
||||||
intent.component = ComponentName(context, AuxioService::class.java)
|
intent.component = ComponentName(context, AuxioService::class.java)
|
||||||
intent.putExtra(AuxioService.INTENT_KEY_START_ID, IntegerTable.START_ID_MEDIA_BUTTON)
|
|
||||||
ContextCompat.startForegroundService(context, intent)
|
ContextCompat.startForegroundService(context, intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.oxycblt.auxio.playback.service
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.support.v4.media.MediaMetadataCompat
|
import android.support.v4.media.MediaMetadataCompat
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
|
@ -29,7 +28,6 @@ import androidx.annotation.DrawableRes
|
||||||
import androidx.car.app.mediaextensions.MetadataExtras
|
import androidx.car.app.mediaextensions.MetadataExtras
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.media.app.NotificationCompat.MediaStyle
|
import androidx.media.app.NotificationCompat.MediaStyle
|
||||||
import androidx.media.session.MediaButtonReceiver
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.ForegroundListener
|
import org.oxycblt.auxio.ForegroundListener
|
||||||
|
@ -110,9 +108,6 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryMediaButtonIntent(intent: Intent): Boolean =
|
|
||||||
MediaButtonReceiver.handleIntent(mediaSession, intent) != null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release this instance, closing the [MediaSessionCompat] and preventing any further updates to
|
* Release this instance, closing the [MediaSessionCompat] and preventing any further updates to
|
||||||
* the [PlaybackNotification].
|
* the [PlaybackNotification].
|
||||||
|
|
|
@ -19,11 +19,9 @@
|
||||||
package org.oxycblt.auxio.playback.service
|
package org.oxycblt.auxio.playback.service
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import org.oxycblt.auxio.AuxioService.Companion.INTENT_KEY_START_ID
|
|
||||||
import org.oxycblt.auxio.ForegroundListener
|
import org.oxycblt.auxio.ForegroundListener
|
||||||
import org.oxycblt.auxio.ForegroundServiceNotification
|
import org.oxycblt.auxio.ForegroundServiceNotification
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
|
@ -85,34 +83,18 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun start(intent: Intent?) {
|
fun start(startedBy: Int) {
|
||||||
// At minimum we want to ensure an active playback state.
|
// At minimum we want to ensure an active playback state.
|
||||||
// TODO: Possibly also force to go foreground?
|
// TODO: Possibly also force to go foreground?
|
||||||
val startId = intent?.getIntExtra(INTENT_KEY_START_ID, -1)
|
L.d("Handling non-native start.")
|
||||||
val action =
|
val action =
|
||||||
when (startId) {
|
when (startedBy) {
|
||||||
IntegerTable.START_ID_ACTIVITY -> null
|
IntegerTable.START_ID_ACTIVITY -> null
|
||||||
IntegerTable.START_ID_TASKER ->
|
IntegerTable.START_ID_TASKER ->
|
||||||
DeferredPlayback.RestoreState(
|
DeferredPlayback.RestoreState(
|
||||||
play = true, fallback = DeferredPlayback.ShuffleAll)
|
play = true, fallback = DeferredPlayback.ShuffleAll)
|
||||||
IntegerTable.START_ID_MEDIA_BUTTON -> {
|
// External services using Auxio better know what they are doing.
|
||||||
if (!sessionHolder.tryMediaButtonIntent(intent)) {
|
else -> DeferredPlayback.RestoreState(play = false)
|
||||||
// Malformed intent, need to restore state immediately
|
|
||||||
DeferredPlayback.RestoreState(
|
|
||||||
play = true, fallback = DeferredPlayback.ShuffleAll)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
L.d("Handling non-native start.")
|
|
||||||
if (intent != null && sessionHolder.tryMediaButtonIntent(intent)) {
|
|
||||||
// Just a media button intent, move on.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// External services using Auxio better know what they are doing.
|
|
||||||
DeferredPlayback.RestoreState(play = false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (action != null) {
|
if (action != null) {
|
||||||
L.d("Initing service fragment using action $action")
|
L.d("Initing service fragment using action $action")
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
package org.oxycblt.auxio.playback.service
|
package org.oxycblt.auxio.playback.service
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.annotation.OptIn
|
|
||||||
import androidx.media3.common.util.UnstableApi
|
|
||||||
import androidx.media3.datasource.ContentDataSource
|
import androidx.media3.datasource.ContentDataSource
|
||||||
import androidx.media3.datasource.DataSource
|
import androidx.media3.datasource.DataSource
|
||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
|
@ -43,7 +41,6 @@ import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
@OptIn(UnstableApi::class)
|
|
||||||
class SystemModule {
|
class SystemModule {
|
||||||
@Provides
|
@Provides
|
||||||
fun mediaSourceFactory(
|
fun mediaSourceFactory(
|
||||||
|
|
|
@ -94,11 +94,7 @@ constructor(
|
||||||
override val parent: MusicParent?,
|
override val parent: MusicParent?,
|
||||||
override val queue: List<Song>,
|
override val queue: List<Song>,
|
||||||
override val shuffled: Boolean
|
override val shuffled: Boolean
|
||||||
) : PlaybackCommand {
|
) : PlaybackCommand
|
||||||
// Only show queue count to reduce memory use
|
|
||||||
override fun toString() =
|
|
||||||
"PlaybackCommand(song=$song, parent=$parent, queue=${queue.size} songs, shuffled=$shuffled)"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun song(song: Song, shuffle: ShuffleMode) =
|
override fun song(song: Song, shuffle: ShuffleMode) =
|
||||||
newCommand(song, null, listOf(song), shuffle)
|
newCommand(song, null, listOf(song), shuffle)
|
||||||
|
|
|
@ -20,9 +20,9 @@ package org.oxycblt.auxio.settings
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.core.net.toUri
|
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
@ -72,9 +72,6 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
|
||||||
binding.aboutLicenses.setOnClickListener { requireContext().openInBrowser(LINK_LICENSES) }
|
binding.aboutLicenses.setOnClickListener { requireContext().openInBrowser(LINK_LICENSES) }
|
||||||
binding.aboutProfile.setOnClickListener { requireContext().openInBrowser(LINK_PROFILE) }
|
binding.aboutProfile.setOnClickListener { requireContext().openInBrowser(LINK_PROFILE) }
|
||||||
binding.aboutDonate.setOnClickListener { requireContext().openInBrowser(LINK_DONATE) }
|
binding.aboutDonate.setOnClickListener { requireContext().openInBrowser(LINK_DONATE) }
|
||||||
binding.aboutSupMarkPitblado.setOnClickListener {
|
|
||||||
requireContext().openInBrowser(LINK_SUP_MARK_PITBLADO)
|
|
||||||
}
|
|
||||||
binding.aboutFeedbackGithub.setOnClickListener {
|
binding.aboutFeedbackGithub.setOnClickListener {
|
||||||
requireContext().openInBrowser(LINK_NEW_ISSUE)
|
requireContext().openInBrowser(LINK_NEW_ISSUE)
|
||||||
}
|
}
|
||||||
|
@ -105,7 +102,7 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.sendEmail(recipient: String) {
|
private fun Context.sendEmail(recipient: String) {
|
||||||
val intent = Intent(Intent.ACTION_SENDTO).apply { data = "mailto:$recipient".toUri() }
|
val intent = Intent(Intent.ACTION_SENDTO).apply { data = Uri.parse("mailto:$recipient") }
|
||||||
startIntent(intent)
|
startIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +113,5 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
|
||||||
const val LINK_NEW_ISSUE = "$LINK_SOURCE/issues/new"
|
const val LINK_NEW_ISSUE = "$LINK_SOURCE/issues/new"
|
||||||
const val LINK_PROFILE = "https://github.com/OxygenCobalt"
|
const val LINK_PROFILE = "https://github.com/OxygenCobalt"
|
||||||
const val LINK_DONATE = "https://github.com/sponsors/OxygenCobalt"
|
const val LINK_DONATE = "https://github.com/sponsors/OxygenCobalt"
|
||||||
const val LINK_SUP_MARK_PITBLADO = "https://github.com/mark-pitblado"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,13 +62,17 @@ interface Settings<Listener> {
|
||||||
*/
|
*/
|
||||||
abstract class Impl<Listener>(private val context: Context) :
|
abstract class Impl<Listener>(private val context: Context) :
|
||||||
Settings<Listener>, SharedPreferences.OnSharedPreferenceChangeListener {
|
Settings<Listener>, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
init {
|
||||||
|
L.d(this::class.simpleName)
|
||||||
|
}
|
||||||
|
|
||||||
protected val sharedPreferences: SharedPreferences =
|
protected val sharedPreferences: SharedPreferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(context.applicationContext)
|
PreferenceManager.getDefaultSharedPreferences(context.applicationContext)
|
||||||
|
|
||||||
/** @see [Context.getString] */
|
/** @see [Context.getString] */
|
||||||
protected fun getString(@StringRes stringRes: Int) = context.getString(stringRes)
|
protected fun getString(@StringRes stringRes: Int) = context.getString(stringRes)
|
||||||
|
|
||||||
protected var listener: Listener? = null
|
private var listener: Listener? = null
|
||||||
|
|
||||||
override fun registerListener(listener: Listener) {
|
override fun registerListener(listener: Listener) {
|
||||||
if (this.listener == null) {
|
if (this.listener == null) {
|
||||||
|
|
|
@ -67,14 +67,5 @@ class MusicPreferenceFragment : BasePreferenceFragment(R.xml.preferences_music)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (preference.key == getString(R.string.set_key_with_hidden)) {
|
|
||||||
L.d("Configuring ignore hidden files setting")
|
|
||||||
preference.onPreferenceChangeListener =
|
|
||||||
Preference.OnPreferenceChangeListener { _, _ ->
|
|
||||||
L.d("Ignore hidden files setting changed, reloading music")
|
|
||||||
musicModel.refresh()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.settings.categories
|
package org.oxycblt.auxio.settings.categories
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
@ -53,7 +54,7 @@ class UIPreferenceFragment : BasePreferenceFragment(R.xml.preferences_ui) {
|
||||||
preference.onPreferenceChangeListener =
|
preference.onPreferenceChangeListener =
|
||||||
Preference.OnPreferenceChangeListener { _, value ->
|
Preference.OnPreferenceChangeListener { _, value ->
|
||||||
L.d("Theme changed, recreating")
|
L.d("Theme changed, recreating")
|
||||||
requireActivity().recreate()
|
AppCompatDelegate.setDefaultNightMode(value as Int)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,6 @@ class StartActionRunner : TaskerPluginRunnerActionNoOutputOrInput() {
|
||||||
while (!AuxioService.isForeground) {
|
while (!AuxioService.isForeground) {
|
||||||
Thread.sleep(100)
|
Thread.sleep(100)
|
||||||
}
|
}
|
||||||
// Actually need to sleep even longer since for some reason the notification still
|
|
||||||
// won't accept media button events for an arbitrary period.
|
|
||||||
Thread.sleep(100)
|
|
||||||
return TaskerPluginResultSucess()
|
return TaskerPluginResultSucess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,25 +46,25 @@ class AnimConfig(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val STANDARD = MR.attr.motionEasingStandardInterpolator
|
val STANDARD = MR.attr.motionEasingStandardInterpolator
|
||||||
// val EMPHASIZED = MR.attr.motionEasingEmphasizedInterpolator
|
val EMPHASIZED = MR.attr.motionEasingEmphasizedInterpolator
|
||||||
val EMPHASIZED_ACCELERATE = MR.attr.motionEasingEmphasizedAccelerateInterpolator
|
val EMPHASIZED_ACCELERATE = MR.attr.motionEasingEmphasizedAccelerateInterpolator
|
||||||
val EMPHASIZED_DECELERATE = MR.attr.motionEasingEmphasizedDecelerateInterpolator
|
val EMPHASIZED_DECELERATE = MR.attr.motionEasingEmphasizedDecelerateInterpolator
|
||||||
val SHORT1 = MR.attr.motionDurationShort1 to 50
|
val SHORT1 = MR.attr.motionDurationShort1 to 50
|
||||||
// val SHORT2 = MR.attr.motionDurationShort2 to 100
|
val SHORT2 = MR.attr.motionDurationShort2 to 100
|
||||||
val SHORT3 = MR.attr.motionDurationShort3 to 150
|
val SHORT3 = MR.attr.motionDurationShort3 to 150
|
||||||
// val SHORT4 = MR.attr.motionDurationShort4 to 200
|
val SHORT4 = MR.attr.motionDurationShort4 to 200
|
||||||
val MEDIUM1 = MR.attr.motionDurationMedium1 to 250
|
val MEDIUM1 = MR.attr.motionDurationMedium1 to 250
|
||||||
val MEDIUM2 = MR.attr.motionDurationMedium2 to 300
|
val MEDIUM2 = MR.attr.motionDurationMedium2 to 300
|
||||||
val MEDIUM3 = MR.attr.motionDurationMedium3 to 350
|
val MEDIUM3 = MR.attr.motionDurationMedium3 to 350
|
||||||
// val MEDIUM4 = MR.attr.motionDurationMedium4 to 400
|
val MEDIUM4 = MR.attr.motionDurationMedium4 to 400
|
||||||
// val LONG1 = MR.attr.motionDurationLong1 to 450
|
val LONG1 = MR.attr.motionDurationLong1 to 450
|
||||||
// val LONG2 = MR.attr.motionDurationLong2 to 500
|
val LONG2 = MR.attr.motionDurationLong2 to 500
|
||||||
// val LONG3 = MR.attr.motionDurationLong3 to 550
|
val LONG3 = MR.attr.motionDurationLong3 to 550
|
||||||
// val LONG4 = MR.attr.motionDurationLong4 to 600
|
val LONG4 = MR.attr.motionDurationLong4 to 600
|
||||||
// val EXTRA_LONG1 = MR.attr.motionDurationExtraLong1 to 700
|
val EXTRA_LONG1 = MR.attr.motionDurationExtraLong1 to 700
|
||||||
// val EXTRA_LONG2 = MR.attr.motionDurationExtraLong2 to 800
|
val EXTRA_LONG2 = MR.attr.motionDurationExtraLong2 to 800
|
||||||
// val EXTRA_LONG3 = MR.attr.motionDurationExtraLong3 to 900
|
val EXTRA_LONG3 = MR.attr.motionDurationExtraLong3 to 900
|
||||||
// val EXTRA_LONG4 = MR.attr.motionDurationExtraLong4 to 1000
|
val EXTRA_LONG4 = MR.attr.motionDurationExtraLong4 to 1000
|
||||||
|
|
||||||
fun of(context: Context, @AttrRes interpolator: Int, duration: Pair<Int, Int>) =
|
fun of(context: Context, @AttrRes interpolator: Int, duration: Pair<Int, Int>) =
|
||||||
AnimConfig(context, interpolator, duration.first, duration.second)
|
AnimConfig(context, interpolator, duration.first, duration.second)
|
||||||
|
@ -122,7 +122,7 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jumpToFadeIn(view: View) {
|
fun jumpToFadeIn(view: View) {
|
||||||
view.apply {
|
view.apply {
|
||||||
alpha = 1f
|
alpha = 1f
|
||||||
scaleX = 1.0f
|
scaleX = 1.0f
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2025 Auxio Project
|
|
||||||
* EatInsetsFrameLayout.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.ui
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.WindowInsets
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import androidx.annotation.AttrRes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [FrameLayout] that works around the pre-Android 10 behavior of propagating mutated insets to
|
|
||||||
* sibling views. Wrap this around views that to isolate mutated window insets.
|
|
||||||
*
|
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
|
||||||
*/
|
|
||||||
class EatInsetsFrameLayout
|
|
||||||
@JvmOverloads
|
|
||||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
|
||||||
FrameLayout(context, attrs, defStyleAttr) {
|
|
||||||
init {
|
|
||||||
clipToPadding = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispatchApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
|
||||||
super.dispatchApplyWindowInsets(insets)
|
|
||||||
return insets
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -72,7 +72,7 @@ class UISettingsImpl @Inject constructor(@ApplicationContext context: Context) :
|
||||||
}
|
}
|
||||||
|
|
||||||
override val roundMode: Boolean
|
override val roundMode: Boolean
|
||||||
get() = sharedPreferences.getBoolean(getString(R.string.set_key_round_mode), true)
|
get() = sharedPreferences.getBoolean(getString(R.string.set_key_round_mode), false)
|
||||||
|
|
||||||
override fun migrate() {
|
override fun migrate() {
|
||||||
if (sharedPreferences.contains(OLD_KEY_ACCENT3)) {
|
if (sharedPreferences.contains(OLD_KEY_ACCENT3)) {
|
||||||
|
|
|
@ -65,22 +65,22 @@ private val accentThemes =
|
||||||
|
|
||||||
private val accentBlackThemes =
|
private val accentBlackThemes =
|
||||||
intArrayOf(
|
intArrayOf(
|
||||||
R.style.Theme_Auxio_Red_Black,
|
R.style.Theme_Auxio_Black_Red,
|
||||||
R.style.Theme_Auxio_Pink_Black,
|
R.style.Theme_Auxio_Black_Pink,
|
||||||
R.style.Theme_Auxio_Purple_Black,
|
R.style.Theme_Auxio_Black_Purple,
|
||||||
R.style.Theme_Auxio_DeepPurple_Black,
|
R.style.Theme_Auxio_Black_DeepPurple,
|
||||||
R.style.Theme_Auxio_Indigo_Black,
|
R.style.Theme_Auxio_Black_Indigo,
|
||||||
R.style.Theme_Auxio_Blue_Black,
|
R.style.Theme_Auxio_Black_Blue,
|
||||||
R.style.Theme_Auxio_DeepBlue_Black,
|
R.style.Theme_Auxio_Black_DeepBlue,
|
||||||
R.style.Theme_Auxio_Cyan_Black,
|
R.style.Theme_Auxio_Black_Cyan,
|
||||||
R.style.Theme_Auxio_Teal_Black,
|
R.style.Theme_Auxio_Black_Teal,
|
||||||
R.style.Theme_Auxio_Green_Black,
|
R.style.Theme_Auxio_Black_Green,
|
||||||
R.style.Theme_Auxio_DeepGreen_Black,
|
R.style.Theme_Auxio_Black_DeepGreen,
|
||||||
R.style.Theme_Auxio_Lime_Black,
|
R.style.Theme_Auxio_Black_Lime,
|
||||||
R.style.Theme_Auxio_Yellow_Black,
|
R.style.Theme_Auxio_Black_Yellow,
|
||||||
R.style.Theme_Auxio_Orange_Black,
|
R.style.Theme_Auxio_Black_Orange,
|
||||||
R.style.Theme_Auxio_Brown_Black,
|
R.style.Theme_Auxio_Black_Brown,
|
||||||
R.style.Theme_Auxio_Grey_Black,
|
R.style.Theme_Auxio_Black_Grey,
|
||||||
R.style.Theme_Auxio_Black // Dynamic colors are on the base theme
|
R.style.Theme_Auxio_Black // Dynamic colors are on the base theme
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
|
@ -35,6 +36,7 @@ import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.app.ShareCompat
|
import androidx.core.app.ShareCompat
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
@ -104,6 +106,10 @@ private fun isUnderImpl(
|
||||||
val View.isRtl: Boolean
|
val View.isRtl: Boolean
|
||||||
get() = layoutDirection == View.LAYOUT_DIRECTION_RTL
|
get() = layoutDirection == View.LAYOUT_DIRECTION_RTL
|
||||||
|
|
||||||
|
/** Whether this [Drawable] is using an RTL layout direction. */
|
||||||
|
val Drawable.isRtl: Boolean
|
||||||
|
get() = DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL
|
||||||
|
|
||||||
/** Get a [Context] from a [ViewBinding]'s root [View]. */
|
/** Get a [Context] from a [ViewBinding]'s root [View]. */
|
||||||
val ViewBinding.context: Context
|
val ViewBinding.context: Context
|
||||||
get() = root.context
|
get() = root.context
|
||||||
|
@ -351,7 +357,7 @@ fun Context.startIntent(intent: Intent) {
|
||||||
// No app installed to open the link
|
// No app installed to open the link
|
||||||
showToast(R.string.err_no_app)
|
showToast(R.string.err_no_app)
|
||||||
}
|
}
|
||||||
} else {
|
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
// On older versions of android, opening links from an ACTION_VIEW intent might
|
// On older versions of android, opening links from an ACTION_VIEW intent might
|
||||||
// not work in all cases, especially when no default app was set. If that is the
|
// not work in all cases, especially when no default app was set. If that is the
|
||||||
// case, we will try to manually handle these cases before we try to launch the
|
// case, we will try to manually handle these cases before we try to launch the
|
||||||
|
|
|
@ -22,11 +22,18 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
|
import kotlinx.coroutines.channels.SendChannel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withTimeout
|
||||||
|
import org.oxycblt.auxio.BuildConfig
|
||||||
|
import timber.log.Timber as L
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper around [StateFlow] exposing a one-time consumable event.
|
* A wrapper around [StateFlow] exposing a one-time consumable event.
|
||||||
|
@ -146,3 +153,71 @@ private fun Fragment.launch(
|
||||||
) {
|
) {
|
||||||
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(state, block) }
|
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(state, block) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val DEFAULT_TIMEOUT = 60000L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps [SendChannel.send] with a specified timeout.
|
||||||
|
*
|
||||||
|
* @param element The element to send.
|
||||||
|
* @param timeout The timeout in milliseconds. Defaults to 10 seconds.
|
||||||
|
* @throws TimeoutException If the timeout is reached, provides context on what element
|
||||||
|
* specifically.
|
||||||
|
*/
|
||||||
|
suspend fun <E> SendChannel<E>.sendWithTimeout(element: E, timeout: Long = DEFAULT_TIMEOUT) {
|
||||||
|
try {
|
||||||
|
withTimeout(timeout) { send(element) }
|
||||||
|
} catch (e: TimeoutCancellationException) {
|
||||||
|
L.e("Failed to send element to channel $e in ${timeout}ms.")
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
throw TimeoutException("Timed out sending element to channel: $e")
|
||||||
|
} else {
|
||||||
|
L.e(e.stackTraceToString())
|
||||||
|
send(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a [ReceiveChannel] consumption with a specified timeout. Note that the timeout will only
|
||||||
|
* start on the first element received, as to prevent initialization of dependent coroutines being
|
||||||
|
* interpreted as a timeout.
|
||||||
|
*
|
||||||
|
* @param action The action to perform on each element received.
|
||||||
|
* @param timeout The timeout in milliseconds. Defaults to 10 seconds.
|
||||||
|
* @throws TimeoutException If the timeout is reached, provides context on what element
|
||||||
|
* specifically.
|
||||||
|
*/
|
||||||
|
suspend fun <E> ReceiveChannel<E>.forEachWithTimeout(
|
||||||
|
timeout: Long = DEFAULT_TIMEOUT,
|
||||||
|
action: suspend (E) -> Unit
|
||||||
|
) {
|
||||||
|
var exhausted = false
|
||||||
|
var subsequent = false
|
||||||
|
val handler: suspend () -> Unit = {
|
||||||
|
val value = receiveCatching()
|
||||||
|
if (value.isClosed && value.exceptionOrNull() == null) {
|
||||||
|
exhausted = true
|
||||||
|
} else {
|
||||||
|
action(value.getOrThrow())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!exhausted) {
|
||||||
|
try {
|
||||||
|
if (subsequent) {
|
||||||
|
withTimeout(timeout) { handler() }
|
||||||
|
} else {
|
||||||
|
handler()
|
||||||
|
subsequent = true
|
||||||
|
}
|
||||||
|
} catch (e: TimeoutCancellationException) {
|
||||||
|
L.e("Failed to send element to channel $e in ${timeout}ms.")
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
throw TimeoutException("Timed out sending element to channel: $e")
|
||||||
|
} else {
|
||||||
|
L.e(e.stackTraceToString())
|
||||||
|
handler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.oxycblt.auxio.widgets
|
||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import androidx.core.graphics.scale
|
|
||||||
import coil3.size.Size
|
import coil3.size.Size
|
||||||
import coil3.transform.Transformation
|
import coil3.transform.Transformation
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
@ -50,7 +49,7 @@ class WidgetBitmapTransformation(reduce: Float) : Transformation() {
|
||||||
val scale = sqrt(maxBitmapArea / inputArea.toDouble())
|
val scale = sqrt(maxBitmapArea / inputArea.toDouble())
|
||||||
val newWidth = (input.width * scale).toInt()
|
val newWidth = (input.width * scale).toInt()
|
||||||
val newHeight = (input.height * scale).toInt()
|
val newHeight = (input.height * scale).toInt()
|
||||||
return input.scale(newWidth, newHeight)
|
return Bitmap.createScaledBitmap(input, newWidth, newHeight, true)
|
||||||
}
|
}
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.oxycblt.auxio.widgets
|
package org.oxycblt.auxio.widgets
|
||||||
|
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.appwidget.AppWidgetProviderInfo
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
@ -65,6 +66,11 @@ fun RemoteViews.setLayoutDirection(@IdRes viewId: Int, layoutDirection: Int) {
|
||||||
setInt(viewId, "setLayoutDirection", layoutDirection)
|
setInt(viewId, "setLayoutDirection", layoutDirection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun AppWidgetManager.setWidgetPreviewCompat(component: ComponentName, remoteViews: RemoteViews) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
setWidgetPreview(component, AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN, remoteViews)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Update the app widget layouts corresponding to the given [WidgetProvider] [ComponentName] with an
|
* Update the app widget layouts corresponding to the given [WidgetProvider] [ComponentName] with an
|
||||||
* adaptive layout, in a version-compatible manner.
|
* adaptive layout, in a version-compatible manner.
|
||||||
|
|
|
@ -3,94 +3,79 @@
|
||||||
xmlns:aapt="http://schemas.android.com/aapt">
|
xmlns:aapt="http://schemas.android.com/aapt">
|
||||||
<aapt:attr name="android:drawable">
|
<aapt:attr name="android:drawable">
|
||||||
<vector
|
<vector
|
||||||
android:width="432dp"
|
android:width="108dp"
|
||||||
android:height="432dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="432"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="432">
|
android:viewportHeight="108">
|
||||||
<group
|
<group
|
||||||
android:name="bg"
|
android:name="bg"
|
||||||
android:pivotX="56"
|
android:pivotX="56"
|
||||||
android:pivotY="56">
|
android:pivotY="56">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#00000000"
|
android:fillColor="#ffffff"
|
||||||
android:strokeColor="#00000000"
|
android:pathData="M 136,54 A 82,82 0 0 1 54,136 82,82 0 0 1 -28,54 82,82 0 0 1 54,-28 82,82 0 0 1 136,54 Z"
|
||||||
android:pathData="M 408,216
|
android:strokeColor="#00000000" />
|
||||||
A 192,192 0 0 1 216,408 192,192 0 0 1 24,216 192,192 0 0 1 216,24 192,192 0 0 1 408,216
|
|
||||||
Z" />
|
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
|
||||||
android:scaleX="8.5"
|
|
||||||
android:scaleY="8.5"
|
|
||||||
android:translateX="114"
|
|
||||||
android:translateY="114">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/transparent"
|
|
||||||
android:pathData="M13 4l4 4m-4-4v13m0 0l-3 3-3-3 3-3"
|
|
||||||
android:strokeWidth="2"
|
|
||||||
android:strokeColor="#80808080"
|
|
||||||
android:strokeLineCap="round"
|
|
||||||
android:strokeLineJoin="round" />
|
|
||||||
</group>
|
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:scaleX="8.5"
|
android:name="base"
|
||||||
android:scaleY="8.5"
|
android:scaleX="2.835"
|
||||||
android:translateX="114"
|
android:scaleY="2.835"
|
||||||
android:translateY="114">
|
android:translateX="19.98"
|
||||||
|
android:translateY="-64">
|
||||||
<path
|
<path
|
||||||
android:name="base"
|
|
||||||
android:fillColor="@android:color/transparent"
|
android:fillColor="@android:color/transparent"
|
||||||
android:pathData="m 13,17 -3,3 -3,-3 3,-3"
|
android:pathData="m 13,17 -3,3 -3,-3 3,-3"
|
||||||
android:strokeWidth="0"
|
android:strokeWidth="2"
|
||||||
android:strokeColor="#004894"
|
android:strokeColor="#004894"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:scaleX="8.5"
|
android:name="lower_stem"
|
||||||
android:scaleY="8.5"
|
android:scaleX="2.835"
|
||||||
android:translateX="114"
|
android:scaleY="2.835"
|
||||||
android:translateY="114">
|
android:translateX="19.98"
|
||||||
|
android:translateY="-64">
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:name="lower_stem"
|
|
||||||
android:fillColor="@android:color/transparent"
|
android:fillColor="@android:color/transparent"
|
||||||
android:pathData="M 13,10.5 V 17"
|
android:pathData="M 13,10.5 V 17"
|
||||||
android:strokeWidth="0"
|
android:strokeWidth="2"
|
||||||
android:strokeColor="#1a61ae"
|
android:strokeColor="#1a61ae"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:scaleX="8.5"
|
android:name="upper_stem"
|
||||||
android:scaleY="8.5"
|
android:scaleX="2.835"
|
||||||
android:translateX="114"
|
android:scaleY="2.835"
|
||||||
android:translateY="114">
|
android:translateX="19.98"
|
||||||
|
android:translateY="-64">
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:name="upper_stem"
|
|
||||||
android:fillColor="@android:color/transparent"
|
android:fillColor="@android:color/transparent"
|
||||||
android:pathData="m 13,4v 6.5"
|
android:pathData="m 13,4v 6.5"
|
||||||
android:strokeWidth="0"
|
android:strokeWidth="2"
|
||||||
android:strokeColor="#357ac9"
|
android:strokeColor="#357ac9"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:scaleX="8.5"
|
android:name="tail"
|
||||||
android:scaleY="8.5"
|
android:scaleX="2.835"
|
||||||
android:translateX="114"
|
android:scaleY="2.835"
|
||||||
android:translateY="114">
|
android:translateX="19.98"
|
||||||
|
android:translateY="-64">
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:name="tail"
|
|
||||||
android:fillColor="@android:color/transparent"
|
android:fillColor="@android:color/transparent"
|
||||||
android:pathData="m 13,4 4,4"
|
android:pathData="m 13,4 4,4"
|
||||||
android:strokeWidth="0"
|
android:strokeWidth="2"
|
||||||
android:strokeColor="#5093e4"
|
android:strokeColor="#5093e4"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
|
@ -106,12 +91,12 @@ Z" />
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="850"
|
android:duration="500"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="strokeWidth"
|
android:propertyName="translateY"
|
||||||
android:startOffset="150"
|
android:startOffset="0"
|
||||||
android:valueFrom="0"
|
android:valueFrom="-512"
|
||||||
android:valueTo="2"
|
android:valueTo="19.98"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
@ -121,12 +106,12 @@ Z" />
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="850"
|
android:duration="500"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="strokeWidth"
|
android:propertyName="translateY"
|
||||||
android:startOffset="150"
|
android:startOffset="0"
|
||||||
android:valueFrom="0"
|
android:valueFrom="-256"
|
||||||
android:valueTo="2"
|
android:valueTo="19.98"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
@ -137,12 +122,12 @@ Z" />
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="850"
|
android:duration="500"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="strokeWidth"
|
android:propertyName="translateY"
|
||||||
android:startOffset="150"
|
android:startOffset="0"
|
||||||
android:valueFrom="0"
|
android:valueFrom="-128"
|
||||||
android:valueTo="2"
|
android:valueTo="19.98"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
@ -152,12 +137,12 @@ Z" />
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="850"
|
android:duration="500"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="strokeWidth"
|
android:propertyName="translateY"
|
||||||
android:startOffset="150"
|
android:startOffset="0"
|
||||||
android:valueFrom="0"
|
android:valueFrom="-64"
|
||||||
android:valueTo="2"
|
android:valueTo="19.98"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
|
|
@ -119,8 +119,7 @@
|
||||||
app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button"
|
app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/detail_cover"
|
app:layout_constraintTop_toBottomOf="@+id/detail_cover" />
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.RippleFixMaterialButton
|
<org.oxycblt.auxio.ui.RippleFixMaterialButton
|
||||||
android:id="@+id/detail_shuffle_button"
|
android:id="@+id/detail_shuffle_button"
|
||||||
|
|
|
@ -101,8 +101,7 @@
|
||||||
app:icon="@drawable/ic_play_24"
|
app:icon="@drawable/ic_play_24"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button"
|
app:layout_constraintEnd_toStartOf="@+id/detail_shuffle_button"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/detail_info"
|
app:layout_constraintTop_toBottomOf="@+id/detail_info" />
|
||||||
tools:ignore="RtlSymmetry"/>
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.RippleFixMaterialButton
|
<org.oxycblt.auxio.ui.RippleFixMaterialButton
|
||||||
android:id="@+id/detail_shuffle_button"
|
android:id="@+id/detail_shuffle_button"
|
||||||
|
|
|
@ -129,8 +129,7 @@
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/detail_play_button"
|
app:layout_constraintBottom_toBottomOf="@+id/detail_play_button"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/detail_play_button"
|
app:layout_constraintStart_toEndOf="@+id/detail_play_button"
|
||||||
app:layout_constraintTop_toTopOf="@+id/detail_play_button"
|
app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
|
|
@ -132,8 +132,7 @@
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/detail_play_button"
|
app:layout_constraintBottom_toBottomOf="@+id/detail_play_button"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/detail_play_button"
|
app:layout_constraintStart_toEndOf="@+id/detail_play_button"
|
||||||
app:layout_constraintTop_toTopOf="@+id/detail_play_button"
|
app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.EatInsetsFrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior">
|
app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior">
|
||||||
|
@ -22,9 +22,7 @@
|
||||||
app:navGraph="@navigation/inner"
|
app:navGraph="@navigation/inner"
|
||||||
tools:layout="@layout/fragment_home" />
|
tools:layout="@layout/fragment_home" />
|
||||||
|
|
||||||
|
<org.oxycblt.auxio.home.EdgeFrameLayout
|
||||||
<org.oxycblt.auxio.ui.EdgeFrameLayout
|
|
||||||
android:id="@+id/main_fab_container"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
@ -41,7 +39,6 @@
|
||||||
android:contentDescription="@string/lbl_new_playlist"
|
android:contentDescription="@string/lbl_new_playlist"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="bottom|end"
|
android:gravity="bottom|end"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
|
||||||
app:sdMainFabAnimationRotateAngle="135"
|
app:sdMainFabAnimationRotateAngle="135"
|
||||||
app:sdMainFabClosedIconColor="@android:color/white"
|
app:sdMainFabClosedIconColor="@android:color/white"
|
||||||
app:sdMainFabClosedSrc="@drawable/ic_add_24" />
|
app:sdMainFabClosedSrc="@drawable/ic_add_24" />
|
||||||
|
@ -50,14 +47,14 @@
|
||||||
android:id="@+id/home_shuffle_fab"
|
android:id="@+id/home_shuffle_fab"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:contentDescription="@string/lbl_shuffle"
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
android:contentDescription="@string/desc_shuffle_all"
|
||||||
android:src="@drawable/ic_shuffle_off_24" />
|
android:src="@drawable/ic_shuffle_off_24" />
|
||||||
|
|
||||||
</org.oxycblt.auxio.ui.EdgeFrameLayout>
|
</org.oxycblt.auxio.home.EdgeFrameLayout>
|
||||||
|
|
||||||
</org.oxycblt.auxio.ui.EatInsetsFrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
|
@ -226,17 +226,6 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/about_sup_mark_pitblado"
|
|
||||||
style="@style/Widget.Auxio.TextView.Icon.Clickable"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/sup_mark_pitblado"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:drawableStartCompat="@drawable/ic_person_24"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/about_licenses" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/about_supporters_promo"
|
android:id="@+id/about_supporters_promo"
|
||||||
style="@style/Widget.Auxio.TextView.Icon.Clickable"
|
style="@style/Widget.Auxio.TextView.Icon.Clickable"
|
||||||
|
|
|
@ -72,7 +72,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="top|start"
|
android:layout_gravity="top|start"
|
||||||
android:transitionGroup="true"
|
android:transitionGroup="true"
|
||||||
android:visibility="invisible"
|
|
||||||
android:layout_margin="@dimen/spacing_medium">
|
android:layout_margin="@dimen/spacing_medium">
|
||||||
|
|
||||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
tools:listitem="@layout/item_song" />
|
tools:listitem="@layout/item_song" />
|
||||||
|
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.EdgeFrameLayout
|
<org.oxycblt.auxio.home.EdgeFrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@
|
||||||
android:layout_height="@dimen/size_icon_huge"
|
android:layout_height="@dimen/size_icon_huge"
|
||||||
android:layout_marginBottom="@dimen/spacing_small"
|
android:layout_marginBottom="@dimen/spacing_small"
|
||||||
android:src="@drawable/ic_song_48"
|
android:src="@drawable/ic_song_48"
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
app:tint="?attr/colorOnSurface" />
|
app:tint="?attr/colorOnSurface" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -54,5 +53,5 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</org.oxycblt.auxio.ui.EdgeFrameLayout>
|
</org.oxycblt.auxio.home.EdgeFrameLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface"
|
||||||
android:transitionGroup="true">
|
android:transitionGroup="true">
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.EatInsetsFrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior">
|
app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior">
|
||||||
|
@ -28,8 +28,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="invisible" />
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.EdgeFrameLayout
|
<org.oxycblt.auxio.home.EdgeFrameLayout
|
||||||
android:id="@+id/main_fab_container"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
@ -46,7 +45,6 @@
|
||||||
android:contentDescription="@string/lbl_new_playlist"
|
android:contentDescription="@string/lbl_new_playlist"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="bottom|end"
|
android:gravity="bottom|end"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
|
||||||
app:sdMainFabAnimationRotateAngle="135"
|
app:sdMainFabAnimationRotateAngle="135"
|
||||||
app:sdMainFabClosedIconColor="@android:color/white"
|
app:sdMainFabClosedIconColor="@android:color/white"
|
||||||
app:sdMainFabClosedSrc="@drawable/ic_add_24" />
|
app:sdMainFabClosedSrc="@drawable/ic_add_24" />
|
||||||
|
@ -55,14 +53,14 @@
|
||||||
android:id="@+id/home_shuffle_fab"
|
android:id="@+id/home_shuffle_fab"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
android:contentDescription="@string/lbl_shuffle"
|
android:contentDescription="@string/lbl_shuffle"
|
||||||
android:src="@drawable/ic_shuffle_off_24" />
|
android:src="@drawable/ic_shuffle_off_24" />
|
||||||
|
|
||||||
</org.oxycblt.auxio.ui.EdgeFrameLayout>
|
</org.oxycblt.auxio.home.EdgeFrameLayout>
|
||||||
|
|
||||||
</org.oxycblt.auxio.ui.EatInsetsFrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/main_sheet_scrim"
|
android:id="@+id/main_sheet_scrim"
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="@dimen/spacing_tiny"
|
android:padding="@dimen/spacing_tiny"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="@dimen/size_touchable_small"
|
android:layout_height="@dimen/size_touchable_small"
|
||||||
android:scaleType="centerInside"
|
android:scaleType="centerInside"
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
android:src="@drawable/ui_scroll_thumb" />
|
android:src="@drawable/ui_scroll_thumb" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -22,7 +22,7 @@
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:background="@drawable/ui_widget_bg_round"
|
android:background="@drawable/ui_widget_bg_round"
|
||||||
android:clipToOutline="true"
|
android:clipToOutline="true"
|
||||||
tools:ignore="ContentDescription,UnusedAttribute" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
android:id="@+id/widget_panel"
|
android:id="@+id/widget_panel"
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:background="@drawable/ui_widget_bg_round"
|
android:background="@drawable/ui_widget_bg_round"
|
||||||
tools:ignore="ContentDescription,UnusedAttribute" />
|
android:clipToOutline="true"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
android:id="@+id/widget_panel"
|
android:id="@+id/widget_panel"
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<string name="lng_widget">عرض وتحكم بشتغيل الموسيقى</string>
|
<string name="lng_widget">عرض وتحكم بشتغيل الموسيقى</string>
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">إعادة المحاولة</string>
|
<string name="lbl_retry">إعادة المحاولة</string>
|
||||||
|
<string name="lbl_grant">منح</string>
|
||||||
<string name="lbl_genres">الانواع</string>
|
<string name="lbl_genres">الانواع</string>
|
||||||
<string name="lbl_artists">فنانين</string>
|
<string name="lbl_artists">فنانين</string>
|
||||||
<string name="lbl_albums">البومات</string>
|
<string name="lbl_albums">البومات</string>
|
||||||
|
@ -26,40 +27,42 @@
|
||||||
<string name="set_play_song_from_album">تشغيل من البوم</string>
|
<string name="set_play_song_from_album">تشغيل من البوم</string>
|
||||||
<string name="set_play_song_from_artist">تشغيل من فنان</string>
|
<string name="set_play_song_from_artist">تشغيل من فنان</string>
|
||||||
<string name="lbl_queue">طابور</string>
|
<string name="lbl_queue">طابور</string>
|
||||||
<string name="lbl_play_next">شغل التالي</string>
|
<string name="lbl_play_next">شغل الاغنية التالية</string>
|
||||||
<string name="lbl_queue_add">أضف إلى الطابور</string>
|
<string name="lbl_queue_add">أضف إلى الطابور</string>
|
||||||
<string name="lng_queue_added">تمت الإضافة إلى الطابور</string>
|
<string name="lng_queue_added">تمت الإضافة إلى الطابور</string>
|
||||||
<string name="lbl_artist_details">أذهب إلى الفنان</string>
|
<string name="lbl_artist_details">أذهب إلى الفنان</string>
|
||||||
<string name="lbl_album_details">أذهب إلى الالبوم</string>
|
<string name="lbl_album_details">أذهب إلى الالبوم</string>
|
||||||
|
<string name="lbl_add">أضف</string>
|
||||||
<string name="lbl_save">حفظ</string>
|
<string name="lbl_save">حفظ</string>
|
||||||
|
<string name="err_no_locations">لا مجلد</string>
|
||||||
<string name="lbl_about">حول</string>
|
<string name="lbl_about">حول</string>
|
||||||
<string name="lbl_version">الإصدار</string>
|
<string name="lbl_version">الإصدار</string>
|
||||||
<string name="lbl_code">كود البرنامج</string>
|
<string name="lbl_code">عرض على الكود في Github</string>
|
||||||
<string name="lbl_licenses">التراخيص</string>
|
<string name="lbl_licenses">التراخيص</string>
|
||||||
<string name="lbl_author_name">الكساندر كابيهارت</string>
|
<string name="lbl_author_name">تمت برمجة التطبيق من قبل الكساندر كابيهارت</string>
|
||||||
<!-- Settings namespace | Settings-related labels -->
|
<!-- Settings namespace | Settings-related labels -->
|
||||||
<string name="set_root_title">الإعدادات</string>
|
<string name="set_root_title">الإعدادات</string>
|
||||||
<string name="set_ui">المظهر والاحساس</string>
|
<string name="set_ui">المظهر</string>
|
||||||
<string name="set_theme">السمة</string>
|
<string name="set_theme">السمة</string>
|
||||||
<string name="set_theme_auto">تلقائي</string>
|
<string name="set_theme_auto">تلقائي</string>
|
||||||
<string name="set_theme_day">فاتح</string>
|
<string name="set_theme_day">فاتح</string>
|
||||||
<string name="set_theme_night">مظلم</string>
|
<string name="set_theme_night">مظلم</string>
|
||||||
<string name="set_accent">نظام الألوان</string>
|
<string name="set_accent">نظام الألوان</string>
|
||||||
<string name="set_black_mode">السمة السوداء</string>
|
<string name="set_black_mode">السمة السوداء</string>
|
||||||
<string name="set_black_mode_desc">استخدام سمة اللون الاسود النقي</string>
|
<string name="set_black_mode_desc">استخدام اللون الاسود القاتم في الوضع المظلم</string>
|
||||||
<string name="set_display">عرض</string>
|
<string name="set_display">عرض</string>
|
||||||
<string name="set_lib_tabs">تبويتات المكتبة</string>
|
<string name="set_lib_tabs">تبويتات المكتبة</string>
|
||||||
<string name="set_lib_tabs_desc">تغيير ظهور وترتيب تبويتات المكتبة</string>
|
<string name="set_lib_tabs_desc">تغيير ظهور وترتيب تبويتات المكتبة</string>
|
||||||
<string name="set_round_mode">وضع دائري</string>
|
<string name="set_round_mode">اغلفة البوم مدورة</string>
|
||||||
<string name="set_round_mode_desc">تفعيل الزوايا المدورة لحدات الواجهه الاضافية (يتطلب اغلفة الالبوم ان تكون مدورة)</string>
|
<string name="set_round_mode_desc">جعل اغلفة الابومات ذات زوايا مدورة</string>
|
||||||
<string name="set_notif_action">فعالية تنبيه مخصصة</string>
|
<string name="set_notif_action">استخدام نشاط بديل للإشعار</string>
|
||||||
<string name="set_audio">صوتيات</string>
|
<string name="set_audio">صوتيات</string>
|
||||||
<string name="set_replay_gain_mode">صخب الصوت</string>
|
<string name="set_replay_gain_mode">صخب الصوت</string>
|
||||||
<string name="set_replay_gain_mode_track">تفضيل المقطع</string>
|
<string name="set_replay_gain_mode_track">تفضيل المقطع</string>
|
||||||
<string name="set_replay_gain_mode_album">تفضيل الالبوم</string>
|
<string name="set_replay_gain_mode_album">تفضيل الالبوم</string>
|
||||||
<string name="set_replay_gain_mode_dynamic">ديناميكي</string>
|
<string name="set_replay_gain_mode_dynamic">ديناميكي</string>
|
||||||
<string name="set_personalize">تخصيص</string>
|
<string name="set_personalize">سلوك</string>
|
||||||
<string name="set_play_in_list_with">عند التشغيل من المكتبة</string>
|
<string name="set_play_in_list_with">عند اختيار اغنية</string>
|
||||||
<string name="set_keep_shuffle">تذكر الخلط</string>
|
<string name="set_keep_shuffle">تذكر الخلط</string>
|
||||||
<string name="set_keep_shuffle_desc">إبقاء وضع الخلط عند تشغيل اغنية جديدة</string>
|
<string name="set_keep_shuffle_desc">إبقاء وضع الخلط عند تشغيل اغنية جديدة</string>
|
||||||
<string name="set_rewind_prev">تشجيع قبل التخطي للخلف</string>
|
<string name="set_rewind_prev">تشجيع قبل التخطي للخلف</string>
|
||||||
|
@ -68,11 +71,13 @@
|
||||||
<string name="set_repeat_pause_desc">ايقاف مؤقت عند تكرار تشغيل اغنية</string>
|
<string name="set_repeat_pause_desc">ايقاف مؤقت عند تكرار تشغيل اغنية</string>
|
||||||
<string name="set_content">محتوى</string>
|
<string name="set_content">محتوى</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">لم يتم ايجاد موسيقى</string>
|
||||||
<string name="err_index_failed">فشل تحميل الموسيقى</string>
|
<string name="err_index_failed">فشل تحميل الموسيقى</string>
|
||||||
|
<string name="err_no_perms">اوكسيو يحتاج إلى صلاحيات لقراءة للاطلاع على مكتبتك للموسيقى</string>
|
||||||
<string name="err_no_app">لا يوجد تطبيق لفتح هذا الرابط</string>
|
<string name="err_no_app">لا يوجد تطبيق لفتح هذا الرابط</string>
|
||||||
<string name="err_bad_location">هذا المجلد غير مدعوم</string>
|
<string name="err_bad_location">هذا المجلد غير مدعوم</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="lng_search_library">ابحث في مكتبتك…</string>
|
<string name="lng_search_library">البحث في مكتبتك…</string>
|
||||||
<!-- Description Namespace | Accessibility Strings -->
|
<!-- Description Namespace | Accessibility Strings -->
|
||||||
<string name="desc_track_number">المقطع %d</string>
|
<string name="desc_track_number">المقطع %d</string>
|
||||||
<string name="desc_play_pause">تشغيل او ايقاف مؤقت</string>
|
<string name="desc_play_pause">تشغيل او ايقاف مؤقت</string>
|
||||||
|
@ -80,6 +85,7 @@
|
||||||
<string name="desc_skip_prev">تخطي للاغنية الاخيرة</string>
|
<string name="desc_skip_prev">تخطي للاغنية الاخيرة</string>
|
||||||
<string name="desc_change_repeat">تغيير وضع التكرار</string>
|
<string name="desc_change_repeat">تغيير وضع التكرار</string>
|
||||||
<string name="desc_shuffle">تشغيل او اطفاء الخلط</string>
|
<string name="desc_shuffle">تشغيل او اطفاء الخلط</string>
|
||||||
|
<string name="desc_shuffle_all">خلط جميع الاغاني</string>
|
||||||
<string name="desc_remove_song">إزالة اغنية من الطابور</string>
|
<string name="desc_remove_song">إزالة اغنية من الطابور</string>
|
||||||
<string name="desc_song_handle">نقل اغنية من الطابور</string>
|
<string name="desc_song_handle">نقل اغنية من الطابور</string>
|
||||||
<string name="desc_tab_handle">تحريك التبويت</string>
|
<string name="desc_tab_handle">تحريك التبويت</string>
|
||||||
|
@ -130,44 +136,44 @@
|
||||||
<item quantity="many">%d ألبومات</item>
|
<item quantity="many">%d ألبومات</item>
|
||||||
<item quantity="other">%d ألبومات</item>
|
<item quantity="other">%d ألبومات</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="lbl_mix">مكس دي جي</string>
|
<string name="lbl_mix">MixMix</string>
|
||||||
<string name="lbl_cancel">الغاء</string>
|
<string name="lbl_cancel">الغاء</string>
|
||||||
<string name="lbl_format">التنسيق</string>
|
<string name="lbl_format">التنسيق</string>
|
||||||
<string name="lbl_size">الحجم</string>
|
<string name="lbl_size">الحجم</string>
|
||||||
<string name="lbl_library_counts">إحصائيات المكتبة</string>
|
<string name="lbl_library_counts">إحصائيات المكتبة</string>
|
||||||
<string name="lbl_bitrate">معدل البت</string>
|
<string name="lbl_bitrate">معدل البت</string>
|
||||||
<string name="lbl_compilation_live">تجميع مباشر</string>
|
<string name="lbl_compilation_live">تجميع مباشر</string>
|
||||||
<string name="lbl_compilation_remix">تجميعات ريمكس</string>
|
<string name="lbl_compilation_remix">تجميعات</string>
|
||||||
<string name="lbl_props">خصائص الاغنية</string>
|
<string name="lbl_props">خصائص الاغنية</string>
|
||||||
<string name="lbl_sample_rate">معدل العينة</string>
|
<string name="lbl_sample_rate">معدل العينة</string>
|
||||||
<string name="lbl_shuffle_shortcut_short">عشوائي</string>
|
<string name="lbl_shuffle_shortcut_short">عشوائي</string>
|
||||||
<string name="lbl_shuffle_shortcut_long">تشغيل عشوائي للكل</string>
|
<string name="lbl_shuffle_shortcut_long">تشغيل كل الاغاني بشكل عشوائي</string>
|
||||||
<string name="lbl_ok">حسنا</string>
|
<string name="lbl_ok">حسنا</string>
|
||||||
<string name="lbl_sort_dsc">تنازلي</string>
|
<string name="lbl_sort_dsc">تنازلي</string>
|
||||||
<string name="lbl_song_detail">عرض الخصائص</string>
|
<string name="lbl_song_detail">عرض الخصائص</string>
|
||||||
<string name="lbl_live_group">مباشر</string>
|
<string name="lbl_live_group">مباشر</string>
|
||||||
<string name="lbl_reset">اعادة ضبط</string>
|
<string name="lbl_reset">اعادة ضبط</string>
|
||||||
<string name="lng_indexing">يتم تحمل مكتبتك الموسيقية …</string>
|
<string name="lng_indexing">يتم تحمل مكتبتك …</string>
|
||||||
<string name="lbl_genre">النوع</string>
|
<string name="lbl_genre">النوع</string>
|
||||||
<string name="lng_observing">مراقبة تغييرات في مكتبتك الموسيقية…</string>
|
<string name="lng_observing">مراقبة تغييرات في مكتبتك</string>
|
||||||
<string name="lbl_observing">مراقبة مكتبة الموسيقة</string>
|
<string name="lbl_observing">مراقبة مكتبة الموسيقة</string>
|
||||||
<string name="lbl_indexer">تحميل الموسيقى</string>
|
<string name="lbl_indexer">تحميل الموسيقى</string>
|
||||||
<string name="lbl_equalizer">المعادل</string>
|
<string name="lbl_equalizer">المعادل</string>
|
||||||
<string name="lbl_singles">فرديات</string>
|
<string name="lbl_singles">منفصل</string>
|
||||||
<string name="lbl_single">فردي</string>
|
<string name="lbl_single">فردي</string>
|
||||||
<string name="lbl_ep">أغنية مطولة</string>
|
<string name="lbl_ep">EP</string>
|
||||||
<string name="lbl_eps">أغاني مطولة</string>
|
<string name="lbl_eps">EPs</string>
|
||||||
<string name="lbl_mixtape">مكس</string>
|
<string name="lbl_mixtape">Mixtape</string>
|
||||||
<string name="lbl_soundtrack">موسيقى تصويرية</string>
|
<string name="lbl_soundtrack">تسجيل صوتي</string>
|
||||||
<string name="lbl_mixtapes">مكسات</string>
|
<string name="lbl_mixtapes">Mixtapes</string>
|
||||||
<string name="lbl_remix_group">RemixesRemixes</string>
|
<string name="lbl_remix_group">RemixesRemixes</string>
|
||||||
<string name="lbl_soundtracks">موسيقات تصويرية</string>
|
<string name="lbl_soundtracks">الموسيقى التصويرية</string>
|
||||||
<string name="lbl_album_live">البوم مباشر</string>
|
<string name="lbl_album_live">البوم مباشر</string>
|
||||||
<string name="lbl_album_remix">البوم ريمكس</string>
|
<string name="lbl_album_remix">ريمكس</string>
|
||||||
<string name="lbl_ep_live">أغنية مطولة مباشرة</string>
|
<string name="lbl_ep_live">مؤاثرات مباشرة</string>
|
||||||
<string name="lbl_ep_remix">اغنية مطولة ريمكس</string>
|
<string name="lbl_ep_remix">مؤاثرات ريمكس</string>
|
||||||
<string name="lbl_single_live">بث مباشر فردي</string>
|
<string name="lbl_single_live">بث مباشر فردي</string>
|
||||||
<string name="lbl_single_remix">ريمكس فردي</string>
|
<string name="lbl_single_remix">ريمكس منفصل</string>
|
||||||
<string name="lbl_compilations">تجميعات</string>
|
<string name="lbl_compilations">تجميعات</string>
|
||||||
<string name="lbl_duration">مدة</string>
|
<string name="lbl_duration">مدة</string>
|
||||||
<string name="lbl_song_count">عدد الأغاني</string>
|
<string name="lbl_song_count">عدد الأغاني</string>
|
||||||
|
@ -175,15 +181,16 @@
|
||||||
<string name="lbl_track">مسار</string>
|
<string name="lbl_track">مسار</string>
|
||||||
<string name="lbl_date_added">تاريخ الاضافة</string>
|
<string name="lbl_date_added">تاريخ الاضافة</string>
|
||||||
<string name="lbl_indexing">تحميل الموسيقى</string>
|
<string name="lbl_indexing">تحميل الموسيقى</string>
|
||||||
<string name="lbl_compilation">تجميع</string>
|
<string name="lbl_compilation">التحويل البرمجي</string>
|
||||||
<string name="lbl_mixes">مكسات دي جي</string>
|
<string name="lbl_mixes">مزيج</string>
|
||||||
<string name="lbl_wiki">ويكي</string>
|
<string name="lbl_wiki">Wiki</string>
|
||||||
<string name="lbl_song">أغنية</string>
|
<string name="lbl_song">أغنية</string>
|
||||||
<string name="lbl_sort_direction">أتجاه</string>
|
<string name="lbl_sort_direction">أتجاه</string>
|
||||||
<string name="lbl_selection">أختيار</string>
|
<string name="lbl_selection">أختيار</string>
|
||||||
<string name="lbl_playlists">قوائم التشغيل</string>
|
<string name="lbl_playlists">قوائم التشغيل</string>
|
||||||
<string name="lbl_playlist">قائمة التشغيل</string>
|
<string name="lbl_playlist">قائمة التشغيل</string>
|
||||||
<string name="lng_playlist_created">تم خلق قائمة التشغيل</string>
|
<string name="lng_playlist_created">تم خلق قائمة التشغيل</string>
|
||||||
|
<string name="lbl_show_error_info">المزيد</string>
|
||||||
<string name="lbl_delete">حذف</string>
|
<string name="lbl_delete">حذف</string>
|
||||||
<string name="lbl_copied">تم النسخ</string>
|
<string name="lbl_copied">تم النسخ</string>
|
||||||
<string name="lbl_playlist_add">إضافة إلى قائمة التشغيل</string>
|
<string name="lbl_playlist_add">إضافة إلى قائمة التشغيل</string>
|
||||||
|
@ -197,66 +204,8 @@
|
||||||
<string name="lng_playlist_deleted">تم حذف قائمة التشغيل</string>
|
<string name="lng_playlist_deleted">تم حذف قائمة التشغيل</string>
|
||||||
<string name="lbl_report">تقرير</string>
|
<string name="lbl_report">تقرير</string>
|
||||||
<string name="lbl_new_playlist">قائمة تشغيل جديدة</string>
|
<string name="lbl_new_playlist">قائمة تشغيل جديدة</string>
|
||||||
<string name="lbl_error_info">معلومات الخطأ</string>
|
<string name="lbl_error_info">معلومات خاطئة</string>
|
||||||
<string name="lng_playlist_renamed">تم إعادة تسمية قائمة التشغيل</string>
|
<string name="lng_playlist_renamed">تم إعادة تسمية قائمة التشغيل</string>
|
||||||
<string name="lbl_rename_playlist">إعادة تسمية قائمة التشغيل</string>
|
<string name="lbl_rename_playlist">إعادة تسمية قائمة التشغيل</string>
|
||||||
<string name="lbl_appears_on">يظهر على</string>
|
<string name="lbl_appears_on">يظهر على</string>
|
||||||
<string name="lbl_music_sources">إختيار المجلد</string>
|
</resources>
|
||||||
<string name="lbl_demos">مقاطع تجريبية</string>
|
|
||||||
<string name="lbl_import">استيراد</string>
|
|
||||||
<string name="lbl_export">تصدير</string>
|
|
||||||
<string name="lbl_export_playlist">تصدير قائمة تشغيل</string>
|
|
||||||
<string name="lbl_feedback">ملاحظات</string>
|
|
||||||
<string name="lbl_github">سجل مشكلة على GitHub</string>
|
|
||||||
<string name="lbl_email">أرسل ايميل</string>
|
|
||||||
<string name="lbl_donate">تبرع</string>
|
|
||||||
<string name="set_action_mode_next">تخطى الى التالي</string>
|
|
||||||
<string name="set_play_in_parent_with">عند التشغيل من خصائص العنصر</string>
|
|
||||||
<string name="set_play_song_none">تشغيل من العناصر المعروظة</string>
|
|
||||||
<string name="set_play_song_from_genre">تشغيل من النوع</string>
|
|
||||||
<string name="set_content_desc">تحكم بكيفية تحميل الاموسيقى والصور</string>
|
|
||||||
<string name="set_observing">التحميل التلقائي</string>
|
|
||||||
<string name="set_exclude_non_music_desc">تجاوز الملفات الصوتية الغير موسيقية, مثل البودكاست</string>
|
|
||||||
<string name="set_separators_desc">تعريف الفواصل التي تدل على علامات متعددة</string>
|
|
||||||
<string name="set_separators_semicolon">فاصلة منقوطة(;)</string>
|
|
||||||
<string name="lbl_path_style">نمط المسار</string>
|
|
||||||
<string name="lbl_more">ألمزيد</string>
|
|
||||||
<string name="lbl_path_style_absolute">مطلق</string>
|
|
||||||
<string name="lbl_supporters">الداعمين</string>
|
|
||||||
<string name="set_bar_action">فعالية شريط تشغيل مخصصة</string>
|
|
||||||
<string name="set_separators_and">العطف(&)</string>
|
|
||||||
<string name="lbl_imported_playlist">قائمة تشغيل مستوردة</string>
|
|
||||||
<string name="set_separators">فواصل متعددة القيم</string>
|
|
||||||
<string name="set_ui_desc">تغيير سمات والوان البرنامج</string>
|
|
||||||
<string name="set_exclude_non_music">تجاوز غير الموسيقى</string>
|
|
||||||
<string name="lbl_demo">مقطع تجريبي</string>
|
|
||||||
<string name="lng_empty_songs">الاغاني الخاصة بك ستضهر هنا.</string>
|
|
||||||
<string name="lng_empty_artists">الفنانين الخاصين بك سيضهرون هنا.</string>
|
|
||||||
<string name="lbl_replaygain_track">تعديل تثبيت مستوى الصوت للاغنية</string>
|
|
||||||
<string name="lbl_replaygain_album">تعديل تثبيت مستوى الصوت للالبوم</string>
|
|
||||||
<string name="lng_playlist_imported">تم استيراد قائمة التشغيل</string>
|
|
||||||
<string name="lng_playlist_exported">تم تصدير قائمة التشغيل</string>
|
|
||||||
<string name="lng_supporters_promo">تبرع للمشروع لتتم اضافة اسمك هنا!</string>
|
|
||||||
<string name="set_action_mode_repeat">وضع التكرار</string>
|
|
||||||
<string name="set_play_song_by_itself">تشغيل اغنية محددة</string>
|
|
||||||
<string name="set_separators_plus">زائد(+)</string>
|
|
||||||
<string name="lbl_import_playlist">استيراد قائمة تشغيل</string>
|
|
||||||
<string name="lbl_empty_playlist">قائمة تشغيل فارغة</string>
|
|
||||||
<string name="set_personalize_desc">تخصيص ادوات تحكم الواجهه و سلوكها</string>
|
|
||||||
<string name="lbl_path">المسار</string>
|
|
||||||
<string name="set_intelligent_sorting">الترتيب الذكي</string>
|
|
||||||
<string name="set_separators_slash">الشارحة(/)</string>
|
|
||||||
<string name="lbl_start_playback">بدء التشغيل</string>
|
|
||||||
<string name="lbl_path_style_relative">نسبي</string>
|
|
||||||
<string name="lbl_windows_paths">إستخدام مسارات متوافقة مع نافذة</string>
|
|
||||||
<string name="lng_tasker_start">تشغيل Auxio بأستخدام الحالة المحفوظه مسبقا. اذا لم تتوفر حالة, كل الاغاني ستشغل بشكل عشوائي.\n\nتحذير:كن حذرا بالتحكم بهذة الخدمة, اذا اغلقتها وفتحتها مجددا,قد يتوقف البرنامج عن العمل.</string>
|
|
||||||
<string name="lbl_author">المؤلف</string>
|
|
||||||
<string name="set_music">الموسيقى</string>
|
|
||||||
<string name="lng_empty_playlists">قوائم التشغيل الخاصة بك ستضهر هنا.</string>
|
|
||||||
<string name="set_behavior">السلوك</string>
|
|
||||||
<string name="set_separators_comma">فاصلة (,)</string>
|
|
||||||
<string name="lng_empty_albums">الالبومات الخاصة بك ستضهر هنا.</string>
|
|
||||||
<string name="lng_empty_genres">الفئات الخاصة بك ستضهر هنا.</string>
|
|
||||||
<string name="set_observing_desc">اعادة تحميل مكتبة الموسيقى عند حصول تغيير(يتطلب تنبيه ثابت)</string>
|
|
||||||
<string name="set_separators_warning">تحذير: استخدام هذا الاعداد قد ينتج عنه ان يتم تفسير بعض العلامات بشكل خاطئ مثل ان تحتوي على قيم متعددة. يمكن ان يتم حل هذا بتقديم الفواصل الغير مرغوبةبالشارحة الخلفية(\\).</string>
|
|
||||||
</resources>
|
|
|
@ -1,8 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="info_app_desc">مشغّل موسيقى بسيط ومعقول للأندرويد.</string>
|
<string name="info_app_desc">مشغّل موسيقى بسيط ومعقول للأندرويد</string>
|
||||||
<string name="lbl_observing">مراقبة مكتبة الموسيقى</string>
|
<string name="lbl_observing">مراقبة مكتبة الموسيقى</string>
|
||||||
<string name="lbl_retry">إعادة المحاولة</string>
|
<string name="lbl_retry">إعادة المحاولة</string>
|
||||||
|
<string name="lbl_grant">منح</string>
|
||||||
<string name="lbl_albums">الألبومات</string>
|
<string name="lbl_albums">الألبومات</string>
|
||||||
<string name="lbl_songs">أغاني</string>
|
<string name="lbl_songs">أغاني</string>
|
||||||
<string name="lbl_song">أغنية</string>
|
<string name="lbl_song">أغنية</string>
|
||||||
|
@ -17,7 +18,8 @@
|
||||||
<string name="lbl_queue_add">إضافة للطابور</string>
|
<string name="lbl_queue_add">إضافة للطابور</string>
|
||||||
<string name="lbl_playlist_add">إضافة لقائمة التشغيل</string>
|
<string name="lbl_playlist_add">إضافة لقائمة التشغيل</string>
|
||||||
<string name="lbl_reset">إعادة ضبط</string>
|
<string name="lbl_reset">إعادة ضبط</string>
|
||||||
<string name="lng_indexing">جارِ تحميل مكتبتك الموسيقية…</string>
|
<string name="lbl_add">إضافة مجلد</string>
|
||||||
|
<string name="lng_indexing">يتم تحميل مكتبتك الموسيقية</string>
|
||||||
<string name="lng_queue_added">أضيفت للطابور</string>
|
<string name="lng_queue_added">أضيفت للطابور</string>
|
||||||
<string name="lng_playlist_created">تم إنشاء قائمة التشغيل</string>
|
<string name="lng_playlist_created">تم إنشاء قائمة التشغيل</string>
|
||||||
<string name="lbl_artists">فنانون</string>
|
<string name="lbl_artists">فنانون</string>
|
||||||
|
@ -83,6 +85,7 @@
|
||||||
<string name="def_disc">لا قرص</string>
|
<string name="def_disc">لا قرص</string>
|
||||||
<string name="cdc_mp4">صوت MPEG-4</string>
|
<string name="cdc_mp4">صوت MPEG-4</string>
|
||||||
<string name="cdc_ogg">أوغ الصوت</string>
|
<string name="cdc_ogg">أوغ الصوت</string>
|
||||||
|
<string name="cdc_mka">صوت ماتروسكا</string>
|
||||||
<string name="cdc_flac">برنامج ترميز الصوت المجاني بدون فقدان البيانات (FLAC)</string>
|
<string name="cdc_flac">برنامج ترميز الصوت المجاني بدون فقدان البيانات (FLAC)</string>
|
||||||
<string name="clr_indigo">نيلي</string>
|
<string name="clr_indigo">نيلي</string>
|
||||||
<string name="clr_blue">أزرق</string>
|
<string name="clr_blue">أزرق</string>
|
||||||
|
@ -106,6 +109,7 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="set_hide_collaborators_desc">إظهار فقط الفنانين المُعتمدين مباشرة على الألبوم (يعمل بشكل أفضل في المكتبات المعروفة بتوسيماتها الجيدة)</string>
|
<string name="set_hide_collaborators_desc">إظهار فقط الفنانين المُعتمدين مباشرة على الألبوم (يعمل بشكل أفضل في المكتبات المعروفة بتوسيماتها الجيدة)</string>
|
||||||
<string name="set_content">المحتوى</string>
|
<string name="set_content">المحتوى</string>
|
||||||
|
<string name="set_locations_list">مجلدات</string>
|
||||||
<string name="set_hide_collaborators">إخفاء المتعاونين</string>
|
<string name="set_hide_collaborators">إخفاء المتعاونين</string>
|
||||||
<string name="set_audio_desc">ضبط سلوك وصوت التشغيل</string>
|
<string name="set_audio_desc">ضبط سلوك وصوت التشغيل</string>
|
||||||
<string name="set_rewind_prev">إعادة التشغيل قبل الانتقال للوراء</string>
|
<string name="set_rewind_prev">إعادة التشغيل قبل الانتقال للوراء</string>
|
||||||
|
@ -113,6 +117,7 @@
|
||||||
<string name="set_remember_pause_desc">البقاء على التشغيل/الإيقاف عند الانتقال أو تعديل قائمة التشغيل</string>
|
<string name="set_remember_pause_desc">البقاء على التشغيل/الإيقاف عند الانتقال أو تعديل قائمة التشغيل</string>
|
||||||
<string name="set_remember_pause">تذكر الإيقاف المؤقت</string>
|
<string name="set_remember_pause">تذكر الإيقاف المؤقت</string>
|
||||||
<string name="set_rescan_desc">مسح ذاكرة التخزين المؤقت للعلامات وإعادة تحميل كامل مكتبة الموسيقى (أبطأ ولكن أكثر اكتمالًا)</string>
|
<string name="set_rescan_desc">مسح ذاكرة التخزين المؤقت للعلامات وإعادة تحميل كامل مكتبة الموسيقى (أبطأ ولكن أكثر اكتمالًا)</string>
|
||||||
|
<string name="err_no_perms">يحتاج Auxio إلى إذن لقراءة مكتبة الموسيقى الخاصة بك.</string>
|
||||||
<string name="err_import_failed">غير قادر على استيراد قائمة التشغيل من هذا الملف</string>
|
<string name="err_import_failed">غير قادر على استيراد قائمة التشغيل من هذا الملف</string>
|
||||||
<string name="err_no_app">لم يتم العثور على تطبيق يمكنه التعامل مع هذه المهمة</string>
|
<string name="err_no_app">لم يتم العثور على تطبيق يمكنه التعامل مع هذه المهمة</string>
|
||||||
<string name="desc_play_pause">تشغيل أو إيقاف مؤقت</string>
|
<string name="desc_play_pause">تشغيل أو إيقاف مؤقت</string>
|
||||||
|
@ -135,6 +140,7 @@
|
||||||
<string name="lbl_demos">تسجيلات تجريبية</string>
|
<string name="lbl_demos">تسجيلات تجريبية</string>
|
||||||
<string name="lbl_mixes">اغاني دي جي</string>
|
<string name="lbl_mixes">اغاني دي جي</string>
|
||||||
<string name="lbl_mix">اغنية دي جي</string>
|
<string name="lbl_mix">اغنية دي جي</string>
|
||||||
|
<string name="lbl_show_error_info">المزيد</string>
|
||||||
<string name="desc_selection_image">صورة التحديد</string>
|
<string name="desc_selection_image">صورة التحديد</string>
|
||||||
<string name="desc_remove_song">إزالة هذه الأغنية</string>
|
<string name="desc_remove_song">إزالة هذه الأغنية</string>
|
||||||
<string name="desc_song_handle">نقل هذه الأغنية</string>
|
<string name="desc_song_handle">نقل هذه الأغنية</string>
|
||||||
|
@ -163,7 +169,9 @@
|
||||||
<string name="lbl_single_remix">اغنية فردية ريميكس</string>
|
<string name="lbl_single_remix">اغنية فردية ريميكس</string>
|
||||||
<string name="set_images">الصور</string>
|
<string name="set_images">الصور</string>
|
||||||
<string name="set_reindex_desc">إعادة تحميل مكتبة الموسيقى، باستخدام العلامات المخزنة مؤقتًا عند الإمكان</string>
|
<string name="set_reindex_desc">إعادة تحميل مكتبة الموسيقى، باستخدام العلامات المخزنة مؤقتًا عند الإمكان</string>
|
||||||
|
<string name="err_no_locations">لا توجد مجلدات</string>
|
||||||
<string name="err_bad_location">هذا المجلد غير مدعوم</string>
|
<string name="err_bad_location">هذا المجلد غير مدعوم</string>
|
||||||
|
<string name="desc_shuffle_all">خلط جميع الأغاني</string>
|
||||||
<string name="clr_cyan">ازرق سماوي</string>
|
<string name="clr_cyan">ازرق سماوي</string>
|
||||||
<string name="fmt_editing">تحرير %s</string>
|
<string name="fmt_editing">تحرير %s</string>
|
||||||
<string name="set_theme_auto">تلقائي</string>
|
<string name="set_theme_auto">تلقائي</string>
|
||||||
|
@ -240,6 +248,7 @@
|
||||||
<string name="set_pre_amp_desc">يتم تطبيق مكبر الصوت المسبق على التعديل الحالي أثناء التشغيل</string>
|
<string name="set_pre_amp_desc">يتم تطبيق مكبر الصوت المسبق على التعديل الحالي أثناء التشغيل</string>
|
||||||
<string name="set_pre_amp_with">ضبط مع العلامات</string>
|
<string name="set_pre_amp_with">ضبط مع العلامات</string>
|
||||||
<string name="set_reindex">تحديث الموسيقى</string>
|
<string name="set_reindex">تحديث الموسيقى</string>
|
||||||
|
<string name="err_no_music">لم يتم العثور على موسيقى</string>
|
||||||
<string name="def_track">لا مسار</string>
|
<string name="def_track">لا مسار</string>
|
||||||
<string name="def_playback">لا يوجد تشغيل الموسيقى</string>
|
<string name="def_playback">لا يوجد تشغيل الموسيقى</string>
|
||||||
<string name="cdc_aac">ترميز الصوت المتقدم (AAC)</string>
|
<string name="cdc_aac">ترميز الصوت المتقدم (AAC)</string>
|
||||||
|
@ -268,61 +277,4 @@
|
||||||
<string name="lng_playlist_added">تمت إضافته إلى قائمة التشغيل</string>
|
<string name="lng_playlist_added">تمت إضافته إلى قائمة التشغيل</string>
|
||||||
<string name="set_root_title">إعدادات</string>
|
<string name="set_root_title">إعدادات</string>
|
||||||
<string name="set_separators_semicolon">الفاصلة المنقوطة (؛)</string>
|
<string name="set_separators_semicolon">الفاصلة المنقوطة (؛)</string>
|
||||||
<string name="lbl_music_sources">اختر المجلدات</string>
|
</resources>
|
||||||
<string name="lbl_import">استورد</string>
|
|
||||||
<string name="lbl_export">صدّر</string>
|
|
||||||
<string name="lbl_export_playlist">صدّر قائمة التشغيل</string>
|
|
||||||
<string name="lbl_sample_rate">معدل العينة</string>
|
|
||||||
<string name="lbl_path_style">نمط المسار</string>
|
|
||||||
<string name="lbl_selection">تحديد</string>
|
|
||||||
<string name="lbl_feedback">الانطباعات</string>
|
|
||||||
<string name="lbl_github">افتح مشكلة على GitHub</string>
|
|
||||||
<string name="lbl_email">إرسل بريد إلكتروني</string>
|
|
||||||
<string name="lbl_supporters">المؤيدون</string>
|
|
||||||
<string name="lbl_more">المزيد</string>
|
|
||||||
<string name="lbl_path_style_relative">نسبي</string>
|
|
||||||
<string name="lbl_path_style_absolute">مطلق</string>
|
|
||||||
<string name="cdc_unknown">غير معروف</string>
|
|
||||||
<string name="lbl_imported_playlist">قائمة التشغيل استوردت</string>
|
|
||||||
<string name="def_album">ألبوم غير معروف</string>
|
|
||||||
<string name="lbl_sort_mode">افرز حسب</string>
|
|
||||||
<string name="lbl_sort_direction">الاتجاه</string>
|
|
||||||
<plurals name="fmt_artist_count">
|
|
||||||
<item quantity="zero">لا فنان</item>
|
|
||||||
<item quantity="one">فنان</item>
|
|
||||||
<item quantity="two">فنانان</item>
|
|
||||||
<item quantity="few">%d فنانين</item>
|
|
||||||
<item quantity="many">%d فنان</item>
|
|
||||||
<item quantity="other">%d فنان</item>
|
|
||||||
</plurals>
|
|
||||||
<string name="lng_empty_songs">ستظهر أغانيك هنا.</string>
|
|
||||||
<string name="lng_empty_albums">ستظهر ألبوماتك هنا.</string>
|
|
||||||
<string name="lng_empty_artists">سوف يظهر الفنانون الخاص بك هنا.</string>
|
|
||||||
<string name="lng_empty_playlists">سوف تظهر قوائم تشغيلك هنا.</string>
|
|
||||||
<string name="lng_empty_genres">سوف تظهر أنواعك هنا.</string>
|
|
||||||
<string name="lbl_replaygain_album">تعديل الألبوم Replaygain</string>
|
|
||||||
<string name="lbl_replaygain_track">تعديل مسار ReplayGain</string>
|
|
||||||
<string name="lbl_author_name">ألكساندر كيبهارت</string>
|
|
||||||
<string name="lbl_donate">تبرّع</string>
|
|
||||||
<string name="lbl_author">المؤلف</string>
|
|
||||||
<string name="lbl_import_playlist">استورد قائمة التشغيل</string>
|
|
||||||
<string name="lbl_path">المسار</string>
|
|
||||||
<string name="set_locations_new">مجلد جديد</string>
|
|
||||||
<string name="lbl_start_playback">بدء التشغيل</string>
|
|
||||||
<string name="lbl_error_info">معلومات الخطأ</string>
|
|
||||||
<string name="lbl_copied">نُسخت</string>
|
|
||||||
<string name="lbl_report">إبلاغ</string>
|
|
||||||
<string name="lng_tasker_start">يبدأ Auxio باستخدام الحالة المحفوظة مسبقًا. إذا لم تتوفر حالة محفوظة، فسيتم خلط جميع الأغاني. سيبدأ التشغيل على الفور. \n\nتحذير: احرص على التحكم في هذه الخدمة، إذا قمت بإغلاقها ثم حاول استخدامها مرة أخرى، فمن المحتمل أن ينهار التطبيق.</string>
|
|
||||||
<string name="lbl_windows_paths">استخدم مسارات متوافقة مع Windows</string>
|
|
||||||
<string name="set_cover_mode_save_space">وفر المساحة</string>
|
|
||||||
<plurals name="fmt_album_count">
|
|
||||||
<item quantity="zero">لا ألبوم</item>
|
|
||||||
<item quantity="one">ألبوم</item>
|
|
||||||
<item quantity="two">ألبومان</item>
|
|
||||||
<item quantity="few">%d ألبومات</item>
|
|
||||||
<item quantity="many">%d ألبوم</item>
|
|
||||||
<item quantity="other">%d ألبوم</item>
|
|
||||||
</plurals>
|
|
||||||
<string name="cnt_mp4">MPEG-4 تحتوي على %s</string>
|
|
||||||
<string name="cdc_alac">Apple Lossless Audio Codec (ALAC)</string>
|
|
||||||
</resources>
|
|
|
@ -3,6 +3,7 @@
|
||||||
<string name="lbl_indexer">Musiqi yüklənir</string>
|
<string name="lbl_indexer">Musiqi yüklənir</string>
|
||||||
<string name="lbl_indexing">Musiqi yüklənir</string>
|
<string name="lbl_indexing">Musiqi yüklənir</string>
|
||||||
<string name="lbl_retry">Təkrar cəhd et</string>
|
<string name="lbl_retry">Təkrar cəhd et</string>
|
||||||
|
<string name="lbl_grant">Qəbul et</string>
|
||||||
<string name="lbl_songs">Mahnılar</string>
|
<string name="lbl_songs">Mahnılar</string>
|
||||||
<string name="lbl_all_songs">Bütün mahnılar</string>
|
<string name="lbl_all_songs">Bütün mahnılar</string>
|
||||||
<string name="lbl_albums">Albomlar</string>
|
<string name="lbl_albums">Albomlar</string>
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
<string name="lbl_artist">Sənətkar</string>
|
<string name="lbl_artist">Sənətkar</string>
|
||||||
<string name="lbl_artists">Sənətkarlar</string>
|
<string name="lbl_artists">Sənətkarlar</string>
|
||||||
<string name="lbl_genre">Janr</string>
|
<string name="lbl_genre">Janr</string>
|
||||||
|
<string name="lbl_show_error_info">Daha çox</string>
|
||||||
<string name="lbl_song">Mahnı</string>
|
<string name="lbl_song">Mahnı</string>
|
||||||
<string name="lbl_mixtapes">Qarışıq lentlər</string>
|
<string name="lbl_mixtapes">Qarışıq lentlər</string>
|
||||||
<string name="lbl_mixtape">Qarışıq lent</string>
|
<string name="lbl_mixtape">Qarışıq lent</string>
|
||||||
|
@ -74,6 +76,7 @@
|
||||||
<string name="lbl_album_details">Alboma keç</string>
|
<string name="lbl_album_details">Alboma keç</string>
|
||||||
<string name="lbl_parent_detail">Baxış</string>
|
<string name="lbl_parent_detail">Baxış</string>
|
||||||
<string name="lbl_share">Paylaş</string>
|
<string name="lbl_share">Paylaş</string>
|
||||||
|
<string name="lbl_add">Əlavə et</string>
|
||||||
<string name="lbl_play">Səsləndir</string>
|
<string name="lbl_play">Səsləndir</string>
|
||||||
<string name="lbl_sort_mode">Çeşidləmə üsulu</string>
|
<string name="lbl_sort_mode">Çeşidləmə üsulu</string>
|
||||||
<string name="lbl_sort_direction">Göstəriş</string>
|
<string name="lbl_sort_direction">Göstəriş</string>
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<string name="set_root_title">Налады</string>
|
<string name="set_root_title">Налады</string>
|
||||||
<string name="info_app_desc">Просты, рацыянальны музычны плэер для Android.</string>
|
<string name="info_app_desc">Просты, рацыянальны музычны плэер для Android.</string>
|
||||||
<string name="lbl_observing">Маніторынг музычнай бібліятэкі</string>
|
<string name="lbl_observing">Маніторынг музычнай бібліятэкі</string>
|
||||||
|
<string name="lbl_grant">Выдаць</string>
|
||||||
<string name="lbl_songs">Песні</string>
|
<string name="lbl_songs">Песні</string>
|
||||||
<string name="set_ui_desc">Змяніце тэму і колеры праграмы</string>
|
<string name="set_ui_desc">Змяніце тэму і колеры праграмы</string>
|
||||||
<string name="lbl_all_songs">Ўсе песні</string>
|
<string name="lbl_all_songs">Ўсе песні</string>
|
||||||
|
@ -87,6 +88,7 @@
|
||||||
<string name="lbl_bitrate">Бітрэйт</string>
|
<string name="lbl_bitrate">Бітрэйт</string>
|
||||||
<string name="lbl_sample_rate">Частата дыскрэтызацыі</string>
|
<string name="lbl_sample_rate">Частата дыскрэтызацыі</string>
|
||||||
<string name="lbl_reset">Скінуць</string>
|
<string name="lbl_reset">Скінуць</string>
|
||||||
|
<string name="lbl_add">Дадаць</string>
|
||||||
<string name="lbl_wiki">Вікі</string>
|
<string name="lbl_wiki">Вікі</string>
|
||||||
<string name="lbl_save">Захаваць</string>
|
<string name="lbl_save">Захаваць</string>
|
||||||
<string name="lbl_version">Версія</string>
|
<string name="lbl_version">Версія</string>
|
||||||
|
@ -111,11 +113,15 @@
|
||||||
<string name="set_pre_amp">Папярэдні ўзмацняльнік ReplayGain</string>
|
<string name="set_pre_amp">Папярэдні ўзмацняльнік ReplayGain</string>
|
||||||
<string name="set_library">Бібліятэка</string>
|
<string name="set_library">Бібліятэка</string>
|
||||||
<string name="set_locations_desc">Кіруйце месцам загрузкі музыкі</string>
|
<string name="set_locations_desc">Кіруйце месцам загрузкі музыкі</string>
|
||||||
|
<string name="set_locations_list">Тэчкі</string>
|
||||||
<string name="set_rescan">Перасканаваць музыку</string>
|
<string name="set_rescan">Перасканаваць музыку</string>
|
||||||
<string name="set_reindex">Абнавіць музыку</string>
|
<string name="set_reindex">Абнавіць музыку</string>
|
||||||
<string name="set_reindex_desc">Перазагрузіце музычную бібліятэку, выкарыстоўваючы па магчымасці кэшаваныя тэгі</string>
|
<string name="set_reindex_desc">Перазагрузіце музычную бібліятэку, выкарыстоўваючы па магчымасці кэшаваныя тэгі</string>
|
||||||
<string name="set_rescan_desc">Ачысціце кэш тэгаў і цалкам перазагрузіце музычную бібліятэку (павольней, але больш поўна)</string>
|
<string name="set_rescan_desc">Ачысціце кэш тэгаў і цалкам перазагрузіце музычную бібліятэку (павольней, але больш поўна)</string>
|
||||||
|
<string name="err_no_perms">Auxio патрабуецца дазвол на чытанне вашай музычнай бібліятэкі</string>
|
||||||
|
<string name="err_no_music">Музыка не знойдзена</string>
|
||||||
<string name="err_index_failed">Памылка загрузкі музыкі</string>
|
<string name="err_index_failed">Памылка загрузкі музыкі</string>
|
||||||
|
<string name="err_no_locations">Няма тэчак</string>
|
||||||
<string name="err_bad_location">Гэтая папка не падтрымліваецца</string>
|
<string name="err_bad_location">Гэтая папка не падтрымліваецца</string>
|
||||||
<string name="desc_track_number">Кампазіцыя %d</string>
|
<string name="desc_track_number">Кампазіцыя %d</string>
|
||||||
<string name="desc_song_handle">Перамясціць песню ў чаргу</string>
|
<string name="desc_song_handle">Перамясціць песню ў чаргу</string>
|
||||||
|
@ -127,6 +133,7 @@
|
||||||
<string name="desc_auxio_icon">Значок Auxio</string>
|
<string name="desc_auxio_icon">Значок Auxio</string>
|
||||||
<string name="desc_shuffle">Ўключыце або выключыце перамешванне</string>
|
<string name="desc_shuffle">Ўключыце або выключыце перамешванне</string>
|
||||||
<string name="desc_remove_song">Выдаліць гэтую песню з чаргі</string>
|
<string name="desc_remove_song">Выдаліць гэтую песню з чаргі</string>
|
||||||
|
<string name="desc_shuffle_all">Перамяшаць усе песні</string>
|
||||||
<string name="desc_exit">Спыніць прайграванне</string>
|
<string name="desc_exit">Спыніць прайграванне</string>
|
||||||
<string name="desc_queue_bar">Адкрыйце чаргу</string>
|
<string name="desc_queue_bar">Адкрыйце чаргу</string>
|
||||||
<string name="desc_clear_search">Ачысціць пошукавы запыт</string>
|
<string name="desc_clear_search">Ачысціць пошукавы запыт</string>
|
||||||
|
@ -141,6 +148,7 @@
|
||||||
<string name="def_date">Без даты</string>
|
<string name="def_date">Без даты</string>
|
||||||
<string name="def_track">Няма дарожкі</string>
|
<string name="def_track">Няма дарожкі</string>
|
||||||
<string name="cdc_mp3">MPEG-1 аўдыё</string>
|
<string name="cdc_mp3">MPEG-1 аўдыё</string>
|
||||||
|
<string name="cdc_mka">Matroska аўдыё</string>
|
||||||
<string name="def_playback">Музыка не грае</string>
|
<string name="def_playback">Музыка не грае</string>
|
||||||
<string name="cdc_mp4">MPEG-4 аўдыё</string>
|
<string name="cdc_mp4">MPEG-4 аўдыё</string>
|
||||||
<string name="clr_red">Чырвоны</string>
|
<string name="clr_red">Чырвоны</string>
|
||||||
|
@ -271,6 +279,7 @@
|
||||||
<string name="lbl_sort_direction">Напрамак</string>
|
<string name="lbl_sort_direction">Напрамак</string>
|
||||||
<string name="desc_selection_image">Абярыце малюнак</string>
|
<string name="desc_selection_image">Абярыце малюнак</string>
|
||||||
<string name="lbl_selection">Абярыце</string>
|
<string name="lbl_selection">Абярыце</string>
|
||||||
|
<string name="lbl_show_error_info">Дадаткова</string>
|
||||||
<string name="lbl_copied">Скапіравана</string>
|
<string name="lbl_copied">Скапіравана</string>
|
||||||
<string name="lbl_error_info">Інфармацыя пра памылку</string>
|
<string name="lbl_error_info">Інфармацыя пра памылку</string>
|
||||||
<string name="lbl_report">Справаздача пра памылку</string>
|
<string name="lbl_report">Справаздача пра памылку</string>
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
<string name="lbl_windows_paths">Използвай съвместими с Windows пътища</string>
|
<string name="lbl_windows_paths">Използвай съвместими с Windows пътища</string>
|
||||||
<string name="info_app_desc">Прост, рационален музикален плейър за android.</string>
|
<string name="info_app_desc">Прост, рационален музикален плейър за android.</string>
|
||||||
<string name="lbl_indexing">Зарежда се музика</string>
|
<string name="lbl_indexing">Зарежда се музика</string>
|
||||||
|
<string name="lbl_show_error_info">Още</string>
|
||||||
<string name="lbl_albums">Албуми</string>
|
<string name="lbl_albums">Албуми</string>
|
||||||
<string name="lbl_ep_live">EP на живо</string>
|
<string name="lbl_ep_live">EP на живо</string>
|
||||||
<string name="lbl_single_live">Сингъл наживо</string>
|
<string name="lbl_single_live">Сингъл наживо</string>
|
||||||
|
@ -96,6 +97,7 @@
|
||||||
<string name="lbl_playback">Сега се изпълнява</string>
|
<string name="lbl_playback">Сега се изпълнява</string>
|
||||||
<string name="lbl_replaygain_track">ReplayGain Регулиране на песента</string>
|
<string name="lbl_replaygain_track">ReplayGain Регулиране на песента</string>
|
||||||
<string name="lbl_shuffle_shortcut_long">Разбъркай всички</string>
|
<string name="lbl_shuffle_shortcut_long">Разбъркай всички</string>
|
||||||
|
<string name="lbl_add">Добави</string>
|
||||||
<string name="lbl_about">Относно</string>
|
<string name="lbl_about">Относно</string>
|
||||||
<string name="lbl_path_style_absolute">Абсолютно</string>
|
<string name="lbl_path_style_absolute">Абсолютно</string>
|
||||||
<string name="lbl_eps">EPs</string>
|
<string name="lbl_eps">EPs</string>
|
||||||
|
@ -184,6 +186,7 @@
|
||||||
<string name="set_replay_gain">Нормализация на звука</string>
|
<string name="set_replay_gain">Нормализация на звука</string>
|
||||||
<string name="set_replay_gain_mode">ReplayGain стратегия</string>
|
<string name="set_replay_gain_mode">ReplayGain стратегия</string>
|
||||||
<string name="set_replay_gain_mode_off">Изключено</string>
|
<string name="set_replay_gain_mode_off">Изключено</string>
|
||||||
|
<string name="lbl_grant">Предоставяне</string>
|
||||||
<string name="lng_supporters_promo">Дарете за проекта, за да бъде добавено името ви тук!</string>
|
<string name="lng_supporters_promo">Дарете за проекта, за да бъде добавено името ви тук!</string>
|
||||||
<string name="lng_search_library">Търсене във вашата библиотека…</string>
|
<string name="lng_search_library">Търсене във вашата библиотека…</string>
|
||||||
<string name="set_bar_action">Персонализирано действие на лентата за възпроизвеждане</string>
|
<string name="set_bar_action">Персонализирано действие на лентата за възпроизвеждане</string>
|
||||||
|
@ -207,15 +210,20 @@
|
||||||
<string name="set_library">Библиотека</string>
|
<string name="set_library">Библиотека</string>
|
||||||
<string name="set_locations">Музикални папки</string>
|
<string name="set_locations">Музикални папки</string>
|
||||||
<string name="set_locations_desc">Управлявайте откъде да се зарежда музиката</string>
|
<string name="set_locations_desc">Управлявайте откъде да се зарежда музиката</string>
|
||||||
|
<string name="set_locations_list">Папки</string>
|
||||||
<string name="set_reindex">Обновяване на музика</string>
|
<string name="set_reindex">Обновяване на музика</string>
|
||||||
|
<string name="err_no_music">Няма намерена музика</string>
|
||||||
<string name="err_index_failed">Неуспешно зареждане на музика</string>
|
<string name="err_index_failed">Неуспешно зареждане на музика</string>
|
||||||
|
<string name="err_no_perms">Auxio се нуждае от разрешение, за да чете вашата музикална библиотека</string>
|
||||||
<string name="err_export_failed">Плейлиста не може да се изнесе в този файл</string>
|
<string name="err_export_failed">Плейлиста не може да се изнесе в този файл</string>
|
||||||
<string name="err_no_app">Няма намерено приложение, което да може да се справи с тази задача</string>
|
<string name="err_no_app">Няма намерено приложение, което да може да се справи с тази задача</string>
|
||||||
|
<string name="err_no_locations">Няма папки</string>
|
||||||
<string name="desc_play_pause">Изпълни или пауза</string>
|
<string name="desc_play_pause">Изпълни или пауза</string>
|
||||||
<string name="desc_skip_next">Премини към следваща песен</string>
|
<string name="desc_skip_next">Премини към следваща песен</string>
|
||||||
<string name="desc_skip_prev">Премини към последна песен</string>
|
<string name="desc_skip_prev">Премини към последна песен</string>
|
||||||
<string name="desc_change_repeat">Промени режима на повторение</string>
|
<string name="desc_change_repeat">Промени режима на повторение</string>
|
||||||
<string name="desc_shuffle">Включи или изключи разбъркване</string>
|
<string name="desc_shuffle">Включи или изключи разбъркване</string>
|
||||||
|
<string name="desc_shuffle_all">Разбъркай всички песни</string>
|
||||||
<string name="desc_exit">Спри възпроизвеждането</string>
|
<string name="desc_exit">Спри възпроизвеждането</string>
|
||||||
<string name="desc_remove_song">Премахни тази песен</string>
|
<string name="desc_remove_song">Премахни тази песен</string>
|
||||||
<string name="desc_song_handle">Премести тази песен</string>
|
<string name="desc_song_handle">Премести тази песен</string>
|
||||||
|
@ -247,6 +255,7 @@
|
||||||
<string name="cdc_mp3">MPEG-1 audio</string>
|
<string name="cdc_mp3">MPEG-1 audio</string>
|
||||||
<string name="cdc_mp4">MPEG-4 audio</string>
|
<string name="cdc_mp4">MPEG-4 audio</string>
|
||||||
<string name="cdc_ogg">Ogg audio</string>
|
<string name="cdc_ogg">Ogg audio</string>
|
||||||
|
<string name="cdc_mka">Matroska audio</string>
|
||||||
<string name="clr_pink">Розово</string>
|
<string name="clr_pink">Розово</string>
|
||||||
<string name="clr_red">Червено</string>
|
<string name="clr_red">Червено</string>
|
||||||
<string name="clr_purple">Лилаво</string>
|
<string name="clr_purple">Лилаво</string>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lng_indexing">Načítání vaší hudební knihovny…</string>
|
<string name="lng_indexing">Načítání vaší hudební knihovny…</string>
|
||||||
<string name="lbl_retry">Zkusit znovu</string>
|
<string name="lbl_retry">Zkusit znovu</string>
|
||||||
|
<string name="lbl_grant">Udělit</string>
|
||||||
<string name="lbl_genres">Žánry</string>
|
<string name="lbl_genres">Žánry</string>
|
||||||
<string name="lbl_artists">Umělci</string>
|
<string name="lbl_artists">Umělci</string>
|
||||||
<string name="lbl_albums">Alba</string>
|
<string name="lbl_albums">Alba</string>
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
<string name="lbl_ok">OK</string>
|
<string name="lbl_ok">OK</string>
|
||||||
<!-- Actual string: Cancel -->
|
<!-- Actual string: Cancel -->
|
||||||
<string name="lbl_cancel">Zrušit</string>
|
<string name="lbl_cancel">Zrušit</string>
|
||||||
|
<string name="lbl_add">Přidat</string>
|
||||||
<string name="lbl_save">Uložit</string>
|
<string name="lbl_save">Uložit</string>
|
||||||
<string name="lbl_about">O aplikaci</string>
|
<string name="lbl_about">O aplikaci</string>
|
||||||
<string name="lbl_version">Verze</string>
|
<string name="lbl_version">Verze</string>
|
||||||
|
@ -88,8 +90,11 @@
|
||||||
<string name="set_reindex">Obnovit hudbu</string>
|
<string name="set_reindex">Obnovit hudbu</string>
|
||||||
<string name="set_reindex_desc">Znovu načíst hudební knihovnu, pokud možno s použitím značek uložených v mezipaměti</string>
|
<string name="set_reindex_desc">Znovu načíst hudební knihovnu, pokud možno s použitím značek uložených v mezipaměti</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">Nenalezena žádná hudba</string>
|
||||||
<string name="err_index_failed">Načítání hudby selhalo</string>
|
<string name="err_index_failed">Načítání hudby selhalo</string>
|
||||||
|
<string name="err_no_perms">Auxio potřebuje oprávnění ke čtení vaší hudební knihovny</string>
|
||||||
<string name="err_no_app">Nebyla nalezena žádná aplikace, která by dokázala vykonat tuto akci</string>
|
<string name="err_no_app">Nebyla nalezena žádná aplikace, která by dokázala vykonat tuto akci</string>
|
||||||
|
<string name="err_no_locations">Žádné složky</string>
|
||||||
<string name="err_bad_location">Tato složka není podporována</string>
|
<string name="err_bad_location">Tato složka není podporována</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="lng_search_library">Prohledat vaší knihovnu…</string>
|
<string name="lng_search_library">Prohledat vaší knihovnu…</string>
|
||||||
|
@ -100,6 +105,7 @@
|
||||||
<string name="desc_skip_prev">Přeskočit na předchozí skladbu</string>
|
<string name="desc_skip_prev">Přeskočit na předchozí skladbu</string>
|
||||||
<string name="desc_change_repeat">Změnit režim opakování</string>
|
<string name="desc_change_repeat">Změnit režim opakování</string>
|
||||||
<string name="desc_shuffle">Vypnout nebo zapnout náhodné přehrávání</string>
|
<string name="desc_shuffle">Vypnout nebo zapnout náhodné přehrávání</string>
|
||||||
|
<string name="desc_shuffle_all">Náhodně přehrávat vše</string>
|
||||||
<string name="desc_remove_song">Odebrat tuto skladbu z fronty</string>
|
<string name="desc_remove_song">Odebrat tuto skladbu z fronty</string>
|
||||||
<string name="desc_song_handle">Přesunout tuto skladbu ve frontě</string>
|
<string name="desc_song_handle">Přesunout tuto skladbu ve frontě</string>
|
||||||
<string name="desc_tab_handle">Přesunout tuto kartu</string>
|
<string name="desc_tab_handle">Přesunout tuto kartu</string>
|
||||||
|
@ -161,6 +167,7 @@
|
||||||
<string name="cdc_mp3">Zvuk MPEG-1</string>
|
<string name="cdc_mp3">Zvuk MPEG-1</string>
|
||||||
<string name="cdc_mp4">Zvuk MPEG-4</string>
|
<string name="cdc_mp4">Zvuk MPEG-4</string>
|
||||||
<string name="cdc_ogg">Zvuk Ogg</string>
|
<string name="cdc_ogg">Zvuk Ogg</string>
|
||||||
|
<string name="cdc_mka">Zvuk Matroska</string>
|
||||||
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
||||||
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
||||||
<string name="fmt_bitrate">%d kbps</string>
|
<string name="fmt_bitrate">%d kbps</string>
|
||||||
|
@ -239,6 +246,7 @@
|
||||||
<string name="lbl_wiki">Wiki</string>
|
<string name="lbl_wiki">Wiki</string>
|
||||||
<string name="fmt_list">%1$s, %2$s</string>
|
<string name="fmt_list">%1$s, %2$s</string>
|
||||||
<string name="lbl_reset">Obnovit</string>
|
<string name="lbl_reset">Obnovit</string>
|
||||||
|
<string name="set_locations_list">Složky</string>
|
||||||
<string name="set_replay_gain">Normalizace hlasitosti</string>
|
<string name="set_replay_gain">Normalizace hlasitosti</string>
|
||||||
<string name="set_behavior">Chování</string>
|
<string name="set_behavior">Chování</string>
|
||||||
<string name="set_ui_desc">Změnit motiv a barvy aplikace</string>
|
<string name="set_ui_desc">Změnit motiv a barvy aplikace</string>
|
||||||
|
@ -282,6 +290,7 @@
|
||||||
<string name="lbl_sort_mode">Seřadit podle</string>
|
<string name="lbl_sort_mode">Seřadit podle</string>
|
||||||
<string name="desc_selection_image">Výběr obrázku</string>
|
<string name="desc_selection_image">Výběr obrázku</string>
|
||||||
<string name="lbl_selection">Výběr</string>
|
<string name="lbl_selection">Výběr</string>
|
||||||
|
<string name="lbl_show_error_info">Další</string>
|
||||||
<string name="lbl_error_info">Informace o chybě</string>
|
<string name="lbl_error_info">Informace o chybě</string>
|
||||||
<string name="lbl_copied">Zkopírovat</string>
|
<string name="lbl_copied">Zkopírovat</string>
|
||||||
<string name="lbl_report">Nahlásit</string>
|
<string name="lbl_report">Nahlásit</string>
|
||||||
|
@ -332,7 +341,4 @@
|
||||||
<string name="lng_empty_artists">Vaši umělci se zobrazí zde.</string>
|
<string name="lng_empty_artists">Vaši umělci se zobrazí zde.</string>
|
||||||
<string name="lng_empty_playlists">Vaše seznamy skladeb se zobrazí zde.</string>
|
<string name="lng_empty_playlists">Vaše seznamy skladeb se zobrazí zde.</string>
|
||||||
<string name="lng_empty_genres">Vaše žánry se zobrazí zde.</string>
|
<string name="lng_empty_genres">Vaše žánry se zobrazí zde.</string>
|
||||||
<string name="set_with_hidden">Zahrnout skryté soubory</string>
|
</resources>
|
||||||
<string name="set_with_hidden_desc">Zahrnout skryté zvukové soubory (např. .cache)</string>
|
|
||||||
<string name="set_cover_mode_as_is">Původní</string>
|
|
||||||
</resources>
|
|
|
@ -4,6 +4,7 @@
|
||||||
<string name="lbl_indexer">Llwytho cerddoriaeth</string>
|
<string name="lbl_indexer">Llwytho cerddoriaeth</string>
|
||||||
<string name="lbl_observing">Yn monitro llyfrgell cerddoriaeth</string>
|
<string name="lbl_observing">Yn monitro llyfrgell cerddoriaeth</string>
|
||||||
<string name="lbl_retry">Ceisio eto</string>
|
<string name="lbl_retry">Ceisio eto</string>
|
||||||
|
<string name="lbl_grant">Caniatáu</string>
|
||||||
<string name="lbl_songs">Caneuon</string>
|
<string name="lbl_songs">Caneuon</string>
|
||||||
<string name="lbl_song">Cân</string>
|
<string name="lbl_song">Cân</string>
|
||||||
<string name="lbl_all_songs">Holl ganeuon</string>
|
<string name="lbl_all_songs">Holl ganeuon</string>
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
<string name="lbl_mixtapes">Tapiau cymysgiad</string>
|
<string name="lbl_mixtapes">Tapiau cymysgiad</string>
|
||||||
<string name="lbl_mixtape">Tâp cymysgiad</string>
|
<string name="lbl_mixtape">Tâp cymysgiad</string>
|
||||||
<string name="info_app_desc">Chwaraewr cerddoriaeth syml a synhwyrol.</string>
|
<string name="info_app_desc">Chwaraewr cerddoriaeth syml a synhwyrol.</string>
|
||||||
|
<string name="lbl_show_error_info">Mwy</string>
|
||||||
<string name="lbl_ep_remix">EP ail-gymysgiad</string>
|
<string name="lbl_ep_remix">EP ail-gymysgiad</string>
|
||||||
<string name="lbl_name">Enw</string>
|
<string name="lbl_name">Enw</string>
|
||||||
<string name="lbl_date">Dyddiad</string>
|
<string name="lbl_date">Dyddiad</string>
|
||||||
|
@ -32,6 +34,7 @@
|
||||||
<string name="lbl_track">Trac</string>
|
<string name="lbl_track">Trac</string>
|
||||||
<string name="lbl_sort">Didoli</string>
|
<string name="lbl_sort">Didoli</string>
|
||||||
<string name="lbl_sort_mode">Didoli gan</string>
|
<string name="lbl_sort_mode">Didoli gan</string>
|
||||||
|
<string name="set_locations_list">Ffolderi</string>
|
||||||
<string name="lbl_playlists">Rhestri chwarae</string>
|
<string name="lbl_playlists">Rhestri chwarae</string>
|
||||||
<string name="lbl_new_playlist">Rhestr chwarae newydd</string>
|
<string name="lbl_new_playlist">Rhestr chwarae newydd</string>
|
||||||
<string name="lbl_empty_playlist">Rhestr chwarae gwag</string>
|
<string name="lbl_empty_playlist">Rhestr chwarae gwag</string>
|
||||||
|
@ -86,6 +89,7 @@
|
||||||
<string name="set_locations">Ffolderi cerddoriaeth</string>
|
<string name="set_locations">Ffolderi cerddoriaeth</string>
|
||||||
<string name="set_reindex">Adnewyddu cerddoriaeth</string>
|
<string name="set_reindex">Adnewyddu cerddoriaeth</string>
|
||||||
<string name="desc_track_number">Trac %d</string>
|
<string name="desc_track_number">Trac %d</string>
|
||||||
|
<string name="desc_shuffle_all">Chwarae pob cân ar hap</string>
|
||||||
<string name="def_artist">Artist anhysbys</string>
|
<string name="def_artist">Artist anhysbys</string>
|
||||||
<string name="def_genre">Genre anhysbys</string>
|
<string name="def_genre">Genre anhysbys</string>
|
||||||
<string name="def_date">Dim dyddiad</string>
|
<string name="def_date">Dim dyddiad</string>
|
||||||
|
@ -153,6 +157,7 @@
|
||||||
<string name="lbl_cancel">Diddymu</string>
|
<string name="lbl_cancel">Diddymu</string>
|
||||||
<string name="lbl_save">Cadw</string>
|
<string name="lbl_save">Cadw</string>
|
||||||
<string name="lbl_reset">Ailosod</string>
|
<string name="lbl_reset">Ailosod</string>
|
||||||
|
<string name="lbl_add">Ychwanegu</string>
|
||||||
<string name="lbl_path_style">Dull llwybr</string>
|
<string name="lbl_path_style">Dull llwybr</string>
|
||||||
<string name="lbl_windows_paths">Defnyddio llwybrau Windows</string>
|
<string name="lbl_windows_paths">Defnyddio llwybrau Windows</string>
|
||||||
<string name="lbl_about">Ynghylch</string>
|
<string name="lbl_about">Ynghylch</string>
|
||||||
|
@ -194,8 +199,11 @@
|
||||||
<string name="set_replay_gain_mode_track">Ffafrio trac</string>
|
<string name="set_replay_gain_mode_track">Ffafrio trac</string>
|
||||||
<string name="set_replay_gain_mode_album">Ffafrio albwm</string>
|
<string name="set_replay_gain_mode_album">Ffafrio albwm</string>
|
||||||
<string name="set_pre_amp_with">Addasiad gyda thagiau</string>
|
<string name="set_pre_amp_with">Addasiad gyda thagiau</string>
|
||||||
|
<string name="err_no_music">Ni chanfuwyd cerddoriaeth</string>
|
||||||
<string name="err_index_failed">Methwyd llwytho cerddoriaeth</string>
|
<string name="err_index_failed">Methwyd llwytho cerddoriaeth</string>
|
||||||
|
<string name="err_no_perms">Mae ar Auxio angen caniatâd i ddarllen eich llyfrgell gerddoriaeth</string>
|
||||||
<string name="err_no_app">Methwyd dod o hyd ap sydd yn gallu gwneud y tasg hon</string>
|
<string name="err_no_app">Methwyd dod o hyd ap sydd yn gallu gwneud y tasg hon</string>
|
||||||
|
<string name="err_no_locations">Dim ffolderi</string>
|
||||||
<string name="desc_skip_next">Neidio i\'r gân nesaf</string>
|
<string name="desc_skip_next">Neidio i\'r gân nesaf</string>
|
||||||
<string name="desc_skip_prev">Neidio i\'r gân ddiwethaf</string>
|
<string name="desc_skip_prev">Neidio i\'r gân ddiwethaf</string>
|
||||||
<string name="desc_change_repeat">Newid y modd ail-chwarae</string>
|
<string name="desc_change_repeat">Newid y modd ail-chwarae</string>
|
||||||
|
@ -237,6 +245,7 @@
|
||||||
<string name="desc_remove_song">Tynnu\'r gân hon</string>
|
<string name="desc_remove_song">Tynnu\'r gân hon</string>
|
||||||
<string name="desc_queue_bar">Agor y ciw</string>
|
<string name="desc_queue_bar">Agor y ciw</string>
|
||||||
<string name="cdc_mp4">Sain MPEG-4</string>
|
<string name="cdc_mp4">Sain MPEG-4</string>
|
||||||
|
<string name="cdc_mka">Sain Matroska</string>
|
||||||
<string name="fmt_deletion_info">Dileu %s? Ni fydd yn bosib dadwneud hyn.</string>
|
<string name="fmt_deletion_info">Dileu %s? Ni fydd yn bosib dadwneud hyn.</string>
|
||||||
<plurals name="fmt_song_count">
|
<plurals name="fmt_song_count">
|
||||||
<item quantity="zero">%d caneuon</item>
|
<item quantity="zero">%d caneuon</item>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">Erneut versuchen</string>
|
<string name="lbl_retry">Erneut versuchen</string>
|
||||||
|
<string name="lbl_grant">Gewähren</string>
|
||||||
<string name="lbl_genres">Genres</string>
|
<string name="lbl_genres">Genres</string>
|
||||||
<string name="lbl_artists">Künstler</string>
|
<string name="lbl_artists">Künstler</string>
|
||||||
<string name="lbl_albums">Alben</string>
|
<string name="lbl_albums">Alben</string>
|
||||||
|
@ -23,7 +24,9 @@
|
||||||
<string name="lng_queue_added">Der Warteschlange hinzugefügt</string>
|
<string name="lng_queue_added">Der Warteschlange hinzugefügt</string>
|
||||||
<string name="lbl_artist_details">Zum Künstler gehen</string>
|
<string name="lbl_artist_details">Zum Künstler gehen</string>
|
||||||
<string name="lbl_album_details">Zum Album gehen</string>
|
<string name="lbl_album_details">Zum Album gehen</string>
|
||||||
|
<string name="lbl_add">Hinzufügen</string>
|
||||||
<string name="lbl_save">Speichern</string>
|
<string name="lbl_save">Speichern</string>
|
||||||
|
<string name="err_no_locations">Keine Ordner</string>
|
||||||
<string name="lbl_about">Über</string>
|
<string name="lbl_about">Über</string>
|
||||||
<string name="lbl_version">Version</string>
|
<string name="lbl_version">Version</string>
|
||||||
<string name="lbl_code">Quellcode</string>
|
<string name="lbl_code">Quellcode</string>
|
||||||
|
@ -61,7 +64,9 @@
|
||||||
<string name="set_reindex">Musik neu laden</string>
|
<string name="set_reindex">Musik neu laden</string>
|
||||||
<string name="set_reindex_desc">Musikbibliothek neu laden, verwendet gecachte Tags wenn möglich</string>
|
<string name="set_reindex_desc">Musikbibliothek neu laden, verwendet gecachte Tags wenn möglich</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">Keine Musik gefunden</string>
|
||||||
<string name="err_index_failed">Laden der Musik fehlgeschlagen</string>
|
<string name="err_index_failed">Laden der Musik fehlgeschlagen</string>
|
||||||
|
<string name="err_no_perms">Auxio benötigt die Berechtigung, um deine Musikbibliothek zu lesen</string>
|
||||||
<string name="err_no_app">Es konnte keine App gefunden werden, die diese Aufgabe übernehmen kann</string>
|
<string name="err_no_app">Es konnte keine App gefunden werden, die diese Aufgabe übernehmen kann</string>
|
||||||
<string name="err_bad_location">Das Verzeichnis wird nicht unterstützt</string>
|
<string name="err_bad_location">Das Verzeichnis wird nicht unterstützt</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
|
@ -124,6 +129,7 @@
|
||||||
<string name="set_lib_tabs">Bibliotheks-Registerkarten</string>
|
<string name="set_lib_tabs">Bibliotheks-Registerkarten</string>
|
||||||
<string name="set_lib_tabs_desc">Sichtbarkeit und Ordnung der Bibliotheksregisterkarten ändern</string>
|
<string name="set_lib_tabs_desc">Sichtbarkeit und Ordnung der Bibliotheksregisterkarten ändern</string>
|
||||||
<string name="lbl_name">Name</string>
|
<string name="lbl_name">Name</string>
|
||||||
|
<string name="desc_shuffle_all">Alle Lieder zufällig</string>
|
||||||
<string name="desc_remove_song">Lied in der Warteschlange löschen</string>
|
<string name="desc_remove_song">Lied in der Warteschlange löschen</string>
|
||||||
<string name="desc_tab_handle">Tab versetzen</string>
|
<string name="desc_tab_handle">Tab versetzen</string>
|
||||||
<string name="def_artist">Unbekannter Künstler</string>
|
<string name="def_artist">Unbekannter Künstler</string>
|
||||||
|
@ -152,6 +158,7 @@
|
||||||
<string name="cdc_ogg">Ogg-Audio</string>
|
<string name="cdc_ogg">Ogg-Audio</string>
|
||||||
<string name="cdc_mp4">MPEG-4-Audio</string>
|
<string name="cdc_mp4">MPEG-4-Audio</string>
|
||||||
<string name="cdc_mp3">MPEG-1-Audio</string>
|
<string name="cdc_mp3">MPEG-1-Audio</string>
|
||||||
|
<string name="cdc_mka">Matroska-Audio</string>
|
||||||
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
||||||
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
||||||
<string name="fmt_bitrate">%d kB/s</string>
|
<string name="fmt_bitrate">%d kB/s</string>
|
||||||
|
@ -237,6 +244,7 @@
|
||||||
<string name="set_music">Musik</string>
|
<string name="set_music">Musik</string>
|
||||||
<string name="set_images">Bilder</string>
|
<string name="set_images">Bilder</string>
|
||||||
<string name="set_library">Bibliothek</string>
|
<string name="set_library">Bibliothek</string>
|
||||||
|
<string name="set_locations_list">Ordner</string>
|
||||||
<string name="set_playback">Wiedergabe</string>
|
<string name="set_playback">Wiedergabe</string>
|
||||||
<string name="set_audio_desc">Ton und Wiedergabeverhalten konfigurieren</string>
|
<string name="set_audio_desc">Ton und Wiedergabeverhalten konfigurieren</string>
|
||||||
<string name="set_replay_gain">Lautstärkenormalisierung</string>
|
<string name="set_replay_gain">Lautstärkenormalisierung</string>
|
||||||
|
@ -273,6 +281,7 @@
|
||||||
<string name="lbl_sort_mode">Sortieren nach</string>
|
<string name="lbl_sort_mode">Sortieren nach</string>
|
||||||
<string name="desc_selection_image">Auswahl-Bild</string>
|
<string name="desc_selection_image">Auswahl-Bild</string>
|
||||||
<string name="lbl_selection">Auswahl</string>
|
<string name="lbl_selection">Auswahl</string>
|
||||||
|
<string name="lbl_show_error_info">Mehr</string>
|
||||||
<string name="lbl_copied">Kopiert</string>
|
<string name="lbl_copied">Kopiert</string>
|
||||||
<string name="lbl_report">Melden</string>
|
<string name="lbl_report">Melden</string>
|
||||||
<string name="lbl_error_info">Fehlerinformation</string>
|
<string name="lbl_error_info">Fehlerinformation</string>
|
||||||
|
@ -323,7 +332,4 @@
|
||||||
<string name="lng_empty_songs">Deine Lieder werden hier angezeigt.</string>
|
<string name="lng_empty_songs">Deine Lieder werden hier angezeigt.</string>
|
||||||
<string name="lng_empty_genres">Deine Genres werden hier angezeigt.</string>
|
<string name="lng_empty_genres">Deine Genres werden hier angezeigt.</string>
|
||||||
<string name="lng_empty_artists">Deine Künstler werden hier angezeigt.</string>
|
<string name="lng_empty_artists">Deine Künstler werden hier angezeigt.</string>
|
||||||
<string name="set_cover_mode_as_is">Unverändert</string>
|
</resources>
|
||||||
<string name="set_with_hidden_desc">Audio-Dateien einbeziehen, die versteckt sind (z. B. .cache)</string>
|
|
||||||
<string name="set_with_hidden">Versteckte Dateien einbeziehen</string>
|
|
||||||
</resources>
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">Προσπάθεια εκ νέου</string>
|
<string name="lbl_retry">Προσπάθεια εκ νέου</string>
|
||||||
|
<string name="lbl_grant">Χορήγηση</string>
|
||||||
<string name="lbl_genres">Είδη</string>
|
<string name="lbl_genres">Είδη</string>
|
||||||
<string name="lbl_artists">Καλλιτέχνες</string>
|
<string name="lbl_artists">Καλλιτέχνες</string>
|
||||||
<string name="lbl_albums">Άλμπουμ</string>
|
<string name="lbl_albums">Άλμπουμ</string>
|
||||||
|
@ -74,8 +75,10 @@
|
||||||
<string name="fmt_lib_artist_count">Καλλιτέχνες που φορτώθηκαν: %d</string>
|
<string name="fmt_lib_artist_count">Καλλιτέχνες που φορτώθηκαν: %d</string>
|
||||||
<string name="lbl_date">Έτος</string>
|
<string name="lbl_date">Έτος</string>
|
||||||
<string name="lbl_disc">Δίσκος</string>
|
<string name="lbl_disc">Δίσκος</string>
|
||||||
|
<string name="err_no_music">Δεν βρέθηκε καθόλου μουσική</string>
|
||||||
<string name="err_index_failed">Η φόρτωση μουσικής απέτυχε</string>
|
<string name="err_index_failed">Η φόρτωση μουσικής απέτυχε</string>
|
||||||
<string name="fmt_bitrate">%d kbps</string>
|
<string name="fmt_bitrate">%d kbps</string>
|
||||||
|
<string name="lbl_add">Πρόσθεση</string>
|
||||||
<string name="lbl_props">Ιδιότητες τραγουδιού</string>
|
<string name="lbl_props">Ιδιότητες τραγουδιού</string>
|
||||||
<string name="lbl_song_detail">Προβολή Ιδιοτήτων</string>
|
<string name="lbl_song_detail">Προβολή Ιδιοτήτων</string>
|
||||||
<string name="lbl_library_counts">Στατιστικά συλλογής</string>
|
<string name="lbl_library_counts">Στατιστικά συλλογής</string>
|
||||||
|
@ -92,6 +95,7 @@
|
||||||
<string name="lbl_name">Όνομα</string>
|
<string name="lbl_name">Όνομα</string>
|
||||||
<string name="lbl_duration">Διάρκεια</string>
|
<string name="lbl_duration">Διάρκεια</string>
|
||||||
<string name="fmt_lib_total_duration">Συνολική διάρκεια: %s</string>
|
<string name="fmt_lib_total_duration">Συνολική διάρκεια: %s</string>
|
||||||
|
<string name="err_no_locations">Καθόλου φάκελοι</string>
|
||||||
<string name="info_app_desc">Μια απλή, λογική εφαρμογή αναπαραγωγής μουσικής για Android.</string>
|
<string name="info_app_desc">Μια απλή, λογική εφαρμογή αναπαραγωγής μουσικής για Android.</string>
|
||||||
<string name="lbl_indexer">Φόρτωση μουσικής</string>
|
<string name="lbl_indexer">Φόρτωση μουσικής</string>
|
||||||
<string name="lng_widget">Προβολή και έλεγχος αναπαραγωγής μουσικής</string>
|
<string name="lng_widget">Προβολή και έλεγχος αναπαραγωγής μουσικής</string>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<string name="lng_widget">Ver y controlar la reproducción musical</string>
|
<string name="lng_widget">Ver y controlar la reproducción musical</string>
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">Reintentar</string>
|
<string name="lbl_retry">Reintentar</string>
|
||||||
|
<string name="lbl_grant">Permitir</string>
|
||||||
<string name="lbl_genres">Géneros</string>
|
<string name="lbl_genres">Géneros</string>
|
||||||
<string name="lbl_artists">Artistas</string>
|
<string name="lbl_artists">Artistas</string>
|
||||||
<string name="lbl_albums">Álbumes</string>
|
<string name="lbl_albums">Álbumes</string>
|
||||||
|
@ -21,36 +22,38 @@
|
||||||
<string name="lbl_sort_asc">Ascendente</string>
|
<string name="lbl_sort_asc">Ascendente</string>
|
||||||
<string name="lbl_playback">En reproducción</string>
|
<string name="lbl_playback">En reproducción</string>
|
||||||
<string name="lbl_play">Reproducir</string>
|
<string name="lbl_play">Reproducir</string>
|
||||||
<string name="lbl_shuffle">Modo aleatorio</string>
|
<string name="lbl_shuffle">Mezcla</string>
|
||||||
<string name="set_play_song_from_all">Reproducir todo</string>
|
<string name="set_play_song_from_all">Reproducir todo</string>
|
||||||
<string name="set_play_song_from_album">Reproducir por álbum</string>
|
<string name="set_play_song_from_album">Reproducir por álbum</string>
|
||||||
<string name="set_play_song_from_artist">Reproducir por artista</string>
|
<string name="set_play_song_from_artist">Reproducir por artista</string>
|
||||||
<string name="lbl_queue">Cola</string>
|
<string name="lbl_queue">Cola</string>
|
||||||
<string name="lbl_play_next">Reproducir siguiente</string>
|
<string name="lbl_play_next">Reproducir siguiente</string>
|
||||||
<string name="lbl_queue_add">Añadir a la cola</string>
|
<string name="lbl_queue_add">Agregar a la cola</string>
|
||||||
<string name="lng_queue_added">Añadido a la cola</string>
|
<string name="lng_queue_added">Agregado a la cola</string>
|
||||||
<string name="lbl_artist_details">Ir al artista</string>
|
<string name="lbl_artist_details">Ir al artista</string>
|
||||||
<string name="lbl_album_details">Ir al álbum</string>
|
<string name="lbl_album_details">Ir al álbum</string>
|
||||||
|
<string name="lbl_add">Agregar</string>
|
||||||
<string name="lbl_save">Guardar</string>
|
<string name="lbl_save">Guardar</string>
|
||||||
|
<string name="err_no_locations">Sin carpetas</string>
|
||||||
<string name="lbl_about">Acerca de</string>
|
<string name="lbl_about">Acerca de</string>
|
||||||
<string name="lbl_version">Versión</string>
|
<string name="lbl_version">Versión</string>
|
||||||
<string name="lbl_code">Código fuente</string>
|
<string name="lbl_code">Código fuente</string>
|
||||||
<string name="lbl_licenses">Licencias</string>
|
<string name="lbl_licenses">Licencias</string>
|
||||||
<string name="lbl_author_name">Desarrollado por Alexander Capehart</string>
|
<string name="lbl_author_name">Desarrollado por Alexander Capehart</string>
|
||||||
<!-- Settings namespace | Settings-related labels -->
|
<!-- Settings namespace | Settings-related labels -->
|
||||||
<string name="set_root_title">Configuración</string>
|
<string name="set_root_title">Ajustes</string>
|
||||||
<string name="set_ui">Aspecto y comportamiento</string>
|
<string name="set_ui">Aspecto y Comportamiento</string>
|
||||||
<string name="set_theme">Tema</string>
|
<string name="set_theme">Tema</string>
|
||||||
<string name="set_theme_auto">Automático</string>
|
<string name="set_theme_auto">Automático</string>
|
||||||
<string name="set_theme_day">Claro</string>
|
<string name="set_theme_day">Claro</string>
|
||||||
<string name="set_theme_night">Oscuro</string>
|
<string name="set_theme_night">Oscuro</string>
|
||||||
<string name="set_accent">Combinación de colores</string>
|
<string name="set_accent">Esquema de color</string>
|
||||||
<string name="set_black_mode">Tema negro</string>
|
<string name="set_black_mode">Tema negro</string>
|
||||||
<string name="set_black_mode_desc">Usar un tema completamente negro</string>
|
<string name="set_black_mode_desc">Usar un tema completamente negro</string>
|
||||||
<string name="set_display">Pantalla</string>
|
<string name="set_display">Pantalla</string>
|
||||||
<string name="set_lib_tabs">Pestañas de la biblioteca</string>
|
<string name="set_lib_tabs">Pestañas de la biblioteca</string>
|
||||||
<string name="set_lib_tabs_desc">Cambiar visibilidad y orden de las pestañas de la biblioteca</string>
|
<string name="set_lib_tabs_desc">Cambiar visibilidad y orden de las pestañas de la biblioteca</string>
|
||||||
<string name="set_round_mode">Modo redondeado</string>
|
<string name="set_round_mode">Carátulas redondeadas</string>
|
||||||
<string name="set_round_mode_desc">Habilitar las esquinas redondeadas en los elementos adicionales de la interfaz del usuario (requiere que las portadas de los álbumes estén redondeadas)</string>
|
<string name="set_round_mode_desc">Habilitar las esquinas redondeadas en los elementos adicionales de la interfaz del usuario (requiere que las portadas de los álbumes estén redondeadas)</string>
|
||||||
<string name="set_notif_action">Usar acciones de notificación personalizadas</string>
|
<string name="set_notif_action">Usar acciones de notificación personalizadas</string>
|
||||||
<string name="set_audio">Sonido</string>
|
<string name="set_audio">Sonido</string>
|
||||||
|
@ -70,11 +73,13 @@
|
||||||
<string name="set_reindex">Actualizar música</string>
|
<string name="set_reindex">Actualizar música</string>
|
||||||
<string name="set_reindex_desc">Recargar la biblioteca musical, utilizando las etiquetas en caché cuando sea posible</string>
|
<string name="set_reindex_desc">Recargar la biblioteca musical, utilizando las etiquetas en caché cuando sea posible</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">No se ha encontrado música</string>
|
||||||
<string name="err_index_failed">Falló la carga de música</string>
|
<string name="err_index_failed">Falló la carga de música</string>
|
||||||
|
<string name="err_no_perms">Auxio necesita permiso para leer su biblioteca de música</string>
|
||||||
<string name="err_no_app">No se encontró ninguna aplicación que pueda manejar esta tarea</string>
|
<string name="err_no_app">No se encontró ninguna aplicación que pueda manejar esta tarea</string>
|
||||||
<string name="err_bad_location">No se admite esta carpeta</string>
|
<string name="err_bad_location">Directorio no soportado</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="lng_search_library">Buscar en la fonoteca…</string>
|
<string name="lng_search_library">Buscar en la biblioteca…</string>
|
||||||
<!-- Description Namespace | Accessibility Strings -->
|
<!-- Description Namespace | Accessibility Strings -->
|
||||||
<string name="desc_track_number">Pista %d</string>
|
<string name="desc_track_number">Pista %d</string>
|
||||||
<string name="desc_play_pause">Reproducir o pausar</string>
|
<string name="desc_play_pause">Reproducir o pausar</string>
|
||||||
|
@ -82,6 +87,7 @@
|
||||||
<string name="desc_skip_prev">Saltar a la última canción</string>
|
<string name="desc_skip_prev">Saltar a la última canción</string>
|
||||||
<string name="desc_change_repeat">Cambiar modo de repetición</string>
|
<string name="desc_change_repeat">Cambiar modo de repetición</string>
|
||||||
<string name="desc_shuffle">Activar o desactivar mezcla</string>
|
<string name="desc_shuffle">Activar o desactivar mezcla</string>
|
||||||
|
<string name="desc_shuffle_all">Mezclar todas las canciones</string>
|
||||||
<string name="desc_remove_song">Quitar canción de la cola</string>
|
<string name="desc_remove_song">Quitar canción de la cola</string>
|
||||||
<string name="desc_song_handle">Mover canción en la cola</string>
|
<string name="desc_song_handle">Mover canción en la cola</string>
|
||||||
<string name="desc_tab_handle">Mover pestaña</string>
|
<string name="desc_tab_handle">Mover pestaña</string>
|
||||||
|
@ -136,12 +142,13 @@
|
||||||
<string name="lbl_song_detail">Ver propiedades</string>
|
<string name="lbl_song_detail">Ver propiedades</string>
|
||||||
<string name="lbl_shuffle_shortcut_short">Mezclar</string>
|
<string name="lbl_shuffle_shortcut_short">Mezclar</string>
|
||||||
<string name="lbl_shuffle_shortcut_long">Mezclar todo</string>
|
<string name="lbl_shuffle_shortcut_long">Mezclar todo</string>
|
||||||
<string name="lbl_ok">Aceptar</string>
|
<string name="lbl_ok">De acuerdo</string>
|
||||||
<string name="lbl_library_counts">Estadísticas de la biblioteca</string>
|
<string name="lbl_library_counts">Estadísticas de la biblioteca</string>
|
||||||
<string name="set_pre_amp_without">Ajuste sin etiquetas</string>
|
<string name="set_pre_amp_without">Ajuste sin etiquetas</string>
|
||||||
<string name="set_pre_amp_warning">Advertencia: Cambiar el pre-amp a un valor alto puede resultar en picos en algunas pistas de audio.</string>
|
<string name="set_pre_amp_warning">Advertencia: Cambiar el pre-amp a un valor alto puede resultar en picos en algunas pistas de audio.</string>
|
||||||
<string name="set_play_song_none">Reproducir desde el elemento que se muestra</string>
|
<string name="set_play_song_none">Reproducir desde el elemento que se muestra</string>
|
||||||
<string name="cdc_flac">Códec de audio sin pérdida libre (FLAC)</string>
|
<string name="cdc_mka">Audio matroska</string>
|
||||||
|
<string name="cdc_flac">Free Losless Audio Codec (FLAC)</string>
|
||||||
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
||||||
<string name="fmt_indexing">Cargando tu biblioteca de música… (%1$d/%2$d)</string>
|
<string name="fmt_indexing">Cargando tu biblioteca de música… (%1$d/%2$d)</string>
|
||||||
<string name="fmt_lib_artist_count">Artistas cargados: %d</string>
|
<string name="fmt_lib_artist_count">Artistas cargados: %d</string>
|
||||||
|
@ -150,15 +157,15 @@
|
||||||
<string name="lbl_song_count">Número de canciones</string>
|
<string name="lbl_song_count">Número de canciones</string>
|
||||||
<string name="set_observing">Recarga automática</string>
|
<string name="set_observing">Recarga automática</string>
|
||||||
<string name="set_observing_desc">Recargar la biblioteca musical cada vez que cambie (requiere una notificación persistente)</string>
|
<string name="set_observing_desc">Recargar la biblioteca musical cada vez que cambie (requiere una notificación persistente)</string>
|
||||||
<string name="lng_indexing">Cargando la fonoteca…</string>
|
<string name="lng_indexing">Cargando tu librería de música…</string>
|
||||||
<string name="lbl_indexing">Cargando música</string>
|
<string name="lbl_indexing">Cargando música</string>
|
||||||
<string name="lbl_observing">Monitorizando la fonoteca</string>
|
<string name="lbl_observing">Monitorizando la librería de música</string>
|
||||||
<string name="lng_observing">Monitorizando cambios en la fonoteca…</string>
|
<string name="lng_observing">Monitorizando cambios en tu librería de música…</string>
|
||||||
<string name="cdc_ogg">Audio Ogg</string>
|
<string name="cdc_ogg">Audio ogg</string>
|
||||||
<string name="set_play_in_parent_with">Cuando se reproduce desde los detalles</string>
|
<string name="set_play_in_parent_with">Cuando se reproduce desde los detalles</string>
|
||||||
<string name="lbl_date_added">Fecha de adición</string>
|
<string name="lbl_date_added">Fecha de añadido</string>
|
||||||
<string name="lbl_props">Propiedades de la canción</string>
|
<string name="lbl_props">Propiedades de la canción</string>
|
||||||
<string name="lbl_sample_rate">Tasa de muestreo</string>
|
<string name="lbl_sample_rate">Frecuencia de muestreo</string>
|
||||||
<string name="lbl_cancel">Cancelar</string>
|
<string name="lbl_cancel">Cancelar</string>
|
||||||
<string name="set_headset_autoplay">Reproducción automática con auriculares</string>
|
<string name="set_headset_autoplay">Reproducción automática con auriculares</string>
|
||||||
<string name="set_locations">Carpetas de música</string>
|
<string name="set_locations">Carpetas de música</string>
|
||||||
|
@ -169,9 +176,9 @@
|
||||||
<string name="lbl_ep">EP</string>
|
<string name="lbl_ep">EP</string>
|
||||||
<string name="lbl_singles">Sencillos</string>
|
<string name="lbl_singles">Sencillos</string>
|
||||||
<string name="lbl_single">Sencillo</string>
|
<string name="lbl_single">Sencillo</string>
|
||||||
<string name="lbl_soundtrack">Banda sonora</string>
|
<string name="lbl_soundtrack">Pista de audio</string>
|
||||||
<string name="lbl_album_remix">Álbum de remezclas</string>
|
<string name="lbl_album_remix">Álbum remix</string>
|
||||||
<string name="lbl_soundtracks">Bandas sonoras</string>
|
<string name="lbl_soundtracks">Pistas de audio</string>
|
||||||
<string name="lbl_mixtapes">Mixtapes (recopilación de canciones)</string>
|
<string name="lbl_mixtapes">Mixtapes (recopilación de canciones)</string>
|
||||||
<string name="lbl_mixtape">Mixtape (recopilación de canciones)</string>
|
<string name="lbl_mixtape">Mixtape (recopilación de canciones)</string>
|
||||||
<string name="lbl_remix_group">Remezclas</string>
|
<string name="lbl_remix_group">Remezclas</string>
|
||||||
|
@ -184,7 +191,7 @@
|
||||||
<string name="fmt_lib_album_count">Álbumes cargados: %d</string>
|
<string name="fmt_lib_album_count">Álbumes cargados: %d</string>
|
||||||
<string name="fmt_lib_total_duration">Duración total: %s</string>
|
<string name="fmt_lib_total_duration">Duración total: %s</string>
|
||||||
<string name="lbl_album_live">Álbum en directo</string>
|
<string name="lbl_album_live">Álbum en directo</string>
|
||||||
<string name="lbl_single_live">Sencillo en directo</string>
|
<string name="lbl_single_live">Single en directo</string>
|
||||||
<string name="lbl_compilation">Compilación</string>
|
<string name="lbl_compilation">Compilación</string>
|
||||||
<string name="lbl_live_group">En directo</string>
|
<string name="lbl_live_group">En directo</string>
|
||||||
<string name="cdc_mp3">Audio MPEG-1</string>
|
<string name="cdc_mp3">Audio MPEG-1</string>
|
||||||
|
@ -192,9 +199,9 @@
|
||||||
<string name="fmt_bitrate">%d kbps</string>
|
<string name="fmt_bitrate">%d kbps</string>
|
||||||
<string name="fmt_db_neg">-%.1f dB</string>
|
<string name="fmt_db_neg">-%.1f dB</string>
|
||||||
<string name="lbl_ep_live">EP en directo</string>
|
<string name="lbl_ep_live">EP en directo</string>
|
||||||
<string name="lbl_single_remix">Sencillo remezclado</string>
|
<string name="lbl_single_remix">Single remix</string>
|
||||||
<string name="lbl_compilations">Compilaciones</string>
|
<string name="lbl_compilations">Compilaciones</string>
|
||||||
<string name="lbl_ep_remix">EP de remezclas</string>
|
<string name="lbl_ep_remix">EP de remixes</string>
|
||||||
<string name="desc_queue_bar">Abrir la cola</string>
|
<string name="desc_queue_bar">Abrir la cola</string>
|
||||||
<string name="lbl_genre">Género</string>
|
<string name="lbl_genre">Género</string>
|
||||||
<string name="set_separators">Separadores de varios valores</string>
|
<string name="set_separators">Separadores de varios valores</string>
|
||||||
|
@ -209,7 +216,7 @@
|
||||||
<string name="lbl_mix">Mezcla de DJ</string>
|
<string name="lbl_mix">Mezcla de DJ</string>
|
||||||
<string name="lbl_equalizer">Ecualizador</string>
|
<string name="lbl_equalizer">Ecualizador</string>
|
||||||
<string name="set_cover_mode">Portadas de álbumes</string>
|
<string name="set_cover_mode">Portadas de álbumes</string>
|
||||||
<string name="set_cover_mode_off">Desactivadas</string>
|
<string name="set_cover_mode_off">Apagado</string>
|
||||||
<string name="set_action_mode_repeat">Modo de repetición</string>
|
<string name="set_action_mode_repeat">Modo de repetición</string>
|
||||||
<string name="set_separators_plus">Más (+)</string>
|
<string name="set_separators_plus">Más (+)</string>
|
||||||
<string name="set_separators_and">Signo et</string>
|
<string name="set_separators_and">Signo et</string>
|
||||||
|
@ -241,6 +248,7 @@
|
||||||
<string name="set_images">Imágenes</string>
|
<string name="set_images">Imágenes</string>
|
||||||
<string name="set_audio_desc">Configurar el comportamiento del sonido y la reproducción</string>
|
<string name="set_audio_desc">Configurar el comportamiento del sonido y la reproducción</string>
|
||||||
<string name="set_playback">Reproducción</string>
|
<string name="set_playback">Reproducción</string>
|
||||||
|
<string name="set_locations_list">Carpetas</string>
|
||||||
<string name="set_ui_desc">Cambiar el tema y los colores de la aplicación</string>
|
<string name="set_ui_desc">Cambiar el tema y los colores de la aplicación</string>
|
||||||
<string name="set_personalize_desc">Personalizar los controles y el comportamiento de la interfaz de usuario</string>
|
<string name="set_personalize_desc">Personalizar los controles y el comportamiento de la interfaz de usuario</string>
|
||||||
<string name="set_library">Biblioteca</string>
|
<string name="set_library">Biblioteca</string>
|
||||||
|
@ -252,17 +260,17 @@
|
||||||
<string name="set_intelligent_sorting_desc">Ignorar palabras como \"the\" al ordenar por nombre (funciona mejor con música en inglés)</string>
|
<string name="set_intelligent_sorting_desc">Ignorar palabras como \"the\" al ordenar por nombre (funciona mejor con música en inglés)</string>
|
||||||
<string name="lbl_new_playlist">Nueva lista de reproducción</string>
|
<string name="lbl_new_playlist">Nueva lista de reproducción</string>
|
||||||
<string name="fmt_def_playlist">Lista de reproducción %d</string>
|
<string name="fmt_def_playlist">Lista de reproducción %d</string>
|
||||||
<string name="lbl_playlist_add">Añadir a la lista de reproducción</string>
|
<string name="lbl_playlist_add">Agregar a la lista de reproducción</string>
|
||||||
<string name="lng_playlist_added">Agregado a la lista de reproducción</string>
|
<string name="lng_playlist_added">Agregado a la lista de reproducción</string>
|
||||||
<string name="lng_playlist_created">Lista de reproducción creada</string>
|
<string name="lng_playlist_created">Lista de reproducción creada</string>
|
||||||
<string name="def_song_count">No hay canciones</string>
|
<string name="def_song_count">No hay canciones</string>
|
||||||
<string name="lbl_delete">Eliminar</string>
|
<string name="lbl_delete">Borrar</string>
|
||||||
<string name="lbl_rename">Cambiar nombre</string>
|
<string name="lbl_rename">Cambiar el nombre</string>
|
||||||
<string name="lbl_rename_playlist">Cambiar nombre de lista de reproducción</string>
|
<string name="lbl_rename_playlist">Cambiar el nombre de la lista de reproducción</string>
|
||||||
<string name="lng_playlist_renamed">Lista de reproducción renombrada</string>
|
<string name="lng_playlist_renamed">Lista de reproducción renombrada</string>
|
||||||
<string name="lng_playlist_deleted">Lista de reproducción eliminada</string>
|
<string name="lng_playlist_deleted">Lista de reproducción borrada</string>
|
||||||
<string name="fmt_deletion_info">¿Borrar %s\? Esto no se puede deshacer.</string>
|
<string name="fmt_deletion_info">¿Borrar %s\? Esto no se puede deshacer.</string>
|
||||||
<string name="lbl_confirm_delete_playlist">¿Quiere eliminar la lista de reproducción?</string>
|
<string name="lbl_confirm_delete_playlist">¿Borrar la lista de reproducción\?</string>
|
||||||
<string name="lbl_edit">Editar</string>
|
<string name="lbl_edit">Editar</string>
|
||||||
<string name="fmt_editing">Editando %s</string>
|
<string name="fmt_editing">Editando %s</string>
|
||||||
<string name="lbl_appears_on">Aparece en</string>
|
<string name="lbl_appears_on">Aparece en</string>
|
||||||
|
@ -277,6 +285,7 @@
|
||||||
<string name="lbl_sort_direction">Dirección</string>
|
<string name="lbl_sort_direction">Dirección</string>
|
||||||
<string name="desc_selection_image">Selección de imágenes</string>
|
<string name="desc_selection_image">Selección de imágenes</string>
|
||||||
<string name="lbl_selection">Selección</string>
|
<string name="lbl_selection">Selección</string>
|
||||||
|
<string name="lbl_show_error_info">Más</string>
|
||||||
<string name="lbl_error_info">Información sobre el error</string>
|
<string name="lbl_error_info">Información sobre el error</string>
|
||||||
<string name="lbl_copied">Copiado</string>
|
<string name="lbl_copied">Copiado</string>
|
||||||
<string name="lbl_report">Informar</string>
|
<string name="lbl_report">Informar</string>
|
||||||
|
@ -319,15 +328,5 @@
|
||||||
<string name="def_album">Álbum desconocido</string>
|
<string name="def_album">Álbum desconocido</string>
|
||||||
<string name="cdc_unknown">Desconocido</string>
|
<string name="cdc_unknown">Desconocido</string>
|
||||||
<string name="cnt_mp4">El MPEG-4 contiene %s</string>
|
<string name="cnt_mp4">El MPEG-4 contiene %s</string>
|
||||||
<string name="cdc_alac">Códec de audio sin pérdida de Apple (ALAC)</string>
|
<string name="cdc_alac">Apple Lossless Audio Codec (ALAC)</string>
|
||||||
<string name="lng_empty_albums">Sus álbumes aparecerán aquí.</string>
|
</resources>
|
||||||
<string name="lng_empty_artists">Sus artistas aparecerán aquí.</string>
|
|
||||||
<string name="lng_empty_genres">Sus géneros aparecerán aquí.</string>
|
|
||||||
<string name="set_locations_new">Nueva carpeta</string>
|
|
||||||
<string name="lng_empty_playlists">Sus listas de reproducción aparecerán aquí.</string>
|
|
||||||
<string name="lng_empty_songs">Sus canciones aparecerán aquí.</string>
|
|
||||||
<string name="set_cover_mode_save_space">Ahorra espacio</string>
|
|
||||||
<string name="set_cover_mode_as_is">Original</string>
|
|
||||||
<string name="set_with_hidden_desc">Incluir ficheros de audio ocultos (ej. .cache)</string>
|
|
||||||
<string name="set_with_hidden">Incluir ficheros ocultos</string>
|
|
||||||
</resources>
|
|
|
@ -2,6 +2,8 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="lbl_indexer">Muusika on laadimisel</string>
|
<string name="lbl_indexer">Muusika on laadimisel</string>
|
||||||
<string name="lbl_observing">Jälgime muudatusi muusikakogus</string>
|
<string name="lbl_observing">Jälgime muudatusi muusikakogus</string>
|
||||||
|
<string name="lbl_show_error_info">Veel</string>
|
||||||
|
<string name="lbl_grant">Anna õigused</string>
|
||||||
<string name="lbl_song">Pala</string>
|
<string name="lbl_song">Pala</string>
|
||||||
<string name="lbl_albums">Albumid</string>
|
<string name="lbl_albums">Albumid</string>
|
||||||
<string name="lbl_album_live">Album elavas esituses muusikaga</string>
|
<string name="lbl_album_live">Album elavas esituses muusikaga</string>
|
||||||
|
@ -55,6 +57,7 @@
|
||||||
<string name="lbl_start_playback">Alusta taasesitust</string>
|
<string name="lbl_start_playback">Alusta taasesitust</string>
|
||||||
<string name="lbl_cancel">Katkesta</string>
|
<string name="lbl_cancel">Katkesta</string>
|
||||||
<string name="lbl_save">Salvesta</string>
|
<string name="lbl_save">Salvesta</string>
|
||||||
|
<string name="lbl_add">Lisa</string>
|
||||||
<string name="lbl_path_style">Asukoha kuvamise viis</string>
|
<string name="lbl_path_style">Asukoha kuvamise viis</string>
|
||||||
<string name="lbl_path_style_absolute">Absoluutne</string>
|
<string name="lbl_path_style_absolute">Absoluutne</string>
|
||||||
<string name="lbl_about">Rakenduse teave</string>
|
<string name="lbl_about">Rakenduse teave</string>
|
||||||
|
@ -227,7 +230,7 @@
|
||||||
<string name="set_separators_comma">Koma (,)</string>
|
<string name="set_separators_comma">Koma (,)</string>
|
||||||
<string name="set_separators_semicolon">Semikoolon (;)</string>
|
<string name="set_separators_semicolon">Semikoolon (;)</string>
|
||||||
<string name="set_separators_plus">Pluss (+)</string>
|
<string name="set_separators_plus">Pluss (+)</string>
|
||||||
<string name="set_separators_and">Ampersand (and-märk)</string>
|
<string name="set_separators_and">Ampersand (&)</string>
|
||||||
<string name="set_separators_desc">Seadista tähemärke, mis eraldavad siltides mitut väärtust</string>
|
<string name="set_separators_desc">Seadista tähemärke, mis eraldavad siltides mitut väärtust</string>
|
||||||
<string name="set_separators_slash">Kaldkriips (/)</string>
|
<string name="set_separators_slash">Kaldkriips (/)</string>
|
||||||
<string name="set_separators_warning">Hoiatus: selle seadistuse kasutamisel ei pruugi mitu väärtust siltides olla alati korralikult tuvastatud; seda olukorda saad proovida lahendada täiendava prefiksi lisamisega kurakaldkriipsu näol (\\).</string>
|
<string name="set_separators_warning">Hoiatus: selle seadistuse kasutamisel ei pruugi mitu väärtust siltides olla alati korralikult tuvastatud; seda olukorda saad proovida lahendada täiendava prefiksi lisamisega kurakaldkriipsu näol (\\).</string>
|
||||||
|
@ -240,15 +243,19 @@
|
||||||
<string name="set_library">Muusikakogu</string>
|
<string name="set_library">Muusikakogu</string>
|
||||||
<string name="set_locations">Muusika kaustad</string>
|
<string name="set_locations">Muusika kaustad</string>
|
||||||
<string name="set_locations_desc">Halda kaustu, kust otsime ja laadime muusikat</string>
|
<string name="set_locations_desc">Halda kaustu, kust otsime ja laadime muusikat</string>
|
||||||
|
<string name="set_locations_list">Kaustad</string>
|
||||||
<string name="set_reindex">Värskenda muusika andmed</string>
|
<string name="set_reindex">Värskenda muusika andmed</string>
|
||||||
<string name="set_reindex_desc">Laadi muusikakogu uuesti ning kui võimalik, siis kasuta puhverdatud silte</string>
|
<string name="set_reindex_desc">Laadi muusikakogu uuesti ning kui võimalik, siis kasuta puhverdatud silte</string>
|
||||||
<string name="set_rescan">Laadi muusikakogu uuesti</string>
|
<string name="set_rescan">Laadi muusikakogu uuesti</string>
|
||||||
<string name="set_rescan_desc">Kustuta puhverdatud siltide andmed ja laadi muusikakogu tervikuna uuesti (aeglasem, aga täpsem tulemus)</string>
|
<string name="set_rescan_desc">Kustuta puhverdatud siltide andmed ja laadi muusikakogu tervikuna uuesti (aeglasem, aga täpsem tulemus)</string>
|
||||||
|
<string name="err_no_music">Muusikat ei leidu</string>
|
||||||
<string name="err_index_failed">Muusika laadimine ei õnnestunud</string>
|
<string name="err_index_failed">Muusika laadimine ei õnnestunud</string>
|
||||||
|
<string name="err_no_perms">Auxio vajab muusikakogu töötlemiseks õigust lugeda faile ja kaustu sinu nutiseadmes</string>
|
||||||
<string name="err_import_failed">Sellest failist ei õnnestu esitusloendit importida</string>
|
<string name="err_import_failed">Sellest failist ei õnnestu esitusloendit importida</string>
|
||||||
<string name="err_export_failed">Sellesse faili ei õnnestu esitusloendit eksportida</string>
|
<string name="err_export_failed">Sellesse faili ei õnnestu esitusloendit eksportida</string>
|
||||||
<string name="err_no_app">Ei leidu selle ülesande täitmiseks sobilikku rakendust</string>
|
<string name="err_no_app">Ei leidu selle ülesande täitmiseks sobilikku rakendust</string>
|
||||||
<string name="desc_track_number">Lugu %d</string>
|
<string name="desc_track_number">Lugu %d</string>
|
||||||
|
<string name="err_no_locations">Kaustu pole määratud</string>
|
||||||
<string name="err_bad_location">See kaust pole toetatud</string>
|
<string name="err_bad_location">See kaust pole toetatud</string>
|
||||||
<string name="desc_play_pause">Esita või peata</string>
|
<string name="desc_play_pause">Esita või peata</string>
|
||||||
<string name="desc_change_repeat">Muuda kordamise režiimi</string>
|
<string name="desc_change_repeat">Muuda kordamise režiimi</string>
|
||||||
|
@ -258,6 +265,7 @@
|
||||||
<string name="desc_exit">Lõpeta taasesitus</string>
|
<string name="desc_exit">Lõpeta taasesitus</string>
|
||||||
<string name="desc_queue_bar">Ava esitusjärjekord</string>
|
<string name="desc_queue_bar">Ava esitusjärjekord</string>
|
||||||
<string name="desc_tab_handle">Liiguta seda vahelehte</string>
|
<string name="desc_tab_handle">Liiguta seda vahelehte</string>
|
||||||
|
<string name="desc_shuffle_all">Sega kõik palad</string>
|
||||||
<string name="desc_remove_song">Eemalda see pala</string>
|
<string name="desc_remove_song">Eemalda see pala</string>
|
||||||
<string name="desc_song_handle">Tõsta see pala teise kohta</string>
|
<string name="desc_song_handle">Tõsta see pala teise kohta</string>
|
||||||
<string name="desc_clear_search">Tühjenda otsinguajalugu</string>
|
<string name="desc_clear_search">Tühjenda otsinguajalugu</string>
|
||||||
|
@ -280,6 +288,7 @@
|
||||||
<string name="cdc_ogg">Ogg Vorbis audio</string>
|
<string name="cdc_ogg">Ogg Vorbis audio</string>
|
||||||
<string name="cdc_mp3">MPEG-1 audio</string>
|
<string name="cdc_mp3">MPEG-1 audio</string>
|
||||||
<string name="cdc_mp4">MPEG-4 audio</string>
|
<string name="cdc_mp4">MPEG-4 audio</string>
|
||||||
|
<string name="cdc_mka">Matroska audio</string>
|
||||||
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
||||||
<string name="fmt_lib_song_count">Laaditud palasid: %d</string>
|
<string name="fmt_lib_song_count">Laaditud palasid: %d</string>
|
||||||
<string name="fmt_deletion_info">Kas kustutame %s? Seda tegevust ei saa tagasi pöörata.</string>
|
<string name="fmt_deletion_info">Kas kustutame %s? Seda tegevust ei saa tagasi pöörata.</string>
|
||||||
|
@ -315,7 +324,4 @@
|
||||||
<string name="lng_empty_genres">Sinu žanrid saavad olema nähtavad siin.</string>
|
<string name="lng_empty_genres">Sinu žanrid saavad olema nähtavad siin.</string>
|
||||||
<string name="lng_empty_albums">Sinu albumid saavad olema nähtavad siin.</string>
|
<string name="lng_empty_albums">Sinu albumid saavad olema nähtavad siin.</string>
|
||||||
<string name="lng_empty_playlists">Sinu esitusloendid saavad olema nähtavad siin.</string>
|
<string name="lng_empty_playlists">Sinu esitusloendid saavad olema nähtavad siin.</string>
|
||||||
<string name="set_with_hidden">Kaasa peidetud failid</string>
|
</resources>
|
||||||
<string name="set_with_hidden_desc">Kaasa peidetud helifailid (nt. .cache)</string>
|
|
||||||
<string name="set_cover_mode_as_is">Sellisena, nagu ta on</string>
|
|
||||||
</resources>
|
|
|
@ -3,6 +3,7 @@
|
||||||
<string name="lbl_indexer">بارگیری موسیقی</string>
|
<string name="lbl_indexer">بارگیری موسیقی</string>
|
||||||
<string name="info_app_desc">یک پخش کننده موسیقی ساده و منطقی برای اندروید.</string>
|
<string name="info_app_desc">یک پخش کننده موسیقی ساده و منطقی برای اندروید.</string>
|
||||||
<string name="lbl_retry">تلاش دوباره</string>
|
<string name="lbl_retry">تلاش دوباره</string>
|
||||||
|
<string name="lbl_grant">اجازه دادن</string>
|
||||||
<string name="lbl_album">آلبوم</string>
|
<string name="lbl_album">آلبوم</string>
|
||||||
<string name="lbl_album_live">آلبوم زنده</string>
|
<string name="lbl_album_live">آلبوم زنده</string>
|
||||||
<string name="lbl_album_remix">آلبوم ریمیکس</string>
|
<string name="lbl_album_remix">آلبوم ریمیکس</string>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<string name="lbl_indexer">Musiikki latautuu</string>
|
<string name="lbl_indexer">Musiikki latautuu</string>
|
||||||
<string name="lbl_indexing">Ladataan musiikkia</string>
|
<string name="lbl_indexing">Ladataan musiikkia</string>
|
||||||
<string name="lbl_retry">Yritä uudelleen</string>
|
<string name="lbl_retry">Yritä uudelleen</string>
|
||||||
|
<string name="lbl_grant">Anna lupa</string>
|
||||||
<string name="lbl_songs">Kappaleet</string>
|
<string name="lbl_songs">Kappaleet</string>
|
||||||
<string name="lbl_all_songs">Kaikki kappaleet</string>
|
<string name="lbl_all_songs">Kaikki kappaleet</string>
|
||||||
<string name="lbl_albums">Albumit</string>
|
<string name="lbl_albums">Albumit</string>
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
<string name="lbl_cancel">Peruuta</string>
|
<string name="lbl_cancel">Peruuta</string>
|
||||||
<string name="lbl_save">Tallenna</string>
|
<string name="lbl_save">Tallenna</string>
|
||||||
<string name="lbl_reset">Palauta oletus</string>
|
<string name="lbl_reset">Palauta oletus</string>
|
||||||
|
<string name="lbl_add">Lisää</string>
|
||||||
<string name="lng_observing">Valvotaa musiikkikirjastoa muutosten varalta…</string>
|
<string name="lng_observing">Valvotaa musiikkikirjastoa muutosten varalta…</string>
|
||||||
<string name="lbl_shuffle_shortcut_short">Sekoita</string>
|
<string name="lbl_shuffle_shortcut_short">Sekoita</string>
|
||||||
<string name="lbl_shuffle_shortcut_long">Sekoita kaikki</string>
|
<string name="lbl_shuffle_shortcut_long">Sekoita kaikki</string>
|
||||||
|
@ -68,7 +70,7 @@
|
||||||
<string name="set_play_song_from_genre">Toista tyylilajista</string>
|
<string name="set_play_song_from_genre">Toista tyylilajista</string>
|
||||||
<string name="set_separators">Moniarvoerottimet</string>
|
<string name="set_separators">Moniarvoerottimet</string>
|
||||||
<string name="set_exclude_non_music_desc">Ohita äänitiedostot, jotka eivät ole musiikkia, kuten podcastit</string>
|
<string name="set_exclude_non_music_desc">Ohita äänitiedostot, jotka eivät ole musiikkia, kuten podcastit</string>
|
||||||
<string name="set_separators_and">Ampersand &</string>
|
<string name="set_separators_and">Ja-merkki (&)</string>
|
||||||
<string name="set_separators_comma">Pilkku (,)</string>
|
<string name="set_separators_comma">Pilkku (,)</string>
|
||||||
<string name="set_separators_plus">Plus (+)</string>
|
<string name="set_separators_plus">Plus (+)</string>
|
||||||
<string name="set_separators_semicolon">Puolipiste (;)</string>
|
<string name="set_separators_semicolon">Puolipiste (;)</string>
|
||||||
|
@ -87,6 +89,7 @@
|
||||||
<string name="set_locations_desc">Määritä mistä musiikki tulee ladata</string>
|
<string name="set_locations_desc">Määritä mistä musiikki tulee ladata</string>
|
||||||
<string name="set_rescan">Läpikäy musiikki uudelleen</string>
|
<string name="set_rescan">Läpikäy musiikki uudelleen</string>
|
||||||
<string name="err_no_app">Tähän tehtävään kykenevää sovellusta ei löytynyt</string>
|
<string name="err_no_app">Tähän tehtävään kykenevää sovellusta ei löytynyt</string>
|
||||||
|
<string name="err_no_locations">Ei kansioita</string>
|
||||||
<string name="desc_track_number">Raita %d</string>
|
<string name="desc_track_number">Raita %d</string>
|
||||||
<string name="desc_skip_next">Siirry seuraavaan kappaleeseen</string>
|
<string name="desc_skip_next">Siirry seuraavaan kappaleeseen</string>
|
||||||
<string name="desc_change_repeat">Muuta kertaustilaa</string>
|
<string name="desc_change_repeat">Muuta kertaustilaa</string>
|
||||||
|
@ -103,6 +106,7 @@
|
||||||
<string name="cdc_mp3">MPEG-1-ääni</string>
|
<string name="cdc_mp3">MPEG-1-ääni</string>
|
||||||
<string name="cdc_mp4">MPEG-4-ääni</string>
|
<string name="cdc_mp4">MPEG-4-ääni</string>
|
||||||
<string name="cdc_ogg">Ogg-ääni</string>
|
<string name="cdc_ogg">Ogg-ääni</string>
|
||||||
|
<string name="cdc_mka">Matroska-ääni</string>
|
||||||
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
||||||
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
||||||
<string name="clr_red">Punainen</string>
|
<string name="clr_red">Punainen</string>
|
||||||
|
@ -161,8 +165,10 @@
|
||||||
<string name="set_round_mode">Pyöristetty tila</string>
|
<string name="set_round_mode">Pyöristetty tila</string>
|
||||||
<string name="lbl_soundtracks">Elokuvamusiikit</string>
|
<string name="lbl_soundtracks">Elokuvamusiikit</string>
|
||||||
<string name="lbl_mixes">DJ-mixaukset</string>
|
<string name="lbl_mixes">DJ-mixaukset</string>
|
||||||
|
<string name="err_no_perms">Auxio tarvitsee luvan lukea musiikkikirjastoa</string>
|
||||||
<string name="set_root_title">Asetukset</string>
|
<string name="set_root_title">Asetukset</string>
|
||||||
<string name="lbl_sort">Järjestä</string>
|
<string name="lbl_sort">Järjestä</string>
|
||||||
|
<string name="err_no_music">Musiikkia ei löytynyt</string>
|
||||||
<string name="lbl_wiki">Wiki</string>
|
<string name="lbl_wiki">Wiki</string>
|
||||||
<string name="clr_grey">Harmaa</string>
|
<string name="clr_grey">Harmaa</string>
|
||||||
<string name="set_ui_desc">Muuta sovelluksen teemaa ja värejä</string>
|
<string name="set_ui_desc">Muuta sovelluksen teemaa ja värejä</string>
|
||||||
|
@ -199,9 +205,11 @@
|
||||||
<string name="set_headset_autoplay">Automaattitoisto kuulokkeilla</string>
|
<string name="set_headset_autoplay">Automaattitoisto kuulokkeilla</string>
|
||||||
<string name="set_headset_autoplay_desc">Aloita aina toisto, kun kuulokkeet yhdistetään (ei välttämättä toimi kaikilla laitteilla)</string>
|
<string name="set_headset_autoplay_desc">Aloita aina toisto, kun kuulokkeet yhdistetään (ei välttämättä toimi kaikilla laitteilla)</string>
|
||||||
<string name="desc_skip_prev">Siirry viimeiseen kappaleeseen</string>
|
<string name="desc_skip_prev">Siirry viimeiseen kappaleeseen</string>
|
||||||
|
<string name="set_locations_list">Kansiot</string>
|
||||||
<string name="desc_play_pause">Toista tai keskeytä</string>
|
<string name="desc_play_pause">Toista tai keskeytä</string>
|
||||||
<string name="err_bad_location">Tämä kansio ei ole tuettu</string>
|
<string name="err_bad_location">Tämä kansio ei ole tuettu</string>
|
||||||
<string name="desc_shuffle">Sekoitus päällä/pois</string>
|
<string name="desc_shuffle">Sekoitus päällä/pois</string>
|
||||||
|
<string name="desc_shuffle_all">Sekoita kaikki kappaleet</string>
|
||||||
<string name="desc_tab_handle">Siirry tätä välilehteä</string>
|
<string name="desc_tab_handle">Siirry tätä välilehteä</string>
|
||||||
<string name="desc_clear_search">Tyhjennä hakuehto</string>
|
<string name="desc_clear_search">Tyhjennä hakuehto</string>
|
||||||
<string name="desc_artist_image">Esittäjän %s kuva</string>
|
<string name="desc_artist_image">Esittäjän %s kuva</string>
|
||||||
|
@ -242,6 +250,7 @@
|
||||||
<string name="set_rescan_desc">Tyhjennä tunnistevälimuisti ja lataa musiikkikirjasto kokonaan uudelleen (hitaampi mutta kattavampi)</string>
|
<string name="set_rescan_desc">Tyhjennä tunnistevälimuisti ja lataa musiikkikirjasto kokonaan uudelleen (hitaampi mutta kattavampi)</string>
|
||||||
<string name="lbl_song">Kappale</string>
|
<string name="lbl_song">Kappale</string>
|
||||||
<string name="lbl_parent_detail">Näytä</string>
|
<string name="lbl_parent_detail">Näytä</string>
|
||||||
|
<string name="lbl_show_error_info">Lisää</string>
|
||||||
<string name="lbl_copied">Kopioitu</string>
|
<string name="lbl_copied">Kopioitu</string>
|
||||||
<string name="lbl_report">Ilmoita virheestä</string>
|
<string name="lbl_report">Ilmoita virheestä</string>
|
||||||
<string name="lbl_selection">Valinta</string>
|
<string name="lbl_selection">Valinta</string>
|
||||||
|
@ -306,11 +315,4 @@
|
||||||
<string name="set_locations_new">Uusi kansio</string>
|
<string name="set_locations_new">Uusi kansio</string>
|
||||||
<string name="cnt_mp4">MPEG-4 sisältäen %s</string>
|
<string name="cnt_mp4">MPEG-4 sisältäen %s</string>
|
||||||
<string name="cdc_unknown">Tuntematon</string>
|
<string name="cdc_unknown">Tuntematon</string>
|
||||||
<string name="lng_empty_songs">Kappaleesi tulevat näkymään tässä.</string>
|
</resources>
|
||||||
<string name="lng_empty_albums">Albumisi tulevat näkymään tässä.</string>
|
|
||||||
<string name="lng_empty_artists">Esittäjäsi tulevat näkymään tässä.</string>
|
|
||||||
<string name="lng_empty_playlists">Soittolistasi tulevat näkymään tässä.</string>
|
|
||||||
<string name="lng_empty_genres">Tyylilajisi tulevat näkymään tässä.</string>
|
|
||||||
<string name="cdc_alac">Apple Lossless Audio Codec (ALAC)</string>
|
|
||||||
<string name="set_cover_mode_save_space">Säätä tilaa</string>
|
|
||||||
</resources>
|
|
|
@ -51,6 +51,7 @@
|
||||||
<string name="lbl_bitrate">Tulin ng mga bit</string>
|
<string name="lbl_bitrate">Tulin ng mga bit</string>
|
||||||
<string name="lbl_sample_rate">Tulin ng sample</string>
|
<string name="lbl_sample_rate">Tulin ng sample</string>
|
||||||
<string name="lbl_shuffle_shortcut_short">Haluin</string>
|
<string name="lbl_shuffle_shortcut_short">Haluin</string>
|
||||||
|
<string name="lbl_add">Idagdag</string>
|
||||||
<string name="lbl_save">I-save</string>
|
<string name="lbl_save">I-save</string>
|
||||||
<string name="lbl_about">Tungkol</string>
|
<string name="lbl_about">Tungkol</string>
|
||||||
<string name="lbl_version">Ulat</string>
|
<string name="lbl_version">Ulat</string>
|
||||||
|
@ -87,6 +88,7 @@
|
||||||
<string name="lbl_live_group">Live</string>
|
<string name="lbl_live_group">Live</string>
|
||||||
<string name="lbl_search">Hanapin</string>
|
<string name="lbl_search">Hanapin</string>
|
||||||
<string name="lbl_singles">Mga Single</string>
|
<string name="lbl_singles">Mga Single</string>
|
||||||
|
<string name="lbl_grant">Bigyan</string>
|
||||||
<string name="lbl_genres">Mga Genre</string>
|
<string name="lbl_genres">Mga Genre</string>
|
||||||
<string name="lng_widget">Tignan at ayusin ang pagtugtog ng kanta</string>
|
<string name="lng_widget">Tignan at ayusin ang pagtugtog ng kanta</string>
|
||||||
<string name="set_theme">Tema</string>
|
<string name="set_theme">Tema</string>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">Réessayer</string>
|
<string name="lbl_retry">Réessayer</string>
|
||||||
|
<string name="lbl_grant">Accorder</string>
|
||||||
<string name="lbl_genres">Genres</string>
|
<string name="lbl_genres">Genres</string>
|
||||||
<string name="lbl_artists">Artistes</string>
|
<string name="lbl_artists">Artistes</string>
|
||||||
<string name="lbl_albums">Albums</string>
|
<string name="lbl_albums">Albums</string>
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
<string name="set_audio">Audio</string>
|
<string name="set_audio">Audio</string>
|
||||||
<string name="set_personalize">Comportement</string>
|
<string name="set_personalize">Comportement</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">Pas de musique trouvée</string>
|
||||||
<!-- Description Namespace | Accessibility Strings -->
|
<!-- Description Namespace | Accessibility Strings -->
|
||||||
<string name="desc_track_number">Morceau %d</string>
|
<string name="desc_track_number">Morceau %d</string>
|
||||||
<string name="desc_play_pause">Lecture ou pause</string>
|
<string name="desc_play_pause">Lecture ou pause</string>
|
||||||
|
@ -83,6 +85,7 @@
|
||||||
<string name="lbl_cancel">Annuler</string>
|
<string name="lbl_cancel">Annuler</string>
|
||||||
<string name="lbl_save">Enregistrer</string>
|
<string name="lbl_save">Enregistrer</string>
|
||||||
<string name="lbl_size">Taille</string>
|
<string name="lbl_size">Taille</string>
|
||||||
|
<string name="lbl_add">Ajouter</string>
|
||||||
<string name="set_display">Affichage</string>
|
<string name="set_display">Affichage</string>
|
||||||
<string name="set_lib_tabs">Onglets de la bibliothèque</string>
|
<string name="set_lib_tabs">Onglets de la bibliothèque</string>
|
||||||
<string name="info_app_desc">Un lecteur de musique simple et rationnel pour Android.</string>
|
<string name="info_app_desc">Un lecteur de musique simple et rationnel pour Android.</string>
|
||||||
|
@ -107,7 +110,7 @@
|
||||||
<string name="lbl_compilation">Compilation</string>
|
<string name="lbl_compilation">Compilation</string>
|
||||||
<string name="lbl_live_group">Live</string>
|
<string name="lbl_live_group">Live</string>
|
||||||
<string name="lbl_indexing">Chargement de la musique</string>
|
<string name="lbl_indexing">Chargement de la musique</string>
|
||||||
<string name="lbl_observing">Suivre la bibliothèque musicale</string>
|
<string name="lbl_observing">Suivre la librairie musicale</string>
|
||||||
<string name="lbl_eps">EP</string>
|
<string name="lbl_eps">EP</string>
|
||||||
<string name="lbl_ep">EP</string>
|
<string name="lbl_ep">EP</string>
|
||||||
<string name="lbl_singles">Singles</string>
|
<string name="lbl_singles">Singles</string>
|
||||||
|
@ -122,11 +125,13 @@
|
||||||
<string name="lbl_album_remix">Album de remix</string>
|
<string name="lbl_album_remix">Album de remix</string>
|
||||||
<string name="lbl_genre">Genre</string>
|
<string name="lbl_genre">Genre</string>
|
||||||
<string name="lbl_equalizer">Égaliseur</string>
|
<string name="lbl_equalizer">Égaliseur</string>
|
||||||
|
<string name="desc_shuffle_all">Lecture aléatoire de tous les titres</string>
|
||||||
<string name="desc_auxio_icon">Icône Auxio</string>
|
<string name="desc_auxio_icon">Icône Auxio</string>
|
||||||
<string name="desc_no_cover">Couverture de l\'album</string>
|
<string name="desc_no_cover">Couverture de l\'album</string>
|
||||||
<string name="def_genre">Genre inconnu</string>
|
<string name="def_genre">Genre inconnu</string>
|
||||||
<string name="clr_dynamic">Dynamique</string>
|
<string name="clr_dynamic">Dynamique</string>
|
||||||
<string name="clr_cyan">Cyan</string>
|
<string name="clr_cyan">Cyan</string>
|
||||||
|
<string name="err_no_locations">Aucun dossier</string>
|
||||||
<string name="desc_music_location_delete">Supprimer le dossier</string>
|
<string name="desc_music_location_delete">Supprimer le dossier</string>
|
||||||
<string name="def_artist">Artiste inconnu</string>
|
<string name="def_artist">Artiste inconnu</string>
|
||||||
<string name="lbl_compilation_live">Compilation en direct</string>
|
<string name="lbl_compilation_live">Compilation en direct</string>
|
||||||
|
@ -195,11 +200,13 @@
|
||||||
<string name="set_replay_gain_mode">Stratégie de normalisation de volume</string>
|
<string name="set_replay_gain_mode">Stratégie de normalisation de volume</string>
|
||||||
<string name="set_replay_gain_mode_track">Par chanson</string>
|
<string name="set_replay_gain_mode_track">Par chanson</string>
|
||||||
<string name="set_replay_gain_mode_album">Par album</string>
|
<string name="set_replay_gain_mode_album">Par album</string>
|
||||||
|
<string name="set_locations_list">Dossiers</string>
|
||||||
<string name="set_replay_gain_mode_dynamic">Par album si un album est en lecture</string>
|
<string name="set_replay_gain_mode_dynamic">Par album si un album est en lecture</string>
|
||||||
<string name="set_library">Bibliothèque</string>
|
<string name="set_library">Bibliothèque</string>
|
||||||
<string name="set_reindex">Actualiser la musique</string>
|
<string name="set_reindex">Actualiser la musique</string>
|
||||||
<string name="set_rescan_desc">Effacer le cache des étiquettes et recharger entièrement la bibliothèque musicale (lent, mais plus complet)</string>
|
<string name="set_rescan_desc">Effacer le cache des étiquettes et recharger entièrement la bibliothèque musicale (lent, mais plus complet)</string>
|
||||||
<string name="err_no_app">Aucune application trouvée qui puisse gérer cette tâche</string>
|
<string name="err_no_app">Aucune application trouvée qui puisse gérer cette tâche</string>
|
||||||
|
<string name="err_no_perms">Auxio a besoin de permissions pour lire votre bibliothèque musicale</string>
|
||||||
<string name="set_intelligent_sorting">Tri intelligent</string>
|
<string name="set_intelligent_sorting">Tri intelligent</string>
|
||||||
<string name="set_intelligent_sorting_desc">Ignorer les nombres ou certains mots comme \"the\" en début de nom lors du tri (fonctionne au mieux avec de la musique en anglais)</string>
|
<string name="set_intelligent_sorting_desc">Ignorer les nombres ou certains mots comme \"the\" en début de nom lors du tri (fonctionne au mieux avec de la musique en anglais)</string>
|
||||||
<string name="set_rescan">Scanner à nouveau la musique</string>
|
<string name="set_rescan">Scanner à nouveau la musique</string>
|
||||||
|
@ -215,6 +222,7 @@
|
||||||
<string name="fmt_sample_rate">%d Hz</string>
|
<string name="fmt_sample_rate">%d Hz</string>
|
||||||
<string name="desc_skip_prev">Passer à la dernière chanson</string>
|
<string name="desc_skip_prev">Passer à la dernière chanson</string>
|
||||||
<string name="lbl_playlist_add">Ajouter à la liste de lecture</string>
|
<string name="lbl_playlist_add">Ajouter à la liste de lecture</string>
|
||||||
|
<string name="cdc_mka">Audio Matroska</string>
|
||||||
<string name="fmt_lib_artist_count">Artistes chargés : %d</string>
|
<string name="fmt_lib_artist_count">Artistes chargés : %d</string>
|
||||||
<string name="set_rewind_prev">Rembobiner avant de revenir en arrière</string>
|
<string name="set_rewind_prev">Rembobiner avant de revenir en arrière</string>
|
||||||
<string name="desc_artist_image">Image d\'artiste pour %s</string>
|
<string name="desc_artist_image">Image d\'artiste pour %s</string>
|
||||||
|
@ -275,6 +283,7 @@
|
||||||
<string name="lbl_sort_mode">Trier par</string>
|
<string name="lbl_sort_mode">Trier par</string>
|
||||||
<string name="lbl_sort_direction">Direction</string>
|
<string name="lbl_sort_direction">Direction</string>
|
||||||
<string name="lbl_selection">Sélection</string>
|
<string name="lbl_selection">Sélection</string>
|
||||||
|
<string name="lbl_show_error_info">En savoir plus</string>
|
||||||
<string name="lbl_copied">Copié</string>
|
<string name="lbl_copied">Copié</string>
|
||||||
<string name="lbl_report">Signaler</string>
|
<string name="lbl_report">Signaler</string>
|
||||||
<string name="lbl_error_info">Info sur l\'erreur</string>
|
<string name="lbl_error_info">Info sur l\'erreur</string>
|
||||||
|
@ -312,4 +321,4 @@
|
||||||
<string name="lbl_github">Faire un ticket sur GitHub</string>
|
<string name="lbl_github">Faire un ticket sur GitHub</string>
|
||||||
<string name="lbl_email">Envoyer un courriel</string>
|
<string name="lbl_email">Envoyer un courriel</string>
|
||||||
<string name="lbl_music_sources">Choisir des dossiers</string>
|
<string name="lbl_music_sources">Choisir des dossiers</string>
|
||||||
</resources>
|
</resources>
|
|
@ -14,6 +14,7 @@
|
||||||
<string name="lbl_singles">Sinxelo</string>
|
<string name="lbl_singles">Sinxelo</string>
|
||||||
<string name="lbl_compilations">Compilacións</string>
|
<string name="lbl_compilations">Compilacións</string>
|
||||||
<string name="lbl_compilation">Compilación</string>
|
<string name="lbl_compilation">Compilación</string>
|
||||||
|
<string name="lbl_grant">Permitir</string>
|
||||||
<string name="lbl_albums">Álbums</string>
|
<string name="lbl_albums">Álbums</string>
|
||||||
<string name="lbl_single_remix">Sinxelo remix</string>
|
<string name="lbl_single_remix">Sinxelo remix</string>
|
||||||
<string name="lbl_retry">Volver a intentar</string>
|
<string name="lbl_retry">Volver a intentar</string>
|
||||||
|
@ -92,6 +93,7 @@
|
||||||
<string name="lbl_song_detail">Ver as propiedades</string>
|
<string name="lbl_song_detail">Ver as propiedades</string>
|
||||||
<string name="lbl_props">Propiedades da canción</string>
|
<string name="lbl_props">Propiedades da canción</string>
|
||||||
<string name="lbl_save">Gardar</string>
|
<string name="lbl_save">Gardar</string>
|
||||||
|
<string name="lbl_add">Engadir</string>
|
||||||
<string name="lbl_licenses">Licenzas</string>
|
<string name="lbl_licenses">Licenzas</string>
|
||||||
<string name="lng_queue_added">Engadido á cola</string>
|
<string name="lng_queue_added">Engadido á cola</string>
|
||||||
<string name="set_personalize">Personalizar</string>
|
<string name="set_personalize">Personalizar</string>
|
||||||
|
@ -160,6 +162,7 @@
|
||||||
<string name="set_rescan_desc">Borrar a caché das etiquetas a recargar completamente a biblioteca de música (máis lento, pero máis completo)</string>
|
<string name="set_rescan_desc">Borrar a caché das etiquetas a recargar completamente a biblioteca de música (máis lento, pero máis completo)</string>
|
||||||
<string name="desc_change_repeat">Cambiar o modo de repetición</string>
|
<string name="desc_change_repeat">Cambiar o modo de repetición</string>
|
||||||
<string name="desc_shuffle">Activar ou desactivar a mezcla</string>
|
<string name="desc_shuffle">Activar ou desactivar a mezcla</string>
|
||||||
|
<string name="desc_shuffle_all">Mezclar todas as cancións</string>
|
||||||
<string name="desc_exit">Deter a reprodución</string>
|
<string name="desc_exit">Deter a reprodución</string>
|
||||||
<string name="desc_queue_bar">Abrir a cola</string>
|
<string name="desc_queue_bar">Abrir a cola</string>
|
||||||
<string name="desc_clear_search">Borrar o historial de busca</string>
|
<string name="desc_clear_search">Borrar o historial de busca</string>
|
||||||
|
@ -176,7 +179,9 @@
|
||||||
<string name="cdc_mp3">Audio MPEG-1</string>
|
<string name="cdc_mp3">Audio MPEG-1</string>
|
||||||
<string name="cdc_mp4">Audio MPEG-4</string>
|
<string name="cdc_mp4">Audio MPEG-4</string>
|
||||||
<string name="err_index_failed">Fallou a carga de música</string>
|
<string name="err_index_failed">Fallou a carga de música</string>
|
||||||
|
<string name="err_no_perms">Auxio necesita permiso para leer a túa biblioteca de música</string>
|
||||||
<string name="err_no_app">Non se atopou ningunha aplicación que poda facer esta tarefa</string>
|
<string name="err_no_app">Non se atopou ningunha aplicación que poda facer esta tarefa</string>
|
||||||
|
<string name="err_no_locations">Sen cartafois</string>
|
||||||
<string name="cdc_ogg">Audio ogg</string>
|
<string name="cdc_ogg">Audio ogg</string>
|
||||||
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
<string name="cdc_aac">Advanced Audio Coding (AAC)</string>
|
||||||
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
<string name="cdc_flac">Free Lossless Audio Codec (FLAC)</string>
|
||||||
|
@ -222,9 +227,12 @@
|
||||||
<string name="set_intelligent_sorting_desc">Ignorar palabras como \"the\" ao ordenar por nome (funciona mellor con música en inglés)</string>
|
<string name="set_intelligent_sorting_desc">Ignorar palabras como \"the\" ao ordenar por nome (funciona mellor con música en inglés)</string>
|
||||||
<string name="set_locations_desc">Xestionar dende onde se carga a música</string>
|
<string name="set_locations_desc">Xestionar dende onde se carga a música</string>
|
||||||
<string name="set_repeat_pause_desc">Pausar cando se repite unha canción</string>
|
<string name="set_repeat_pause_desc">Pausar cando se repite unha canción</string>
|
||||||
|
<string name="set_locations_list">Cartafois</string>
|
||||||
<string name="def_track">Ningunha pista</string>
|
<string name="def_track">Ningunha pista</string>
|
||||||
<string name="desc_skip_prev">Saltar á última canción</string>
|
<string name="desc_skip_prev">Saltar á última canción</string>
|
||||||
|
<string name="err_no_music">Sen música</string>
|
||||||
<string name="desc_track_number">Pista %d</string>
|
<string name="desc_track_number">Pista %d</string>
|
||||||
|
<string name="cdc_mka">Audio Matroska</string>
|
||||||
<string name="lbl_mixtapes">Mixtapes (compilación de cancións)</string>
|
<string name="lbl_mixtapes">Mixtapes (compilación de cancións)</string>
|
||||||
<string name="lbl_mixtape">Mixtapes (compilación de cancións)</string>
|
<string name="lbl_mixtape">Mixtapes (compilación de cancións)</string>
|
||||||
<string name="lbl_remix_group">Remix</string>
|
<string name="lbl_remix_group">Remix</string>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">पुन: प्रयास करें</string>
|
<string name="lbl_retry">पुन: प्रयास करें</string>
|
||||||
|
<string name="lbl_grant">अनुदान</string>
|
||||||
<string name="lbl_artists">कलाकार</string>
|
<string name="lbl_artists">कलाकार</string>
|
||||||
<string name="lbl_albums">एल्बम</string>
|
<string name="lbl_albums">एल्बम</string>
|
||||||
<string name="lbl_songs">गीत</string>
|
<string name="lbl_songs">गीत</string>
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
<string name="set_audio">ऑडियो</string>
|
<string name="set_audio">ऑडियो</string>
|
||||||
<string name="set_personalize">चाल चलन</string>
|
<string name="set_personalize">चाल चलन</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">कोई संगीत नहीं मिला</string>
|
||||||
<!-- Description Namespace | Accessibility Strings -->
|
<!-- Description Namespace | Accessibility Strings -->
|
||||||
<string name="desc_play_pause">चलाएं/रोकें</string>
|
<string name="desc_play_pause">चलाएं/रोकें</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
|
@ -139,6 +141,7 @@
|
||||||
<item quantity="other">%d कलाकार</item>
|
<item quantity="other">%d कलाकार</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="lbl_observing">संगीत लाइब्रेरी की निगरानी</string>
|
<string name="lbl_observing">संगीत लाइब्रेरी की निगरानी</string>
|
||||||
|
<string name="lbl_add">जोड़ें</string>
|
||||||
<string name="lbl_ep">ईपी</string>
|
<string name="lbl_ep">ईपी</string>
|
||||||
<string name="lbl_rename">नाम बदलें</string>
|
<string name="lbl_rename">नाम बदलें</string>
|
||||||
<string name="set_separators_semicolon">अर्धविराम (;)</string>
|
<string name="set_separators_semicolon">अर्धविराम (;)</string>
|
||||||
|
@ -199,10 +202,12 @@
|
||||||
<string name="set_repeat_pause_desc">जब कोई गीत दोहराया जाता है तो रुक जाएं</string>
|
<string name="set_repeat_pause_desc">जब कोई गीत दोहराया जाता है तो रुक जाएं</string>
|
||||||
<string name="set_pre_amp">रीप्लेगेन प्री-एम्प</string>
|
<string name="set_pre_amp">रीप्लेगेन प्री-एम्प</string>
|
||||||
<string name="set_pre_amp_with">टैग के साथ समायोजन</string>
|
<string name="set_pre_amp_with">टैग के साथ समायोजन</string>
|
||||||
|
<string name="set_locations_list">फ़ोल्डर</string>
|
||||||
<string name="err_index_failed">संगीत लोड करना विफल रहा</string>
|
<string name="err_index_failed">संगीत लोड करना विफल रहा</string>
|
||||||
<string name="err_bad_location">यह फ़ोल्डर समर्थित नहीं है</string>
|
<string name="err_bad_location">यह फ़ोल्डर समर्थित नहीं है</string>
|
||||||
<string name="desc_change_repeat">रिपीट मोड बदलें</string>
|
<string name="desc_change_repeat">रिपीट मोड बदलें</string>
|
||||||
<string name="desc_shuffle">शफ़ल चालू या बंद करें</string>
|
<string name="desc_shuffle">शफ़ल चालू या बंद करें</string>
|
||||||
|
<string name="desc_shuffle_all">सभी गीत शफ़ल करें</string>
|
||||||
<string name="desc_exit">प्लेबैक बंद करो</string>
|
<string name="desc_exit">प्लेबैक बंद करो</string>
|
||||||
<string name="desc_song_handle">इस गीत को इस स्थानांतरित करें</string>
|
<string name="desc_song_handle">इस गीत को इस स्थानांतरित करें</string>
|
||||||
<string name="def_genre">अज्ञात शैली</string>
|
<string name="def_genre">अज्ञात शैली</string>
|
||||||
|
@ -256,6 +261,8 @@
|
||||||
<string name="set_rewind_prev">वापस जाने से पहले रिवाइंड करें</string>
|
<string name="set_rewind_prev">वापस जाने से पहले रिवाइंड करें</string>
|
||||||
<string name="set_replay_gain_mode_track">ट्रैक को प्राथमिकता दें</string>
|
<string name="set_replay_gain_mode_track">ट्रैक को प्राथमिकता दें</string>
|
||||||
<string name="set_rescan_desc">टैग कैश साफ़ करें और संगीत लाइब्रेरी को पूरी तरह पुनः लोड करें (धीमी, लेकिन अधिक पूर्ण)</string>
|
<string name="set_rescan_desc">टैग कैश साफ़ करें और संगीत लाइब्रेरी को पूरी तरह पुनः लोड करें (धीमी, लेकिन अधिक पूर्ण)</string>
|
||||||
|
<string name="err_no_perms">Auxio को आपकी संगीत लाइब्रेरी पढ़ने के लिए अनुमति की आवश्यकता है</string>
|
||||||
|
<string name="err_no_locations">कोई फ़ोल्डर नहीं</string>
|
||||||
<string name="clr_brown">भूरा</string>
|
<string name="clr_brown">भूरा</string>
|
||||||
<string name="clr_yellow">पीला</string>
|
<string name="clr_yellow">पीला</string>
|
||||||
<string name="clr_lime">नींबू रंग</string>
|
<string name="clr_lime">नींबू रंग</string>
|
||||||
|
@ -264,6 +271,7 @@
|
||||||
<string name="desc_skip_next">अगले गाने पर जाएं</string>
|
<string name="desc_skip_next">अगले गाने पर जाएं</string>
|
||||||
<string name="desc_auxio_icon">ऑक्सियो आइकन</string>
|
<string name="desc_auxio_icon">ऑक्सियो आइकन</string>
|
||||||
<string name="cdc_ogg">Ogg ऑडियो</string>
|
<string name="cdc_ogg">Ogg ऑडियो</string>
|
||||||
|
<string name="cdc_mka">Matroska ऑडियो</string>
|
||||||
<string name="clr_pink">गुलाबी</string>
|
<string name="clr_pink">गुलाबी</string>
|
||||||
<string name="set_intelligent_sorting">बुद्धिमान छंटाई</string>
|
<string name="set_intelligent_sorting">बुद्धिमान छंटाई</string>
|
||||||
<string name="set_intelligent_sorting_desc">संख्याओं या \"the\" जैसे शब्दों से शुरू होने वाले नामों को सही ढंग से क्रमबद्ध करें (अंग्रेजी भाषा के संगीत के साथ सबसे अच्छा काम करता है)</string>
|
<string name="set_intelligent_sorting_desc">संख्याओं या \"the\" जैसे शब्दों से शुरू होने वाले नामों को सही ढंग से क्रमबद्ध करें (अंग्रेजी भाषा के संगीत के साथ सबसे अच्छा काम करता है)</string>
|
||||||
|
@ -275,6 +283,7 @@
|
||||||
<string name="lbl_error_info">त्रुटि की जानकारी</string>
|
<string name="lbl_error_info">त्रुटि की जानकारी</string>
|
||||||
<string name="lbl_report">रिपोर्ट करें</string>
|
<string name="lbl_report">रिपोर्ट करें</string>
|
||||||
<string name="lbl_copied">कापी किया गया</string>
|
<string name="lbl_copied">कापी किया गया</string>
|
||||||
|
<string name="lbl_show_error_info">और</string>
|
||||||
<string name="def_album_count">कोई एल्बम नहीं</string>
|
<string name="def_album_count">कोई एल्बम नहीं</string>
|
||||||
<string name="lbl_demo">डेमो</string>
|
<string name="lbl_demo">डेमो</string>
|
||||||
<string name="lbl_demos">डेमो</string>
|
<string name="lbl_demos">डेमो</string>
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
<string name="lbl_shuffle_shortcut_long">Izmiješaj sve</string>
|
<string name="lbl_shuffle_shortcut_long">Izmiješaj sve</string>
|
||||||
<string name="lbl_ok">U redu</string>
|
<string name="lbl_ok">U redu</string>
|
||||||
<string name="lbl_cancel">Odustani</string>
|
<string name="lbl_cancel">Odustani</string>
|
||||||
|
<string name="lbl_add">Dodaj</string>
|
||||||
<string name="lbl_save">Spremi</string>
|
<string name="lbl_save">Spremi</string>
|
||||||
<string name="lbl_about">O</string>
|
<string name="lbl_about">O</string>
|
||||||
<string name="lbl_version">Inačica</string>
|
<string name="lbl_version">Inačica</string>
|
||||||
|
@ -86,12 +87,16 @@
|
||||||
<string name="set_locations_desc">Upravljaj odakle će se glazba učitati</string>
|
<string name="set_locations_desc">Upravljaj odakle će se glazba učitati</string>
|
||||||
<string name="set_observing">Automatsko ponovno učitavanje</string>
|
<string name="set_observing">Automatsko ponovno učitavanje</string>
|
||||||
<string name="set_observing_desc">Ponovo učitaj svoju zbirku glazbe čim se dogode promjene (zahtijeva stalno obavještavanje)</string>
|
<string name="set_observing_desc">Ponovo učitaj svoju zbirku glazbe čim se dogode promjene (zahtijeva stalno obavještavanje)</string>
|
||||||
|
<string name="err_no_music">Nijedna glazba nije pronađena</string>
|
||||||
<string name="err_index_failed">Greška u učitvanju glazbe</string>
|
<string name="err_index_failed">Greška u učitvanju glazbe</string>
|
||||||
|
<string name="err_no_perms">Auxio treba dozvolu za čitanje tvoje zbirke glazbe</string>
|
||||||
<string name="err_no_app">Nijedna aplikacija ne može obraditi ovaj zadatak</string>
|
<string name="err_no_app">Nijedna aplikacija ne može obraditi ovaj zadatak</string>
|
||||||
|
<string name="err_no_locations">Nema mapa</string>
|
||||||
<string name="err_bad_location">Ova mapa nije podržana</string>
|
<string name="err_bad_location">Ova mapa nije podržana</string>
|
||||||
<string name="lng_search_library">Pretraži svoju zbirku …</string>
|
<string name="lng_search_library">Pretraži svoju zbirku …</string>
|
||||||
<string name="desc_track_number">Zvučni zapis %d</string>
|
<string name="desc_track_number">Zvučni zapis %d</string>
|
||||||
<string name="desc_shuffle">Omogućite ili onemogućite miješanje</string>
|
<string name="desc_shuffle">Omogućite ili onemogućite miješanje</string>
|
||||||
|
<string name="desc_shuffle_all">Izmiješaj sve pjesme</string>
|
||||||
<string name="desc_remove_song">Ukoni ovu pjesmu iz popisa pjesama</string>
|
<string name="desc_remove_song">Ukoni ovu pjesmu iz popisa pjesama</string>
|
||||||
<string name="desc_song_handle">Premjesti ovu pjesmu u popisu pjesama</string>
|
<string name="desc_song_handle">Premjesti ovu pjesmu u popisu pjesama</string>
|
||||||
<string name="desc_tab_handle">Pomakni ovu karticu</string>
|
<string name="desc_tab_handle">Pomakni ovu karticu</string>
|
||||||
|
@ -153,6 +158,7 @@
|
||||||
<string name="lbl_retry">Pokušaj ponovo</string>
|
<string name="lbl_retry">Pokušaj ponovo</string>
|
||||||
<string name="lbl_indexer">Učitavanje glazbe</string>
|
<string name="lbl_indexer">Učitavanje glazbe</string>
|
||||||
<string name="lng_widget">Prikaži i upravljaj reprodukcijom glazbe</string>
|
<string name="lng_widget">Prikaži i upravljaj reprodukcijom glazbe</string>
|
||||||
|
<string name="lbl_grant">Dozvoli</string>
|
||||||
<string name="lbl_single_live">Singl uživo</string>
|
<string name="lbl_single_live">Singl uživo</string>
|
||||||
<string name="lbl_single_remix">Singl remiks</string>
|
<string name="lbl_single_remix">Singl remiks</string>
|
||||||
<string name="lbl_single">Singl</string>
|
<string name="lbl_single">Singl</string>
|
||||||
|
@ -161,7 +167,7 @@
|
||||||
<string name="lbl_search">Traži</string>
|
<string name="lbl_search">Traži</string>
|
||||||
<string name="lbl_filter_all">Sve</string>
|
<string name="lbl_filter_all">Sve</string>
|
||||||
<string name="lbl_queue_add">Dodaj u redoslijed</string>
|
<string name="lbl_queue_add">Dodaj u redoslijed</string>
|
||||||
<string name="lng_queue_added">Dodano u redoslijed izvođenja</string>
|
<string name="lng_queue_added">Dodano u redoslijed</string>
|
||||||
<string name="lbl_song_detail">Pogledaj svojstva</string>
|
<string name="lbl_song_detail">Pogledaj svojstva</string>
|
||||||
<string name="lbl_artist_details">Idi na izvođača</string>
|
<string name="lbl_artist_details">Idi na izvođača</string>
|
||||||
<string name="lbl_album_details">Idi na album</string>
|
<string name="lbl_album_details">Idi na album</string>
|
||||||
|
@ -185,6 +191,7 @@
|
||||||
<string name="desc_skip_prev">Preskoči na prethodnu pjesmu</string>
|
<string name="desc_skip_prev">Preskoči na prethodnu pjesmu</string>
|
||||||
<string name="desc_change_repeat">Promijeni način ponavljanja</string>
|
<string name="desc_change_repeat">Promijeni način ponavljanja</string>
|
||||||
<string name="clr_purple">Ljubičasto</string>
|
<string name="clr_purple">Ljubičasto</string>
|
||||||
|
<string name="cdc_mka">Matroska zvuk</string>
|
||||||
<string name="desc_queue_bar">Otvori redoslijed</string>
|
<string name="desc_queue_bar">Otvori redoslijed</string>
|
||||||
<string name="lbl_genre">Žanr</string>
|
<string name="lbl_genre">Žanr</string>
|
||||||
<string name="set_separators_comma">Zarez (,)</string>
|
<string name="set_separators_comma">Zarez (,)</string>
|
||||||
|
@ -226,6 +233,7 @@
|
||||||
<string name="fmt_list">%1$s, %2$s</string>
|
<string name="fmt_list">%1$s, %2$s</string>
|
||||||
<string name="lbl_reset">Resetiraj</string>
|
<string name="lbl_reset">Resetiraj</string>
|
||||||
<string name="set_replay_gain">Normalizacija glasnoće</string>
|
<string name="set_replay_gain">Normalizacija glasnoće</string>
|
||||||
|
<string name="set_locations_list">Mape</string>
|
||||||
<string name="lbl_sort_dsc">Silazno</string>
|
<string name="lbl_sort_dsc">Silazno</string>
|
||||||
<string name="set_ui_desc">Promijenite temu i boje aplikacije</string>
|
<string name="set_ui_desc">Promijenite temu i boje aplikacije</string>
|
||||||
<string name="set_personalize_desc">Prilagodite kontrole i ponašanje korisničkog sučelja</string>
|
<string name="set_personalize_desc">Prilagodite kontrole i ponašanje korisničkog sučelja</string>
|
||||||
|
@ -268,6 +276,7 @@
|
||||||
<string name="lbl_sort_direction">Smjer</string>
|
<string name="lbl_sort_direction">Smjer</string>
|
||||||
<string name="desc_selection_image">Slika odabira</string>
|
<string name="desc_selection_image">Slika odabira</string>
|
||||||
<string name="lbl_selection">Odabir</string>
|
<string name="lbl_selection">Odabir</string>
|
||||||
|
<string name="lbl_show_error_info">Više</string>
|
||||||
<string name="lbl_error_info">Podaci greške</string>
|
<string name="lbl_error_info">Podaci greške</string>
|
||||||
<string name="lbl_report">Prijavi</string>
|
<string name="lbl_report">Prijavi</string>
|
||||||
<string name="lbl_copied">Kopirano</string>
|
<string name="lbl_copied">Kopirano</string>
|
||||||
|
@ -313,9 +322,4 @@
|
||||||
<string name="cnt_mp4">MPEG-4 sadrži %s</string>
|
<string name="cnt_mp4">MPEG-4 sadrži %s</string>
|
||||||
<string name="set_cover_mode_save_space">Niža kvaliteta</string>
|
<string name="set_cover_mode_save_space">Niža kvaliteta</string>
|
||||||
<string name="set_locations_new">Nova mapa</string>
|
<string name="set_locations_new">Nova mapa</string>
|
||||||
<string name="lng_empty_songs">Tvoje pjesme će se ovdje prikazati.</string>
|
</resources>
|
||||||
<string name="lng_empty_albums">Tvoji albumi će se ovdje prikazati.</string>
|
|
||||||
<string name="lng_empty_artists">Tvoji izvođači će se ovdje prikazati.</string>
|
|
||||||
<string name="lng_empty_playlists">Tvoji popisi pjesama će se ovdje prikazati.</string>
|
|
||||||
<string name="lng_empty_genres">Tvoji žanrovi će se ovdje prikazati.</string>
|
|
||||||
</resources>
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Label Namespace | Static Labels -->
|
<!-- Label Namespace | Static Labels -->
|
||||||
<string name="lbl_retry">Újra</string>
|
<string name="lbl_retry">Újra</string>
|
||||||
|
<string name="lbl_grant">Engedélyez</string>
|
||||||
<string name="lbl_genres">Műfajok</string>
|
<string name="lbl_genres">Műfajok</string>
|
||||||
<string name="lbl_artists">Előadók</string>
|
<string name="lbl_artists">Előadók</string>
|
||||||
<string name="lbl_albums">Albumok</string>
|
<string name="lbl_albums">Albumok</string>
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
<string name="set_audio">Hang</string>
|
<string name="set_audio">Hang</string>
|
||||||
<string name="set_personalize">Testreszabás</string>
|
<string name="set_personalize">Testreszabás</string>
|
||||||
<!-- Error Namespace | Error Labels -->
|
<!-- Error Namespace | Error Labels -->
|
||||||
|
<string name="err_no_music">Nem található zene</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="lng_search_library">Keresés a könyvtárban…</string>
|
<string name="lng_search_library">Keresés a könyvtárban…</string>
|
||||||
<!-- Description Namespace | Accessibility Strings -->
|
<!-- Description Namespace | Accessibility Strings -->
|
||||||
|
@ -110,6 +112,7 @@
|
||||||
<string name="lbl_mix">DJ Mix</string>
|
<string name="lbl_mix">DJ Mix</string>
|
||||||
<string name="lbl_genre">Műfaj</string>
|
<string name="lbl_genre">Műfaj</string>
|
||||||
<string name="lbl_props">Dal tulajdonságai</string>
|
<string name="lbl_props">Dal tulajdonságai</string>
|
||||||
|
<string name="err_no_locations">Nincs mappa</string>
|
||||||
<string name="set_black_mode_desc">Tiszta fekete sötét téma használata</string>
|
<string name="set_black_mode_desc">Tiszta fekete sötét téma használata</string>
|
||||||
<string name="clr_dynamic">Dinamikus</string>
|
<string name="clr_dynamic">Dinamikus</string>
|
||||||
<string name="set_cover_mode">Album borítók</string>
|
<string name="set_cover_mode">Album borítók</string>
|
||||||
|
@ -160,6 +163,7 @@
|
||||||
<string name="lbl_rename_playlist">Lejátszólista átnevezés</string>
|
<string name="lbl_rename_playlist">Lejátszólista átnevezés</string>
|
||||||
<string name="lbl_rename">Átnevez</string>
|
<string name="lbl_rename">Átnevez</string>
|
||||||
<string name="lbl_date_added">Hozzáadás dátuma</string>
|
<string name="lbl_date_added">Hozzáadás dátuma</string>
|
||||||
|
<string name="set_locations_list">Mappák</string>
|
||||||
<string name="lbl_save">Ment</string>
|
<string name="lbl_save">Ment</string>
|
||||||
<string name="lbl_reset">Alaphelyzet</string>
|
<string name="lbl_reset">Alaphelyzet</string>
|
||||||
<string name="lbl_author_name">Fejlesztő Alexander Capehart</string>
|
<string name="lbl_author_name">Fejlesztő Alexander Capehart</string>
|
||||||
|
@ -181,6 +185,7 @@
|
||||||
<string name="def_date">Nincs dátum</string>
|
<string name="def_date">Nincs dátum</string>
|
||||||
<string name="set_cover_mode_balanced">Gyors</string>
|
<string name="set_cover_mode_balanced">Gyors</string>
|
||||||
<string name="set_exclude_non_music">A nem zenei anyagok kizárása</string>
|
<string name="set_exclude_non_music">A nem zenei anyagok kizárása</string>
|
||||||
|
<string name="desc_shuffle_all">Keverés minden dalból</string>
|
||||||
<string name="cdc_ogg">Ogg audio</string>
|
<string name="cdc_ogg">Ogg audio</string>
|
||||||
<string name="set_display">Megjelenítés</string>
|
<string name="set_display">Megjelenítés</string>
|
||||||
<string name="lbl_track">Hangsáv</string>
|
<string name="lbl_track">Hangsáv</string>
|
||||||
|
@ -201,6 +206,7 @@
|
||||||
<string name="lbl_observing">Zene könyvtár figyelése</string>
|
<string name="lbl_observing">Zene könyvtár figyelése</string>
|
||||||
<string name="desc_exit">Lejátszás megállítása</string>
|
<string name="desc_exit">Lejátszás megállítása</string>
|
||||||
<string name="info_app_desc">Egyszerű, praktikus zenelejátszó androidra.</string>
|
<string name="info_app_desc">Egyszerű, praktikus zenelejátszó androidra.</string>
|
||||||
|
<string name="cdc_mka">Matroska hang</string>
|
||||||
<string name="lbl_album">Album</string>
|
<string name="lbl_album">Album</string>
|
||||||
<string name="lbl_singles">Kislemezek</string>
|
<string name="lbl_singles">Kislemezek</string>
|
||||||
<string name="lbl_single">Kislemez</string>
|
<string name="lbl_single">Kislemez</string>
|
||||||
|
@ -216,6 +222,7 @@
|
||||||
<string name="lbl_shuffle_shortcut_short">Keverés</string>
|
<string name="lbl_shuffle_shortcut_short">Keverés</string>
|
||||||
<string name="lbl_artist">Előadó</string>
|
<string name="lbl_artist">Előadó</string>
|
||||||
<string name="lbl_remix_group">Remixek</string>
|
<string name="lbl_remix_group">Remixek</string>
|
||||||
|
<string name="lbl_add">Hozzáad</string>
|
||||||
<string name="fmt_db_pos">+%.1f dB</string>
|
<string name="fmt_db_pos">+%.1f dB</string>
|
||||||
<string name="set_separators_slash">Per jel (/)</string>
|
<string name="set_separators_slash">Per jel (/)</string>
|
||||||
<plurals name="fmt_artist_count">
|
<plurals name="fmt_artist_count">
|
||||||
|
@ -259,6 +266,7 @@
|
||||||
<string name="lbl_appears_on">Megjelenik itt,</string>
|
<string name="lbl_appears_on">Megjelenik itt,</string>
|
||||||
<string name="lbl_share">Megoszt</string>
|
<string name="lbl_share">Megoszt</string>
|
||||||
<string name="lbl_confirm_delete_playlist">Lejátszólista törlése\?</string>
|
<string name="lbl_confirm_delete_playlist">Lejátszólista törlése\?</string>
|
||||||
|
<string name="err_no_perms">Az Auxio engedélyt kér a zenei könyvtár olvasásához</string>
|
||||||
<string name="desc_remove_song">Távolítsa el ezt a dalt</string>
|
<string name="desc_remove_song">Távolítsa el ezt a dalt</string>
|
||||||
<string name="desc_auxio_icon">Auxio ikon</string>
|
<string name="desc_auxio_icon">Auxio ikon</string>
|
||||||
<string name="def_disc">Nincs lemez</string>
|
<string name="def_disc">Nincs lemez</string>
|
||||||
|
@ -272,6 +280,7 @@
|
||||||
<string name="lbl_sort_mode">Rendezés</string>
|
<string name="lbl_sort_mode">Rendezés</string>
|
||||||
<string name="lbl_selection">Kiválasztás</string>
|
<string name="lbl_selection">Kiválasztás</string>
|
||||||
<string name="desc_selection_image">Kép kiválasztás</string>
|
<string name="desc_selection_image">Kép kiválasztás</string>
|
||||||
|
<string name="lbl_show_error_info">További</string>
|
||||||
<string name="lbl_copied">Másolva</string>
|
<string name="lbl_copied">Másolva</string>
|
||||||
<string name="lbl_report">Jelentés</string>
|
<string name="lbl_report">Jelentés</string>
|
||||||
<string name="lbl_error_info">Hiba információ</string>
|
<string name="lbl_error_info">Hiba információ</string>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue