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
\nError: %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);