#include <stdio.h>
#include <libspotify/api.h>
#include <pthread.h>
#include <assert.h>
#include <mach/clock.h>
#include <mach/mach.h>
#define COMMAND_SP_LOGOUT 1
#define COMMAND_SP_PRINTUSER 2
extern uint8_t g_appkey[];
extern int g_appkey_size;
void notifyMainThread(sp_session* session);
void* spotifyLoop(void*);
void loggedIn(sp_session* session, sp_error error);
void loggedOut(sp_session* session);
void logMessage(sp_session* session, const char* data);
static sp_session* spotifySession;
static int notify_do = 0;
static int command = 0;
static int logged_out = 0;
static pthread_mutex_t notify_mutex;
static pthread_cond_t notify_cond;
static pthread_t spotifyThread;
static sp_session_callbacks sessionCallbacks = {
.notify_main_thread = ¬ifyMainThread,
.logged_in = &loggedIn,
.logged_out = &loggedOut,
.log_message = &logMessage,
};
static sp_session_config sessionConfig = {
.api_version = SPOTIFY_API_VERSION,
.cache_location = "tmp",
.settings_location = "tmp",
.application_key = g_appkey,
.application_key_size = 0,
.user_agent = "nodejs-spotify-adapter",
.callbacks = &sessionCallbacks,
NULL,
};
void* spotifyLoop(void* nervNicht) {
sp_error error;
sp_session* session;
int next_timeout = 0;
const char* username = "SET";
const char* password = "SET";
sessionConfig.application_key_size = g_appkey_size;
error = sp_session_create(&sessionConfig, &session);
if(SP_ERROR_OK != error) {
fprintf(stderr, "Could not create Spotify session: %s\n", sp_error_message(error));
}
spotifySession = session;
pthread_mutex_init(¬ify_mutex, NULL);
pthread_cond_init(¬ify_cond, NULL);
sp_session_login(session, username, password, 0, NULL);
pthread_mutex_lock(¬ify_mutex);
int log_out_called = 0;
while(!logged_out) {
if(log_out_called) fprintf(stdout, "Loop while logout in process, command: %d, notify: %d, timeout: %d\n", command, notify_do, next_timeout);
if(next_timeout == 0) {
while(notify_do == 0) {
pthread_cond_wait(¬ify_cond, ¬ify_mutex);
}
} else {
struct timespec ts;
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec + next_timeout / 1000;
ts.tv_nsec = mts.tv_nsec + (next_timeout % 1000) * 1000;
while(!notify_do && !command) {
if(pthread_cond_timedwait(¬ify_cond, ¬ify_mutex, &ts))
break;
}
}
if(log_out_called) fprintf(stdout, "2 Loop while logout in process, command: %d, notify: %d, timeout: %d\n", command, notify_do, next_timeout);
if(command) {
if(command == COMMAND_SP_LOGOUT) {
sp_session_logout(spotifySession);
log_out_called = 1;
} else if(command == COMMAND_SP_PRINTUSER) {
sp_user* user = sp_session_user(spotifySession);
const char* name = sp_user_display_name(user);
fprintf(stdout, "User: %s\n", name);
}
}
command = 0;
notify_do = 0;
pthread_mutex_unlock(¬ify_mutex);
do {
if(log_out_called) fprintf(stdout, "3 Loop while logout in process, command: %d, notify: %d, timeout: %d\n", command, notify_do, next_timeout);
sp_session_process_events(session, &next_timeout);
if(log_out_called) fprintf(stdout, "4 Loop while logout in process, command: %d, notify: %d, timeout: %d\n", command, notify_do, next_timeout);
} while(next_timeout == 0);
pthread_mutex_lock(¬ify_mutex);
}
sp_session_release(session);
fprintf(stdout, "Exiting spotify main loop\n");
return 0;
}
void notifyMainThread(sp_session* session) {
pthread_mutex_lock(¬ify_mutex);
notify_do = 1;
pthread_cond_signal(¬ify_cond);
pthread_mutex_unlock(¬ify_mutex);
}
void loggedIn(sp_session* session, sp_error error) {
if(SP_ERROR_OK != error) {
fprintf(stderr, "Error logging in: %s\n", sp_error_message(error));
} else {
fprintf(stdout, "Service is logged in!\n");
}
}
void loggedOut(sp_session* session) {
fprintf(stdout, "Service is logged out\n");
logged_out = 1;
}
void logMessage(sp_session* session, const char* data) {
fprintf(stdout, "%s\n", data);
}
void printUser() {
pthread_mutex_lock(¬ify_mutex);
command = COMMAND_SP_PRINTUSER;
pthread_cond_signal(¬ify_cond);
pthread_mutex_unlock(¬ify_mutex);
}
void logout() {
pthread_t caller = pthread_self();
fprintf(stdout, "Logout called by %u\n", (unsigned int)caller);
pthread_mutex_lock(¬ify_mutex);
command = COMMAND_SP_LOGOUT;
pthread_cond_signal(¬ify_cond);
pthread_mutex_unlock(¬ify_mutex);
}
void login() {
pthread_t caller = pthread_self();
fprintf(stdout, "Login called by %u\n", (unsigned int)caller);
pthread_create(&spotifyThread, NULL, spotifyLoop, NULL);
}