[spotify] Rescan of single playlists if update trigger received from
libspotify (Readds "spotify:savedtracks" playlist to avoid deletion of saved tracks)
This commit is contained in:
parent
adac1d3b5f
commit
99945fa576
209
src/spotify.c
209
src/spotify.c
|
@ -158,6 +158,11 @@ static enum spotify_state g_state;
|
||||||
static int spotify_base_plid;
|
static int spotify_base_plid;
|
||||||
// Flag telling us if access to the web api was granted
|
// Flag telling us if access to the web api was granted
|
||||||
static bool spotify_access_token_valid;
|
static bool spotify_access_token_valid;
|
||||||
|
// The base playlist id for Spotify saved tracks in the db
|
||||||
|
static int spotify_saved_plid;
|
||||||
|
|
||||||
|
// Flag to avoid triggering playlist change events while the (re)scan is running
|
||||||
|
static bool scanning;
|
||||||
|
|
||||||
// Audio fifo
|
// Audio fifo
|
||||||
static audio_fifo_t *g_audio_fifo;
|
static audio_fifo_t *g_audio_fifo;
|
||||||
|
@ -414,7 +419,11 @@ fptr_assign_all()
|
||||||
|
|
||||||
|
|
||||||
static enum command_state
|
static enum command_state
|
||||||
scan_webapi(void *arg, int *ret);
|
webapi_scan(void *arg, int *ret);
|
||||||
|
static enum command_state
|
||||||
|
webapi_pl_save(void *arg, int *ret);
|
||||||
|
static enum command_state
|
||||||
|
webapi_pl_remove(void *arg, int *ret);
|
||||||
|
|
||||||
/* ------------------------------- MISC HELPERS ---------------------------- */
|
/* ------------------------------- MISC HELPERS ---------------------------- */
|
||||||
|
|
||||||
|
@ -947,6 +956,33 @@ uri_register(void *arg, int *retval)
|
||||||
return COMMAND_END;
|
return COMMAND_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
webapi_playlist_updated(sp_playlist *pl)
|
||||||
|
{
|
||||||
|
sp_link *link;
|
||||||
|
char url[1024];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!scanning)
|
||||||
|
{
|
||||||
|
// Run playlist save in the library thread
|
||||||
|
link = fptr_sp_link_create_from_playlist(pl);
|
||||||
|
if (!link)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Could not create link for playlist: '%s'\n", fptr_sp_playlist_name(pl));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fptr_sp_link_as_string(link, url, sizeof(url));
|
||||||
|
if (ret == sizeof(url))
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_SPOTIFY, "Spotify link truncated: %s\n", url);
|
||||||
|
}
|
||||||
|
fptr_sp_link_release(link);
|
||||||
|
|
||||||
|
library_exec_async(webapi_pl_save, strdup(url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------- PLAYLIST CALLBACKS ------------------------- */
|
/* -------------------------- PLAYLIST CALLBACKS ------------------------- */
|
||||||
/**
|
/**
|
||||||
|
@ -966,17 +1002,30 @@ static void playlist_update_in_progress(sp_playlist *pl, bool done, void *userda
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Playlist update (status %d): %s\n", done, fptr_sp_playlist_name(pl));
|
DPRINTF(E_DBG, L_SPOTIFY, "Playlist update (status %d): %s\n", done, fptr_sp_playlist_name(pl));
|
||||||
|
|
||||||
if (!spotify_access_token_valid) // TODO Trigger update of library on pl change
|
if (spotify_access_token_valid)
|
||||||
|
{
|
||||||
|
webapi_playlist_updated(pl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
spotify_playlist_save(pl);
|
spotify_playlist_save(pl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void playlist_metadata_updated(sp_playlist *pl, void *userdata)
|
static void playlist_metadata_updated(sp_playlist *pl, void *userdata)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Playlist metadata updated: %s\n", fptr_sp_playlist_name(pl));
|
DPRINTF(E_DBG, L_SPOTIFY, "Playlist metadata updated: %s\n", fptr_sp_playlist_name(pl));
|
||||||
|
|
||||||
if (!spotify_access_token_valid) // TODO Trigger update of library on pl change
|
if (spotify_access_token_valid)
|
||||||
|
{
|
||||||
|
//TODO Update disabled to prevent multiple triggering of updates e. g. on adding a playlist
|
||||||
|
//webapi_playlist_updated(pl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
spotify_playlist_save(pl);
|
spotify_playlist_save(pl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1006,8 +1055,37 @@ static void playlist_added(sp_playlistcontainer *pc, sp_playlist *pl,
|
||||||
|
|
||||||
fptr_sp_playlist_add_callbacks(pl, &pl_callbacks, NULL);
|
fptr_sp_playlist_add_callbacks(pl, &pl_callbacks, NULL);
|
||||||
|
|
||||||
if (!spotify_access_token_valid) // TODO Trigger update of library on pl change
|
if (spotify_access_token_valid)
|
||||||
|
{
|
||||||
|
webapi_playlist_updated(pl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
spotify_playlist_save(pl);
|
spotify_playlist_save(pl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
playlist_remove(const char *uri)
|
||||||
|
{
|
||||||
|
struct playlist_info *pli;
|
||||||
|
int plid;
|
||||||
|
|
||||||
|
pli = db_pl_fetch_bypath(uri);
|
||||||
|
|
||||||
|
if (!pli)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_SPOTIFY, "Playlist %s not found, can't delete\n", uri);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
plid = pli->id;
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
|
|
||||||
|
db_spotify_pl_delete(plid);
|
||||||
|
spotify_cleanup_files();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1023,19 +1101,14 @@ static void playlist_added(sp_playlistcontainer *pc, sp_playlist *pl,
|
||||||
static void
|
static void
|
||||||
playlist_removed(sp_playlistcontainer *pc, sp_playlist *pl, int position, void *userdata)
|
playlist_removed(sp_playlistcontainer *pc, sp_playlist *pl, int position, void *userdata)
|
||||||
{
|
{
|
||||||
struct playlist_info *pli;
|
|
||||||
sp_link *link;
|
sp_link *link;
|
||||||
char url[1024];
|
char url[1024];
|
||||||
int plid;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DPRINTF(E_INFO, L_SPOTIFY, "Playlist removed: %s\n", fptr_sp_playlist_name(pl));
|
DPRINTF(E_INFO, L_SPOTIFY, "Playlist removed: %s\n", fptr_sp_playlist_name(pl));
|
||||||
|
|
||||||
fptr_sp_playlist_remove_callbacks(pl, &pl_callbacks, NULL);
|
fptr_sp_playlist_remove_callbacks(pl, &pl_callbacks, NULL);
|
||||||
|
|
||||||
if (spotify_access_token_valid) // TODO Trigger update of library on pl change
|
|
||||||
return;
|
|
||||||
|
|
||||||
link = fptr_sp_link_create_from_playlist(pl);
|
link = fptr_sp_link_create_from_playlist(pl);
|
||||||
if (!link)
|
if (!link)
|
||||||
{
|
{
|
||||||
|
@ -1050,21 +1123,16 @@ playlist_removed(sp_playlistcontainer *pc, sp_playlist *pl, int position, void *
|
||||||
}
|
}
|
||||||
fptr_sp_link_release(link);
|
fptr_sp_link_release(link);
|
||||||
|
|
||||||
pli = db_pl_fetch_bypath(url);
|
if (spotify_access_token_valid)
|
||||||
|
|
||||||
if (!pli)
|
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SPOTIFY, "Playlist %s not found, can't delete\n", url);
|
// Run playlist remove in the library thread
|
||||||
return;
|
if (!scanning)
|
||||||
|
library_exec_async(webapi_pl_remove, strdup(url));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playlist_remove(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
plid = pli->id;
|
|
||||||
|
|
||||||
free_pli(pli, 0);
|
|
||||||
|
|
||||||
db_spotify_pl_delete(plid);
|
|
||||||
|
|
||||||
spotify_cleanup_files();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1997,7 +2065,7 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch
|
||||||
spotify_access_token_valid = true;
|
spotify_access_token_valid = true;
|
||||||
|
|
||||||
// Trigger scan after successful access to spotifywebapi
|
// Trigger scan after successful access to spotifywebapi
|
||||||
library_exec_async(scan_webapi, NULL);
|
library_exec_async(webapi_scan, NULL);
|
||||||
|
|
||||||
evbuffer_add_printf(evbuf, "ok, all done</p>\n");
|
evbuffer_add_printf(evbuf, "ok, all done</p>\n");
|
||||||
|
|
||||||
|
@ -2140,6 +2208,9 @@ scan_saved_albums()
|
||||||
cache_artwork_ping(track.uri, album.mtime, 0);
|
cache_artwork_ping(track.uri, album.mtime, 0);
|
||||||
|
|
||||||
free_mfi(&mfi, 1);
|
free_mfi(&mfi, 1);
|
||||||
|
|
||||||
|
if (spotify_saved_plid)
|
||||||
|
db_pl_add_item_bypath(spotify_saved_plid, track.uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2224,8 +2295,10 @@ scan_playlists()
|
||||||
|
|
||||||
plid = library_add_playlist_info(playlist.uri, playlist.name, virtual_path, PL_PLAIN, spotify_base_plid, DIR_SPOTIFY);
|
plid = library_add_playlist_info(playlist.uri, playlist.name, virtual_path, PL_PLAIN, spotify_base_plid, DIR_SPOTIFY);
|
||||||
|
|
||||||
if (plid)
|
if (plid > 0)
|
||||||
scan_playlisttracks(&playlist, plid);
|
scan_playlisttracks(&playlist, plid);
|
||||||
|
else
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Error adding playlist: '%s' (%s) \n", playlist.name, playlist.uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2235,6 +2308,58 @@ scan_playlists()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Thread: library */
|
||||||
|
static int
|
||||||
|
scan_playlist(const char *uri)
|
||||||
|
{
|
||||||
|
struct spotify_request request;
|
||||||
|
struct spotify_playlist playlist;
|
||||||
|
char virtual_path[PATH_MAX];
|
||||||
|
int plid;
|
||||||
|
|
||||||
|
db_transaction_begin();
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(struct spotify_request));
|
||||||
|
|
||||||
|
if (0 == spotifywebapi_playlist_start(&request, uri, &playlist))
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_SPOTIFY, "Got playlist: '%s' (%s) \n", playlist.name, playlist.uri);
|
||||||
|
|
||||||
|
if (playlist.owner)
|
||||||
|
{
|
||||||
|
snprintf(virtual_path, PATH_MAX, "/spotify:/%s (%s)", playlist.name, playlist.owner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(virtual_path, PATH_MAX, "/spotify:/%s", playlist.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
plid = library_add_playlist_info(playlist.uri, playlist.name, virtual_path, PL_PLAIN, spotify_base_plid, DIR_SPOTIFY);
|
||||||
|
|
||||||
|
if (plid > 0)
|
||||||
|
scan_playlisttracks(&playlist, plid);
|
||||||
|
else
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Error adding playlist: '%s' (%s) \n", playlist.name, playlist.uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
spotifywebapi_request_end(&request);
|
||||||
|
db_transaction_end();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_saved_tracks_playlist()
|
||||||
|
{
|
||||||
|
spotify_saved_plid = library_add_playlist_info("spotify:savedtracks", "Spotify Saved", "/spotify:/Spotify Saved", PL_PLAIN, spotify_base_plid, DIR_SPOTIFY);
|
||||||
|
|
||||||
|
if (spotify_saved_plid <= 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Error adding playlist for saved tracks\n");
|
||||||
|
spotify_saved_plid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Thread: library */
|
/* Thread: library */
|
||||||
static int
|
static int
|
||||||
initscan()
|
initscan()
|
||||||
|
@ -2242,6 +2367,8 @@ initscan()
|
||||||
cfg_t *spotify_cfg;
|
cfg_t *spotify_cfg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
scanning = true;
|
||||||
|
|
||||||
/* Refresh access token for the spotify webapi */
|
/* Refresh access token for the spotify webapi */
|
||||||
spotify_access_token_valid = (0 == spotifywebapi_token_refresh());
|
spotify_access_token_valid = (0 == spotifywebapi_token_refresh());
|
||||||
if (!spotify_access_token_valid)
|
if (!spotify_access_token_valid)
|
||||||
|
@ -2257,6 +2384,7 @@ initscan()
|
||||||
* Add playlist folder for all spotify playlists
|
* Add playlist folder for all spotify playlists
|
||||||
*/
|
*/
|
||||||
spotify_base_plid = 0;
|
spotify_base_plid = 0;
|
||||||
|
spotify_saved_plid = 0;
|
||||||
spotify_cfg = cfg_getsec(cfg, "spotify");
|
spotify_cfg = cfg_getsec(cfg, "spotify");
|
||||||
if (! cfg_getbool(spotify_cfg, "base_playlist_disable"))
|
if (! cfg_getbool(spotify_cfg, "base_playlist_disable"))
|
||||||
{
|
{
|
||||||
|
@ -2278,10 +2406,13 @@ initscan()
|
||||||
*/
|
*/
|
||||||
if (spotify_access_token_valid)
|
if (spotify_access_token_valid)
|
||||||
{
|
{
|
||||||
|
create_saved_tracks_playlist();
|
||||||
scan_saved_albums();
|
scan_saved_albums();
|
||||||
scan_playlists();
|
scan_playlists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scanning = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2289,11 +2420,14 @@ initscan()
|
||||||
static int
|
static int
|
||||||
rescan()
|
rescan()
|
||||||
{
|
{
|
||||||
|
scanning = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan saved tracks from the web api
|
* Scan saved tracks from the web api
|
||||||
*/
|
*/
|
||||||
if (spotify_access_token_valid)
|
if (spotify_access_token_valid)
|
||||||
{
|
{
|
||||||
|
create_saved_tracks_playlist();
|
||||||
scan_saved_albums();
|
scan_saved_albums();
|
||||||
scan_playlists();
|
scan_playlists();
|
||||||
}
|
}
|
||||||
|
@ -2306,6 +2440,8 @@ rescan()
|
||||||
db_transaction_end();
|
db_transaction_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scanning = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2316,14 +2452,34 @@ fullrescan()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thread: httpd */
|
/* Thread: library */
|
||||||
static enum command_state
|
static enum command_state
|
||||||
scan_webapi(void *arg, int *ret)
|
webapi_scan(void *arg, int *ret)
|
||||||
{
|
{
|
||||||
*ret = rescan();
|
*ret = rescan();
|
||||||
return COMMAND_END;
|
return COMMAND_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Thread: library */
|
||||||
|
static enum command_state
|
||||||
|
webapi_pl_save(void *arg, int *ret)
|
||||||
|
{
|
||||||
|
const char *uri = arg;
|
||||||
|
|
||||||
|
*ret = scan_playlist(uri);
|
||||||
|
return COMMAND_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread: library */
|
||||||
|
static enum command_state
|
||||||
|
webapi_pl_remove(void *arg, int *ret)
|
||||||
|
{
|
||||||
|
const char *uri = arg;
|
||||||
|
|
||||||
|
*ret = playlist_remove(uri);
|
||||||
|
return COMMAND_END;
|
||||||
|
}
|
||||||
|
|
||||||
/* Thread: main */
|
/* Thread: main */
|
||||||
int
|
int
|
||||||
spotify_init(void)
|
spotify_init(void)
|
||||||
|
@ -2334,6 +2490,7 @@ spotify_init(void)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spotify_access_token_valid = false;
|
spotify_access_token_valid = false;
|
||||||
|
scanning = false;
|
||||||
|
|
||||||
/* Initialize libspotify */
|
/* Initialize libspotify */
|
||||||
g_libhandle = dlopen("libspotify.so", RTLD_LAZY);
|
g_libhandle = dlopen("libspotify.so", RTLD_LAZY);
|
||||||
|
|
|
@ -50,6 +50,7 @@ static const char *spotify_client_id = "0e684a5422384114a8ae7ac020f01789";
|
||||||
static const char *spotify_client_secret = "232af95f39014c9ba218285a5c11a239";
|
static const char *spotify_client_secret = "232af95f39014c9ba218285a5c11a239";
|
||||||
static const char *spotify_auth_uri = "https://accounts.spotify.com/authorize";
|
static const char *spotify_auth_uri = "https://accounts.spotify.com/authorize";
|
||||||
static const char *spotify_token_uri = "https://accounts.spotify.com/api/token";
|
static const char *spotify_token_uri = "https://accounts.spotify.com/api/token";
|
||||||
|
static const char *spotify_playlist_uri = "https://api.spotify.com/v1/users/%s/playlists/%s";
|
||||||
|
|
||||||
|
|
||||||
/*--------------------- HELPERS FOR SPOTIFY WEB API -------------------------*/
|
/*--------------------- HELPERS FOR SPOTIFY WEB API -------------------------*/
|
||||||
|
@ -690,18 +691,67 @@ spotifywebapi_playlists_fetch(struct spotify_request *request, struct spotify_pl
|
||||||
|
|
||||||
if (request->index >= request->count)
|
if (request->index >= request->count)
|
||||||
{
|
{
|
||||||
|
DPRINTF(E_DBG, L_SPOTIFY, "All playlists processed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonplaylist = json_object_array_get_idx(request->items, request->index);
|
jsonplaylist = json_object_array_get_idx(request->items, request->index);
|
||||||
|
if (!jsonplaylist)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Error fetching playlist at index '%d'\n", request->index);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
playlist_metadata(jsonplaylist, playlist);
|
playlist_metadata(jsonplaylist, playlist);
|
||||||
|
|
||||||
request->index++;
|
request->index++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extracts the owner and the id from a spotify playlist uri
|
||||||
|
*
|
||||||
|
* Playlist-uri has the following format: spotify:user:[owner]:playlist:[id]
|
||||||
|
* Owner and plid must be freed by the caller.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
get_owner_plid_from_uri(const char *uri, char **owner, char **plid)
|
||||||
|
{
|
||||||
|
char *ptr1;
|
||||||
|
char *ptr2;
|
||||||
|
char *tmp;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
ptr1 = strchr(uri, ':');
|
||||||
|
if (!ptr1)
|
||||||
|
return -1;
|
||||||
|
ptr1++;
|
||||||
|
ptr1 = strchr(ptr1, ':');
|
||||||
|
if (!ptr1)
|
||||||
|
return -1;
|
||||||
|
ptr1++;
|
||||||
|
ptr2 = strchr(ptr1, ':');
|
||||||
|
|
||||||
|
len = ptr2 - ptr1;
|
||||||
|
|
||||||
|
tmp = malloc(sizeof(char) * (len + 1));
|
||||||
|
strncpy(tmp, ptr1, len);
|
||||||
|
tmp[len] = '\0';
|
||||||
|
*owner = tmp;
|
||||||
|
|
||||||
|
ptr2++;
|
||||||
|
ptr1 = strchr(ptr2, ':');
|
||||||
|
if (!ptr1)
|
||||||
|
{
|
||||||
|
free(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ptr1++;
|
||||||
|
*plid = strdup(ptr1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
spotifywebapi_playlisttracks_fetch(struct spotify_request *request, struct spotify_track *track)
|
spotifywebapi_playlisttracks_fetch(struct spotify_request *request, struct spotify_track *track)
|
||||||
{
|
{
|
||||||
|
@ -731,3 +781,44 @@ spotifywebapi_playlisttracks_fetch(struct spotify_request *request, struct spoti
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spotifywebapi_playlist_start(struct spotify_request *request, const char *path, struct spotify_playlist *playlist)
|
||||||
|
{
|
||||||
|
char uri[1024];
|
||||||
|
char *owner;
|
||||||
|
char *id;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = get_owner_plid_from_uri(path, &owner, &id);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Error extracting owner and id from playlist uri '%s'\n", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snprintf(uri, sizeof(uri), spotify_playlist_uri, owner, id);
|
||||||
|
if (ret < 0 || ret >= sizeof(uri))
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SPOTIFY, "Error creating playlist endpoint uri for playlist '%s'\n", path);
|
||||||
|
free(owner);
|
||||||
|
free(id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = spotifywebapi_request_uri(request, uri);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
free(owner);
|
||||||
|
free(id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
request->haystack = json_tokener_parse(request->response_body);
|
||||||
|
playlist_metadata(request->haystack, playlist);
|
||||||
|
|
||||||
|
free(owner);
|
||||||
|
free(id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,7 @@ int
|
||||||
spotifywebapi_playlists_fetch(struct spotify_request *request, struct spotify_playlist* playlist);
|
spotifywebapi_playlists_fetch(struct spotify_request *request, struct spotify_playlist* playlist);
|
||||||
int
|
int
|
||||||
spotifywebapi_playlisttracks_fetch(struct spotify_request *request, struct spotify_track *track);
|
spotifywebapi_playlisttracks_fetch(struct spotify_request *request, struct spotify_track *track);
|
||||||
|
int
|
||||||
|
spotifywebapi_playlist_start(struct spotify_request *request, const char *path, struct spotify_playlist *playlist);
|
||||||
|
|
||||||
#endif /* SRC_SPOTIFY_WEBAPI_H_ */
|
#endif /* SRC_SPOTIFY_WEBAPI_H_ */
|
||||||
|
|
Loading…
Reference in New Issue