1
0
mirror of https://github.com/SuperBFG7/ympd synced 2024-06-28 15:43:15 +00:00

Implemented filtering in browse filesystem view

This commit is contained in:
jcorporation 2018-06-03 09:52:38 +01:00
parent 234772155a
commit 19eeae728c
6 changed files with 135 additions and 55 deletions

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -193,6 +193,6 @@ main {
margin-right:5px; margin-right:5px;
} }
#browseFilesystemGotoLetters > a { #browseFilesystemFilterLetters > button {
min-width:23px; min-width:28px;
} }

View File

@ -203,7 +203,7 @@
<div class="card-header" id="panel-heading-browse"> <div class="card-header" id="panel-heading-browse">
<ul class="nav nav-tabs card-header-tabs"> <ul class="nav nav-tabs card-header-tabs">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" href="#/browse/filesystem/0/" id="cardBrowseNavFilesystem">Filesystem</a> <a class="nav-link text-dark" href="#/browse/filesystem/0/!/" id="cardBrowseNavFilesystem">Filesystem</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" href="#/browse/playlists/0" id="cardBrowseNavPlaylists">Playlists</a> <a class="nav-link text-dark" href="#/browse/playlists/0" id="cardBrowseNavPlaylists">Playlists</a>
@ -213,6 +213,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="card-body hide" id="cardBrowsePlaylists"> <div class="card-body hide" id="cardBrowsePlaylists">
<div class="btn-toolbar collapse show" id="browsePlaylistsButtons" role="toolbar"> <div class="btn-toolbar collapse show" id="browsePlaylistsButtons" role="toolbar">
<div id="browsePlaylistsPaginationTop" class="btn-group mr-2"> <div id="browsePlaylistsPaginationTop" class="btn-group mr-2">
@ -277,8 +278,8 @@
<button id="browseFilesystemAddAllSongs" class="btn btn-secondary">Add all</button> <button id="browseFilesystemAddAllSongs" class="btn btn-secondary">Add all</button>
</div> </div>
<div class="btn-group mr-2"> <div class="btn-group mr-2">
<button id="browseFilesystemGoto" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Goto</button> <button id="browseFilesystemFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button>
<div class="dropdown-menu bg-dark px-2" id="browseFilesystemGotoLetters"> <div class="dropdown-menu bg-dark px-2" id="browseFilesystemFilterLetters">
</div> </div>
</div> </div>
<div id="browseFilesystemPaginationTop" class="btn-group mr-2"> <div id="browseFilesystemPaginationTop" class="btn-group mr-2">
@ -416,7 +417,7 @@
<div class="d-flex flex-fill navbar-nav" id="navbar-bottom"> <div class="d-flex flex-fill navbar-nav" id="navbar-bottom">
<div class="nav-item flex-fill text-center" id="navPlayback"><a class="nav-link" href="#/playing/">Playback</a></div> <div class="nav-item flex-fill text-center" id="navPlayback"><a class="nav-link" href="#/playing/">Playback</a></div>
<div class="nav-item flex-fill text-center" id="navQueue"><a class="nav-link" href="#/queue/0/Any Tag/">Queue</a></div> <div class="nav-item flex-fill text-center" id="navQueue"><a class="nav-link" href="#/queue/0/Any Tag/">Queue</a></div>
<div class="nav-item flex-fill text-center" id="navBrowse"><a class="nav-link" href="#/browse/filesystem/0/">Browse</a></div> <div class="nav-item flex-fill text-center" id="navBrowse"><a class="nav-link" href="#/browse/filesystem/0/!/">Browse</a></div>
<div class="nav-item flex-fill text-center" id="navSearch"><a class="nav-link" href="#/search/0/Any Tag/">Search</a></div> <div class="nav-item flex-fill text-center" id="navSearch"><a class="nav-link" href="#/search/0/Any Tag/">Search</a></div>
</div> </div>
</nav> </nav>

View File

