Add support for expanding playlists
authorHugo Villeneuve <hugo@hugovil.com>
Thu, 5 Jan 2023 22:35:22 +0000 (17:35 -0500)
committerHugo Villeneuve <hugo@hugovil.com>
Sat, 7 Jan 2023 00:33:26 +0000 (19:33 -0500)
htdocs/js/mpd.js
src/mpd_client.c
src/mpd_client.h

index 8b571e2..a6e7125 100644 (file)
@@ -735,7 +735,9 @@ function webSocketConnect() {
                                     break;
                                 case 'plist':
                                     socket.send(
-                                        'MPD_API_ADD_PLAYLIST,' +
+                                        'MPD_API_EXPAND_PLAYLIST,' +
+                                           pagination +
+                                           ',' +
                                             decodeURIComponent(
                                                 $(this).attr('uri')
                                             )
index c3601ee..522199d 100644 (file)
@@ -227,9 +227,9 @@ int callback_mpd(struct mg_connection *c) {
         out_play_track:
             free(p_charbuf);
             break;
-        case MPD_API_ADD_PLAYLIST:
+        case MPD_API_EXPAND_PLAYLIST:
             p_charbuf = strdup(c->content);
-            if (strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAYLIST"))
+            if (strcmp(strtok(p_charbuf, ","), "MPD_API_EXPAND_PLAYLIST"))
                 goto out_playlist;
 
             uint_buf = strtoul(strtok(NULL, ","), NULL, 10);
@@ -504,6 +504,17 @@ char *mpd_get_title(struct mpd_song const *song) {
     return str;
 }
 
+char *mpd_get_name(struct mpd_song const *song) {
+    char *str;
+
+    str = (char *)mpd_song_get_tag(song, MPD_TAG_NAME, 0);
+    if (str == NULL) {
+        str = basename((char *)mpd_song_get_uri(song));
+    }
+
+    return str;
+}
+
 char *mpd_get_album(struct mpd_song const *song) {
     char *str;
 
@@ -781,6 +792,74 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset) {
     return cur - buffer;
 }
 
+int mpd_put_playlist(char *buffer, char *pl_name, unsigned int offset) {
+    char *cur = buffer;
+    const char *end = buffer + MAX_SIZE;
+    struct mpd_entity *entity;
+    unsigned int entity_count = 0;
+
+    if (!mpd_send_list_playlist_meta(mpd.conn, pl_name))
+        RETURN_ERROR_AND_RECOVER("mpd_send_list_playlist_meta");
+
+    cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"browse\",\"data\":[ ");
+
+    while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
+        const struct mpd_song *song;
+
+        if (offset > entity_count) {
+            mpd_entity_free(entity);
+            entity_count++;
+            continue;
+        } else if (offset + MAX_ELEMENTS_PER_PAGE - 1 < entity_count) {
+            mpd_entity_free(entity);
+            cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\",\"count\":");
+            cur += json_emit_int(cur, end - cur, entity_count);
+            cur += json_emit_raw_str(cur, end - cur, "} ");
+            break;
+        }
+
+        switch (mpd_entity_get_type(entity)) {
+            case MPD_ENTITY_TYPE_UNKNOWN:
+                break;
+
+            case MPD_ENTITY_TYPE_DIRECTORY:
+                break;
+
+            case MPD_ENTITY_TYPE_PLAYLIST:
+                break;
+
+            case MPD_ENTITY_TYPE_SONG:
+                song = mpd_entity_get_song(entity);
+                cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"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));
+                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, ",\"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_name(song));
+                cur += json_emit_raw_str(cur, end - cur, "},");
+                break;
+        }
+        mpd_entity_free(entity);
+        entity_count++;
+    }
+
+    if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(mpd.conn)) {
+        fprintf(stderr, "MPD mpd_send_list_playlist_meta: %s\n", mpd_connection_get_error_message(mpd.conn));
+        mpd.conn_state = MPD_FAILURE;
+        return 0;
+    }
+
+    /* remove last ',' */
+    cur--;
+
+    cur += json_emit_raw_str(cur, end - cur, "]}");
+    return cur - buffer;
+}
+
 int mpd_search(char *buffer, char *searchstr) {
     int i = 0;
     char *cur = buffer;
index ca9c6e3..384e983 100644 (file)
@@ -44,7 +44,7 @@
     X(MPD_API_GET_MPDHOST)      \
     X(MPD_API_ADD_TRACK)        \
     X(MPD_API_ADD_PLAY_TRACK)   \
-    X(MPD_API_ADD_PLAYLIST)     \
+    X(MPD_API_EXPAND_PLAYLIST)  \
     X(MPD_API_PLAY_TRACK)       \
     X(MPD_API_SAVE_QUEUE)       \
     X(MPD_API_RM_TRACK)         \
@@ -120,6 +120,7 @@ int mpd_put_channels(char *buffer);
 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_put_playlist(char *buffer, char *pl_name, unsigned int offset);
 int mpd_search(char *buffer, char *searchstr);
 void mpd_disconnect();
 #endif