mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-15 08:45:02 -05:00
[spotify] Add spotify status info and notify about status changes
This commit is contained in:
parent
7bf6aec3a6
commit
29c0264444
@ -55,6 +55,7 @@
|
|||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "listener.h"
|
||||||
|
|
||||||
/* TODO for the web api:
|
/* TODO for the web api:
|
||||||
* - UI should be prettier
|
* - 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
|
// Flag to avoid triggering playlist change events while the (re)scan is running
|
||||||
static bool scanning;
|
static bool scanning;
|
||||||
|
|
||||||
|
static pthread_mutex_t status_lck;
|
||||||
|
static struct spotify_status_info spotify_status_info;
|
||||||
|
|
||||||
// Timeout timespec
|
// Timeout timespec
|
||||||
static struct timespec spotify_artwork_timeout = { SPOTIFY_ARTWORK_TIMEOUT, 0 };
|
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)
|
if (SP_ERROR_OK != error)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Login failed: %s\n", fptr_sp_error_message(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1439,6 +1451,14 @@ logged_in(sp_session *sess, sp_error error)
|
|||||||
pl = fptr_sp_playlistcontainer_playlist(pc, i);
|
pl = fptr_sp_playlistcontainer_playlist(pc, i);
|
||||||
fptr_sp_playlist_add_callbacks(pl, &pl_callbacks, NULL);
|
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");
|
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_mutex_lock(&login_lck));
|
||||||
|
|
||||||
CHECK_ERR(L_SPOTIFY, pthread_cond_signal(&login_cond));
|
CHECK_ERR(L_SPOTIFY, pthread_cond_signal(&login_cond));
|
||||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&login_lck));
|
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 *code;
|
||||||
const char *err;
|
const char *err;
|
||||||
|
char *user = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
code = evhttp_find_header(param, "code");
|
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, "<p>Requesting access token from Spotify...\n");
|
evbuffer_add_printf(evbuf, "<p>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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
evbuffer_add_printf(evbuf, "failed</p>\n<p>Error: %s</p>\n", err);
|
evbuffer_add_printf(evbuf, "failed</p>\n<p>Error: %s</p>\n", err);
|
||||||
@ -1825,11 +1853,23 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch
|
|||||||
// Received a valid access token
|
// Received a valid access token
|
||||||
spotify_access_token_valid = true;
|
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
|
// Trigger scan after successful access to spotifywebapi
|
||||||
library_exec_async(webapi_scan, 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");
|
||||||
|
|
||||||
|
listener_notify(LISTENER_SPOTIFY);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1842,6 +1882,14 @@ spotify_uri_register(const char *uri)
|
|||||||
commands_exec_async(cmdbase, uri_register, tmp);
|
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 */
|
/* Thread: library */
|
||||||
void
|
void
|
||||||
spotify_login(char **arglist)
|
spotify_login(char **arglist)
|
||||||
@ -2237,10 +2285,12 @@ create_base_playlist()
|
|||||||
static int
|
static int
|
||||||
initscan()
|
initscan()
|
||||||
{
|
{
|
||||||
|
char *user = NULL;
|
||||||
|
|
||||||
scanning = true;
|
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(&user));
|
||||||
if (!spotify_access_token_valid)
|
if (!spotify_access_token_valid)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SPOTIFY, "Spotify webapi token refresh failed. "
|
DPRINTF(E_LOG, L_SPOTIFY, "Spotify webapi token refresh failed. "
|
||||||
@ -2249,6 +2299,15 @@ initscan()
|
|||||||
|
|
||||||
db_spotify_purge();
|
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;
|
spotify_saved_plid = 0;
|
||||||
|
|
||||||
@ -2450,6 +2509,10 @@ spotify_init(void)
|
|||||||
break;
|
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();
|
spotify_audio_buffer = evbuffer_new();
|
||||||
|
|
||||||
CHECK_ERR(L_SPOTIFY, evbuffer_enable_locking(spotify_audio_buffer, NULL));
|
CHECK_ERR(L_SPOTIFY, evbuffer_enable_locking(spotify_audio_buffer, NULL));
|
||||||
|
@ -5,6 +5,18 @@
|
|||||||
#include <event2/event.h>
|
#include <event2/event.h>
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
#include <event2/http.h>
|
#include <event2/http.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct spotify_status_info
|
||||||
|
{
|
||||||
|
bool libspotify_installed;
|
||||||
|
bool libspotify_logged_in;
|
||||||
|
char libspotify_user[100];
|
||||||
|
|
||||||
|
bool webapi_token_valid;
|
||||||
|
char webapi_user[100];
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
spotify_playback_setup(const char *path);
|
spotify_playback_setup(const char *path);
|
||||||
@ -39,6 +51,9 @@ spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const ch
|
|||||||
void
|
void
|
||||||
spotify_login(char **arglist);
|
spotify_login(char **arglist);
|
||||||
|
|
||||||
|
void
|
||||||
|
spotify_status_info_get(struct spotify_status_info *info);
|
||||||
|
|
||||||
int
|
int
|
||||||
spotify_init(void);
|
spotify_init(void);
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
static char *spotify_access_token;
|
static char *spotify_access_token;
|
||||||
static char *spotify_refresh_token;
|
static char *spotify_refresh_token;
|
||||||
static char *spotify_user_country;
|
static char *spotify_user_country;
|
||||||
|
static char *spotify_user;
|
||||||
|
|
||||||
static int32_t expires_in = 3600;
|
static int32_t expires_in = 3600;
|
||||||
static time_t token_requested = 0;
|
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));
|
memset(request, 0, sizeof(struct spotify_request));
|
||||||
|
|
||||||
if (0 > spotifywebapi_token_refresh())
|
if (0 > spotifywebapi_token_refresh(NULL))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -585,13 +586,15 @@ spotifywebapi_playlist_start(struct spotify_request *request, const char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
request_user_country()
|
request_user_info()
|
||||||
{
|
{
|
||||||
struct spotify_request request;
|
struct spotify_request request;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
free(spotify_user_country);
|
free(spotify_user_country);
|
||||||
spotify_user_country = NULL;
|
spotify_user_country = NULL;
|
||||||
|
free(spotify_user);
|
||||||
|
spotify_user = NULL;
|
||||||
|
|
||||||
ret = request_uri(&request, spotify_me_uri);
|
ret = request_uri(&request, spotify_me_uri);
|
||||||
|
|
||||||
@ -601,8 +604,10 @@ request_user_country()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
spotify_user = safe_strdup(jparse_str_from_obj(request.haystack, "id"));
|
||||||
spotify_user_country = safe_strdup(jparse_str_from_obj(request.haystack, "country"));
|
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);
|
spotifywebapi_request_end(&request);
|
||||||
@ -733,7 +738,7 @@ tokens_get(struct keyval *kv, const char **err)
|
|||||||
if (spotify_refresh_token)
|
if (spotify_refresh_token)
|
||||||
db_admin_set("spotify_refresh_token", spotify_refresh_token);
|
db_admin_set("spotify_refresh_token", spotify_refresh_token);
|
||||||
|
|
||||||
request_user_country();
|
request_user_info();
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -746,7 +751,7 @@ tokens_get(struct keyval *kv, const char **err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
struct keyval kv;
|
||||||
int ret;
|
int ret;
|
||||||
@ -767,13 +772,17 @@ spotifywebapi_token_get(const char *code, const char *redirect_uri, const char *
|
|||||||
else
|
else
|
||||||
ret = tokens_get(&kv, err);
|
ret = tokens_get(&kv, err);
|
||||||
|
|
||||||
|
if (user && ret == 0)
|
||||||
|
{
|
||||||
|
*user = safe_strdup(spotify_user);
|
||||||
|
}
|
||||||
keyval_clear(&kv);
|
keyval_clear(&kv);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
spotifywebapi_token_refresh()
|
spotifywebapi_token_refresh(char **user)
|
||||||
{
|
{
|
||||||
struct keyval kv;
|
struct keyval kv;
|
||||||
char *refresh_token;
|
char *refresh_token;
|
||||||
@ -808,6 +817,10 @@ spotifywebapi_token_refresh()
|
|||||||
else
|
else
|
||||||
ret = tokens_get(&kv, &err);
|
ret = tokens_get(&kv, &err);
|
||||||
|
|
||||||
|
if (user && ret == 0)
|
||||||
|
{
|
||||||
|
*user = safe_strdup(spotify_user);
|
||||||
|
}
|
||||||
free(refresh_token);
|
free(refresh_token);
|
||||||
keyval_clear(&kv);
|
keyval_clear(&kv);
|
||||||
|
|
||||||
|
@ -98,9 +98,9 @@ struct spotify_request
|
|||||||
char *
|
char *
|
||||||
spotifywebapi_oauth_uri_get(const char *redirect_uri);
|
spotifywebapi_oauth_uri_get(const char *redirect_uri);
|
||||||
int
|
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
|
int
|
||||||
spotifywebapi_token_refresh();
|
spotifywebapi_token_refresh(char **user);
|
||||||
|
|
||||||
void
|
void
|
||||||
spotifywebapi_request_end(struct spotify_request *request);
|
spotifywebapi_request_end(struct spotify_request *request);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user