From 29c0264444038e476fc0efb7c1b3d49a51fac41b Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 19 Aug 2017 08:36:43 +0200 Subject: [PATCH] [spotify] Add spotify status info and notify about status changes --- src/spotify.c | 67 ++++++++++++++++++++++++++++++++++++++++++-- src/spotify.h | 15 ++++++++++ src/spotify_webapi.c | 25 +++++++++++++---- src/spotify_webapi.h | 4 +-- 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/src/spotify.c b/src/spotify.c index 066879e8..b8a1a2fa 100644 --- a/src/spotify.c +++ b/src/spotify.c @@ -55,6 +55,7 @@ #include "commands.h" #include "library.h" #include "input.h" +#include "listener.h" /* TODO for the web api: * - UI should be prettier @@ -140,6 +141,9 @@ static int spotify_saved_plid; // Flag to avoid triggering playlist change events while the (re)scan is running static bool scanning; +static pthread_mutex_t status_lck; +static struct spotify_status_info spotify_status_info; + // Timeout timespec static struct timespec spotify_artwork_timeout = { SPOTIFY_ARTWORK_TIMEOUT, 0 }; @@ -1415,6 +1419,14 @@ logged_in(sp_session *sess, sp_error error) if (SP_ERROR_OK != error) { DPRINTF(E_LOG, L_SPOTIFY, "Login failed: %s\n", fptr_sp_error_message(error)); + + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + spotify_status_info.libspotify_logged_in = false; + spotify_status_info.libspotify_user[0] = '\0'; + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); + + listener_notify(LISTENER_SPOTIFY); + return; } @@ -1439,6 +1451,14 @@ logged_in(sp_session *sess, sp_error error) pl = fptr_sp_playlistcontainer_playlist(pc, i); fptr_sp_playlist_add_callbacks(pl, &pl_callbacks, NULL); } + + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + spotify_status_info.libspotify_logged_in = true; + snprintf(spotify_status_info.libspotify_user, sizeof(spotify_status_info.libspotify_user), "%s", fptr_sp_session_user_name(sess)); + spotify_status_info.libspotify_user[sizeof(spotify_status_info.libspotify_user) - 1] = '\0'; + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); + + listener_notify(LISTENER_SPOTIFY); } /** @@ -1453,10 +1473,17 @@ logged_out(sp_session *sess) { DPRINTF(E_INFO, L_SPOTIFY, "Logout complete\n"); + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + spotify_status_info.libspotify_logged_in = false; + spotify_status_info.libspotify_user[0] = '\0'; + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); + CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&login_lck)); CHECK_ERR(L_SPOTIFY, pthread_cond_signal(&login_cond)); CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&login_lck)); + + listener_notify(LISTENER_SPOTIFY); } /** @@ -1802,6 +1829,7 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch { const char *code; const char *err; + char *user = NULL; int ret; code = evhttp_find_header(param, "code"); @@ -1815,7 +1843,7 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch evbuffer_add_printf(evbuf, "

Requesting access token from Spotify...\n"); - ret = spotifywebapi_token_get(code, redirect_uri, &err); + ret = spotifywebapi_token_get(code, redirect_uri, &user, &err); if (ret < 0) { evbuffer_add_printf(evbuf, "failed

\n

Error: %s

\n", err); @@ -1825,11 +1853,23 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch // Received a valid access token spotify_access_token_valid = true; + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + spotify_status_info.webapi_token_valid = spotify_access_token_valid; + if (user) + { + snprintf(spotify_status_info.webapi_user, sizeof(spotify_status_info.webapi_user), "%s", user); + spotify_status_info.webapi_user[sizeof(spotify_status_info.webapi_user) - 1] = '\0'; + free(user); + } + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); + // Trigger scan after successful access to spotifywebapi library_exec_async(webapi_scan, NULL); evbuffer_add_printf(evbuf, "ok, all done

