From f2489601c1000320413987f729b53f429cf53cd5 Mon Sep 17 00:00:00 2001 From: jcorporation Date: Mon, 10 Sep 2018 22:32:15 +0200 Subject: [PATCH] Feat: browse and search database by more tags #43 #36 --- htdocs/index.html | 54 ++++++++++------ htdocs/js/mympd.js | 154 +++++++++++++++++++++++++++------------------ src/mpd_client.c | 48 +++++++------- src/mpd_client.h | 8 +-- src/mympd.c | 2 + 5 files changed, 161 insertions(+), 105 deletions(-) diff --git a/htdocs/index.html b/htdocs/index.html index 470cc6f..5809b80 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -120,8 +120,8 @@ @@ -135,12 +135,15 @@ @@ -296,8 +299,20 @@
+
+ + +
- +
@@ -316,7 +331,7 @@
- +
@@ -363,8 +378,8 @@ @@ -440,12 +455,15 @@ diff --git a/htdocs/js/mympd.js b/htdocs/js/mympd.js index c69a4bb..b822908 100644 --- a/htdocs/js/mympd.js +++ b/htdocs/js/mympd.js @@ -47,9 +47,14 @@ app.apps = { "Playback": { "state": "0/-/", "scrollPos": 0 }, } }, "Database": { - "active": "Artist", - "views": { "Artist": { "state": "0/-/", "scrollPos": 0 }, - "Album": { "state": "0/-/", "scrollPos": 0 } + "active": "AlbumArtist", + "views": { "AlbumArtist": { "state": "0/-/", "scrollPos": 0 }, + "Genre": { "state": "0/-/", "scrollPos": 0 }, + "Artist": { "state": "0/-/", "scrollPos": 0 }, + "Composer": { "state": "0/-/", "scrollPos": 0 }, + "Performer": { "state": "0/-/", "scrollPos": 0 }, + "Date": { "state": "0/-/", "scrollPos": 0 }, + "Album": { "state": "0/-/", "scrollPos": 0 }, } } } @@ -212,13 +217,25 @@ function appRoute() { sendAPI({"cmd": "MPD_API_PLAYLIST_CONTENT_LIST", "data": {"offset": app.current.page, "filter": app.current.filter, "uri": app.current.search}}, parsePlaylists); doSetFilterLetter('BrowsePlaylistsFilter'); } - else if (app.current.app == 'Browse' && app.current.tab == 'Database' && app.current.view == 'Artist') { - sendAPI({"cmd": "MPD_API_DATABASE_ARTIST_LIST","data": {"offset": app.current.page, "filter": app.current.filter}}, parseListDBtags); - doSetFilterLetter('BrowseDatabaseFilter'); - } - else if (app.current.app == 'Browse' && app.current.tab == 'Database' && app.current.view == 'Album') { - sendAPI({"cmd": "MPD_API_DATABASE_ARTISTALBUM_LIST", "data": {"offset": app.current.page, "filter": app.current.filter, "albumartist": app.current.search}}, parseListDBtags); - doSetFilterLetter('BrowseDatabaseFilter'); + + else if (app.current.app == 'Browse' && app.current.tab == 'Database') { + if (app.current.search != '') { + sendAPI({"cmd": "MPD_API_DATABASE_TAG_ALBUM_LIST", "data": {"offset": app.current.page, "filter": app.current.filter, "search": app.current.search, "tag": app.current.view}}, parseListDBtags); + doSetFilterLetter('BrowseDatabaseFilter'); + } + else { + sendAPI({"cmd": "MPD_API_DATABASE_TAG_LIST","data": {"offset": app.current.page, "filter": app.current.filter, "tag": app.current.view}}, parseListDBtags); + doSetFilterLetter('BrowseDatabaseFilter'); + var btns = document.getElementById('BrowseDatabaseByTagDropdown').getElementsByTagName('button'); + var btnsLen = btns.length; + for (var i = 0; i < btnsLen; i++) { + btns[i].classList.remove('active'); + if (btns[i].getAttribute('data-tag') == app.current.view) { + btns[i].classList.add('active'); + document.getElementById('btnBrowseDatabaseByTag').innerText = btns[i].innerText; + } + } + } } else if (app.current.app == 'Browse' && app.current.tab == 'Filesystem') { sendAPI({"cmd": "MPD_API_DATABASE_FILESYSTEM_LIST", "data": {"offset": app.current.page, "path": (app.current.search ? app.current.search : "/"), "filter": app.current.filter}}, parseFilesystem); @@ -442,9 +459,9 @@ function appInit() { } }, false); - document.getElementById('BrowseDatabaseArtistList').addEventListener('click', function(event) { + document.getElementById('BrowseDatabaseTagList').addEventListener('click', function(event) { if (event.target.nodeName == 'TD') { - appGoto('Browse', 'Database', 'Album', '0/-/' + event.target.parentNode.getAttribute('data-uri')); + appGoto('Browse', 'Database', app.current.view, '0/-/' + event.target.parentNode.getAttribute('data-uri')); } }, false); @@ -505,6 +522,10 @@ function appInit() { appGoto('Search', undefined, undefined, '0/' + app.current.filter + '/' + this.value); }, false); + document.getElementById('BrowseDatabaseByTagDropdown').addEventListener('click', function(event) { + if (event.target.nodeName == 'BUTTON') + appGoto(app.current.app, app.current.tab, event.target.getAttribute('data-tag') , '0/' + app.current.filter + '/' + app.current.search); + }, false); document.getElementsByTagName('body')[0].addEventListener('click', function(event) { var oldPopover = document.getElementsByClassName('popover')[0]; @@ -1212,14 +1233,60 @@ function parsePlaylists(obj) { } function parseListDBtags(obj) { - if (app.current.app !== 'Browse' && app.current.tab !== 'Database' && app.current.view !== 'Artist') return; - - if (obj.tagtype == 'AlbumArtist') { - document.getElementById('BrowseDatabaseAlbumList').classList.add('hide'); - document.getElementById('BrowseDatabaseArtistList').classList.remove('hide'); - document.getElementById('btnBrowseDatabaseArtist').parentNode.classList.add('hide'); +// if (app.current.app !== 'Browse' && app.current.tab !== 'Database' && app.current.view !== 'AlbumArtist') +// return; + if (app.current.search != '') { + document.getElementById('BrowseDatabaseAlbumList').classList.remove('hide'); + document.getElementById('BrowseDatabaseTagList').classList.add('hide'); + document.getElementById('btnBrowseDatabaseByTag').parentNode.classList.add('hide'); + document.getElementById('btnBrowseDatabaseTag').parentNode.classList.remove('hide'); + document.getElementById('btnBrowseDatabaseTag').innerHTML = '« ' + app.current.view; var nrItems = obj.data.length; - var tbody = document.getElementById(app.current.app + app.current.tab + app.current.view + 'List').getElementsByTagName('tbody')[0]; + if (nrItems == 1 && obj.data[0].value == '') + nrItems = 0; + var cardContainer = document.getElementById('BrowseDatabaseAlbumList'); + var cards = cardContainer.getElementsByClassName('col-md'); + for (var i = 0; i < nrItems; i++) { + var id=genId(obj.data[i].value); + if (cards[i]) + if (cards[i].getAttribute('id') == id) + continue; + var card=document.createElement('div'); + card.classList.add('col-md'); + card.classList.add('mr-0'); + card.setAttribute('id', id); + card.innerHTML = '
' + + ' ' + + '
' + + '
' + obj.searchstr + '
' + + '

' + obj.data[i].value + '

' + + '
'+ + ''; + + if (i < cards.length) + cards[i].replaceWith(card); + else + cardContainer.append(card); + + sendAPI({"cmd": "MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST", "data": { "album": obj.data[i].value, "search": app.current.search, "tag": app.current.view}}, parseListTitles); + } + var cardsLen = cards.length - 1; + for (var i = cardsLen; i >= nrItems; i --) { + cards[i].remove(); + } + setPagination(obj.totalEntities); + document.getElementById('BrowseDatabaseAlbumList').classList.remove('opacity05'); + } + else { + document.getElementById('BrowseDatabaseAlbumList').classList.add('hide'); + document.getElementById('BrowseDatabaseTagList').classList.remove('hide'); + document.getElementById('btnBrowseDatabaseByTag').parentNode.classList.remove('hide'); + document.getElementById('btnBrowseDatabaseTag').parentNode.classList.add('hide'); + var nrItems = obj.data.length; + if (nrItems == 1 && obj.data[0].value == '') + nrItems = 0; + var tbody = document.getElementById(app.current.app + app.current.tab + 'TagList').getElementsByTagName('tbody')[0]; var tr = tbody.getElementsByTagName('tr'); for (var i = 0; i < nrItems; i++) { var uri = encodeURI(obj.data[i].value); @@ -1247,52 +1314,13 @@ function parseListDBtags(obj) { if (nrItems == 0) tbody.innerHTML = '' + ''; - document.getElementById('BrowseDatabaseArtistList').classList.remove('opacity05'); - - } else if (obj.tagtype == 'Album') { - document.getElementById('BrowseDatabaseAlbumList').classList.remove('hide'); - document.getElementById('BrowseDatabaseArtistList').classList.add('hide'); - document.getElementById('btnBrowseDatabaseArtist').parentNode.classList.remove('hide'); - var nrItems = obj.data.length; - var cardContainer = document.getElementById('BrowseDatabaseAlbumList'); - var cards = cardContainer.getElementsByClassName('col-md'); - for (var i = 0; i < nrItems; i++) { - var id=genId(obj.data[i].value); - if (cards[i]) - if (cards[i].getAttribute('id') == id) - continue; - var card=document.createElement('div'); - card.classList.add('col-md'); - card.classList.add('mr-0'); - card.setAttribute('id', id); - card.innerHTML = '
' + - ' ' + - '
' + - '
' + obj.searchstr + '
' + - '

' + obj.data[i].value + '

' + - '
error_outlineNo entries found.
'+ - ''; - - if (i < cards.length) - cards[i].replaceWith(card); - else - cardContainer.append(card); - - sendAPI({"cmd": "MPD_API_DATABASE_ARTISTALBUMTITLE_LIST", "data": { "albumartist": obj.searchstr, "album": obj.data[i].value}}, parseListTitles); - } - var cardsLen = cards.length - 1; - for (var i = cardsLen; i >= nrItems; i --) { - cards[i].remove(); - } - setPagination(obj.totalEntities); - document.getElementById('BrowseDatabaseAlbumList').classList.remove('opacity05'); + document.getElementById('BrowseDatabaseTagList').classList.remove('opacity05'); } } function parseListTitles(obj) { - if (app.current.app !== 'Browse' && app.current.tab !== 'Database' && app.current.view !== 'Album') - return; +// if (app.current.app !== 'Browse' && app.current.tab !== 'Database' && app.current.view !== 'Album') +// return; var id = genId(obj.album); var card = document.getElementById('card' + id) @@ -2114,6 +2142,10 @@ function addFilterLetter(x) { }, false); } +function gotoTagList() { + appGoto(app.current.app, app.current.tab, app.current.view, '0/-/'); +} + function chVolume(increment) { var newValue = parseInt(domCache.volumeBar.value) + increment; if (newValue < 0) diff --git a/src/mpd_client.c b/src/mpd_client.c index afcf8d0..100d5be 100644 --- a/src/mpd_client.c +++ b/src/mpd_client.c @@ -162,14 +162,6 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { } n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); break; - case MPD_API_DATABASE_ARTISTALBUMTITLE_LIST: - je = json_scanf(msg.p, msg.len, "{data: {albumartist: %Q, album: %Q}}", &p_charbuf1, &p_charbuf2); - if (je == 2) { - n = mympd_put_songs_in_album(mpd.buf, p_charbuf1, p_charbuf2); - free(p_charbuf1); - free(p_charbuf2); - } - break; case MPD_API_WELCOME: n = mympd_put_welcome(mpd.buf); break; @@ -295,21 +287,32 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { free(p_charbuf1); } break; - case MPD_API_DATABASE_ARTIST_LIST: - je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q}}", &uint_buf1, &p_charbuf1); - if (je == 2) { - n = mympd_put_db_tag(mpd.buf, uint_buf1, "AlbumArtist", "", "", p_charbuf1); - free(p_charbuf1); - } - break; - case MPD_API_DATABASE_ARTISTALBUM_LIST: - je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q, albumartist: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); + case MPD_API_DATABASE_TAG_LIST: + je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q, tag: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); if (je == 3) { - n = mympd_put_db_tag(mpd.buf, uint_buf1, "Album", "AlbumArtist", p_charbuf2, p_charbuf1); + n = mympd_put_db_tag(mpd.buf, uint_buf1, p_charbuf2, "", "", p_charbuf1); free(p_charbuf1); free(p_charbuf2); } break; + case MPD_API_DATABASE_TAG_ALBUM_LIST: + je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q, search: %Q, tag: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2, &p_charbuf3); + if (je == 4) { + n = mympd_put_db_tag(mpd.buf, uint_buf1, "Album", p_charbuf3, p_charbuf2, p_charbuf1); + free(p_charbuf1); + free(p_charbuf2); + free(p_charbuf3); + } + break; + case MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST: + je = json_scanf(msg.p, msg.len, "{data: {album: %Q, search: %Q, tag: %Q}}", &p_charbuf1, &p_charbuf2, &p_charbuf3); + if (je == 3) { + n = mympd_put_songs_in_album(mpd.buf, p_charbuf1, p_charbuf2, p_charbuf3); + free(p_charbuf1); + free(p_charbuf2); + free(p_charbuf3); + } + break; case MPD_API_PLAYLIST_RENAME: je = json_scanf(msg.p, msg.len, "{data: {from: %Q, to: %Q}}", &p_charbuf1, &p_charbuf2); if (je == 2) { @@ -1410,7 +1413,7 @@ int mympd_put_db_tag(char *buffer, unsigned int offset, char *mpdtagtype, char * return len; } -int mympd_put_songs_in_album(char *buffer, char *albumartist, char *album) { +int mympd_put_songs_in_album(char *buffer, char *album, char *search, char *tag) { struct mpd_song *song; unsigned long entity_count = 0; unsigned long entities_returned = 0; @@ -1421,7 +1424,7 @@ int mympd_put_songs_in_album(char *buffer, char *albumartist, char *album) { if (mpd_search_db_songs(mpd.conn, true) == false) RETURN_ERROR_AND_RECOVER("mpd_search_db_songs"); - if (mpd_search_add_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM_ARTIST, albumartist) == false) + if (mpd_search_add_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, mpd_tag_name_parse(tag), search) == false) RETURN_ERROR_AND_RECOVER("mpd_search_add_tag_constraint"); if (mpd_search_add_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM, album) == false) @@ -1450,11 +1453,12 @@ int mympd_put_songs_in_album(char *buffer, char *albumartist, char *album) { mpd_song_free(song); } - len += json_printf(&out, "], totalEntities: %d, returnedEntities: %d, albumartist: %Q, album: %Q, cover: %Q}", + len += json_printf(&out, "], totalEntities: %d, returnedEntities: %d, album: %Q, search: %Q, tag: %Q, cover: %Q}", entity_count, entities_returned, - albumartist, album, + search, + tag, cover ); } diff --git a/src/mpd_client.h b/src/mpd_client.h index c1adf3f..d39cc27 100644 --- a/src/mpd_client.h +++ b/src/mpd_client.h @@ -75,9 +75,9 @@ X(MPD_API_DATABASE_SEARCH) \ X(MPD_API_DATABASE_UPDATE) \ X(MPD_API_DATABASE_FILESYSTEM_LIST) \ - X(MPD_API_DATABASE_ARTISTALBUM_LIST) \ - X(MPD_API_DATABASE_ARTISTALBUMTITLE_LIST) \ - X(MPD_API_DATABASE_ARTIST_LIST) \ + X(MPD_API_DATABASE_TAG_LIST) \ + X(MPD_API_DATABASE_TAG_ALBUM_LIST) \ + X(MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST) \ X(MPD_API_DATABASE_STATS) \ X(MPD_API_DATABASE_SONGDETAILS) \ X(MPD_API_PLAYER_PLAY_TRACK) \ @@ -194,7 +194,7 @@ int mympd_put_welcome(char *buffer); int mympd_put_stats(char *buffer); int mympd_put_settings(char *buffer); int mympd_put_db_tag(char *buffer, unsigned int offset, char *mpdtagtype, char *mpdsearchtagtype, char *searchstr, char *filter); -int mympd_put_songs_in_album(char *buffer, char *albumartist, char *album); +int mympd_put_songs_in_album(char *buffer, char *album, char *search, char *tag); int mympd_put_playlists(char *buffer, unsigned int offset, char *filter); int mympd_put_playlist_list(char *buffer, char *uri, unsigned int offset, char *filter); int mympd_put_songdetails(char *buffer, char *uri); diff --git a/src/mympd.c b/src/mympd.c index be7a21d..d5312d9 100644 --- a/src/mympd.c +++ b/src/mympd.c @@ -229,6 +229,7 @@ int main(int argc, char **argv) { nc = mg_bind_opt(&mgr, config.sslport, ev_handler, bind_opts); if (nc == NULL) { printf("Error listening on port %s: %s\n", config.sslport, err); + mg_mgr_free(&mgr); return EXIT_FAILURE; } } @@ -236,6 +237,7 @@ int main(int argc, char **argv) { nc = mg_bind(&mgr, config.webport, ev_handler); if (nc == NULL) { printf("Error listening on port %s\n", config.webport); + mg_mgr_free(&mgr); return EXIT_FAILURE; } }