diff --git a/htdocs/index.html b/htdocs/index.html
index f608b53..b662f05 100644
--- a/htdocs/index.html
+++ b/htdocs/index.html
@@ -743,16 +743,30 @@
-
+
Notifications
diff --git a/htdocs/js/mympd.js b/htdocs/js/mympd.js
index a8edbd0..9e5889d 100644
--- a/htdocs/js/mympd.js
+++ b/htdocs/js/mympd.js
@@ -808,7 +808,6 @@ function parseSettings(obj) {
toggleBtn('btnConsume', obj.data.consume);
toggleBtn('btnSingle', obj.data.single);
toggleBtn('btnRepeat', obj.data.repeat);
- toggleBtn('btnJukebox', obj.data.jukeboxMode);
if (obj.data.crossfade != undefined) {
document.getElementById('inputCrossfade').removeAttribute('disabled');
@@ -859,26 +858,26 @@ function parseSettings(obj) {
var stickerEls = document.getElementsByClassName('stickers');
var stickerElsLen = stickerEls.length;
var displayStickers = obj.data.stickers == true ? '' : 'none';
- for (var i = 0; i < stickerElsLen; i++) {
+ for (var i = 0; i < stickerElsLen; i++)
stickerEls[i].style.display = displayStickers;
- }
var smartplsEls = document.getElementsByClassName('smartpls');
var smartplsElsLen = smartplsEls.length;
var displaySmartpls = obj.data.smartpls == true ? '' : 'none';
- for (var i = 0; i < smartplsElsLen; i++) {
+ for (var i = 0; i < smartplsElsLen; i++)
smartplsEls[i].style.display = displaySmartpls;
- }
- if (obj.data.mixramp == true) {
+ if (obj.data.mixramp == true)
document.getElementsByClassName('mixramp')[0].style.display = '';
- } else {
+ else
document.getElementsByClassName('mixramp')[0].style.display = 'none';
- }
+
+ document.getElementById('selectJukeboxMode').value = obj.data.jukeboxMode;
+ document.getElementById('inputJukeboxQueueLength').value = obj.data.jukeboxQueueLength;
settings = obj.data;
- playlistEl = 'jukeboxPlaylist';
+ playlistEl = 'selectJukeboxPlaylist';
sendAPI({"cmd": "MPD_API_PLAYLIST_LIST", "data": {"offset": 0, "filter": "-"}}, getAllPlaylists);
settings.mpdstream = 'http://';
@@ -1544,12 +1543,12 @@ function getAllPlaylists(obj) {
if (obj.offset == 0) {
if (playlistEl == 'addToPlaylistPlaylist')
playlists = '';
- else if (playlistEl == 'jukeboxPlaylist')
+ else if (playlistEl == 'selectJukeboxPlaylist')
playlists = '';
}
for (var i = 0; i < nrItems; i++) {
playlists += '';
}
@@ -1831,7 +1830,8 @@ function showMenu(el, event) {
addMenuItem({"cmd": "replaceQueue", "options": [type, uri, name]}, 'Replace queue') +
(x.getAttribute('data-ro') == 'false' ? addMenuItem({"cmd": "removeFromPlaylist", "options": [x.getAttribute('data-uri'),
el.parentNode.parentNode.getAttribute('data-songpos')]}, 'Remove') : '') +
- addMenuItem({"cmd": "showAddToPlaylist", "options": [uri]}, 'Add to playlist');
+ addMenuItem({"cmd": "showAddToPlaylist", "options": [uri]}, 'Add to playlist') +
+ (uri.indexOf('http') == -1 ? addMenuItem({"cmd": "songDetails", "options": [uri]}, 'Songdetails') : '');
}
else if (app.current.app == 'Queue') {
menu += addMenuItem({"cmd": "delQueueSong", "options": ["single", el.parentNode.parentNode.getAttribute('data-trackid')]}, 'Remove') +
@@ -1999,6 +1999,20 @@ function confirmSettings() {
formOK = false;
}
}
+ var inputJukeboxQueueLength = document.getElementById('inputJukeboxQueueLength');
+ var value = parseInt(inputJukeboxQueueLength.value);
+ if (!isNaN(value)) {
+ if (value > 0) {
+ inputJukeboxQueueLength.value = value;
+ } else {
+ inputJukeboxQueueLength.classList.add('is-invalid');
+ formOK = false;
+ }
+ }
+ else {
+ inputJukeboxQueueLength.classList.add('is-invalid');
+ formOK = false;
+ }
if (settings.mixramp) {
var inputMixrampdb = document.getElementById('inputMixrampdb');
if (!inputMixrampdb.getAttribute('disabled')) {
@@ -2026,7 +2040,8 @@ function confirmSettings() {
if (formOK == true) {
var selectReplaygain = document.getElementById('selectReplaygain');
- var selectJukeboxPlaylist = document.getElementById('jukeboxPlaylist');
+ var selectJukeboxPlaylist = document.getElementById('selectJukeboxPlaylist');
+ var selectJukeboxMode = document.getElementById('selectJukeboxMode');
sendAPI({"cmd": "MPD_API_SETTINGS_SET", "data": {
"consume": (document.getElementById('btnConsume').classList.contains('active') ? 1 : 0),
"random": (document.getElementById('btnRandom').classList.contains('active') ? 1 : 0),
@@ -2038,8 +2053,9 @@ function confirmSettings() {
"mixrampdelay": (settings.mixramp == true ? document.getElementById('inputMixrampdelay').value : settings.mixrampdelay),
"notificationWeb": (document.getElementById('btnnotifyWeb').classList.contains('active') ? true : false),
"notificationPage": (document.getElementById('btnnotifyPage').classList.contains('active') ? true : false),
- "jukeboxMode": (document.getElementById('btnJukebox').classList.contains('active') ? true : false),
- "jukeboxPlaylist": selectJukeboxPlaylist.options[selectJukeboxPlaylist.selectedIndex].value
+ "jukeboxMode": selectJukeboxMode.options[selectJukeboxMode.selectedIndex].value,
+ "jukeboxPlaylist": selectJukeboxPlaylist.options[selectJukeboxPlaylist.selectedIndex].value,
+ "jukeboxQueueLength": document.getElementById('inputJukeboxQueueLength').value
}}, getSettings);
modalSettings.hide();
} else
diff --git a/src/mpd_client.c b/src/mpd_client.c
index cbf5bc9..139c36b 100644
--- a/src/mpd_client.c
+++ b/src/mpd_client.c
@@ -112,23 +112,25 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) {
n = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length);
break;
case MPD_API_SETTINGS_SET:
- je = json_scanf(msg.p, msg.len, "{data: {notificationWeb: %B, notificationPage: %B, jukeboxMode: %B, jukeboxPlaylist: %Q}}",
+ je = json_scanf(msg.p, msg.len, "{data: {notificationWeb: %B, notificationPage: %B, jukeboxMode: %d, jukeboxPlaylist: %Q, jukeboxQueueLength: %d}}",
&mympd_state.notificationWeb,
&mympd_state.notificationPage,
&mympd_state.jukeboxMode,
- &mympd_state.jukeboxPlaylist);
- if (je == 4) {
+ &mympd_state.jukeboxPlaylist,
+ &mympd_state.jukeboxQueueLength);
+ if (je == 5) {
char tmpfile[400];
char statefile[400];
snprintf(tmpfile, 400, "%s/tmp/mympd.state", config.varlibdir );
snprintf(statefile, 400, "%s/mympd.state", config.varlibdir );
- json_fprintf(tmpfile, "{notificationWeb: %B, notificationPage: %B, jukeboxMode: %B, jukeboxPlaylist: %Q}",
+ json_fprintf(tmpfile, "{notificationWeb: %B, notificationPage: %B, jukeboxMode: %d, jukeboxPlaylist: %Q, jukeboxQueueLength: %d}",
mympd_state.notificationWeb,
mympd_state.notificationPage,
mympd_state.jukeboxMode,
- mympd_state.jukeboxPlaylist);
+ mympd_state.jukeboxPlaylist,
+ mympd_state.jukeboxQueueLength);
rename(tmpfile, statefile);
- if (mympd_state.jukeboxMode == true)
+ if (mympd_state.jukeboxMode > 0)
mympd_jukebox();
}
@@ -597,7 +599,7 @@ void mympd_parse_idle(struct mg_mgr *s, int idle_bitmask) {
break;
case MPD_IDLE_QUEUE:
len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_queue\"}");
- if (mympd_state.jukeboxMode == true)
+ if (mympd_state.jukeboxMode > 0)
mympd_jukebox();
break;
case MPD_IDLE_PLAYER:
@@ -783,8 +785,8 @@ void mympd_idle(struct mg_mgr *s, int timeout) {
mpd.conn_state = MPD_CONNECTED;
mympd_mpd_features();
mympd_smartpls_update_all();
- if (mympd_state.jukeboxMode == true)
- mympd_jukebox();
+ if (mympd_state.jukeboxMode > 0)
+ mympd_jukebox();
mpd_send_idle(mpd.conn);
break;
@@ -976,9 +978,11 @@ char* mympd_get_tag(struct mpd_song const *song, enum mpd_tag_type tag) {
void mympd_jukebox() {
struct mpd_status *status;
status = mpd_run_status(mpd.conn);
- int queue_length, num_songs, rand_song, i;
+ int queue_length, num_songs, rand_song, i, j, addSongs;
struct mpd_entity *entity;
const struct mpd_song *song;
+ struct mpd_pair *pair;
+ char *album;
if (!status) {
printf("MPD mpd_run_status: %s\n", mpd_connection_get_error_message(mpd.conn));
@@ -987,66 +991,86 @@ void mympd_jukebox() {
}
queue_length = mpd_status_get_queue_length(status);
mpd_status_free(status);
- if (queue_length > 0)
+ if (queue_length > mympd_state.jukeboxQueueLength)
return;
srand((unsigned int)time(NULL));
-
- if (strcmp(mympd_state.jukeboxPlaylist, "Database") == 0) {
- struct mpd_stats *stats = mpd_run_stats(mpd.conn);
- num_songs = mpd_stats_get_number_of_songs(stats);
- mpd_stats_free(stats);
+
+ if (mympd_state.jukeboxMode == 2) {
+ //Add whole album
+ mpd_search_db_tags(mpd.conn, MPD_TAG_ALBUM);
+ mpd_search_commit(mpd.conn);
+ num_songs = 0;
+ while ((pair = mpd_recv_pair_tag(mpd.conn, MPD_TAG_ALBUM)) != NULL) {
+ num_songs++;
+ mpd_return_pair(mpd.conn, pair);
+ }
+ mpd_response_finish(mpd.conn);
num_songs--;
if (num_songs > 0) {
rand_song = rand() % num_songs;
- mpd_send_list_all(mpd.conn, "/");
+ mpd_search_db_tags(mpd.conn, MPD_TAG_ALBUM);
+ mpd_search_commit(mpd.conn);
i = 0;
+ while ((pair = mpd_recv_pair_tag(mpd.conn, MPD_TAG_ALBUM )) != NULL) {
+ if (i == rand_song) {
+ album = strdup(pair->value);
+ break;
+ }
+ i++;
+ mpd_return_pair(mpd.conn, pair);
+ }
+ mpd_return_pair(mpd.conn, pair);
+ mpd_response_finish(mpd.conn);
+ printf("Jukebox enabled, adding random album %s: %d/%d\n", album, rand_song, num_songs);
+ mpd_send_command(mpd.conn, "searchadd", "Album", album, NULL);
+ mpd_response_finish(mpd.conn);
+ }
+ }
+ else if (mympd_state.jukeboxMode == 1) {
+ //Add tracks
+ if (strcmp(mympd_state.jukeboxPlaylist, "Database") == 0) {
+ struct mpd_stats *stats = mpd_run_stats(mpd.conn);
+ num_songs = mpd_stats_get_number_of_songs(stats);
+ mpd_stats_free(stats);
+ }
+ else {
+ mpd_send_list_playlist(mpd.conn, mympd_state.jukeboxPlaylist);
+ num_songs = 0;
while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
- if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
- if (i == rand_song)
- break;
- i++;
+ num_songs++;
+ mpd_entity_free(entity);
+ }
+ }
+ num_songs--;
+ addSongs = mympd_state.jukeboxQueueLength - queue_length;
+ if (num_songs > 0) {
+ for (j = 0; j < addSongs; j++) {
+ rand_song = rand() % num_songs;
+ if (strcmp(mympd_state.jukeboxPlaylist, "Database") == 0)
+ mpd_send_list_all(mpd.conn, "/");
+ else
+ mpd_send_list_playlist(mpd.conn, mympd_state.jukeboxPlaylist);
+ i = 0;
+ while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
+ if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
+ if (i == rand_song)
+ break;
+ i++;
+ }
+ mpd_entity_free(entity);
+ }
+ mpd_response_finish(mpd.conn);
+ song = mpd_entity_get_song(entity);
+ if (song != NULL) {
+ printf("Jukebox enabled, adding random song: %d/%d\n", rand_song, num_songs);
+ mpd_run_add(mpd.conn, mpd_song_get_uri(song));
}
mpd_entity_free(entity);
}
- mpd_response_finish(mpd.conn);
- song = mpd_entity_get_song(entity);
- if (song != NULL) {
- printf("Jukebox enabled, playing random song from database: %d/%d\n", rand_song, num_songs);
- mpd_run_add(mpd.conn, mpd_song_get_uri(song));
- mpd_run_play(mpd.conn);
- }
- mpd_entity_free(entity);
- }
- }
- else {
- mpd_send_list_playlist(mpd.conn, mympd_state.jukeboxPlaylist);
- num_songs = 0;
- while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
- num_songs++;
- mpd_entity_free(entity);
- }
- num_songs--;
- if (num_songs > 0) {
- rand_song = rand() % num_songs;
- mpd_send_list_playlist(mpd.conn, mympd_state.jukeboxPlaylist);
- i = 0;
- while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
- if (i == rand_song)
- break;
- i++;
- mpd_entity_free(entity);
- }
- mpd_response_finish(mpd.conn);
- song = mpd_entity_get_song(entity);
- if (song != NULL) {
- printf("Jukebox enabled, playing random song from %s: %d/%d\n", mympd_state.jukeboxPlaylist, rand_song, num_songs);
- mpd_run_add(mpd.conn, mpd_song_get_uri(song));
- mpd_run_play(mpd.conn);
- }
- mpd_entity_free(entity);
}
}
+ mpd_run_play(mpd.conn);
}
int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length) {
@@ -1138,7 +1162,7 @@ int mympd_put_settings(char *buffer) {
"repeat: %d, single: %d, crossfade: %d, consume: %d, random: %d, "
"mixrampdb: %f, mixrampdelay: %f, mpdhost: %Q, mpdport: %d, passwort_set: %B, "
"streamport: %d, coverimage: %Q, stickers: %B, mixramp: %B, smartpls: %B, maxElementsPerPage: %d, "
- "replaygain: %Q, notificationWeb: %B, notificationPage: %B, jukeboxMode: %B, jukeboxPlaylist: %Q, "
+ "replaygain: %Q, notificationWeb: %B, notificationPage: %B, jukeboxMode: %d, jukeboxPlaylist: %Q, jukeboxQueueLength: %d, "
"tags: { Artist: %B, Album: %B, AlbumArtist: %B, Title: %B, Track: %B, Genre: %B, Date: %B,"
"Composer: %B, Performer: %B }"
"}}",
@@ -1163,6 +1187,7 @@ int mympd_put_settings(char *buffer) {
mympd_state.notificationPage,
mympd_state.jukeboxMode,
mympd_state.jukeboxPlaylist,
+ mympd_state.jukeboxQueueLength,
mpd.tag_artist,
mpd.tag_album,
mpd.tag_album_artist,
diff --git a/src/mpd_client.h b/src/mpd_client.h
index 2028baa..fcd816f 100644
--- a/src/mpd_client.h
+++ b/src/mpd_client.h
@@ -178,8 +178,9 @@ typedef struct {
typedef struct {
bool notificationWeb;
bool notificationPage;
- bool jukeboxMode;
+ int jukeboxMode;
const char* jukeboxPlaylist;
+ int jukeboxQueueLength;
} t_mympd_state;
t_mympd_state mympd_state;
diff --git a/src/mympd.c b/src/mympd.c
index c9de0ae..efe39cc 100644
--- a/src/mympd.c
+++ b/src/mympd.c
@@ -244,22 +244,25 @@ int main(int argc, char **argv) {
snprintf(statefile, 400, "%s/mympd.state", config.varlibdir);
if (access(statefile, F_OK ) != -1 ) {
char *content = json_fread(statefile);
- int je = json_scanf(content, strlen(content), "{notificationWeb: %B, notificationPage: %B, jukeboxMode: %B, jukeboxPlaylist: %Q}",
+ int je = json_scanf(content, strlen(content), "{notificationWeb: %B, notificationPage: %B, jukeboxMode: %d, jukeboxPlaylist: %Q, jukeboxQueueLength: %d}",
&mympd_state.notificationWeb,
&mympd_state.notificationPage,
&mympd_state.jukeboxMode,
- &mympd_state.jukeboxPlaylist);
- if (je != 4) {
+ &mympd_state.jukeboxPlaylist,
+ &mympd_state.jukeboxQueueLength);
+ if (je != 5) {
mympd_state.notificationWeb = false;
mympd_state.notificationPage = true;
- mympd_state.jukeboxMode = false;
+ mympd_state.jukeboxMode = 0;
mympd_state.jukeboxPlaylist = "Database";
+ mympd_state.jukeboxQueueLength = 1;
}
} else {
mympd_state.notificationWeb = false;
mympd_state.notificationPage = true;
- mympd_state.jukeboxMode = false;
+ mympd_state.jukeboxMode = 0;
mympd_state.jukeboxPlaylist = "Database";
+ mympd_state.jukeboxQueueLength = 1;
}
signal(SIGTERM, signal_handler);