Compare commits
230 commits
v4.0.0-dev
...
dev
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e2918d3a95 | ||
![]() |
01a159754d | ||
![]() |
6a42f7c5d2 | ||
![]() |
e9b3649156 | ||
![]() |
94795fe24c | ||
![]() |
ef7ef8da95 | ||
![]() |
102ed85c42 | ||
![]() |
273dc971ba | ||
![]() |
a3722acb5a | ||
![]() |
93953aee8b | ||
![]() |
a71ef0daf2 | ||
![]() |
44633142d9 | ||
![]() |
9e683a7856 | ||
![]() |
5825ec3ebc | ||
![]() |
132b689b0c | ||
![]() |
e7454e636b | ||
![]() |
159159b889 | ||
![]() |
b630063f8c | ||
![]() |
6b6fc4d62a | ||
![]() |
93dee00285 | ||
![]() |
e73dffcb2a | ||
![]() |
296bd9ca06 | ||
![]() |
7429dd5174 | ||
![]() |
6705e869da | ||
![]() |
77c9151006 | ||
![]() |
04e4ea82ed | ||
![]() |
a9707cbb33 | ||
![]() |
f213c21225 | ||
![]() |
e64b30f00f | ||
![]() |
3df6e2f0b1 | ||
![]() |
7523298237 | ||
![]() |
b21b2e49d3 | ||
![]() |
eaba11fa44 | ||
![]() |
1193ef0bb9 | ||
![]() |
aac6d8ef4d | ||
![]() |
343856ac69 | ||
![]() |
90282f0f74 | ||
![]() |
63227a1f1f | ||
![]() |
73b2b92180 | ||
![]() |
daf1687426 | ||
![]() |
8023d2c037 | ||
![]() |
c2dcbd61f8 | ||
![]() |
b3c66d9b55 | ||
![]() |
652f0891fc | ||
![]() |
2f5b78dd84 | ||
![]() |
b8733a180c | ||
![]() |
b573fd2260 | ||
![]() |
436ef8de91 | ||
![]() |
05e864e7b5 | ||
![]() |
f030b440f6 | ||
![]() |
513fd98047 | ||
![]() |
f125e37e95 | ||
![]() |
219d26b4dc | ||
![]() |
879caf17db | ||
![]() |
cd535eda2e | ||
![]() |
e2d28f98f4 | ||
![]() |
9a70ae1c4e | ||
![]() |
f5483b5bc5 | ||
![]() |
e3715d3b2d | ||
![]() |
0d05b94884 | ||
![]() |
afa094d753 | ||
![]() |
cfa4fc30e1 | ||
![]() |
971c0e3a25 | ||
![]() |
9937e773a3 | ||
![]() |
70b26dfb63 | ||
![]() |
ac1fec74da | ||
![]() |
d62c85f8a5 | ||
![]() |
4de42a3a55 | ||
![]() |
4821051d34 | ||
![]() |
10a520e812 | ||
![]() |
95f615e980 | ||
![]() |
e434c4cdfe | ||
![]() |
d9afc6a0eb | ||
![]() |
a2af205c71 | ||
![]() |
6b8c0faf44 | ||
![]() |
e092d81cf2 | ||
![]() |
46806ee31f | ||
![]() |
84a7393221 | ||
![]() |
518cd28c03 | ||
![]() |
fe770337e6 | ||
![]() |
1fc9ca5147 | ||
![]() |
387a36a3f8 | ||
![]() |
20a06ba2fb | ||
![]() |
e046aeb671 | ||
![]() |
22249cc95b | ||
![]() |
6feee93438 | ||
![]() |
0d0a20d760 | ||
![]() |
f0ea0a3e2e | ||
![]() |
859e31d825 | ||
![]() |
b48bf3729e | ||
![]() |
4fbbbfdc76 | ||
![]() |
a7000bc9e5 | ||
![]() |
8104985a4e | ||
![]() |
fce77ec8a0 | ||
![]() |
a78b213537 | ||
![]() |
ce5f0fa2c9 | ||
![]() |
2e4a147b55 | ||
![]() |
216d9802ef | ||
![]() |
7906867a96 | ||
![]() |
25901a0f76 | ||
![]() |
403f93b6df | ||
![]() |
0bbba2efaf | ||
![]() |
3741f1ff07 | ||
![]() |
b388474655 | ||
![]() |
584af83a07 | ||
![]() |
0387400a4a | ||
![]() |
94f8457d69 | ||
![]() |
876554e6c7 | ||
![]() |
22b231843f | ||
![]() |
be270a422b | ||
![]() |
10eb0be7d0 | ||
![]() |
e2b0601d4c | ||
![]() |
ddeba2c496 | ||
![]() |
59c33b9be2 | ||
![]() |
cacf0142c5 | ||
![]() |
fbcd676149 | ||
![]() |
6cc1e8a543 | ||
![]() |
8a8fd0f3c9 | ||
![]() |
98299722bc | ||
![]() |
91b8b38732 | ||
![]() |
d6c2514473 | ||
![]() |
50e2dde6e2 | ||
![]() |
582b0c6eef | ||
![]() |
3834e92192 | ||
![]() |
117678a066 | ||
![]() |
b306456d46 | ||
![]() |
1d44ce5d71 | ||
![]() |
bfcaba4acd | ||
![]() |
442abb7040 | ||
![]() |
251197b47b | ||
![]() |
52e359d431 | ||
![]() |
f21ef6cf85 | ||
![]() |
c609e1d63a | ||
![]() |
b6af921238 | ||
![]() |
528389546c | ||
![]() |
2ff08ac813 | ||
![]() |
db4e927780 | ||
![]() |
c3aba06e2f | ||
![]() |
3d374504e2 | ||
![]() |
a6a98f9bf7 | ||
![]() |
a7969f99c3 | ||
![]() |
dddab1eda7 | ||
![]() |
9ae3587a7e | ||
![]() |
6589cd44eb | ||
![]() |
bfdccd3ba5 | ||
![]() |
357c7cc329 | ||
![]() |
e442fcf253 | ||
![]() |
a1d62c2a08 | ||
![]() |
3d154ea66c | ||
![]() |
3efd4ea59f | ||
![]() |
9632e06ca6 | ||
![]() |
210285b39a | ||
![]() |
15d2faf354 | ||
![]() |
1459498ff3 | ||
![]() |
ef732219d7 | ||
![]() |
431f541ec8 | ||
![]() |
fb2f228a97 | ||
![]() |
72ffac4209 | ||
![]() |
ee7e63d1dc | ||
![]() |
f9109b8a9c | ||
![]() |
2e4b6681d1 | ||
![]() |
a0c82ac812 | ||
![]() |
c881a1c5b4 | ||
![]() |
e78fde44e0 | ||
![]() |
7880c777ba | ||
![]() |
7c8863bd3a | ||
![]() |
97bd259728 | ||
![]() |
e3e19fb0ac | ||
![]() |
9685f3cf51 | ||
![]() |
9d22cc37b8 | ||
![]() |
d49286981c | ||
![]() |
0785711cd6 | ||
![]() |
a0e10ef8dd | ||
![]() |
1bf44eba91 | ||
![]() |
3aae8ea534 | ||
![]() |
b81ecf44c0 | ||
![]() |
020c6900a5 | ||
![]() |
4d704e86a6 | ||
![]() |
ad2ec5a655 | ||
![]() |
b0b55b5069 | ||
![]() |
c9d4b01f9f | ||
![]() |
b6d80189ca | ||
![]() |
71aa887438 | ||
![]() |
b108970fe5 | ||
![]() |
f28f2dd9f7 | ||
![]() |
847d5aa1fc | ||
![]() |
e1f07def10 | ||
![]() |
f134d3e11b | ||
![]() |
10aaf0afd2 | ||
![]() |
a1289ffaca | ||
![]() |
ad4b9a3859 | ||
![]() |
08e09af5b3 | ||
![]() |
cc6c5084ff | ||
![]() |
2f43113ce2 | ||
![]() |
04e871f421 | ||
![]() |
698f0bc13c | ||
![]() |
85a2952ae1 | ||
![]() |
c35902a6aa | ||
![]() |
1132e486ca | ||
![]() |
e6b326a571 | ||
![]() |
ae6a0438be | ||
![]() |
c359048721 | ||
![]() |
29320f426e | ||
![]() |
8bd89c5967 | ||
![]() |
9b82b5aee0 | ||
![]() |
c5241dec60 | ||
![]() |
998375f28a | ||
![]() |
e0059e9dc0 | ||
![]() |
3d690eb637 | ||
![]() |
0e34a28dfb | ||
![]() |
8c3750778f | ||
![]() |
802e215482 | ||
![]() |
6ee43b106f | ||
![]() |
f8ec77e137 | ||
![]() |
4a08809e50 | ||
![]() |
8c4b8dfb56 | ||
![]() |
ff074d0e3a | ||
![]() |
3bd4027802 | ||
![]() |
6f2b7abbef | ||
![]() |
58e0956cad | ||
![]() |
e94b74edd4 | ||
![]() |
b3f4fdfb4a | ||
![]() |
e519e8f8be | ||
![]() |
ed3e0845d6 | ||
![]() |
5375c862b3 | ||
![]() |
4318e70052 | ||
![]() |
7b9c14a118 | ||
![]() |
0ead77d6e6 | ||
![]() |
6a6d15f3e8 | ||
![]() |
605800e9a5 |
248 changed files with 5975 additions and 6334 deletions
1
.github/ISSUE_TEMPLATE/bug-crash-report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug-crash-report.yml
vendored
|
@ -34,6 +34,7 @@ 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,3 +14,5 @@ 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 = v2.0.2
|
tag = ee1931b
|
||||||
|
|
52
CHANGELOG.md
52
CHANGELOG.md
|
@ -1,5 +1,52 @@
|
||||||
# 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
|
||||||
|
@ -23,6 +70,7 @@
|
||||||
- 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
|
||||||
|
@ -34,11 +82,15 @@
|
||||||
- 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/v3.6.3">
|
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v4.0.4">
|
||||||
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v3.6.3&color=64B5F6&style=flat">
|
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v4.0.4&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,7 +15,12 @@
|
||||||
</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="170"></a>
|
<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://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>
|
||||||
|
|
||||||
|
@ -28,14 +33,12 @@ 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=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot0.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/shot1.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/shot2.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/shot3.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/shot4.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/shot5.png" width=250>
|
||||||
<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>
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,29 +64,39 @@ 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 (by default)
|
- No rounded album covers (if you want them)
|
||||||
|
|
||||||
## 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
|
||||||
- Notifcations (`POST_NOTIFICATION`) to indicate ongoing playback and music loading
|
- Notifications (`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 custom version of Media3 that enables some extra features. This adds some caveats to the build process:
|
Auxio relies on a patched version of Media3 that enables some extra playback features, alongside taglib for metadata
|
||||||
|
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.0-dev"
|
versionName "4.0.4"
|
||||||
versionCode 54
|
versionCode 63
|
||||||
|
|
||||||
minSdk min_sdk
|
minSdk min_sdk
|
||||||
targetSdk target_sdk
|
targetSdk target_sdk
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
<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" />
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
|
@ -1309,7 +1309,6 @@ 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;
|
||||||
|
@ -1633,12 +1632,13 @@ 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(hideable ? STATE_HIDDEN : STATE_COLLAPSED);
|
setState(canActuallyHide ? STATE_HIDDEN : STATE_COLLAPSED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hideable && isHideableWhenDragging()) {
|
if (canActuallyHide) {
|
||||||
bottomContainerBackHelper.finishBackProgressNotPersistent(
|
bottomContainerBackHelper.finishBackProgressNotPersistent(
|
||||||
backEvent,
|
backEvent,
|
||||||
new AnimatorListenerAdapter() {
|
new AnimatorListenerAdapter() {
|
||||||
|
|
|
@ -36,6 +36,7 @@ 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 :
|
||||||
|
@ -53,24 +54,30 @@ 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)
|
||||||
return super.onStartCommand(intent, flags, startId)
|
// If we die we want to not restart, we will immediately try to foreground in and just
|
||||||
|
// 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 super.onBind(intent)
|
return binder
|
||||||
}
|
}
|
||||||
|
|
||||||
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(startId)
|
playbackFragment.start(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
|
@ -134,6 +141,7 @@ 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,6 +65,8 @@ 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 */
|
||||||
|
@ -141,4 +143,6 @@ 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,7 +18,6 @@
|
||||||
|
|
||||||
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
|
||||||
|
@ -27,6 +26,7 @@ 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 {
|
||||||
// TODO: Due to draw caching even *this* isn't effective enough to avoid the bottom
|
// This is where I shove literally all the UI logic that won't behave any callback
|
||||||
// sheets continually getting stuck. I need something with even more frequent updates,
|
// or "normal" method I've tried. Surely running this on every frame will actually cause
|
||||||
// or otherwise bottom sheets get stuck.
|
// it to work properly!
|
||||||
|
|
||||||
// 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,6 +367,10 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,8 +513,6 @@ 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,6 +22,7 @@ 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
|
||||||
|
@ -298,6 +299,11 @@ 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.
|
||||||
|
@ -323,4 +329,6 @@ 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 [DeviceLibrary]. */
|
/** Sanitize this instance with a [Library]. */
|
||||||
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]. */
|
||||||
|
|
|
@ -24,9 +24,11 @@ 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
|
||||||
|
@ -42,10 +44,12 @@ 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,12 +37,10 @@ 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
|
||||||
|
@ -53,7 +51,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.AdaptiveTabStrategy
|
import org.oxycblt.auxio.home.tabs.NamedTabStrategy
|
||||||
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
|
||||||
|
@ -68,7 +66,6 @@ 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
|
||||||
|
@ -94,7 +91,6 @@ 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)
|
||||||
|
@ -270,9 +266,7 @@ 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.homeTabs, binding.homePager, NamedTabStrategy(homeModel.currentTabTypes))
|
||||||
binding.homePager,
|
|
||||||
AdaptiveTabStrategy(requireContext(), homeModel.currentTabTypes))
|
|
||||||
.attach()
|
.attach()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,11 +508,5 @@ 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,6 +190,8 @@ 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(
|
||||||
|
@ -230,13 +232,24 @@ 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 horizontalMargin = context.getDimenPixels(R.dimen.spacing_mid_large)
|
val rightMargin = context.getDimenPixels(R.dimen.spacing_tiny)
|
||||||
setMargins(horizontalMargin, 0, horizontalMargin, 0)
|
if (position == actionItems.lastIndex) {
|
||||||
|
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,7 +43,6 @@ 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
|
||||||
|
@ -128,7 +127,7 @@ class AlbumListFragment :
|
||||||
|
|
||||||
// Last added -> Format as date
|
// Last added -> Format as date
|
||||||
is Sort.Mode.ByDateAdded -> {
|
is Sort.Mode.ByDateAdded -> {
|
||||||
val dateAddedMillis = album.dateAdded.secsToMs()
|
val dateAddedMillis = album.addedMs
|
||||||
formatterSb.setLength(0)
|
formatterSb.setLength(0)
|
||||||
DateUtils.formatDateRange(
|
DateUtils.formatDateRange(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -42,7 +42,6 @@ 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
|
||||||
|
@ -128,7 +127,7 @@ class SongListFragment :
|
||||||
|
|
||||||
// Last added -> Format as date
|
// Last added -> Format as date
|
||||||
is Sort.Mode.ByDateAdded -> {
|
is Sort.Mode.ByDateAdded -> {
|
||||||
val dateAddedMillis = song.dateAdded.secsToMs()
|
val dateAddedMillis = song.addedMs
|
||||||
formatterSb.setLength(0)
|
formatterSb.setLength(0)
|
||||||
DateUtils.formatDateRange(
|
DateUtils.formatDateRange(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Auxio Project
|
||||||
|
* NamedTabStrategy.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 com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy
|
||||||
|
import org.oxycblt.auxio.music.MusicType
|
||||||
|
|
||||||
|
class NamedTabStrategy(private val homeTabs: List<MusicType>) : TabConfigurationStrategy {
|
||||||
|
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
|
||||||
|
tab.setText(homeTabs[position].nameRes)
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,8 @@ 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.
|
||||||
|
@ -43,6 +44,7 @@ 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 {
|
||||||
|
@ -59,6 +61,7 @@ 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,9 +27,8 @@ 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.SiloedCoverId
|
import org.oxycblt.auxio.image.covers.SettingCovers
|
||||||
import org.oxycblt.auxio.image.covers.SiloedCovers
|
import org.oxycblt.musikr.covers.CoverResult
|
||||||
import org.oxycblt.musikr.cover.ObtainResult
|
|
||||||
|
|
||||||
class CoverProvider : ContentProvider() {
|
class CoverProvider : ContentProvider() {
|
||||||
override fun onCreate(): Boolean = true
|
override fun onCreate(): Boolean = true
|
||||||
|
@ -39,12 +38,10 @@ 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 {
|
||||||
val siloedCovers = SiloedCovers.from(requireNotNull(context), coverId.silo)
|
when (val result = SettingCovers.immutable(requireNotNull(context)).obtain(id)) {
|
||||||
when (val res = siloedCovers.obtain(id)) {
|
is CoverResult.Hit -> result.cover.fd()
|
||||||
is ObtainResult.Hit -> res.cover.fd()
|
else -> null
|
||||||
is ObtainResult.Miss -> null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ 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
|
||||||
|
@ -64,7 +65,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.cover.CoverCollection
|
import org.oxycblt.musikr.covers.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
|
||||||
|
@ -172,7 +173,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 (childCount == 0) {
|
if (isEmpty()) {
|
||||||
addView(image)
|
addView(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,7 +410,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 surfaceg" color for
|
// Re-tint the drawable to use the analogous "on surface" 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.cover.CoverCollection
|
import org.oxycblt.musikr.covers.CoverCollection
|
||||||
|
|
||||||
class CoverCollectionFetcher
|
class CoverCollectionFetcher
|
||||||
private constructor(
|
private constructor(
|
||||||
|
@ -90,8 +90,7 @@ 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 =
|
val mosaicBitmap = createBitmap(mosaicSize.width, mosaicSize.height)
|
||||||
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,32 +18,20 @@
|
||||||
|
|
||||||
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.cover.Cover
|
import org.oxycblt.musikr.covers.Cover
|
||||||
|
|
||||||
class CoverFetcher private constructor(private val context: Context, private val cover: Cover) :
|
class CoverFetcher private constructor(private val cover: Cover) : Fetcher {
|
||||||
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(
|
||||||
|
@ -52,59 +40,8 @@ class CoverFetcher private constructor(private val context: Context, private val
|
||||||
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(options.context, data)
|
CoverFetcher(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.cover.Cover
|
import org.oxycblt.musikr.covers.Cover
|
||||||
import org.oxycblt.musikr.cover.CoverCollection
|
import org.oxycblt.musikr.covers.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.transform.RoundedCornersTransformation] that can handle non-1:1 aspect ratio
|
* A vendoring of coil's RoundedCornersTransformation that can handle non-1:1 aspect ratio images
|
||||||
* images without cropping them.
|
* without cropping them.
|
||||||
*
|
*
|
||||||
* @author Coil Team, Alexander Capehart (OxygenCobalt)
|
* @author Coil Team, Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
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
|
||||||
|
@ -46,7 +47,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 Bitmap.createScaledBitmap(dst, desiredWidth, desiredHeight, true)
|
return dst.scale(desiredWidth, desiredHeight)
|
||||||
}
|
}
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* 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) 2024 Auxio Project
|
* Copyright (c) 2023 Auxio Project
|
||||||
* CoverModule.kt is part of Auxio.
|
* CoversModule.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,19 +20,11 @@ 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 CoverModule {
|
interface CoilModule {
|
||||||
@Binds fun configCovers(impl: SettingCoversImpl): SettingCovers
|
@Binds fun settingCovers(imageSettings: SettingCoversImpl): SettingCovers
|
||||||
}
|
|
||||||
|
|
||||||
@Module
|
|
||||||
@InstallIn(SingletonComponent::class)
|
|
||||||
class CoverProvidesModule {
|
|
||||||
@Provides fun identifier(): CoverIdentifier = CoverIdentifier.md5()
|
|
||||||
}
|
}
|
|
@ -18,18 +18,20 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.image.covers
|
package org.oxycblt.auxio.image.covers
|
||||||
|
|
||||||
import android.content.Context
|
import org.oxycblt.musikr.covers.Cover
|
||||||
import org.oxycblt.musikr.cover.Cover
|
import org.oxycblt.musikr.covers.CoverResult
|
||||||
import org.oxycblt.musikr.cover.MutableCovers
|
import org.oxycblt.musikr.covers.MutableCovers
|
||||||
import org.oxycblt.musikr.cover.ObtainResult
|
import org.oxycblt.musikr.covers.stored.CoverStorage
|
||||||
|
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||||
|
import org.oxycblt.musikr.metadata.Metadata
|
||||||
|
|
||||||
class NullCovers(private val context: Context) : MutableCovers {
|
class NullCovers(private val storage: CoverStorage) : MutableCovers<NullCover> {
|
||||||
override suspend fun obtain(id: String) = ObtainResult.Hit(NullCover)
|
override suspend fun obtain(id: String) = CoverResult.Hit(NullCover)
|
||||||
|
|
||||||
override suspend fun write(data: ByteArray): Cover = NullCover
|
override suspend fun create(file: DeviceFile, metadata: Metadata) = CoverResult.Hit(NullCover)
|
||||||
|
|
||||||
override suspend fun cleanup(excluding: Collection<Cover>) {
|
override suspend fun cleanup(excluding: Collection<Cover>) {
|
||||||
context.coversDir().listFiles()?.forEach { it.deleteRecursively() }
|
storage.ls(setOf()).map { storage.rm(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2024 Auxio Project
|
* Copyright (c) 2025 Auxio Project
|
||||||
* CoverUtil.kt is part of Auxio.
|
* RevisionedTranscoding.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 android.content.Context
|
import java.util.UUID
|
||||||
import kotlinx.coroutines.Dispatchers
|
import org.oxycblt.musikr.covers.stored.Transcoding
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
suspend fun Context.coversDir() =
|
class RevisionedTranscoding(revision: UUID, private val inner: Transcoding) : Transcoding by inner {
|
||||||
withContext(Dispatchers.IO) { filesDir.resolve("covers").apply { mkdirs() } }
|
override val tag = "_$revision${inner.tag}"
|
||||||
|
}
|
|
@ -19,30 +19,55 @@
|
||||||
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.cover.CoverIdentifier
|
import org.oxycblt.musikr.covers.Cover
|
||||||
import org.oxycblt.musikr.cover.CoverParams
|
import org.oxycblt.musikr.covers.Covers
|
||||||
import org.oxycblt.musikr.cover.MutableCovers
|
import org.oxycblt.musikr.covers.FDCover
|
||||||
|
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 create(context: Context, revision: UUID): MutableCovers
|
suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
suspend fun immutable(context: Context): Covers<FDCover> =
|
||||||
|
ChainedCovers(StoredCovers(CoverStorage.at(context.coversDir())), FSCovers(context))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingCoversImpl
|
class SettingCoversImpl @Inject constructor(private val imageSettings: ImageSettings) :
|
||||||
@Inject
|
|
||||||
constructor(private val imageSettings: ImageSettings, private val identifier: CoverIdentifier) :
|
|
||||||
SettingCovers {
|
SettingCovers {
|
||||||
override suspend fun create(context: Context, revision: UUID): MutableCovers =
|
override suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover> {
|
||||||
when (imageSettings.coverMode) {
|
val coverStorage = CoverStorage.at(context.coversDir())
|
||||||
CoverMode.OFF -> NullCovers(context)
|
val transcoding =
|
||||||
CoverMode.SAVE_SPACE -> siloedCovers(context, revision, CoverParams.of(500, 70))
|
when (imageSettings.coverMode) {
|
||||||
CoverMode.BALANCED -> siloedCovers(context, revision, CoverParams.of(750, 85))
|
CoverMode.OFF -> return NullCovers(coverStorage)
|
||||||
CoverMode.HIGH_QUALITY -> siloedCovers(context, revision, CoverParams.of(1000, 100))
|
CoverMode.SAVE_SPACE -> Compress(Bitmap.CompressFormat.JPEG, 500, 70)
|
||||||
}
|
CoverMode.BALANCED -> Compress(Bitmap.CompressFormat.JPEG, 750, 85)
|
||||||
|
CoverMode.HIGH_QUALITY -> Compress(Bitmap.CompressFormat.JPEG, 1000, 100)
|
||||||
private suspend fun siloedCovers(context: Context, revision: UUID, with: CoverParams) =
|
CoverMode.AS_IS -> NoTranscoding
|
||||||
MutableSiloedCovers.from(context, CoverSilo(revision, with), identifier)
|
}
|
||||||
|
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() }
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
* 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,6 +19,7 @@
|
||||||
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
|
||||||
|
@ -34,6 +35,7 @@ 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
|
||||||
|
@ -90,6 +92,7 @@ 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)
|
||||||
|
@ -339,7 +342,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 || childCount == 0) {
|
if (computeVerticalScrollRange() < height || isEmpty()) {
|
||||||
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.dateAdded }
|
Direction.ASCENDING -> songs.sortBy { it.addedMs }
|
||||||
Direction.DESCENDING -> songs.sortByDescending { it.dateAdded }
|
Direction.DESCENDING -> songs.sortByDescending { it.addedMs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.dateAdded }
|
Direction.ASCENDING -> albums.sortBy { it.addedMs }
|
||||||
Direction.DESCENDING -> albums.sortByDescending { it.dateAdded }
|
Direction.DESCENDING -> albums.sortByDescending { it.addedMs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ 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
|
||||||
|
@ -38,7 +39,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.StoredCache
|
import org.oxycblt.musikr.cache.MutableCache
|
||||||
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
|
||||||
|
@ -187,8 +188,8 @@ interface MusicRepository {
|
||||||
/**
|
/**
|
||||||
* Flags indicating which kinds of music information changed.
|
* Flags indicating which kinds of music information changed.
|
||||||
*
|
*
|
||||||
* @param deviceLibrary Whether the current [DeviceLibrary] has changed.
|
* @param deviceLibrary Whether the current songs/albums/artists/genres has changed.
|
||||||
* @param library Whether the current [Playlist]s have changed.
|
* @param userLibrary Whether the current playlists have changed.
|
||||||
*/
|
*/
|
||||||
data class Changes(val deviceLibrary: Boolean, val userLibrary: Boolean)
|
data class Changes(val deviceLibrary: Boolean, val userLibrary: Boolean)
|
||||||
|
|
||||||
|
@ -236,14 +237,14 @@ class MusicRepositoryImpl
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val storedCache: StoredCache,
|
private val cache: MutableCache,
|
||||||
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: MusicRepository.IndexingWorker? = null
|
@Volatile private var indexingWorker: 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
|
||||||
|
@ -282,7 +283,7 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun registerWorker(worker: MusicRepository.IndexingWorker) {
|
override fun registerWorker(worker: IndexingWorker) {
|
||||||
if (indexingWorker != null) {
|
if (indexingWorker != null) {
|
||||||
L.w("Worker is already registered")
|
L.w("Worker is already registered")
|
||||||
return
|
return
|
||||||
|
@ -292,7 +293,7 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun unregisterWorker(worker: MusicRepository.IndexingWorker) {
|
override fun unregisterWorker(worker: 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
|
||||||
|
@ -347,7 +348,8 @@ 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")
|
||||||
library.rewritePlaylist(playlist, songs)
|
val newLibrary = 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) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,14 +385,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) storedCache.visible() else storedCache.invisible()
|
val cache = if (withCache) cache else WriteOnlyMutableCache(cache)
|
||||||
val covers = settingCovers.create(context, newRevision)
|
val covers = settingCovers.mutate(context, newRevision)
|
||||||
val storage = Storage(cache, covers, storedPlaylists)
|
val storage = Storage(cache, covers, storedPlaylists)
|
||||||
val interpretation = Interpretation(nameFactory, separators)
|
val interpretation = Interpretation(nameFactory, separators, withHidden)
|
||||||
|
|
||||||
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,6 +40,8 @@ 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. */
|
||||||
|
@ -83,13 +85,19 @@ 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))
|
||||||
this@edit.apply()
|
commit()
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
@ -116,7 +124,9 @@ 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,15 +27,10 @@ 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,6 +53,9 @@ 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,6 +25,7 @@ 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
|
||||||
|
@ -80,7 +81,7 @@ class MusicSourcesDialog :
|
||||||
|
|
||||||
val locations =
|
val locations =
|
||||||
savedInstanceState?.getStringArrayList(KEY_PENDING_LOCATIONS)?.mapNotNull {
|
savedInstanceState?.getStringArrayList(KEY_PENDING_LOCATIONS)?.mapNotNull {
|
||||||
MusicLocation.existing(requireContext(), Uri.parse(it))
|
MusicLocation.existing(requireContext(), it.toUri())
|
||||||
} ?: 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 [NewPlaylistFooterAdapter].
|
* A [RecyclerView.ViewHolder] that displays a "New Playlist" choice in [NewLocationFooterAdapter].
|
||||||
* Use [from] to create an instance.
|
* Use [from] to create an instance.
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
|
|
|
@ -92,6 +92,7 @@ constructor(
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
if (musicRepository.indexingState == null) {
|
if (musicRepository.indexingState == null) {
|
||||||
|
L.d("Requesting index")
|
||||||
musicRepository.requestIndex(true)
|
musicRepository.requestIndex(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ 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.StoredCache
|
import org.oxycblt.musikr.cache.MutableCache
|
||||||
|
import org.oxycblt.musikr.cache.db.MutableDBCache
|
||||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -33,7 +34,7 @@ import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
class MusikrShimModule {
|
class MusikrShimModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun storedCache(@ApplicationContext context: Context) = StoredCache.from(context)
|
fun cache(@ApplicationContext context: Context): MutableCache = MutableDBCache.from(context)
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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,13 +48,6 @@ 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 ?: return null
|
val library = musicRepository.library?.takeIf { !it.empty() } ?: 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,7 +18,9 @@
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +30,7 @@ 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,11 +21,14 @@ 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
|
||||||
|
@ -35,6 +38,7 @@ 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
|
||||||
|
@ -45,7 +49,6 @@ 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
|
||||||
|
@ -61,6 +64,7 @@ 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,
|
||||||
|
@ -146,7 +150,7 @@ class ExoPlaybackStateHolder(
|
||||||
|
|
||||||
override fun handleDeferred(action: DeferredPlayback): Boolean {
|
override fun handleDeferred(action: DeferredPlayback): Boolean {
|
||||||
val library =
|
val library =
|
||||||
musicRepository.library
|
musicRepository.library?.takeIf { !it.empty() }
|
||||||
// No library, cannot do anything.
|
// No library, cannot do anything.
|
||||||
?: return false
|
?: return false
|
||||||
|
|
||||||
|
@ -181,13 +185,34 @@ 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")
|
||||||
// library.findSongForUri(context, action.uri)?.let { song ->
|
context.applicationContext.contentResolver
|
||||||
// playbackManager.play(
|
.query(
|
||||||
// requireNotNull(commandFactory.song(song,
|
action.uri,
|
||||||
// ShuffleMode.IMPLICIT)) {
|
arrayOf(OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE),
|
||||||
// "Invalid playback parameters"
|
null,
|
||||||
// })
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +397,6 @@ 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
|
||||||
|
@ -393,9 +417,13 @@ class ExoPlaybackStateHolder(
|
||||||
}
|
}
|
||||||
|
|
||||||
repeatMode(repeatMode)
|
repeatMode(repeatMode)
|
||||||
// Positions in milliseconds will drift during tight restores (i.e what the music loader
|
// See if we differ by more than a second. This allows us to avoid a meaningless seek
|
||||||
// does to sanitize the state), compare by seconds instead.
|
// in the case of a "tight restore" (i.e music was reloaded).
|
||||||
if (positionMs.msToSecs() != player.currentPosition.msToSecs() || shouldSeek) {
|
// In the case that this is a false positive, it's not very percievable (at least compared
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,14 +435,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) {
|
||||||
playbackManager.playing(false)
|
sessionOngoing = false
|
||||||
|
playbackManager.ack(this, StateAck.SessionEnded)
|
||||||
}
|
}
|
||||||
sessionOngoing = false
|
|
||||||
playbackManager.ack(this, StateAck.SessionEnded)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +527,7 @@ class ExoPlaybackStateHolder(
|
||||||
// --- MUSICREPOSITORY METHODS ---
|
// --- MUSICREPOSITORY METHODS ---
|
||||||
|
|
||||||
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
||||||
if (changes.deviceLibrary && musicRepository.library != null) {
|
if (changes.deviceLibrary && musicRepository.library?.takeIf { !it.empty() } != 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)
|
||||||
|
@ -520,7 +548,9 @@ class ExoPlaybackStateHolder(
|
||||||
|
|
||||||
private fun save(cb: () -> Unit) {
|
private fun save(cb: () -> Unit) {
|
||||||
saveJob {
|
saveJob {
|
||||||
persistenceRepository.saveState(playbackManager.toSavedState())
|
if (sessionOngoing) {
|
||||||
|
persistenceRepository.saveState(playbackManager.toSavedState())
|
||||||
|
}
|
||||||
withContext(Dispatchers.Main) { cb() }
|
withContext(Dispatchers.Main) { cb() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,7 +561,9 @@ class ExoPlaybackStateHolder(
|
||||||
delay(SAVE_BUFFER)
|
delay(SAVE_BUFFER)
|
||||||
yield()
|
yield()
|
||||||
L.d("Committing saved state")
|
L.d("Committing saved state")
|
||||||
persistenceRepository.saveState(playbackManager.toSavedState())
|
if (sessionOngoing) {
|
||||||
|
persistenceRepository.saveState(playbackManager.toSavedState())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ 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
|
||||||
|
|
||||||
|
@ -47,8 +48,11 @@ 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,6 +20,7 @@ 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
|
||||||
|
@ -28,6 +29,7 @@ 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
|
||||||
|
@ -108,6 +110,9 @@ 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,9 +19,11 @@
|
||||||
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
|
||||||
|
@ -83,18 +85,34 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun start(startedBy: Int) {
|
fun start(intent: Intent?) {
|
||||||
// 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?
|
||||||
L.d("Handling non-native start.")
|
val startId = intent?.getIntExtra(INTENT_KEY_START_ID, -1)
|
||||||
val action =
|
val action =
|
||||||
when (startedBy) {
|
when (startId) {
|
||||||
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)
|
||||||
// External services using Auxio better know what they are doing.
|
IntegerTable.START_ID_MEDIA_BUTTON -> {
|
||||||
else -> DeferredPlayback.RestoreState(play = false)
|
if (!sessionHolder.tryMediaButtonIntent(intent)) {
|
||||||
|
// 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,6 +19,8 @@
|
||||||
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
|
||||||
|
@ -41,6 +43,7 @@ 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,7 +94,11 @@ 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,6 +72,9 @@ 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)
|
||||||
}
|
}
|
||||||
|
@ -102,7 +105,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 = Uri.parse("mailto:$recipient") }
|
val intent = Intent(Intent.ACTION_SENDTO).apply { data = "mailto:$recipient".toUri() }
|
||||||
startIntent(intent)
|
startIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,5 +116,6 @@ 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,17 +62,13 @@ 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)
|
||||||
|
|
||||||
private var listener: Listener? = null
|
protected var listener: Listener? = null
|
||||||
|
|
||||||
override fun registerListener(listener: Listener) {
|
override fun registerListener(listener: Listener) {
|
||||||
if (this.listener == null) {
|
if (this.listener == null) {
|
||||||
|
|
|
@ -67,5 +67,14 @@ 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,7 +18,6 @@
|
||||||
|
|
||||||
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
|
||||||
|
@ -54,7 +53,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")
|
||||||
AppCompatDelegate.setDefaultNightMode(value as Int)
|
requireActivity().recreate()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,9 @@ 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(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun jumpToFadeIn(view: View) {
|
private fun jumpToFadeIn(view: View) {
|
||||||
view.apply {
|
view.apply {
|
||||||
alpha = 1f
|
alpha = 1f
|
||||||
scaleX = 1.0f
|
scaleX = 1.0f
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.home
|
package org.oxycblt.auxio.ui
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
@ -40,7 +40,6 @@ 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
|
||||||
}
|
}
|
|
@ -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), false)
|
get() = sharedPreferences.getBoolean(getString(R.string.set_key_round_mode), true)
|
||||||
|
|
||||||
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_Black_Red,
|
R.style.Theme_Auxio_Red_Black,
|
||||||
R.style.Theme_Auxio_Black_Pink,
|
R.style.Theme_Auxio_Pink_Black,
|
||||||
R.style.Theme_Auxio_Black_Purple,
|
R.style.Theme_Auxio_Purple_Black,
|
||||||
R.style.Theme_Auxio_Black_DeepPurple,
|
R.style.Theme_Auxio_DeepPurple_Black,
|
||||||
R.style.Theme_Auxio_Black_Indigo,
|
R.style.Theme_Auxio_Indigo_Black,
|
||||||
R.style.Theme_Auxio_Black_Blue,
|
R.style.Theme_Auxio_Blue_Black,
|
||||||
R.style.Theme_Auxio_Black_DeepBlue,
|
R.style.Theme_Auxio_DeepBlue_Black,
|
||||||
R.style.Theme_Auxio_Black_Cyan,
|
R.style.Theme_Auxio_Cyan_Black,
|
||||||
R.style.Theme_Auxio_Black_Teal,
|
R.style.Theme_Auxio_Teal_Black,
|
||||||
R.style.Theme_Auxio_Black_Green,
|
R.style.Theme_Auxio_Green_Black,
|
||||||
R.style.Theme_Auxio_Black_DeepGreen,
|
R.style.Theme_Auxio_DeepGreen_Black,
|
||||||
R.style.Theme_Auxio_Black_Lime,
|
R.style.Theme_Auxio_Lime_Black,
|
||||||
R.style.Theme_Auxio_Black_Yellow,
|
R.style.Theme_Auxio_Yellow_Black,
|
||||||
R.style.Theme_Auxio_Black_Orange,
|
R.style.Theme_Auxio_Orange_Black,
|
||||||
R.style.Theme_Auxio_Black_Brown,
|
R.style.Theme_Auxio_Brown_Black,
|
||||||
R.style.Theme_Auxio_Black_Grey,
|
R.style.Theme_Auxio_Grey_Black,
|
||||||
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,7 +24,6 @@ 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
|
||||||
|
@ -36,7 +35,6 @@ 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
|
||||||
|
@ -106,10 +104,6 @@ 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
|
||||||
|
@ -357,7 +351,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 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
} else {
|
||||||
// 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,18 +22,11 @@ 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.
|
||||||
|
@ -153,71 +146,3 @@ 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,6 +20,7 @@ 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
|
||||||
|
@ -49,7 +50,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 Bitmap.createScaledBitmap(input, newWidth, newHeight, true)
|
return input.scale(newWidth, newHeight)
|
||||||
}
|
}
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
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
|
||||||
|
@ -66,11 +65,6 @@ 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,79 +3,94 @@
|
||||||
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="108dp"
|
android:width="432dp"
|
||||||
android:height="108dp"
|
android:height="432dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="432"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="432">
|
||||||
<group
|
<group
|
||||||
android:name="bg"
|
android:name="bg"
|
||||||
android:pivotX="56"
|
android:pivotX="56"
|
||||||
android:pivotY="56">
|
android:pivotY="56">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#ffffff"
|
android:fillColor="#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:strokeColor="#00000000"
|
||||||
android:strokeColor="#00000000" />
|
android:pathData="M 408,216
|
||||||
|
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
|
<group
|
||||||
android:name="base"
|
android:scaleX="8.5"
|
||||||
android:scaleX="2.835"
|
android:scaleY="8.5"
|
||||||
android:scaleY="2.835"
|
android:translateX="114"
|
||||||
android:translateX="19.98"
|
android:translateY="114">
|
||||||
android:translateY="-64">
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/transparent"
|
android:fillColor="@android:color/transparent"
|
||||||
android:pathData="m 13,17 -3,3 -3,-3 3,-3"
|
android:pathData="M13 4l4 4m-4-4v13m0 0l-3 3-3-3 3-3"
|
||||||
android:strokeWidth="2"
|
android:strokeWidth="2"
|
||||||
|
android:strokeColor="#80808080"
|
||||||
|
android:strokeLineCap="round"
|
||||||
|
android:strokeLineJoin="round" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group
|
||||||
|
android:scaleX="8.5"
|
||||||
|
android:scaleY="8.5"
|
||||||
|
android:translateX="114"
|
||||||
|
android:translateY="114">
|
||||||
|
<path
|
||||||
|
android:name="base"
|
||||||
|
android:fillColor="@android:color/transparent"
|
||||||
|
android:pathData="m 13,17 -3,3 -3,-3 3,-3"
|
||||||
|
android:strokeWidth="0"
|
||||||
android:strokeColor="#004894"
|
android:strokeColor="#004894"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:name="lower_stem"
|
android:scaleX="8.5"
|
||||||
android:scaleX="2.835"
|
android:scaleY="8.5"
|
||||||
android:scaleY="2.835"
|
android:translateX="114"
|
||||||
android:translateX="19.98"
|
android:translateY="114">
|
||||||
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="2"
|
android:strokeWidth="0"
|
||||||
android:strokeColor="#1a61ae"
|
android:strokeColor="#1a61ae"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:name="upper_stem"
|
android:scaleX="8.5"
|
||||||
android:scaleX="2.835"
|
android:scaleY="8.5"
|
||||||
android:scaleY="2.835"
|
android:translateX="114"
|
||||||
android:translateX="19.98"
|
android:translateY="114">
|
||||||
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="2"
|
android:strokeWidth="0"
|
||||||
android:strokeColor="#357ac9"
|
android:strokeColor="#357ac9"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:name="tail"
|
android:scaleX="8.5"
|
||||||
android:scaleX="2.835"
|
android:scaleY="8.5"
|
||||||
android:scaleY="2.835"
|
android:translateX="114"
|
||||||
android:translateX="19.98"
|
android:translateY="114">
|
||||||
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="2"
|
android:strokeWidth="0"
|
||||||
android:strokeColor="#5093e4"
|
android:strokeColor="#5093e4"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:strokeLineJoin="round" />
|
android:strokeLineJoin="round" />
|
||||||
|
@ -91,12 +106,12 @@
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="500"
|
android:duration="850"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="translateY"
|
android:propertyName="strokeWidth"
|
||||||
android:startOffset="0"
|
android:startOffset="150"
|
||||||
android:valueFrom="-512"
|
android:valueFrom="0"
|
||||||
android:valueTo="19.98"
|
android:valueTo="2"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
@ -106,12 +121,12 @@
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="500"
|
android:duration="850"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="translateY"
|
android:propertyName="strokeWidth"
|
||||||
android:startOffset="0"
|
android:startOffset="150"
|
||||||
android:valueFrom="-256"
|
android:valueFrom="0"
|
||||||
android:valueTo="19.98"
|
android:valueTo="2"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
@ -122,12 +137,12 @@
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="500"
|
android:duration="850"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="translateY"
|
android:propertyName="strokeWidth"
|
||||||
android:startOffset="0"
|
android:startOffset="150"
|
||||||
android:valueFrom="-128"
|
android:valueFrom="0"
|
||||||
android:valueTo="19.98"
|
android:valueTo="2"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
@ -137,12 +152,12 @@
|
||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<set>
|
<set>
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="500"
|
android:duration="850"
|
||||||
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized_decelerate"
|
||||||
android:propertyName="translateY"
|
android:propertyName="strokeWidth"
|
||||||
android:startOffset="0"
|
android:startOffset="150"
|
||||||
android:valueFrom="-64"
|
android:valueFrom="0"
|
||||||
android:valueTo="19.98"
|
android:valueTo="2"
|
||||||
android:valueType="floatType"
|
android:valueType="floatType"
|
||||||
tools:ignore="PrivateResource" />
|
tools:ignore="PrivateResource" />
|
||||||
</set>
|
</set>
|
||||||
|
|
|
@ -119,7 +119,8 @@
|
||||||
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,7 +101,8 @@
|
||||||
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,7 +129,8 @@
|
||||||
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,7 +132,8 @@
|
||||||
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">
|
||||||
|
|
||||||
|
|
||||||
<FrameLayout
|
<org.oxycblt.auxio.ui.EatInsetsFrameLayout
|
||||||
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,7 +22,9 @@
|
||||||
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"
|
||||||
|
@ -39,6 +41,7 @@
|
||||||
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" />
|
||||||
|
@ -47,14 +50,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_gravity="bottom|end"
|
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
android:contentDescription="@string/desc_shuffle_all"
|
android:layout_gravity="bottom|end"
|
||||||
|
android:contentDescription="@string/lbl_shuffle"
|
||||||
android:src="@drawable/ic_shuffle_off_24" />
|
android:src="@drawable/ic_shuffle_off_24" />
|
||||||
|
|
||||||
</org.oxycblt.auxio.home.EdgeFrameLayout>
|
</org.oxycblt.auxio.ui.EdgeFrameLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</org.oxycblt.auxio.ui.EatInsetsFrameLayout>
|
||||||
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
|
@ -226,6 +226,17 @@
|
||||||
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,6 +72,7 @@
|
||||||
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.home.EdgeFrameLayout
|
<org.oxycblt.auxio.ui.EdgeFrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
||||||
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
|
||||||
|
@ -53,5 +54,5 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</org.oxycblt.auxio.home.EdgeFrameLayout>
|
</org.oxycblt.auxio.ui.EdgeFrameLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface"
|
||||||
android:transitionGroup="true">
|
android:transitionGroup="true">
|
||||||
|
|
||||||
<FrameLayout
|
<org.oxycblt.auxio.ui.EatInsetsFrameLayout
|
||||||
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,7 +28,8 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="invisible" />
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<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"
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
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" />
|
||||||
|
@ -53,14 +55,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_gravity="bottom|end"
|
|
||||||
android:layout_margin="@dimen/spacing_medium"
|
android:layout_margin="@dimen/spacing_medium"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
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.home.EdgeFrameLayout>
|
</org.oxycblt.auxio.ui.EdgeFrameLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</org.oxycblt.auxio.ui.EatInsetsFrameLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/main_sheet_scrim"
|
android:id="@+id/main_sheet_scrim"
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
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:app="http://schemas.android.com/apk/res-auto">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<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" />
|
tools:ignore="ContentDescription,UnusedAttribute" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
android:id="@+id/widget_panel"
|
android:id="@+id/widget_panel"
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
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"
|
||||||
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"
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
<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>
|
||||||
|
@ -27,42 +26,40 @@
|
||||||
<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">عرض على الكود في Github</string>
|
<string name="lbl_code">كود البرنامج</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>
|
||||||
|
@ -71,13 +68,11 @@
|
||||||
<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>
|
||||||
|
@ -85,7 +80,6 @@
|
||||||
<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>
|
||||||
|
@ -136,44 +130,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">MixMix</string>
|
<string name="lbl_mix">مكس دي جي</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">EP</string>
|
<string name="lbl_ep">أغنية مطولة</string>
|
||||||
<string name="lbl_eps">EPs</string>
|
<string name="lbl_eps">أغاني مطولة</string>
|
||||||
<string name="lbl_mixtape">Mixtape</string>
|
<string name="lbl_mixtape">مكس</string>
|
||||||
<string name="lbl_soundtrack">تسجيل صوتي</string>
|
<string name="lbl_soundtrack">موسيقى تصويرية</string>
|
||||||
<string name="lbl_mixtapes">Mixtapes</string>
|
<string name="lbl_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>
|
||||||
|
@ -181,16 +175,15 @@
|
||||||
<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">Wiki</string>
|
<string name="lbl_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>
|
||||||
|
@ -204,8 +197,66 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="lbl_music_sources">إختيار المجلد</string>
|
||||||
|
<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,9 +1,8 @@
|
||||||
<?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>
|
||||||
|
@ -18,8 +17,7 @@
|
||||||
<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="lbl_add">إضافة مجلد</string>
|
<string name="lng_indexing">جارِ تحميل مكتبتك الموسيقية…</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>
|
||||||
|
@ -85,7 +83,6 @@
|
||||||
<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>
|
||||||
|
@ -109,7 +106,6 @@
|
||||||
</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>
|
||||||
|
@ -117,7 +113,6 @@
|
||||||
<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>
|
||||||
|
@ -140,7 +135,6 @@
|
||||||
<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>
|
||||||
|
@ -169,9 +163,7 @@
|
||||||
<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>
|
||||||
|
@ -248,7 +240,6 @@
|
||||||
<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>
|
||||||
|
@ -277,4 +268,61 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="lbl_music_sources">اختر المجلدات</string>
|
||||||
|
<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,7 +3,6 @@
|
||||||
<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>
|
||||||
|
@ -35,7 +34,6 @@
|
||||||
<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>
|
||||||
|
@ -76,7 +74,6 @@
|
||||||
<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,7 +23,6 @@
|
||||||
<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>
|
||||||
|
@ -88,7 +87,6 @@
|
||||||
<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>
|
||||||
|
@ -113,15 +111,11 @@
|
||||||
<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>
|
||||||
|
@ -133,7 +127,6 @@
|
||||||
<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>
|
||||||
|
@ -148,7 +141,6 @@
|
||||||
<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>
|
||||||
|
@ -279,7 +271,6 @@
|
||||||
<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,7 +76,6 @@
|
||||||
<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>
|
||||||
|
@ -97,7 +96,6 @@
|
||||||
<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>
|
||||||
|
@ -186,7 +184,6 @@
|
||||||
<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>
|
||||||
|
@ -210,20 +207,15 @@
|
||||||
<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>
|
||||||
|
@ -255,7 +247,6 @@
|
||||||
<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,7 +7,6 @@
|
||||||
<!-- 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>
|
||||||
|
@ -42,7 +41,6 @@
|
||||||
<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>
|
||||||
|
@ -90,11 +88,8 @@
|
||||||
<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>
|
||||||
|
@ -105,7 +100,6 @@
|
||||||
<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>
|
||||||
|
@ -167,7 +161,6 @@
|
||||||
<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>
|
||||||
|
@ -246,7 +239,6 @@
|
||||||
<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>
|
||||||
|
@ -290,7 +282,6 @@
|
||||||
<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>
|
||||||
|
@ -341,4 +332,7 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="set_with_hidden">Zahrnout skryté soubory</string>
|
||||||
|
<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,7 +4,6 @@
|
||||||
<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>
|
||||||
|
@ -24,7 +23,6 @@
|
||||||
<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>
|
||||||
|
@ -34,7 +32,6 @@
|
||||||
<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>
|
||||||
|
@ -89,7 +86,6 @@
|
||||||
<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>
|
||||||
|
@ -157,7 +153,6 @@
|
||||||
<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>
|
||||||
|
@ -199,11 +194,8 @@
|
||||||
<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>
|
||||||
|
@ -245,7 +237,6 @@
|
||||||
<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,7 +2,6 @@
|
||||||
<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>
|
||||||
|
@ -24,9 +23,7 @@
|
||||||
<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>
|
||||||
|
@ -64,9 +61,7 @@
|
||||||
<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 -->
|
||||||
|
@ -129,7 +124,6 @@
|
||||||
<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>
|
||||||
|
@ -158,7 +152,6 @@
|
||||||
<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>
|
||||||
|
@ -244,7 +237,6 @@
|
||||||
<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>
|
||||||
|
@ -281,7 +273,6 @@
|
||||||
<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>
|
||||||
|
@ -332,4 +323,7 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="set_cover_mode_as_is">Unverändert</string>
|
||||||
|
<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,7 +2,6 @@
|
||||||
<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>
|
||||||
|
@ -75,10 +74,8 @@
|
||||||
<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>
|
||||||
|
@ -95,7 +92,6 @@
|
||||||
<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,7 +5,6 @@
|
||||||
<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>
|
||||||
|
@ -22,38 +21,36 @@
|
||||||
<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">Mezcla</string>
|
<string name="lbl_shuffle">Modo aleatorio</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">Agregar a la cola</string>
|
<string name="lbl_queue_add">Añadir a la cola</string>
|
||||||
<string name="lng_queue_added">Agregado a la cola</string>
|
<string name="lng_queue_added">Añadido 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">Ajustes</string>
|
<string name="set_root_title">Configuración</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">Esquema de color</string>
|
<string name="set_accent">Combinación de colores</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">Carátulas redondeadas</string>
|
<string name="set_round_mode">Modo redondeado</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>
|
||||||
|
@ -73,13 +70,11 @@
|
||||||
<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">Directorio no soportado</string>
|
<string name="err_bad_location">No se admite esta carpeta</string>
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="lng_search_library">Buscar en la biblioteca…</string>
|
<string name="lng_search_library">Buscar en la fonoteca…</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>
|
||||||
|
@ -87,7 +82,6 @@
|
||||||
<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>
|
||||||
|
@ -142,13 +136,12 @@
|
||||||
<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">De acuerdo</string>
|
<string name="lbl_ok">Aceptar</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_mka">Audio matroska</string>
|
<string name="cdc_flac">Códec de audio sin pérdida libre (FLAC)</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>
|
||||||
|
@ -157,15 +150,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 tu librería de música…</string>
|
<string name="lng_indexing">Cargando la fonoteca…</string>
|
||||||
<string name="lbl_indexing">Cargando música</string>
|
<string name="lbl_indexing">Cargando música</string>
|
||||||
<string name="lbl_observing">Monitorizando la librería de música</string>
|
<string name="lbl_observing">Monitorizando la fonoteca</string>
|
||||||
<string name="lng_observing">Monitorizando cambios en tu librería de música…</string>
|
<string name="lng_observing">Monitorizando cambios en la fonoteca…</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 añadido</string>
|
<string name="lbl_date_added">Fecha de adición</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">Frecuencia de muestreo</string>
|
<string name="lbl_sample_rate">Tasa 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>
|
||||||
|
@ -176,9 +169,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">Pista de audio</string>
|
<string name="lbl_soundtrack">Banda sonora</string>
|
||||||
<string name="lbl_album_remix">Álbum remix</string>
|
<string name="lbl_album_remix">Álbum de remezclas</string>
|
||||||
<string name="lbl_soundtracks">Pistas de audio</string>
|
<string name="lbl_soundtracks">Bandas sonoras</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>
|
||||||
|
@ -191,7 +184,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">Single en directo</string>
|
<string name="lbl_single_live">Sencillo 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>
|
||||||
|
@ -199,9 +192,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">Single remix</string>
|
<string name="lbl_single_remix">Sencillo remezclado</string>
|
||||||
<string name="lbl_compilations">Compilaciones</string>
|
<string name="lbl_compilations">Compilaciones</string>
|
||||||
<string name="lbl_ep_remix">EP de remixes</string>
|
<string name="lbl_ep_remix">EP de remezclas</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>
|
||||||
|
@ -216,7 +209,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">Apagado</string>
|
<string name="set_cover_mode_off">Desactivadas</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>
|
||||||
|
@ -248,7 +241,6 @@
|
||||||
<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>
|
||||||
|
@ -260,17 +252,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">Agregar a la lista de reproducción</string>
|
<string name="lbl_playlist_add">Añadir 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">Borrar</string>
|
<string name="lbl_delete">Eliminar</string>
|
||||||
<string name="lbl_rename">Cambiar el nombre</string>
|
<string name="lbl_rename">Cambiar nombre</string>
|
||||||
<string name="lbl_rename_playlist">Cambiar el nombre de la lista de reproducción</string>
|
<string name="lbl_rename_playlist">Cambiar nombre de 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 borrada</string>
|
<string name="lng_playlist_deleted">Lista de reproducción eliminada</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">¿Borrar la lista de reproducción\?</string>
|
<string name="lbl_confirm_delete_playlist">¿Quiere eliminar 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>
|
||||||
|
@ -285,7 +277,6 @@
|
||||||
<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>
|
||||||
|
@ -328,5 +319,15 @@
|
||||||
<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">Apple Lossless Audio Codec (ALAC)</string>
|
<string name="cdc_alac">Códec de audio sin pérdida de Apple (ALAC)</string>
|
||||||
</resources>
|
<string name="lng_empty_albums">Sus álbumes aparecerán aquí.</string>
|
||||||
|
<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,8 +2,6 @@
|
||||||
<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>
|
||||||
|
@ -57,7 +55,6 @@
|
||||||
<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>
|
||||||
|
@ -230,7 +227,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 (&)</string>
|
<string name="set_separators_and">Ampersand (and-märk)</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>
|
||||||
|
@ -243,19 +240,15 @@
|
||||||
<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>
|
||||||
|
@ -265,7 +258,6 @@
|
||||||
<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>
|
||||||
|
@ -288,7 +280,6 @@
|
||||||
<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>
|
||||||
|
@ -324,4 +315,7 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="set_with_hidden">Kaasa peidetud failid</string>
|
||||||
|
<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,7 +3,6 @@
|
||||||
<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,7 +4,6 @@
|
||||||
<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>
|
||||||
|
@ -51,7 +50,6 @@
|
||||||
<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>
|
||||||
|
@ -70,7 +68,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">Ja-merkki (&)</string>
|
<string name="set_separators_and">Ampersand &</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>
|
||||||
|
@ -89,7 +87,6 @@
|
||||||
<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>
|
||||||
|
@ -106,7 +103,6 @@
|
||||||
<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>
|
||||||
|
@ -165,10 +161,8 @@
|
||||||
<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>
|
||||||
|
@ -205,11 +199,9 @@
|
||||||
<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>
|
||||||
|
@ -250,7 +242,6 @@
|
||||||
<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>
|
||||||
|
@ -315,4 +306,11 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="lng_empty_songs">Kappaleesi tulevat näkymään tässä.</string>
|
||||||
|
<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,7 +51,6 @@
|
||||||
<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>
|
||||||
|
@ -88,7 +87,6 @@
|
||||||
<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,7 +2,6 @@
|
||||||
<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>
|
||||||
|
@ -38,7 +37,6 @@
|
||||||
<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>
|
||||||
|
@ -85,7 +83,6 @@
|
||||||
<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>
|
||||||
|
@ -110,7 +107,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 librairie musicale</string>
|
<string name="lbl_observing">Suivre la bibliothèque 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>
|
||||||
|
@ -125,13 +122,11 @@
|
||||||
<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>
|
||||||
|
@ -200,13 +195,11 @@
|
||||||
<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>
|
||||||
|
@ -222,7 +215,6 @@
|
||||||
<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>
|
||||||
|
@ -283,7 +275,6 @@
|
||||||
<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>
|
||||||
|
@ -321,4 +312,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,7 +14,6 @@
|
||||||
<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>
|
||||||
|
@ -93,7 +92,6 @@
|
||||||
<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>
|
||||||
|
@ -162,7 +160,6 @@
|
||||||
<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>
|
||||||
|
@ -179,9 +176,7 @@
|
||||||
<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>
|
||||||
|
@ -227,12 +222,9 @@
|
||||||
<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,7 +2,6 @@
|
||||||
<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>
|
||||||
|
@ -31,7 +30,6 @@
|
||||||
<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 -->
|
||||||
|
@ -141,7 +139,6 @@
|
||||||
<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>
|
||||||
|
@ -202,12 +199,10 @@
|
||||||
<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>
|
||||||
|
@ -261,8 +256,6 @@
|
||||||
<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>
|
||||||
|
@ -271,7 +264,6 @@
|
||||||
<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>
|
||||||
|
@ -283,7 +275,6 @@
|
||||||
<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,7 +48,6 @@
|
||||||
<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>
|
||||||
|
@ -87,16 +86,12 @@
|
||||||
<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>
|
||||||
|
@ -158,7 +153,6 @@
|
||||||
<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>
|
||||||
|
@ -167,7 +161,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</string>
|
<string name="lng_queue_added">Dodano u redoslijed izvođenja</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>
|
||||||
|
@ -191,7 +185,6 @@
|
||||||
<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>
|
||||||
|
@ -233,7 +226,6 @@
|
||||||
<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>
|
||||||
|
@ -276,7 +268,6 @@
|
||||||
<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>
|
||||||
|
@ -322,4 +313,9 @@
|
||||||
<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>
|
||||||
</resources>
|
<string name="lng_empty_songs">Tvoje pjesme će se ovdje prikazati.</string>
|
||||||
|
<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>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue