int cmd_playlist(int argc, char **argv) { int index, i; sp_track *track; sp_playlist *playlist; sp_playlistcontainer *pc = sp_session_playlistcontainer(g_session); if (argc < 1) { printf("playlist [playlist index]\n"); return 0; } index = atoi(argv[1]); if (index < 0 || index > sp_playlistcontainer_num_playlists(pc)) { printf("invalid index\n"); return 0; } playlist = sp_playlistcontainer_playlist(pc, index); printf("Playlist %s by %s%s%s\n", sp_playlist_name(playlist), sp_user_display_name(sp_playlist_owner(playlist)), sp_playlist_is_collaborative(playlist) ? " (collaborative)" : "", sp_playlist_has_pending_changes(playlist) ? " with pending changes" : "" ); for (i = 0; i < sp_playlist_num_tracks(playlist); ++i) { track = sp_playlist_track(playlist, i); printf("%d. %c %s%s %s\n", i, sp_track_is_starred(g_session, track) ? '*' : ' ', sp_track_is_local(g_session, track) ? "local" : " ", sp_track_is_autolinked(g_session, track) ? "autolinked" : " ", sp_track_name(track)); } return 1; }
// session->mutex must be locked static int wait_for_playlist_pending_changes(php_spotify_playlist *playlist) { struct timespec ts; int err = 0; php_spotify_session *session; assert(playlist != NULL); session = playlist->session; DEBUG_PRINT("wait_for_playlist_pending_changes\n"); // Block for a max of SPOTIFY_TIMEOUT seconds clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += SPOTIFY_TIMEOUT; request_lock(); while(err == 0) { DEBUG_PRINT("wait_for_playlist_pending_changes loop\n"); int pending_changes; session_lock(session); pending_changes = sp_playlist_has_pending_changes(playlist->playlist); session_unlock(session); if (!pending_changes) break; // Wait until a callback is fired err = request_sleep_lock(&ts); } request_unlock(); DEBUG_PRINT("wait_for_playlist_pending_changes end(%d)\n", err); return err; }
static void put_playlist_patch(sp_playlist *playlist, struct evhttp_request *request, void *userdata) { struct state *state = userdata; struct evbuffer *buf = evhttp_request_get_input_buffer(request); size_t buflen = evbuffer_get_length(buf); if (buflen == 0) { send_error(request, HTTP_BADREQUEST, "No body"); return; } // Read request body json_error_t loads_error; json_t *json = read_request_body_json(request, &loads_error); if (json == NULL) { send_error(request, HTTP_BADREQUEST, loads_error.text ? loads_error.text : "Unable to parse JSON"); return; } if (!json_is_array(json)) { json_decref(json); send_error(request, HTTP_BADREQUEST, "Not valid JSON array"); return; } // Handle empty array int num_tracks = json_array_size(json); if (num_tracks == 0) { send_reply(request, HTTP_OK, "OK", NULL); return; } sp_track **tracks = calloc(num_tracks, sizeof (sp_track *)); int num_valid_tracks = 0; for (int i = 0; i < num_tracks; i++) { json_t *item = json_array_get(json, i); if (!json_is_string(item)) { json_decref(item); continue; } char *uri = strdup(json_string_value(item)); sp_link *track_link = sp_link_create_from_string(uri); free(uri); if (track_link == NULL) continue; if (sp_link_type(track_link) != SP_LINKTYPE_TRACK) { sp_link_release(track_link); continue; } sp_track *track = sp_link_as_track(track_link); if (track == NULL) continue; tracks[num_valid_tracks++] = track; } json_decref(json); // Bail if no tracks could be read from input if (num_valid_tracks == 0) { send_error(request, HTTP_BADREQUEST, "No valid tracks"); free(tracks); return; } tracks = realloc(tracks, num_valid_tracks * sizeof (sp_track *)); // Apply diff apr_pool_t *pool = state->pool; svn_diff_t *diff; svn_error_t *diff_error = diff_playlist_tracks(&diff, playlist, tracks, num_valid_tracks, pool); if (diff_error != SVN_NO_ERROR) { free(tracks); svn_handle_error2(diff_error, stderr, false, "Diff"); send_error(request, HTTP_BADREQUEST, "Search failed"); return; } svn_error_t *apply_error = diff_playlist_tracks_apply(diff, playlist, tracks, num_valid_tracks, state->session); if (apply_error != SVN_NO_ERROR) { free(tracks); svn_handle_error2(apply_error, stderr, false, "Updating playlist"); send_error(request, HTTP_BADREQUEST, "Could not apply diff"); return; } if (!sp_playlist_has_pending_changes(playlist)) { free(tracks); get_playlist(playlist, request, NULL); return; } free(tracks); register_playlist_callbacks(playlist, request, &get_playlist, &playlist_update_in_progress_callbacks, NULL); }