\n"); + listener_notify(LISTENER_SPOTIFY); + return; } @@ -1842,6 +1882,14 @@ spotify_uri_register(const char *uri) commands_exec_async(cmdbase, uri_register, tmp); } +void +spotify_status_info_get(struct spotify_status_info *info) +{ + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + memcpy(info, &spotify_status_info, sizeof(struct spotify_status_info)); + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); +} + /* Thread: library */ void spotify_login(char **arglist) @@ -2237,10 +2285,12 @@ create_base_playlist() static int initscan() { + char *user = NULL; + scanning = true; /* Refresh access token for the spotify webapi */ - spotify_access_token_valid = (0 == spotifywebapi_token_refresh()); + spotify_access_token_valid = (0 == spotifywebapi_token_refresh(&user)); if (!spotify_access_token_valid) { DPRINTF(E_LOG, L_SPOTIFY, "Spotify webapi token refresh failed. " @@ -2249,6 +2299,15 @@ initscan() db_spotify_purge(); } + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + spotify_status_info.webapi_token_valid = spotify_access_token_valid; + if (user) + { + snprintf(spotify_status_info.webapi_user, sizeof(spotify_status_info.webapi_user), "%s", user); + spotify_status_info.webapi_user[sizeof(spotify_status_info.webapi_user) - 1] = '\0'; + free(user); + } + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); spotify_saved_plid = 0; @@ -2450,6 +2509,10 @@ spotify_init(void) break; } + CHECK_ERR(L_REMOTE, pthread_mutex_lock(&status_lck)); + spotify_status_info.libspotify_installed = true; + CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&status_lck)); + spotify_audio_buffer = evbuffer_new(); CHECK_ERR(L_SPOTIFY, evbuffer_enable_locking(spotify_audio_buffer, NULL)); diff --git a/src/spotify.h b/src/spotify.h index 0d1f0907..fffa9bb6 100644 --- a/src/spotify.h +++ b/src/spotify.h @@ -5,6 +5,18 @@ #include #include #include +#include + + +struct spotify_status_info +{ + bool libspotify_installed; + bool libspotify_logged_in; + char libspotify_user[100]; + + bool webapi_token_valid; + char webapi_user[100]; +}; int spotify_playback_setup(const char *path); @@ -39,6 +51,9 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch void spotify_login(char **arglist); +void +spotify_status_info_get(struct spotify_status_info *info); + int spotify_init(void); diff --git a/src/spotify_webapi.c b/src/spotify_webapi.c index 3be9f568..79a8906a 100644 --- a/src/spotify_webapi.c +++ b/src/spotify_webapi.c @@ -37,6 +37,7 @@ static char *spotify_access_token; static char *spotify_refresh_token; static char *spotify_user_country; +static char *spotify_user; static int32_t expires_in = 3600; static time_t token_requested = 0; @@ -172,7 +173,7 @@ request_uri(struct spotify_request *request, const char *uri) memset(request, 0, sizeof(struct spotify_request)); - if (0 > spotifywebapi_token_refresh()) + if (0 > spotifywebapi_token_refresh(NULL)) { return -1; } @@ -585,13 +586,15 @@ spotifywebapi_playlist_start(struct spotify_request *request, const char *path, } static int -request_user_country() +request_user_info() { struct spotify_request request; int ret; free(spotify_user_country); spotify_user_country = NULL; + free(spotify_user); + spotify_user = NULL; ret = request_uri(&request, spotify_me_uri); @@ -601,8 +604,10 @@ request_user_country() } else { + spotify_user = safe_strdup(jparse_str_from_obj(request.haystack, "id")); spotify_user_country = safe_strdup(jparse_str_from_obj(request.haystack, "country")); - DPRINTF(E_DBG, L_SPOTIFY, "User country: '%s'\n", spotify_user_country); + + DPRINTF(E_DBG, L_SPOTIFY, "User '%s', country '%s'\n", spotify_user, spotify_user_country); } spotifywebapi_request_end(&request); @@ -733,7 +738,7 @@ tokens_get(struct keyval *kv, const char **err) if (spotify_refresh_token) db_admin_set("spotify_refresh_token", spotify_refresh_token); - request_user_country(); + request_user_info(); ret = 0; @@ -746,7 +751,7 @@ tokens_get(struct keyval *kv, const char **err) } int -spotifywebapi_token_get(const char *code, const char *redirect_uri, const char **err) +spotifywebapi_token_get(const char *code, const char *redirect_uri, char **user, const char **err) { struct keyval kv; int ret; @@ -767,13 +772,17 @@ spotifywebapi_token_get(const char *code, const char *redirect_uri, const char * else ret = tokens_get(&kv, err); + if (user && ret == 0) + { + *user = safe_strdup(spotify_user); + } keyval_clear(&kv); return ret; } int -spotifywebapi_token_refresh() +spotifywebapi_token_refresh(char **user) { struct keyval kv; char *refresh_token; @@ -808,6 +817,10 @@ spotifywebapi_token_refresh() else ret = tokens_get(&kv, &err); + if (user && ret == 0) + { + *user = safe_strdup(spotify_user); + } free(refresh_token); keyval_clear(&kv); diff --git a/src/spotify_webapi.h b/src/spotify_webapi.h index a195217d..11af153c 100644 --- a/src/spotify_webapi.h +++ b/src/spotify_webapi.h @@ -98,9 +98,9 @@ struct spotify_request char * spotifywebapi_oauth_uri_get(const char *redirect_uri); int -spotifywebapi_token_get(const char *code, const char *redirect_uri, const char **err); +spotifywebapi_token_get(const char *code, const char *redirect_uri, char **user, const char **err); int -spotifywebapi_token_refresh(); +spotifywebapi_token_refresh(char **user); void spotifywebapi_request_end(struct spotify_request *request);