Implement fixes for my favorite pet peeves in Vanilla (#714)

* Ignore Visual Studio's cache.

* If only one of (ARTIST, ALBUMARTIST) is present, populate the other.
This is only natural and most applications that implement media library population do this.

* On completion of the queue, rewind to the beginning of the queue, so that a subsequent Play command will play the whole queue again.

* Correct <plurals> values according to the best practices and add a CLDR rules link for translators to look for their language's specific informaiton.
This commit is contained in:
Dmitri Davydok 2018-01-26 12:10:28 -08:00 committed by Adrian Ulrich
parent 4ac73f9625
commit 44627437dc
4 changed files with 35 additions and 12 deletions

3
.gitignore vendored
View File

@ -37,3 +37,6 @@ proguard/
*.iml *.iml
out out
.settings/ .settings/
# Visual Studio 2015 cache/options directory
.vs/

View File

@ -82,24 +82,35 @@ THE SOFTWARE.
<string name="go_home">Home directory</string> <string name="go_home">Home directory</string>
<string name="jumping_to_song">Song is already in queue, jumping…</string> <string name="jumping_to_song">Song is already in queue, jumping…</string>
<!--
As a developer, you should always supply "one" and "other"
strings. Your translators will know which strings are actually
needed for their language. Always include %d in "one" because
translators will need to use %d for languages where "one"
doesn't mean 1 (as explained above).
Translators should use http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules and
http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html, Type cardinal,
to see which categories apply to integer numbers in their languages
-->
<plurals name="playing"> <plurals name="playing">
<item quantity="one">1 track playing.</item> <item quantity="one">%d track playing.</item>
<item quantity="other">%d tracks playing.</item> <item quantity="other">%d tracks playing.</item>
</plurals> </plurals>
<plurals name="enqueued"> <plurals name="enqueued">
<item quantity="one">1 track enqueued.</item> <item quantity="one">%d track enqueued.</item>
<item quantity="other">%d tracks enqueued.</item> <item quantity="other">%d tracks enqueued.</item>
</plurals> </plurals>
<plurals name="added_to_playlist"> <plurals name="added_to_playlist">
<item quantity="one">1 track added to playlist %2$s.</item> <item quantity="one">%1$d track added to playlist %2$s.</item>
<item quantity="other">%1$d tracks added to playlist %2$s.</item> <item quantity="other">%1$d tracks added to playlist %2$s.</item>
</plurals> </plurals>
<plurals name="removed_from_playlist"> <plurals name="removed_from_playlist">
<item quantity="one">1 track removed from playlist %2$s.</item> <item quantity="one">%1$d track removed from playlist %2$s.</item>
<item quantity="other">%1$d tracks removed from playlist %2$s.</item> <item quantity="other">%1$d tracks removed from playlist %2$s.</item>
</plurals> </plurals>
<plurals name="deleted"> <plurals name="deleted">
<item quantity="one">1 track deleted.</item> <item quantity="one">%d track deleted.</item>
<item quantity="other">%d tracks deleted.</item> <item quantity="other">%d tracks deleted.</item>
</plurals> </plurals>
<string name="delete_file_failed">Failed to delete %s.</string> <string name="delete_file_failed">Failed to delete %s.</string>

View File

@ -292,8 +292,8 @@ public class MediaMetadataExtractor extends HashMap<String, ArrayList<String>> {
Log.v("VanillaMusic", "Error creating fis for "+path+": "+e); Log.v("VanillaMusic", "Error creating fis for "+path+": "+e);
} }
// Check if this is an useable audio file // Check if this is a usable audio file
if (nativelyReadable == false || if (!nativelyReadable ||
mediaTags.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO) == null || mediaTags.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO) == null ||
mediaTags.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO) != null || mediaTags.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO) != null ||
mediaTags.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) == null) { mediaTags.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) == null) {
@ -339,7 +339,7 @@ public class MediaMetadataExtractor extends HashMap<String, ArrayList<String>> {
convertNumericGenre(); convertNumericGenre();
// We consider this a media file if it has some common tags OR // We consider this a media file if it has some common tags OR
// if bastp was able to parse it (which is stricter than Androids own parser) // if bastp was able to parse it (which is stricter than Android's own parser)
mIsMediaFile = (containsKey(TITLE) || containsKey(ALBUM) || containsKey(ARTIST) || !bastpType.equals("")); mIsMediaFile = (containsKey(TITLE) || containsKey(ALBUM) || containsKey(ARTIST) || !bastpType.equals(""));
mediaTags.release(); mediaTags.release();
@ -369,6 +369,14 @@ public class MediaMetadataExtractor extends HashMap<String, ArrayList<String>> {
} }
} }
// If only one of (ARTIST, ALBUMARTIST) is present, populate the other
if (!containsKey(ARTIST) && containsKey(ALBUMARTIST)) {
put(ARTIST, get(ALBUMARTIST));
}
if (containsKey(ARTIST) && !containsKey(ALBUMARTIST)) {
put(ALBUMARTIST, get(ARTIST));
}
// Try to guess YEAR from date field if only DATE was specified // Try to guess YEAR from date field if only DATE was specified
// We expect it to match \d{4} // We expect it to match \d{4}
if (!containsKey(YEAR) && bastp.containsKey("DATE")) { if (!containsKey(YEAR) && bastp.containsKey("DATE")) {

View File

@ -176,7 +176,7 @@ public final class PlaybackService extends Service
*/ */
public static final String ACTION_CYCLE_REPEAT = "ch.blinkenlights.android.vanilla.CYCLE_REPEAT"; public static final String ACTION_CYCLE_REPEAT = "ch.blinkenlights.android.vanilla.CYCLE_REPEAT";
/** /**
* Pause music and hide the notifcation. * Pause music and hide the notification.
*/ */
public static final String ACTION_CLOSE_NOTIFICATION = "ch.blinkenlights.android.vanilla.CLOSE_NOTIFICATION"; public static final String ACTION_CLOSE_NOTIFICATION = "ch.blinkenlights.android.vanilla.CLOSE_NOTIFICATION";
/** /**
@ -1420,7 +1420,7 @@ public final class PlaybackService extends Service
/* Automatically advance to next song IF we are currently playing or already did skip something /* Automatically advance to next song IF we are currently playing or already did skip something
* This will stop after skipping 10 songs to avoid endless loops (queue full of broken stuff */ * This will stop after skipping 10 songs to avoid endless loops (queue full of broken stuff */
if(mTimeline.isEndOfQueue() == false && getSong(1) != null && (playing || (mSkipBroken > 0 && mSkipBroken < 10))) { if(!mTimeline.isEndOfQueue() && getSong(1) != null && (playing || (mSkipBroken > 0 && mSkipBroken < 10))) {
mSkipBroken++; mSkipBroken++;
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SKIP_BROKEN_SONG, getTimelinePosition(), 0), 1000); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SKIP_BROKEN_SONG, getTimelinePosition(), 0), 1000);
} }
@ -1443,9 +1443,10 @@ public final class PlaybackService extends Service
} else if (finishAction(mState) == SongTimeline.FINISH_STOP_CURRENT) { } else if (finishAction(mState) == SongTimeline.FINISH_STOP_CURRENT) {
unsetFlag(FLAG_PLAYING); unsetFlag(FLAG_PLAYING);
setCurrentSong(+1); setCurrentSong(+1);
} else if (mTimeline.isEndOfQueue()) {
unsetFlag(FLAG_PLAYING);
} else { } else {
if (mTimeline.isEndOfQueue()) {
unsetFlag(FLAG_PLAYING);
}
setCurrentSong(+1); setCurrentSong(+1);
} }
} }