Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: commands for next/previous album that respect shuffle settings #3007

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
678 changes: 678 additions & 0 deletions Tests/AlbumNavigationTests.cpp

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions Tests/TestData/AlbumNavigation.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
0 Metallica Master of Puppets Battery
0 Metallica Master of Puppets Master of Puppets
0 Metallica Master of Puppets The Thing That Should Not Be
0 Metallica Master of Puppets Welcome Home (Sanitarium)
0 Metallica Master of Puppets Disposable Heroes
0 Metallica Master of Puppets Leper Messiah
0 Metallica Master of Puppets Orion
0 Metallica Master of Puppets Damage, Inc.
2 Iron Maiden Powerslave Aces High
2 Iron Maiden Powerslave 2 Minutes to Midnight
2 Iron Maiden Powerslave Losfer Words (Big 'Orra)
2 Iron Maiden Powerslave Flash of the Blade
2 Iron Maiden Powerslave The Duellists
2 Iron Maiden Powerslave Back in the Village
2 Iron Maiden Powerslave Powerslave
2 Iron Maiden Powerslave Rime of the Ancient Mariner
1 King Crimson Red Red
1 King Crimson Red Fallen Angel
1 King Crimson Red One More Red Nightmare
1 King Crimson Red Providence
1 King Crimson Red Starless
5 changes: 4 additions & 1 deletion include/deadbeef/deadbeef.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,11 @@ enum {
// which includes a switch to another output plugin.
// p1 contains the new state.
DB_EV_PLAYBACK_STATE_DID_CHANGE = 25,
#endif

DB_EV_PLAY_NEXT_ALBUM = 26, // switch to next album
DB_EV_PLAY_PREV_ALBUM = 27, // switch to prev album
DB_EV_PLAY_RANDOM_ALBUM = 28, // play random album
#endif
// -----------------
// structured events

Expand Down
44 changes: 43 additions & 1 deletion plugins/hotkeys/hotkeys.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,24 @@ action_play_random_cb (struct DB_plugin_action_s *action, ddb_action_context_t c
return 0;
}

int
action_play_random_album_cb (struct DB_plugin_action_s *action, ddb_action_context_t ctx) {
deadbeef->sendmessage (DB_EV_PLAY_RANDOM_ALBUM, 0, 0, 0);
return 0;
}

int
action_play_next_album_cb (struct DB_plugin_action_s *action, ddb_action_context_t ctx) {
deadbeef->sendmessage (DB_EV_PLAY_NEXT_ALBUM, 0, 0, 0);
return 0;
}

int
action_play_prev_album_cb (struct DB_plugin_action_s *action, ddb_action_context_t ctx) {
deadbeef->sendmessage (DB_EV_PLAY_PREV_ALBUM, 0, 0, 0);
return 0;
}

int
action_seek_5p_forward_cb (struct DB_plugin_action_s *action, ddb_action_context_t ctx) {
DB_playItem_t *it = deadbeef->streamer_get_playing_track_safe ();
Expand Down Expand Up @@ -1189,12 +1207,36 @@ static DB_plugin_action_t action_play_pause = {
.next = &action_toggle_pause
};

static DB_plugin_action_t action_play_next_album = {
.title = "Playback/Play Next Album",
.name = "playback_next_album",
.flags = DB_ACTION_COMMON,
.callback2 = action_play_next_album_cb,
.next = &action_play_pause
};

static DB_plugin_action_t action_play_prev_album = {
.title = "Playback/Play Previous Album",
.name = "playback_prev_album",
.flags = DB_ACTION_COMMON,
.callback2 = action_play_prev_album_cb,
.next = &action_play_next_album
};

static DB_plugin_action_t action_play_random_album = {
.title = "Playback/Play Random Album",
.name = "playback_random_album",
.flags = DB_ACTION_COMMON,
.callback2 = action_play_random_album_cb,
.next = &action_play_prev_album
};

static DB_plugin_action_t action_play_random = {
.title = "Playback/Play Random",
.name = "playback_random",
.flags = DB_ACTION_COMMON,
.callback2 = action_play_random_cb,
.next = &action_play_pause
.next = &action_play_random_album
};

static DB_plugin_action_t action_seek_1s_forward = {
Expand Down
9 changes: 9 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,12 @@ player_mainloop (void) {
case DB_EV_PREV:
streamer_move_to_prevsong (1);
break;
case DB_EV_PLAY_NEXT_ALBUM:
streamer_move_to_nextalbum (1);
break;
case DB_EV_PLAY_PREV_ALBUM:
streamer_move_to_prevalbum (1);
break;
case DB_EV_PAUSE:
if (output->state () != DDB_PLAYBACK_STATE_PAUSED) {
output->pause ();
Expand All @@ -889,6 +895,9 @@ player_mainloop (void) {
case DB_EV_PLAY_RANDOM:
streamer_move_to_randomsong (1);
break;
case DB_EV_PLAY_RANDOM_ALBUM:
streamer_move_to_randomalbum (1);
break;
case DB_EV_CONFIGCHANGED:
conf_save ();
streamer_configchanged ();
Expand Down
61 changes: 28 additions & 33 deletions src/playlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,24 +1679,7 @@ plt_insert_item (playlist_t *playlist, playItem_t *after, playItem_t *it) {

// shuffle
playItem_t *prev = it->prev[PL_MAIN];
const char *aa = NULL, *prev_aa = NULL;
if (prev) {
aa = pl_find_meta_raw (it, "band");
if (!aa) {
aa = pl_find_meta_raw (it, "album artist");
}
if (!aa) {
aa = pl_find_meta_raw (it, "albumartist");
}
prev_aa = pl_find_meta_raw (prev, "band");
if (!prev_aa) {
prev_aa = pl_find_meta_raw (prev, "album artist");
}
if (!prev_aa) {
prev_aa = pl_find_meta_raw (prev, "albumartist");
}
}
if (streamer_get_shuffle () == DDB_SHUFFLE_ALBUMS && prev && pl_find_meta_raw (prev, "album") == pl_find_meta_raw (it, "album") && ((aa && prev_aa && aa == prev_aa) || pl_find_meta_raw (prev, "artist") == pl_find_meta_raw (it, "artist"))) {
if (streamer_get_shuffle () == DDB_SHUFFLE_ALBUMS && prev && pl_items_from_same_album(prev, it)) {
it->shufflerating = prev->shufflerating;
}
else {
Expand Down Expand Up @@ -2610,27 +2593,13 @@ plt_reshuffle (playlist_t *playlist, playItem_t **ppmin, playItem_t **ppmax) {
playItem_t *pmin = NULL;
playItem_t *pmax = NULL;
playItem_t *prev = NULL;
const char *alb = NULL;
const char *art = NULL;
const char *aa = NULL;
for (playItem_t *it = playlist->head[PL_MAIN]; it; it = it->next[PL_MAIN]) {
const char *new_aa = NULL;
new_aa = pl_find_meta_raw (it, "band");
if (!new_aa) {
new_aa = pl_find_meta_raw (it, "album artist");
}
if (!new_aa) {
new_aa = pl_find_meta_raw (it, "albumartist");
}
if (streamer_get_shuffle () == DDB_SHUFFLE_ALBUMS && prev && alb == pl_find_meta_raw (it, "album") && ((aa && new_aa && aa == new_aa) || art == pl_find_meta_raw (it, "artist"))) {
if (streamer_get_shuffle () == DDB_SHUFFLE_ALBUMS && prev && pl_items_from_same_album(it, prev)) {
it->shufflerating = prev->shufflerating;
}
else {
prev = it;
it->shufflerating = rand ();
alb = pl_find_meta_raw (it, "album");
art = pl_find_meta_raw (it, "artist");
aa = new_aa;
}
if (!pmin || it->shufflerating < pmin->shufflerating) {
pmin = it;
Expand Down Expand Up @@ -4170,3 +4139,29 @@ pl_set_shufflerating (playItem_t *it, int rating) {
it->shufflerating = rating;
pl_unlock();
}

int
pl_items_from_same_album (playItem_t* a, playItem_t* b){
const char *keys[] = {
"band",
"album artist",
"albumartist",
"artist",
NULL
};

const char *a_artist = NULL;
const char *b_artist = NULL;
for (int i = 0; keys[i]; i++) {
if (!a_artist) {
a_artist = pl_find_meta_raw (a, keys[i]);
}
if (!b_artist) {
b_artist = pl_find_meta_raw (b, keys[i]);
}
if (a_artist && b_artist) {
break;
}
}
return pl_find_meta_raw(a, "album") == pl_find_meta_raw (b, "album") && a_artist == b_artist;
}
3 changes: 3 additions & 0 deletions src/playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,9 @@ pl_get_shufflerating (playItem_t *it);
void
pl_set_shufflerating (playItem_t *it, int rating);

int
pl_items_from_same_album(playItem_t* a, playItem_t* b);

#ifdef __cplusplus
}
#endif
Expand Down
Loading