@ -27,15 +27,16 @@ var last_state;
var last_outputs; var last_outputs;
var current_app; var current_app;
var pagination = 0; var pagination = 0;
var browsepath = ""; var filterLetter = '!'
var lastSongTitle = ""; var browsepath = '';
var lastSongTitle = '';
var current_song = new Object(); var current_song = new Object();
var MAX_ELEMENTS_PER_PAGE = 100; var MAX_ELEMENTS_PER_PAGE = 100;
var isTouch = Modernizr.touch ? 1 : 0; var isTouch = Modernizr.touch ? 1 : 0;
var playstate = ""; var playstate = '';
var progressBar; var progressBar;
var volumeBar; var volumeBar;
var coverImageFile = ""; var coverImageFile = '';
var app = $.sammy(function() { var app = $.sammy(function() {
@ -115,17 +116,36 @@ var app = $.sammy(function() {
$('#cardBrowseNavDatabase').addClass('active'); $('#cardBrowseNavDatabase').addClass('active');
}); });
this.get(/\#\/browse\/filesystem\/(\d+)\/(.*)/, function() { this.get(/\#\/browse\/filesystem\/(\d+)\/(\w|\!)\/(.*)/, function() {
prepare(); prepare();
browsepath = this.params['splat'][1];
pagination = parseInt(this.params['splat'][0]); pagination = parseInt(this.params['splat'][0]);
filterLetter = this.params['splat'][1];
browsepath = this.params['splat'][2];
current_app = 'browseFilesystem'; current_app = 'browseFilesystem';
$('#navBrowse').addClass('active'); $('#navBrowse').addClass('active');
$('#cardBrowse').removeClass('hide'); $('#cardBrowse').removeClass('hide');
$('#cardBrowseFilesystem').removeClass('hide'); $('#cardBrowseFilesystem').removeClass('hide');
$('#cardBrowseNavFilesystem').addClass('active'); $('#cardBrowseNavFilesystem').addClass('active');
$('#browseBreadcrumb').empty().append("<li class=\"breadcrumb-item\"><a uri=\"\">root</a></li>"); $('#browseBreadcrumb').empty().append("<li class=\"breadcrumb-item\"><a uri=\"\">root</a></li>");
socket.send('MPD_API_GET_BROWSE,'+pagination+','+(browsepath ? browsepath : "/")); socket.send('MPD_API_GET_BROWSE,'+pagination+','+(browsepath ? browsepath : "/")+','+filterLetter);
$('#browseFilesystemFilterLetters > button').removeClass('btn-success').addClass('btn-secondary');
if (filterLetter == '0') {
$('#browseFilesystemFilter').text('Filter: #');
$('#browseFilesystemFilterLetters > button').each(function() {
if ($(this).text() == '#') {
$(this).addClass('btn-success');
}
});
} else if (filterLetter != '!') {
$('#browseFilesystemFilter').text('Filter: '+filterLetter);
$('#browseFilesystemFilterLetters > button').each(function() {
if ($(this).text() == filterLetter) {
$(this).addClass('btn-success');
}
});
} else {
$('#browseFilesystemFilter').text('Filter');
}
// Don't add all songs from root // Don't add all songs from root
var add_all_songs = $('#browseFilesystemAddAllSongs'); var add_all_songs = $('#browseFilesystemAddAllSongs');
if (browsepath) { if (browsepath) {
@ -509,8 +529,8 @@ function webSocketConnect() {
case 'dir': case 'dir':
pagination = 0; pagination = 0;
browsepath = $(this).attr("uri"); browsepath = $(this).attr("uri");
$("#browseFilesystemList > a").attr("href", '#/browse/filesystem/'+pagination+'/'+browsepath); $("#browseFilesystemList > a").attr("href", '#/browse/filesystem/'+pagination+'/'+filterLetter+'/'+browsepath);
app.setLocation('#/browse/filesystem/'+pagination+'/'+browsepath); app.setLocation('#/browse/filesystem/'+pagination+'/'+filterLetter+'/'+browsepath);
break; break;
case 'song': case 'song':
socket.send("MPD_API_ADD_TRACK," + decodeURI($(this).attr("uri"))); socket.send("MPD_API_ADD_TRACK," + decodeURI($(this).attr("uri")));
@ -528,8 +548,8 @@ function webSocketConnect() {
click: function() { click: function() {
pagination = 0; pagination = 0;
browsepath = $(this).attr("uri"); browsepath = $(this).attr("uri");
$("#browseFilesystemList > a").attr("href", '#/browse/filesystem/'+pagination+'/'+browsepath); $("#browseFilesystemList > a").attr("href", '#/browse/filesystem/'+pagination+'/'+filterLetter+'/'+browsepath);
app.setLocation('#/browse/filesystem/'+pagination+'/'+browsepath); app.setLocation('#/browse/filesystem/'+pagination+'/'+filterLetter+'/'+browsepath);
} }
}); });
@ -1056,7 +1076,7 @@ function gotoPage(x,element,event) {
doSearch($('#searchstr2').val()); doSearch($('#searchstr2').val());
break; break;
case "browseFilesystem": case "browseFilesystem":
app.setLocation('#/browse/filesystem/'+pagination+'/'+browsepath); app.setLocation('#/browse/filesystem/'+pagination+'/'+filterLetter+'/'+browsepath);
break; break;
case "browsePlaylists": case "browsePlaylists":
app.setLocation('#/browse/playlists/'+pagination); app.setLocation('#/browse/playlists/'+pagination);
@ -1170,11 +1190,17 @@ $(document).keydown(function(e){
e.preventDefault(); e.preventDefault();
}); });
function setFilterLetter(filter) {
app.setLocation('#/browse/filesystem/'+pagination+'/'+filter+'/'+browsepath);
}
function add_filter () { function add_filter () {
$('#browseFilesystemGotoLetters').append('<a class="mr-1 mb-1 btn btn-sm btn-secondary" onclick="gotoLetter(\'#\');" href="#/browse/filesystem/' + pagination + '/' + browsepath + '">#</a>'); $('#browseFilesystemFilterLetters').append('<button class="mr-1 mb-1 btn btn-sm btn-secondary" onclick="setFilterLetter(\'!\');">'+
'<span class="material-icons" style="font-size:14px;">delete</span></button>');
$('#browseFilesystemFilterLetters').append('<button class="mr-1 mb-1 btn btn-sm btn-secondary" onclick="setFilterLetter(\'0\');">#</button>');
for (i = 65; i <= 90; i++) { for (i = 65; i <= 90; i++) {
var c = String.fromCharCode(i); var c = String.fromCharCode(i);
$('#browseFilesystemGotoLetters').append('<a class="mr-1 mb-1 btn-sm btn btn-secondary" onclick="gotoLetter(\'' + c + '\');" href="#/browse/filesystem/' + pagination + '/' + browsepath + '">' + c + '</a>'); $('#browseFilesystemFilterLetters').append('<button class="mr-1 mb-1 btn-sm btn btn-secondary" onclick="setFilterLetter(\'' + c + '\');">' + c + '</button>');
} }
} }

View File

@ -27,6 +27,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <libgen.h> #include <libgen.h>
#include <ctype.h>
#include <mpd/client.h> #include <mpd/client.h>
#include <mpd/message.h> #include <mpd/message.h>
@ -66,7 +67,7 @@ int callback_mpd(struct mg_connection *c)
double double_buf; double double_buf;
int int_buf; int int_buf;
char *p_charbuf = NULL, *token; char *p_charbuf = NULL, *token;
char *mpdtagtype = NULL; char *p_charbuf2 = NULL;
char *searchstr = NULL; char *searchstr = NULL;
fprintf(stdout,"%s\n",c->content); fprintf(stdout,"%s\n",c->content);
@ -175,7 +176,7 @@ int callback_mpd(struct mg_connection *c)
n = mpd_put_playlists(mpd.buf, uint_buf); n = mpd_put_playlists(mpd.buf, uint_buf);
break; break;
case MPD_API_GET_BROWSE: case MPD_API_GET_BROWSE:
p_charbuf = strdup(c->content); /* p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE")) if(strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE"))
goto out_browse; goto out_browse;
@ -186,8 +187,33 @@ int callback_mpd(struct mg_connection *c)
free(p_charbuf); free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
n = mpd_put_browse(mpd.buf, get_arg2(p_charbuf), uint_buf); n = mpd_put_browse(mpd.buf, get_arg2(p_charbuf), uint_buf);
out_browse:
free(p_charbuf);*/
p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE"))
goto out_browse;
uint_buf = strtoul(strtok(NULL, ","), NULL, 10);
if((token = strtok(NULL, ",")) == NULL) {
goto out_browse;
} else {
p_charbuf2 = strdup(token);
}
if((token = strtok(NULL, ",")) == NULL) {
free(p_charbuf2);
goto out_browse;
} else {
searchstr = strdup(token);
}
n = mpd_put_browse(mpd.buf, p_charbuf2, uint_buf, searchstr);
free(searchstr);
free(p_charbuf2);
out_browse: out_browse:
free(p_charbuf); free(p_charbuf);
break;
break; break;
case MPD_API_ADD_TRACK: case MPD_API_ADD_TRACK:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
@ -254,19 +280,20 @@ out_save_queue:
if((token = strtok(NULL, ",")) == NULL) { if((token = strtok(NULL, ",")) == NULL) {
goto out_search_queue; goto out_search_queue;
} else { } else {
mpdtagtype = strdup(token); p_charbuf2 = strdup(token);
} }
uint_buf = strtoul(strtok(NULL, ","), NULL, 10); uint_buf = strtoul(strtok(NULL, ","), NULL, 10);
if((token = strtok(NULL, ",")) == NULL) { if((token = strtok(NULL, ",")) == NULL) {
free(mpdtagtype); free(p_charbuf2);
goto out_search_queue; goto out_search_queue;
} else { } else {
searchstr = strdup(token); searchstr = strdup(token);
} }
n = mpd_search_queue(mpd.buf, mpdtagtype, uint_buf, searchstr); n = mpd_search_queue(mpd.buf, p_charbuf2, uint_buf, searchstr);
free(searchstr); free(searchstr);
free(p_charbuf2);
out_search_queue: out_search_queue:
free(p_charbuf); free(p_charbuf);
break; break;
@ -277,17 +304,18 @@ out_search_queue:
if((token = strtok(NULL, ",")) == NULL) { if((token = strtok(NULL, ",")) == NULL) {
goto out_search_add; goto out_search_add;
} else { } else {
mpdtagtype = strdup(token); p_charbuf2 = strdup(token);
} }
if((token = strtok(NULL, ",")) == NULL) { if((token = strtok(NULL, ",")) == NULL) {
free(mpdtagtype); free(p_charbuf2);
goto out_search_add; goto out_search_add;
} else { } else {
searchstr = strdup(token); searchstr = strdup(token);
} }
n = mpd_search_add(mpd.buf, mpdtagtype, searchstr); n = mpd_search_add(mpd.buf, p_charbuf2, searchstr);
free(searchstr); free(searchstr);
free(p_charbuf2);
out_search_add: out_search_add:
free(p_charbuf); free(p_charbuf);
break; break;
@ -298,19 +326,20 @@ out_search_add:
if((token = strtok(NULL, ",")) == NULL) { if((token = strtok(NULL, ",")) == NULL) {
goto out_search; goto out_search;
} else { } else {
mpdtagtype = strdup(token); p_charbuf2 = strdup(token);
} }
uint_buf = strtoul(strtok(NULL, ","), NULL, 10); uint_buf = strtoul(strtok(NULL, ","), NULL, 10);
if((token = strtok(NULL, ",")) == NULL) { if((token = strtok(NULL, ",")) == NULL) {
free(mpdtagtype); free(p_charbuf2);
goto out_search; goto out_search;
} else { } else {
searchstr = strdup(token); searchstr = strdup(token);
} }
n = mpd_search(mpd.buf, mpdtagtype, uint_buf, searchstr); n = mpd_search(mpd.buf, p_charbuf2, uint_buf, searchstr);
free(searchstr); free(searchstr);
free(p_charbuf2);
out_search: out_search:
free(p_charbuf); free(p_charbuf);
break; break;
@ -793,7 +822,7 @@ int mpd_put_queue(char *buffer, unsigned int offset)
return cur - buffer; return cur - buffer;
} }
int mpd_put_browse(char *buffer, char *path, unsigned int offset) int mpd_put_browse(char *buffer, char *path, unsigned int offset, char *filter)
{ {
char *cur = buffer; char *cur = buffer;
const char *end = buffer + MAX_SIZE; const char *end = buffer + MAX_SIZE;
@ -801,6 +830,7 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset)
const struct mpd_playlist *pl; const struct mpd_playlist *pl;
unsigned int entity_count = 0; unsigned int entity_count = 0;
unsigned int entities_returned = 0; unsigned int entities_returned = 0;
const char *entityName;
if (!mpd_send_list_meta(mpd.conn, path)) if (!mpd_send_list_meta(mpd.conn, path))
RETURN_ERROR_AND_RECOVER("mpd_send_list_meta"); RETURN_ERROR_AND_RECOVER("mpd_send_list_meta");
@ -811,45 +841,68 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset)
const struct mpd_song *song; const struct mpd_song *song;
const struct mpd_directory *dir; const struct mpd_directory *dir;
entity_count ++; entity_count ++;
if(entity_count > offset && entity_count <= offset+MAX_ELEMENTS_PER_PAGE) { if(entity_count > offset && entity_count <= offset+MAX_ELEMENTS_PER_PAGE) {
switch (mpd_entity_get_type(entity)) { switch (mpd_entity_get_type(entity)) {
case MPD_ENTITY_TYPE_UNKNOWN: case MPD_ENTITY_TYPE_UNKNOWN:
entity_count --;
break; break;
case MPD_ENTITY_TYPE_SONG: case MPD_ENTITY_TYPE_SONG:
entities_returned ++;
song = mpd_entity_get_song(entity); song = mpd_entity_get_song(entity);
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":"); entityName = mpd_get_title(song);
cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song)); if (strncmp(filter,"!",1) == 0 || strncasecmp(filter,entityName,1) == 0 ||
cur += json_emit_raw_str(cur, end - cur, ",\"album\":"); ( strncmp(filter,"0",1) == 0 && isalpha(*entityName) == 0 )
cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song)); ) {
cur += json_emit_raw_str(cur, end - cur, ",\"artist\":"); entities_returned ++;
cur += json_emit_quoted_str(cur, end - cur, mpd_get_artist(song)); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":");
cur += json_emit_raw_str(cur, end - cur, ",\"duration\":"); cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song));
cur += json_emit_int(cur, end - cur, mpd_song_get_duration(song)); cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
cur += json_emit_raw_str(cur, end - cur, ",\"title\":"); cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
cur += json_emit_quoted_str(cur, end - cur, mpd_get_title(song)); cur += json_emit_raw_str(cur, end - cur, ",\"artist\":");
cur += json_emit_raw_str(cur, end - cur, "},"); cur += json_emit_quoted_str(cur, end - cur, mpd_get_artist(song));
cur += json_emit_raw_str(cur, end - cur, ",\"duration\":");
cur += json_emit_int(cur, end - cur, mpd_song_get_duration(song));
cur += json_emit_raw_str(cur, end - cur, ",\"title\":");
cur += json_emit_quoted_str(cur, end - cur, entityName);
cur += json_emit_raw_str(cur, end - cur, "},");
} else {
entity_count --;
}
break; break;
case MPD_ENTITY_TYPE_DIRECTORY: case MPD_ENTITY_TYPE_DIRECTORY:
entities_returned ++; dir = mpd_entity_get_directory(entity);
dir = mpd_entity_get_directory(entity); entityName = mpd_directory_get_path(dir);
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"directory\",\"dir\":"); char *dirName = strrchr(entityName, '/');
cur += json_emit_quoted_str(cur, end - cur, mpd_directory_get_path(dir)); if (dirName != NULL) {
cur += json_emit_raw_str(cur, end - cur, "},"); dirName ++;
} else {
dirName = strdup(entityName);
}
if (strncmp(filter,"!",1) == 0 || strncasecmp(filter,dirName,1) == 0) {
entities_returned ++;
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"directory\",\"dir\":");
cur += json_emit_quoted_str(cur, end - cur, entityName);
cur += json_emit_raw_str(cur, end - cur, "},");
} else {
entity_count --;
}
break; break;
case MPD_ENTITY_TYPE_PLAYLIST: case MPD_ENTITY_TYPE_PLAYLIST:
pl = mpd_entity_get_playlist(entity); pl = mpd_entity_get_playlist(entity);
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"playlist\",\"plist\":"); entityName = mpd_playlist_get_path(pl);
cur += json_emit_quoted_str(cur, end - cur, mpd_playlist_get_path(pl)); if (strncmp(filter,"!",1) == 0 || strncasecmp(filter,entityName,1) == 0) {
cur += json_emit_raw_str(cur, end - cur, "},"); entities_returned ++;
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"playlist\",\"plist\":");
cur += json_emit_quoted_str(cur, end - cur, entityName );
cur += json_emit_raw_str(cur, end - cur, "},");
} else {
entity_count --;
}
break; break;
} }
} }
mpd_entity_free(entity); mpd_entity_free(entity);
entity_count++;
} }
if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(mpd.conn)) { if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(mpd.conn)) {

View File

@ -130,7 +130,7 @@ int mpd_put_outputs(char *buffer, int putnames);
int mpd_put_current_song(char *buffer); int mpd_put_current_song(char *buffer);
int mpd_put_queue(char *buffer, unsigned int offset); int mpd_put_queue(char *buffer, unsigned int offset);
int mpd_put_playlists(char *buffer, unsigned int offset); int mpd_put_playlists(char *buffer, unsigned int offset);
int mpd_put_browse(char *buffer, char *path, unsigned int offset); int mpd_put_browse(char *buffer, char *path, unsigned int offset, char *filter);
int mpd_search(char *buffer, char *mpdtagtype, unsigned int offset, char *searchstr); int mpd_search(char *buffer, char *mpdtagtype, unsigned int offset, char *searchstr);
int mpd_search_add(char *buffer, char *mpdtagtype, char *searchstr); int mpd_search_add(char *buffer, char *mpdtagtype, char *searchstr);
int mpd_search_queue(char *buffer, char *mpdtagtype, unsigned int offset, char *searchstr); int mpd_search_queue(char *buffer, char *mpdtagtype, unsigned int offset, char *searchstr);