1
0
mirror of https://github.com/SuperBFG7/ympd synced 2025-05-04 08:24:07 +00:00

Merge branch 'queue-view-rewrite' - First bunch of queue rewrite changes

This commit is contained in:
jcorporation 2018-05-27 14:19:26 +01:00
commit 7013d2f557
13 changed files with 2804 additions and 91 deletions

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.6)
project (mympd C)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
set(CPACK_PACKAGE_VERSION_MAJOR "2")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "1")
set(CPACK_PACKAGE_VERSION_PATCH "0")
if(CMAKE_BUILD_TYPE MATCHES RELEASE)
set(ASSETS_PATH "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/htdocs")

View File

@ -35,8 +35,7 @@ Unix Build Instructions
2. create build directory ```cd /path/to/src; mkdir build; cd build```
3. create makefile ```cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_BUILD_TYPE=RELEASE```
4. build ```make```
5. install ```sudo make install``` or just run with ```./mympd```
Optional:
5. install ```sudo make install```
6. Link your mpd music directory to ```/usr/share/mympd/htdocs/library``` and put ```folder.jpg``` files in your album directories
7. Configure your mpd with http stream output to use the local player

View File

@ -98,27 +98,50 @@
</div>
<div class="card-body">
<div class="btn-toolbar" id="queue-buttons" role="toolbar">
<div id="trashmode" class="btn-group mr-2" data-toggle="radio">
<button id="btntrashmodeup" type="button" class="btn btn-secondary" title="Delete upward">
<span class="material-icons">vertical_align_top</span>
<span class="material-icons">delete</span>
<div id="trashmode" class="btn-group mr-2">
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">delete</span></button>
<div class="dropdown-menu bg-dark px-2" id="trashmodebtns">
<h6 class="dropdown-header text-light">Trashmode</h6>
<button id="btntrashmodeup" type="button" class="btn btn-secondary btn-block">
<span class="material-icons" style="float:left;">vertical_align_top</span>
<span style="margin-left:1rem;">Delete upward</span>
</button>
<button id="btntrashmodesingle" type="button" class="btn btn-success" title="Delete single">
<span class="material-icons">delete</span>
<button id="btntrashmodesingle" type="button" class="btn btn-success btn-block">
<span class="material-icons" style="float:left;">delete</span>
<span style="margin-left:1rem;">Delete single</span>
</button>
<button id="btntrashmodedown" type="button" class="btn btn-secondary" title="Delete downward">
<span class="material-icons">delete</span>
<span class="material-icons">vertical_align_bottom</span>
<button id="btntrashmodedown" type="button" class="btn btn-secondary btn-block">
<span class="material-icons" style="float:left;">vertical_align_bottom</span>
<span style="margin-left:1rem;">Delete downward</span>
</button>
</div>
</div>
<div id="queue-actions" class="btn-group mr-2">
<button type="button" class="btn btn-secondary" onclick="socket.send('MPD_API_SEND_SHUFFLE');" title="Shuffle queue">
<span class="material-icons">shuffle</span>
</button>
<button type="button" class="btn btn-secondary" onclick="socket.send('MPD_API_RM_ALL');" title="Clear queue">
<span class="material-icons">clear_all</span>
</button>
<a href="#" data-toggle="modal" data-target="#savequeue" class="btn btn-secondary" title="Save queue">
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#savequeue" title="Save queue">
<span class="material-icons">save</span>
</a>
</button>
</div>
<form id="searchqueue" role="search">
<div class="input-group mr-2">
<input type="text" class="form-control" placeholder="Search Queue" id="searchqueuestr"/>
<div class="input-group-append">
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span></button>
<div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchqueuetag">
<h6 class="dropdown-header text-light">Search in Tag</h6>
<button type="button" class="btn btn-success btn-block">Any Tag</button>
<button type="button" class="btn btn-secondary btn-block">Title</button>
<button type="button" class="btn btn-secondary btn-block">Artist</button>
<button type="button" class="btn btn-secondary btn-block">Album</button>
</div>
</div>
</div>
</form>
</div>
<table id="queueList" class="table table-hover">
@ -142,9 +165,9 @@
</tbody>
</table>
<ul class="pagination justify-content-center">
<li id="queuePrev" class="page-item hide"><a class="page-link text-secondary" href="">Previous</a></li>
<li id="queueNext" class="page-item hide"><a class="page-link text-secondary" href="">Next</a></li>
<ul id="queuePagination" class="pagination justify-content-center hide">
<li id="queuePrev" class="page-item disabled"><a class="page-link text-secondary" href="">Previous</a></li>
<li id="queueNext" class="page-item disabled"><a class="page-link text-secondary" href="">Next</a></li>
</ul>
</div>
</div>
@ -183,9 +206,9 @@
</tbody>
</table>
<ul class="pagination justify-content-center">
<li id="browsePrev" class="page-item hide"><a class="page-link text-secondary" href="">Previous</a></li>
<li id="browseNext" class="page-item hide"><a class="page-link text-secondary" href="">Next</a></li>
<ul id="browsePagination" class="pagination justify-content-center hide">
<li id="browsePrev" class="page-item disabled"><a class="page-link text-secondary" href="">Previous</a></li>
<li id="browseNext" class="page-item disabled"><a class="page-link text-secondary" href="">Next</a></li>
</ul>
</div>
</div>
@ -226,6 +249,19 @@
</nav>
</footer>
<div class="modal" id="modalConnectionError" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><span class="material-icons">error</span> Connection Error</h5>
</div>
<div class="modal-body">
<p>Connection to myMPD failed. Trying to reconnect.</p>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="settings" tabindex="-1" role="dialog" aria-labelledby="settingsLabel" aria-hidden="true">
<div class="modal-dialog">
@ -300,8 +336,8 @@
<h4><a style="color:#28a745" href="https://github.com/jcorporation/ympd"><span class="material-icons">play_circle_outline</span> myMPD</a>&nbsp;&ndash;&nbsp;<small>MPD Web GUI - written in C, utilizing Websockets and Bootstrap/JS</small></h4>
<p>myMPD is a lightweight MPD web client that runs without a dedicated webserver or interpreter. It's tuned for minimal resource usage and requires only very litte dependencies. myMPD is a fork of <a style="color:#28a745" href="http://www.ympd.org">ympd</a>.</p>
<ul>
<li>Version: 2.0.0</li>
<li>Homepage: <a style="color:#28a745" target="_blank" href="https://github.com/jcorporation/ympd">https://github.com/jcorporation/ympd</a></li>
<li>Version: 2.1.0</li>
<li>Homepage: <a style="color:#28a745" target="_blank" href="https://github.com/jcorporation/mympd">https://github.com/jcorporation/mympd</a></li>
<li>Autor: Juergen Mang &lt;<a style="color:#28a745" href="mailto:mail@jcgames.de">mail@jcgames.de</a>&gt;</li>
</ul>
</div>
@ -366,7 +402,7 @@
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/js.cookie.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/bootstrap-slider.min.js"></script>
<script src="js/bootstrap-notify.min.js"></script>
<script src="js/sammy.js"></script>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
htdocs/js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -45,7 +45,8 @@ var app = $.sammy(function() {
$('#cardQueue').addClass('hide');
$('#cardBrowse').addClass('hide');
$('#cardSearch').addClass('hide');
$('.page-item').addClass('hide');
$('.pagination').addClass('hide');
$('#searchqueue > input').val('');
pagination = 0;
browsepath = '';
}
@ -157,7 +158,7 @@ $(document).ready(function(){
$('#mainMenu').on('shown.bs.dropdown', function () {
$('#search > input').val('');
$('#search > input').focus();
})
});
if(!notificationsSupported())
$('#btnnotifyWeb').addClass("disabled");
@ -182,7 +183,7 @@ function webSocketConnect() {
socket.onopen = function() {
console.log("connected");
showNotification('Connected to myMPD','','','success');
$('#modalConnectionError').modal('hide');
app.run();
/* emit initial request for output names */
socket.send('MPD_API_GET_OUTPUTS');
@ -200,26 +201,41 @@ function webSocketConnect() {
}
switch (obj.type) {
case 'queuesearch':
//Do the same as queue
case 'queue':
if(current_app !== 'queue')
break;
$('#panel-heading-queue').empty();
if (obj.totalTime > 0) {
if (obj.totalSongs > 0) {
$('#panel-heading-queue').text(obj.totalSongs+' Songs');
}
if (typeof(obj.totalTime) != undefined && obj.totalTime > 0 ) {
var days = Math.floor(obj.totalTime / 86400);
var hours = Math.floor(obj.totalTime / 3600) - days * 24;
var minutes = Math.floor(obj.totalTime / 60) - hours * 60 - days * 1440;
var seconds = obj.totalTime - days * 86400 - hours * 3600 - minutes * 60;
$('#panel-heading-queue').text(obj.totalSongs+' Songs ' +
$('#panel-heading-queue').append(' ' +
(days > 0 ? days + '\u2009d ' : '') +
(hours > 0 ? hours + '\u2009h ' + (minutes < 10 ? '0' : '') : '') +
minutes + '\u2009m ' + (seconds < 10 ? '0' : '') + seconds + '\u2009s');
} else {
$('#panel-heading-queue').empty();
}
$('#queueList > tbody').empty();
var nrItems=0;
for (var song in obj.data) {
nrItems++;
if (obj.data[song].type == 'wrap') {
$('#queueList > tbody').append(
"<tr><td><span class=\"material-icons\">error_outline</span></td>" +
"<td colspan=\"3\">Too many results, please refine your search!</td>" +
"<td></td><td></td></tr>"
);
continue;
}
var minutes = Math.floor(obj.data[song].duration / 60);
var seconds = obj.data[song].duration - minutes * 60;
@ -231,11 +247,26 @@ function webSocketConnect() {
"<td>"+ minutes + ":" + (seconds < 10 ? '0' : '') + seconds +
"</td><td></td></tr>");
}
if (obj.type == 'queuesearch' && nrItems == 0) {
$('#queueList > tbody').append(
"<tr><td><span class=\"material-icons\">error_outline</span></td>" +
"<td colspan=\"3\">No results, please refine your search!</td>" +
"<td></td><td></td></tr>"
);
}
if (obj.type == 'queue') {
if(obj.data.length && obj.data[obj.data.length-1].pos + 1 >= pagination + MAX_ELEMENTS_PER_PAGE) {
$('#queueNext').removeClass('disabled');
$('#queuePagination').removeClass('hide');
}
if(pagination > 0) {
$('#queuePrev').removeClass('disabled');
$('#queuePagination').removeClass('hide');
}
} else {
$('#queuePagination').addClass('hide');
}
if(obj.data.length && obj.data[obj.data.length-1].pos + 1 >= pagination + MAX_ELEMENTS_PER_PAGE)
$('#queueNext').removeClass('hide');
if(pagination > 0)
$('#queuePrev').removeClass('hide');
if ( isTouch ) {
$('#queueList > tbody > tr > td:last-child').append(
"<a class=\"pull-right btn-group-hover color-darkgrey\" href=\"#/\" " +
@ -279,6 +310,7 @@ function webSocketConnect() {
break;
case 'search':
$('#searchList').find("tr:gt(0)").remove();
break;
case 'browse':
if(current_app !== 'browse' && current_app !== 'search')
break;
@ -345,7 +377,8 @@ function webSocketConnect() {
break;
case 'wrap':
if(current_app == 'browse') {
$('#browseNext').removeClass('hide');
$('#browseNext').removeClass('disabled');
$('#browsePagination').removeClass('hide');
} else {
$('#'+current_app+'List > tbody').append(
"<tr><td><span class=\"material-icons\">error_outline</span></td>" +
@ -356,8 +389,10 @@ function webSocketConnect() {
break;
}
if(pagination > 0)
$('#browsePrev').removeClass('hide');
if(pagination > 0) {
$('#browsePrev').removeClass('disabled');
$('#browsePagination').removeClass('hide');
}
}
@ -513,6 +548,7 @@ function webSocketConnect() {
break;
case 'disconnected':
showNotification('myMPD lost connection to MPD','','','danger');
break;
case 'update_queue':
if(current_app === 'queue') {
@ -533,8 +569,12 @@ function webSocketConnect() {
}
socket.onclose = function(){
console.log("disconnected");
showNotification('Connection to myMPD lost, retrying in 3 seconds','','','danger');
console.log('disconnected');
$('#modalConnectionError').modal('show');
setTimeout(function() {
console.log('reconnect');
webSocketConnect();
},3000);
}
} catch(exception) {
@ -661,15 +701,15 @@ function toggleoutput(button, id) {
socket.send("MPD_API_TOGGLE_OUTPUT,"+id+"," + ($(button).hasClass('btn-success') ? 0 : 1));
}
$('#trashmode').children("button").on('click', function(e) {
$('#trashmode').children("button").removeClass("btn-success").addClass('btn-secondary');
$('#trashmodebtns > button').on('click', function(e) {
$('#trashmodebtns').children("button").removeClass("btn-success").addClass('btn-secondary');
$(this).removeClass("btn-secondary").addClass("btn-success");
});
$('#btnnotifyWeb').on('click', function (e) {
if(Cookies.get('notificationWeb') === 'true') {
Cookies.set('notificationWeb', false, { expires: 424242 });
$('#btnnotify').removeClass('btn-success').addClass('btn-secondary');
$('#btnnotifyWeb').removeClass('btn-success').addClass('btn-secondary');
} else {
Notification.requestPermission(function (permission) {
if(!('permission' in Notification)) {
@ -705,6 +745,35 @@ $('#search').submit(function () {
return false;
});
$('#searchqueuestr').keyup(function (event) {
doQueueSearch();
});
$('#searchqueuetag > button').on('click',function (e) {
$('#searchqueuetag > button').removeClass('btn-success').addClass('btn-secondary');
$(this).removeClass('btn-secondary').addClass('btn-success');
doQueueSearch();
});
function doQueueSearch() {
var searchstr=$('#searchqueuestr').val();
var mpdtag='Any Tag';
$('#searchqueuetag > button').each(function() {
if ($(this).hasClass('btn-success')) { mpdtag=$(this).text(); }
});
if (searchstr.length >= 3) {
socket.send('MPD_API_SEARCH_QUEUE,' + mpdtag + ',' + searchstr);
}
if (searchstr.length == 0) {
socket.send('MPD_API_GET_QUEUE,0');
}
}
$('#searchqueue').submit(function () {
return false;
});
$('.page-link').on('click', function (e) {
switch ($(this).text()) {

View File

@ -65,14 +65,14 @@ int callback_mpd(struct mg_connection *c)
unsigned int uint_buf, uint_buf_2;
int int_buf;
char *p_charbuf = NULL, *token;
char *mpdtagtype = NULL;
char *searchstr = NULL;
fprintf(stdout,"%s\n",c->content);
if(cmd_id == -1)
return MG_TRUE;
// if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST &&
// cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS)
// return MG_TRUE;
switch(cmd_id)
{
case MPD_API_UPDATE_DB:
@ -234,6 +234,31 @@ out_playlist:
out_save_queue:
free(p_charbuf);
break;
case MPD_API_SEARCH_QUEUE:
p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEARCH_QUEUE"))
goto out_search_queue;
if((token = strtok(NULL, ",")) == NULL) {
goto out_search_queue;
} else {
mpdtagtype = strdup(token);
}
if((token = strtok(NULL, ",")) == NULL) {
free(mpdtagtype);
goto out_search;
} else {
searchstr = strdup(token);
}
//free(p_charbuf);
//p_charbuf = strdup(c->content);
n = mpd_search_queue(mpd.buf, mpdtagtype, searchstr);
free(searchstr);
out_search_queue:
free(p_charbuf);
break;
case MPD_API_SEARCH:
p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEARCH"))
@ -248,6 +273,9 @@ out_save_queue:
out_search:
free(p_charbuf);
break;
case MPD_API_SEND_SHUFFLE:
mpd_run_shuffle(mpd.conn);
break;
case MPD_API_SEND_MESSAGE:
p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEND_MESSAGE"))
@ -625,10 +653,6 @@ int mpd_put_queue(char *buffer, unsigned int offset)
cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
cur += json_emit_raw_str(cur, end - cur, ",\"title\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_title(song));
cur += json_emit_raw_str(cur, end - cur, ",\"artist\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_artist(song));
cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
cur += json_emit_raw_str(cur, end - cur, "},");
}
@ -734,10 +758,10 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset)
int mpd_search(char *buffer, char *searchstr)
{
int i = 0;
char *cur = buffer;
const char *end = buffer + MAX_SIZE;
struct mpd_song *song;
unsigned long totalSongs = 0;
if(mpd_search_db_songs(mpd.conn, false) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_db_songs");
@ -749,7 +773,10 @@ int mpd_search(char *buffer, char *searchstr)
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"search\",\"data\":[ ");
while((song = mpd_recv_song(mpd.conn)) != NULL) {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":");
totalSongs ++;
if (totalSongs <=300) {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\"");
cur += json_emit_raw_str(cur, end - cur, ",\"uri\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song));
cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
@ -761,25 +788,87 @@ int mpd_search(char *buffer, char *searchstr)
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, mpd_get_title(song));
cur += json_emit_raw_str(cur, end - cur, ",\"artist\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_artist(song));
cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
cur += json_emit_raw_str(cur, end - cur, "},");
}
mpd_song_free(song);
}
/* Maximum results */
if(i++ >= 300)
if(totalSongs++ > 300)
{
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\"},");
break;
}
}
/* remove last ',' */
cur--;
cur += json_emit_raw_str(cur, end - cur, "]}");
cur += json_emit_raw_str(cur, end - cur, "]");
cur += json_emit_raw_str(cur, end - cur, ",\"totalSongs\":");
cur += json_emit_int(cur, end - cur, totalSongs);
cur += json_emit_raw_str(cur, end - cur, "}");
}
return cur - buffer;
}
int mpd_search_queue(char *buffer, char *mpdtagtype, char *searchstr)
{
char *cur = buffer;
const char *end = buffer + MAX_SIZE;
struct mpd_song *song;
unsigned long totalSongs = 0;
if(mpd_search_queue_songs(mpd.conn, false) == false) {
RETURN_ERROR_AND_RECOVER("mpd_search_queue_songs");
}
if (mpd_tag_name_parse(mpdtagtype) != MPD_TAG_UNKNOWN) {
if (mpd_search_add_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, mpd_tag_name_parse(mpdtagtype), searchstr) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_add_tag_constraint");
}
else {
if (mpd_search_add_any_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, searchstr) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_add_any_tag_constraint");
}
if(mpd_search_commit(mpd.conn) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_commit");
else {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"queuesearch\",\"data\":[ ");
while((song = mpd_recv_song(mpd.conn)) != NULL) {
totalSongs ++;
if(totalSongs <= 100) {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\"");
// cur += json_emit_raw_str(cur, end - cur, ",\"uri\":");
// cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song));
cur += json_emit_raw_str(cur, end - cur, ",\"id\":");
cur += json_emit_int(cur, end - cur, mpd_song_get_id(song));
cur += json_emit_raw_str(cur, end - cur, ",\"pos\":");
cur += json_emit_int(cur, end - cur, mpd_song_get_pos(song));
cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
cur += json_emit_raw_str(cur, end - cur, ",\"artist\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_get_artist(song));
// cur += json_emit_raw_str(cur, end - cur, ",\"album_artist\":");
// cur += json_emit_quoted_str(cur, end - cur, mpd_get_album_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, mpd_get_title(song));
cur += json_emit_raw_str(cur, end - cur, "},");
mpd_song_free(song);
}
}
if (totalSongs > 100) {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\"},");
}
cur--;
cur += json_emit_raw_str(cur, end - cur, "]");
cur += json_emit_raw_str(cur, end - cur, ",\"totalSongs\":");
cur += json_emit_int(cur, end - cur, totalSongs);
cur += json_emit_raw_str(cur, end - cur, "}");
}
return cur - buffer;
}

View File

@ -54,6 +54,7 @@
X(MPD_API_RM_RANGE) \
X(MPD_API_RM_ALL) \
X(MPD_API_MOVE_TRACK) \
X(MPD_API_SEARCH_QUEUE) \
X(MPD_API_SEARCH) \
X(MPD_API_SEND_MESSAGE) \
X(MPD_API_SET_VOLUME) \
@ -71,7 +72,8 @@
X(MPD_API_TOGGLE_SINGLE) \
X(MPD_API_TOGGLE_CROSSFADE) \
X(MPD_API_TOGGLE_REPEAT) \
X(MPD_API_GET_OPTIONS)
X(MPD_API_GET_OPTIONS) \
X(MPD_API_SEND_SHUFFLE)
enum mpd_cmd_ids {
MPD_CMDS(GEN_ENUM)
@ -119,6 +121,7 @@ int mpd_put_current_song(char *buffer);
int mpd_put_queue(char *buffer, unsigned int offset);
int mpd_put_browse(char *buffer, char *path, unsigned int offset);
int mpd_search(char *buffer, char *searchstr);
int mpd_search_queue(char *buffer, char *mp3tag, char *searchstr);
void mpd_disconnect();
#endif