From 9b1d4ecee61715002eed28b566b1646a764177a6 Mon Sep 17 00:00:00 2001 From: jcorporation Date: Wed, 24 May 2023 00:41:44 +0200 Subject: [PATCH] Feat: MYMPD_API_PLAYLIST_COPY accepts multiple sources #1001 --- htdocs/js/apidoc.js | 10 +++--- src/mympd_api/mympd_api_handler.c | 12 ++++--- src/mympd_api/playlists.c | 55 ++++++++++++++++--------------- src/mympd_api/playlists.h | 2 +- 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/htdocs/js/apidoc.js b/htdocs/js/apidoc.js index ccf39a54b..3038e8d57 100644 --- a/htdocs/js/apidoc.js +++ b/htdocs/js/apidoc.js @@ -538,12 +538,12 @@ const APImethods = { } }, "MYMPD_API_PLAYLIST_COPY": { - "desc": "Copies or moves a source playlist to a destination playlist.", + "desc": "Copies or moves source playlists to a destination playlist.", "params": { - "srcPlist": { - "type": APItypes.string, - "example": "test_plist", - "desc": "Source MPD playlist to rename" + "srcPlists": { + "type": APItypes.array, + "example": "[\"test_plist\"]", + "desc": "Source MPD playlists to copy" }, "dstPlist": { "type": APItypes.string, diff --git a/src/mympd_api/mympd_api_handler.c b/src/mympd_api/mympd_api_handler.c index 1aba80dbc..4dfa8e536 100644 --- a/src/mympd_api/mympd_api_handler.c +++ b/src/mympd_api/mympd_api_handler.c @@ -1310,14 +1310,18 @@ void mympd_api_handler(struct t_partition_state *partition_state, struct t_work_ } } break; - case MYMPD_API_PLAYLIST_COPY: - if (json_get_string(request->data, "$.params.srcPlist", 1, FILENAME_LEN_MAX, &sds_buf1, vcb_isfilename, &error) == true && - json_get_string(request->data, "$.params.dstPlist", 1, FILENAME_LEN_MAX, &sds_buf2, vcb_isfilename, &error) == true && + case MYMPD_API_PLAYLIST_COPY: { + struct t_list src_plists; + list_init(&src_plists); + if (json_get_array_string(request->data, "$.params.srcPlists", &src_plists, vcb_isfilename, JSONRPC_ARRAY_MAX, &error) == true && + json_get_string(request->data, "$.params.dstPlist", 1, FILENAME_LEN_MAX, &sds_buf1, vcb_isfilename, &error) == true && json_get_uint(request->data, "$.params.mode", 0, 4, &uint_buf1, &error)) { - response->data = mympd_api_playlist_copy(partition_state, response->data, request->id, sds_buf1, sds_buf2, uint_buf1); + response->data = mympd_api_playlist_copy(partition_state, response->data, request->id, &src_plists, sds_buf1, uint_buf1); } + list_clear(&src_plists); break; + } case MYMPD_API_DATABASE_FILESYSTEM_LIST: { struct t_tags tagcols; reset_t_tags(&tagcols); diff --git a/src/mympd_api/playlists.c b/src/mympd_api/playlists.c index 32bf66cc8..81f2dc46a 100644 --- a/src/mympd_api/playlists.c +++ b/src/mympd_api/playlists.c @@ -52,46 +52,53 @@ static void free_t_pl_data(void *data) { } /** - * Copies or moves a playlist to a new playlist or insert/append/replace to an existing playlist. + * Copies or moves source playlists to a destination playlist. * @param partition_state pointer to partition state * @param buffer already allocated sds string to append the response * @param request_id jsonrpc request id - * @param src_plist playlist to copy + * @param src_plists playlists to copy * @param dst_plist destination playlist - * @return true on success, else false + * @param mode copy mode enum + * @return jsonrpc response */ sds mympd_api_playlist_copy(struct t_partition_state *partition_state, sds buffer, - long request_id, sds src_plist, sds dst_plist, enum plist_copy_modes mode) + long request_id, struct t_list *src_plists, sds dst_plist, enum plist_copy_modes mode) { enum mympd_cmd_ids cmd_id = MYMPD_API_PLAYLIST_COPY; - bool rc = mpd_send_list_playlist(partition_state->conn, src_plist); - if (mympd_check_rc_error_and_recover_respond(partition_state, &buffer, cmd_id, request_id, rc, "mpd_send_list_playlist") == false) { - return buffer; - } - struct mpd_song *song; + //copy sources in temporary list struct t_list src; list_init(&src); - while ((song = mpd_recv_song(partition_state->conn)) != NULL) { - list_push(&src, mpd_song_get_uri(song), 0, NULL, NULL); - } - mpd_response_finish(partition_state->conn); - if (mympd_check_error_and_recover_respond(partition_state, &buffer, cmd_id, request_id) == false) { - list_clear(&src); - return buffer; + struct t_list_node *current = src_plists->head; + while (current != NULL) { + bool rc = mpd_send_list_playlist(partition_state->conn, current->key); + if (mympd_check_rc_error_and_recover_respond(partition_state, &buffer, cmd_id, request_id, rc, "mpd_send_list_playlist") == false) { + return buffer; + } + struct mpd_song *song; + while ((song = mpd_recv_song(partition_state->conn)) != NULL) { + list_push(&src, mpd_song_get_uri(song), 0, NULL, NULL); + } + mpd_response_finish(partition_state->conn); + if (mympd_check_error_and_recover_respond(partition_state, &buffer, cmd_id, request_id) == false) { + list_clear(&src); + return buffer; + } + current = current->next; } + if (mode == PLAYLIST_COPY_REPLACE) { //clear dst playlist - rc = mpd_run_playlist_clear(partition_state->conn, dst_plist); + bool rc = mpd_run_playlist_clear(partition_state->conn, dst_plist); if (mympd_check_rc_error_and_recover_respond(partition_state, &buffer, cmd_id, request_id, rc, "mpd_run_playlist_clear") == false) { list_clear(&src); return buffer; } } - struct t_list_node *current; + + //insert or append to dst playlist unsigned i = 0; unsigned j = 0; while ((current = list_shift_first(&src)) != NULL) { - //insert or append to dst playlist if (i == 0 && mpd_command_list_begin(partition_state->conn, false) == false) { @@ -110,7 +117,7 @@ sds mympd_api_playlist_copy(struct t_partition_state *partition_state, sds buffe if (i == MPD_COMMANDS_MAX || src.head == NULL) { - rc = mpd_command_list_end(partition_state->conn) && mpd_response_finish(partition_state->conn); + bool rc = mpd_command_list_end(partition_state->conn) && mpd_response_finish(partition_state->conn); if (mympd_check_rc_error_and_recover_respond(partition_state, &buffer, cmd_id, request_id, rc, "mpd_run_playlist_clear") == false) { list_clear(&src); return buffer; @@ -130,13 +137,9 @@ sds mympd_api_playlist_copy(struct t_partition_state *partition_state, sds buffe JSONRPC_FACILITY_PLAYLIST, JSONRPC_SEVERITY_INFO, "Playlist successfully replaced"); case PLAYLIST_MOVE_APPEND: case PLAYLIST_MOVE_INSERT: { - //delete src playlist - struct t_list plist; - list_init(&plist); - list_push(&plist, src_plist, 0, NULL, NULL); + //delete src playlists bool result; - buffer = mympd_api_playlist_delete(partition_state, buffer, request_id, &plist, false, &result); - list_clear(&plist); + buffer = mympd_api_playlist_delete(partition_state, buffer, request_id, src_plists, false, &result); if (result == false) { return buffer; } diff --git a/src/mympd_api/playlists.h b/src/mympd_api/playlists.h index e874cf6b1..2561b333d 100644 --- a/src/mympd_api/playlists.h +++ b/src/mympd_api/playlists.h @@ -44,5 +44,5 @@ bool mympd_api_playlist_content_append(struct t_partition_state *partition_state bool mympd_api_playlist_content_insert(struct t_partition_state *partition_state, sds plist, struct t_list *uris, unsigned to); bool mympd_api_playlist_content_replace(struct t_partition_state *partition_state, sds plist, struct t_list *uris); sds mympd_api_playlist_copy(struct t_partition_state *partition_state, sds buffer, - long request_id, sds src_plist, sds dst_plist, enum plist_copy_modes mode); + long request_id, struct t_list *src_plists, sds dst_plist, enum plist_copy_modes mode); #endif