Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Seems to compile

  • Loading branch information...
commit 936bae1d1168203e840878bb830b62d695156617 1 parent ef727e1
Chris West authored
211 foo_input_spotify/SpotifySession.cpp
View
@@ -5,8 +5,6 @@
#include <foobar2000.h>
#include <libspotify/api.h>
-#include "../helpers/dropdown_helper.h"
-#include <functional>
#include <shlobj.h>
#include <stdint.h>
@@ -53,112 +51,102 @@ void CALLBACK play_token_lost(sp_session *sess);
BOOL CALLBACK makeSpotifySession(PINIT_ONCE initOnce, PVOID param, PVOID *context);
-class SpotifySession {
- INIT_ONCE initOnce;
- sp_session *sp;
- HANDLE loggedInEvent;
- SpotifyThreadData threadData;
- CriticalSection spotifyCS;
- HANDLE processEventsEvent;
-public:
- Buffer buf;
-
- SpotifySession() :
- loggedInEvent(CreateEvent(NULL, TRUE, FALSE, NULL)),
- threadData(spotifyCS) {
-
- processEventsEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-
- threadData.processEventsEvent = processEventsEvent;
- threadData.sess = getAnyway();
-
- memset(&initOnce, 0, sizeof(INIT_ONCE));
-
- static sp_session_callbacks session_callbacks = {};
- static sp_session_config spconfig = {};
-
- PWSTR path;
- if (SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &path))
- throw pfc::exception("couldn't get local app data path");
- size_t num;
- char lpath[MAX_PATH];
- if (wcstombs_s(&num, lpath, MAX_PATH, path, MAX_PATH))
- throw pfc::exception("couldn't convert local app data path");
- if (strcat_s(lpath, "\\foo_input_spotify"))
- throw pfc::exception("couldn't append to path");
-
- spconfig.api_version = SPOTIFY_API_VERSION,
- spconfig.cache_location = lpath;
- spconfig.settings_location = lpath;
- spconfig.application_key = g_appkey;
- spconfig.application_key_size = g_appkey_size;
- spconfig.user_agent = "spotify-foobar2000-faux-" MYVERSION;
- spconfig.userdata = this;
- spconfig.callbacks = &session_callbacks;
-
- session_callbacks.logged_in = &logged_in;
- session_callbacks.notify_main_thread = &notify_main_thread;
- session_callbacks.music_delivery = &music_delivery;
- session_callbacks.play_token_lost = &play_token_lost;
- session_callbacks.end_of_track = &end_of_track;
- session_callbacks.log_message = &log_message;
- session_callbacks.message_to_user = &message_to_user;
- session_callbacks.start_playback = &start_playback;
-
- {
- LockedCS lock(spotifyCS);
-
- if (NULL == CreateThread(NULL, 0, &spotifyThread, &threadData, 0, NULL)) {
- throw pfc::exception("Couldn't create thread");
- }
-
- sp_error err = sp_session_create(&spconfig, &sp);
-
- if (SP_ERROR_OK != err) {
- throw pfc::exception("Couldn't create spotify session");
- }
+SpotifySession::SpotifySession() :
+ loggedInEvent(CreateEvent(NULL, TRUE, FALSE, NULL)),
+ threadData(spotifyCS) {
+
+ processEventsEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ threadData.processEventsEvent = processEventsEvent;
+ threadData.sess = getAnyway();
+
+ memset(&initOnce, 0, sizeof(INIT_ONCE));
+
+ static sp_session_callbacks session_callbacks = {};
+ static sp_session_config spconfig = {};
+
+ PWSTR path;
+ if (SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &path))
+ throw pfc::exception("couldn't get local app data path");
+ size_t num;
+ char lpath[MAX_PATH];
+ if (wcstombs_s(&num, lpath, MAX_PATH, path, MAX_PATH))
+ throw pfc::exception("couldn't convert local app data path");
+ if (strcat_s(lpath, "\\foo_input_spotify"))
+ throw pfc::exception("couldn't append to path");
+
+ spconfig.api_version = SPOTIFY_API_VERSION,
+ spconfig.cache_location = lpath;
+ spconfig.settings_location = lpath;
+ spconfig.application_key = g_appkey;
+ spconfig.application_key_size = g_appkey_size;
+ spconfig.user_agent = "spotify-foobar2000-faux-" MYVERSION;
+ spconfig.userdata = this;
+ spconfig.callbacks = &session_callbacks;
+
+ session_callbacks.logged_in = &logged_in;
+ session_callbacks.notify_main_thread = &notify_main_thread;
+ session_callbacks.music_delivery = &music_delivery;
+ session_callbacks.play_token_lost = &play_token_lost;
+ session_callbacks.end_of_track = &end_of_track;
+ session_callbacks.log_message = &log_message;
+ session_callbacks.message_to_user = &message_to_user;
+ session_callbacks.start_playback = &start_playback;
+
+ {
+ LockedCS lock(spotifyCS);
+
+ if (NULL == CreateThread(NULL, 0, &spotifyThread, &threadData, 0, NULL)) {
+ throw pfc::exception("Couldn't create thread");
}
- }
- ~SpotifySession() {
- CloseHandle(loggedInEvent);
- CloseHandle(processEventsEvent);
- }
+ sp_error err = sp_session_create(&spconfig, &sp);
- sp_session *getAnyway() {
- return sp;
+ if (SP_ERROR_OK != err) {
+ throw pfc::exception("Couldn't create spotify session");
+ }
}
+}
- sp_session *get() {
- InitOnceExecuteOnce(&initOnce,
- makeSpotifySession,
- NULL,
- NULL);
- return getAnyway();
- }
+SpotifySession::~SpotifySession() {
+ CloseHandle(loggedInEvent);
+ CloseHandle(processEventsEvent);
+}
- CriticalSection &getSpotifyCS() {
- return spotifyCS;
- }
+sp_session *SpotifySession::getAnyway() {
+ return sp;
+}
- void waitForLogin() {
- WaitForSingleObject(loggedInEvent, INFINITE);
- }
+sp_session *SpotifySession::get() {
+ InitOnceExecuteOnce(&initOnce,
+ makeSpotifySession,
+ this,
+ NULL);
+ return getAnyway();
+}
- void loggedIn(sp_error err) {
- if (SP_ERROR_OK != err) {
- LockedCS lock(spotifyCS);
- pfc::string8 s = "Logging-in went wrong. This is not recoverable. Please restart";
- s += sp_error_message(err);
- console::error(s);
- }
- SetEvent(loggedInEvent);
- }
+CriticalSection &SpotifySession::getSpotifyCS() {
+ return spotifyCS;
+}
+
+void SpotifySession::waitForLogin() {
+ WaitForSingleObject(loggedInEvent, INFINITE);
+}
- void processEvents() {
- SetEvent(processEventsEvent);
+void SpotifySession::loggedIn(sp_error err) {
+ if (SP_ERROR_OK != err) {
+ LockedCS lock(spotifyCS);
+ pfc::string8 s = "Logging-in went wrong. This is not recoverable. Please restart";
+ s += sp_error_message(err);
+ console::error(s);
}
-};
+ SetEvent(loggedInEvent);
+}
+
+void SpotifySession::processEvents() {
+ SetEvent(processEventsEvent);
+}
+
BOOL CALLBACK makeSpotifySession(PINIT_ONCE initOnce, PVOID param, PVOID *context) {
pfc::string8 username;
@@ -167,15 +155,22 @@ BOOL CALLBACK makeSpotifySession(PINIT_ONCE initOnce, PVOID param, PVOID *contex
pfc::string8 password;
spotifyPassword.get(password);
+ SpotifySession *ss = static_cast<SpotifySession *>(param);
{
- sp_session *sess = ss.getAnyway();
- LockedCS lock(ss.getSpotifyCS());
+
+ sp_session *sess = ss->getAnyway();
+ LockedCS lock(ss->getSpotifyCS());
sp_session_login(sess, username.get_ptr(), password.get_ptr());
}
- ss.waitForLogin();
+ ss->waitForLogin();
return TRUE;
}
+/** sp_session_userdata is assumed to be thread safe. */
+SpotifySession *from(sp_session *sess) {
+ return static_cast<SpotifySession *>(sp_session_userdata(sess));
+}
+
void CALLBACK log_message(sp_session *sess, const char *error) {
console::formatter() << "spotify log: " << error;
}
@@ -190,23 +185,23 @@ void CALLBACK start_playback(sp_session *sess) {
void CALLBACK logged_in(sp_session *sess, sp_error error)
{
- ss.loggedIn(error);
+ from(sess)->loggedIn(error);
}
void CALLBACK notify_main_thread(sp_session *sess)
{
- ss.processEvents();
+ from(sess)->processEvents();
}
int CALLBACK music_delivery(sp_session *sess, const sp_audioformat *format,
const void *frames, int num_frames)
{
if (num_frames == 0) {
- ss.buf.flush();
+ from(sess)->buf.flush();
return 0;
}
- if (ss.buf.isFull()) {
+ if (from(sess)->buf.isFull()) {
return 0;
}
@@ -215,17 +210,17 @@ int CALLBACK music_delivery(sp_session *sess, const sp_audioformat *format,
void *data = new char[s];
memcpy(data, frames, s);
- ss.buf.add(data, s, format->sample_rate, format->channels);
+ from(sess)->buf.add(data, s, format->sample_rate, format->channels);
return num_frames;
}
void CALLBACK end_of_track(sp_session *sess)
{
- ss.buf.add(NULL, 0, 0, 0);
+ from(sess)->buf.add(NULL, 0, 0, 0);
}
void CALLBACK play_token_lost(sp_session *sess)
{
- failed = true;
+ console::complain("Message from Spotify", "play token lost");
}
38 foo_input_spotify/SpotifySession.h
View
@@ -0,0 +1,38 @@
+#include "util.h"
+#include <libspotify/api.h>
+
+struct SpotifyThreadData {
+ SpotifyThreadData(CriticalSection &cs) : cs(cs) {
+ }
+
+ HANDLE processEventsEvent;
+ CriticalSection &cs;
+ sp_session *sess;
+};
+
+class SpotifySession {
+ INIT_ONCE initOnce;
+ sp_session *sp;
+ HANDLE loggedInEvent;
+ SpotifyThreadData threadData;
+ CriticalSection spotifyCS;
+ HANDLE processEventsEvent;
+public:
+ Buffer buf;
+
+ SpotifySession();
+
+ ~SpotifySession();
+
+ sp_session *getAnyway();
+
+ sp_session *get();
+
+ CriticalSection &getSpotifyCS();
+
+ void waitForLogin();
+
+ void loggedIn(sp_error err);
+
+ void processEvents();
+};
2  foo_input_spotify/foo_input_spotify.vcxproj
View
@@ -14,9 +14,11 @@
<ClCompile Include="input_spotify.cpp" />
<ClCompile Include="key-930.c" />
<ClCompile Include="SpotifySession.cpp" />
+ <ClCompile Include="util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="SpotifySession.h" />
+ <ClInclude Include="util.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{02F13FAE-C9D9-4C70-A691-582C3B49B15C}</ProjectGuid>
6 foo_input_spotify/foo_input_spotify.vcxproj.filters
View
@@ -24,10 +24,16 @@
<ClCompile Include="SpotifySession.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SpotifySession.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
99 foo_input_spotify/input_spotify.cpp
View
@@ -3,7 +3,6 @@
#define _WIN32_WINNT 0x0600
#include <foobar2000.h>
-#include <libspotify/api.h>
#include "../helpers/dropdown_helper.h"
#include <functional>
@@ -21,101 +20,6 @@ extern "C" {
SpotifySession ss;
-volatile bool failed = false;
-
-struct Gentry {
- void *data;
- size_t size;
- int sampleRate;
- int channels;
-};
-
-struct CriticalSection {
- CRITICAL_SECTION cs;
- CriticalSection() {
- InitializeCriticalSection(&cs);
- }
-
- ~CriticalSection() {
- DeleteCriticalSection(&cs);
- }
-};
-
-struct LockedCS {
- CRITICAL_SECTION &cs;
- LockedCS(CriticalSection &o) : cs(o.cs) {
- EnterCriticalSection(&cs);
- }
-
- ~LockedCS() {
- LeaveCriticalSection(&cs);
- }
-};
-
-struct Buffer {
-
- size_t entries;
- size_t ptr;
-
- static const size_t MAX_ENTRIES = 255;
-
- Gentry *entry[MAX_ENTRIES];
-
- CONDITION_VARIABLE bufferNotEmpty;
- CriticalSection bufferLock;
-
- Buffer() : entries(0), ptr(0) {
- InitializeConditionVariable(&bufferNotEmpty);
- }
-
- ~Buffer() {
- flush();
- }
-
- void add(void *data, size_t size, int sampleRate, int channels) {
- Gentry *e = new Gentry;
- e->data = data;
- e->size = size;
- e->sampleRate = sampleRate;
- e->channels = channels;
-
- {
- LockedCS lock(bufferLock);
- entry[(ptr + entries) % MAX_ENTRIES] = e;
- ++entries;
- }
- WakeConditionVariable(&bufferNotEmpty);
- }
-
- bool isFull() {
- return entries >= MAX_ENTRIES;
- }
-
- void flush() {
- while (entries > 0)
- free(take());
- }
-
- Gentry *take() {
- LockedCS lock(bufferLock);
- while (entries == 0) {
- SleepConditionVariableCS(&bufferNotEmpty, &bufferLock.cs, INFINITE);
- }
-
- Gentry *e = entry[ptr++];
- --entries;
- if (MAX_ENTRIES == ptr)
- ptr = 0;
-
- return e;
- }
-
- void free(Gentry *e) {
- delete[] e->data;
- delete e;
- }
-};
-
// {FDE57F91-397C-45F6-B907-A40E378DDB7A}
static const GUID spotifyUsernameGuid =
{ 0xfde57f91, 0x397c, 0x45f6, { 0xb9, 0x7, 0xa4, 0xe, 0x37, 0x8d, 0xdb, 0x7a } };
@@ -201,9 +105,6 @@ class InputSpotify
bool decode_run( audio_chunk & p_chunk, abort_callback & p_abort )
{
- if (failed)
- throw exception_io_data("failed");
-
Gentry *e = ss.buf.take();
if (NULL == e->data) {
52 foo_input_spotify/util.cpp
View
@@ -0,0 +1,52 @@
+#include "util.h"
+
+Buffer::Buffer() : entries(0), ptr(0) {
+ InitializeConditionVariable(&bufferNotEmpty);
+}
+
+Buffer::~Buffer() {
+ flush();
+}
+
+void Buffer::add(void *data, size_t size, int sampleRate, int channels) {
+ Gentry *e = new Gentry;
+ e->data = data;
+ e->size = size;
+ e->sampleRate = sampleRate;
+ e->channels = channels;
+
+ {
+ LockedCS lock(bufferLock);
+ entry[(ptr + entries) % MAX_ENTRIES] = e;
+ ++entries;
+ }
+ WakeConditionVariable(&bufferNotEmpty);
+}
+
+bool Buffer::isFull() {
+ return entries >= MAX_ENTRIES;
+}
+
+void Buffer::flush() {
+ while (entries > 0)
+ free(take());
+}
+
+Gentry *Buffer::take() {
+ LockedCS lock(bufferLock);
+ while (entries == 0) {
+ SleepConditionVariableCS(&bufferNotEmpty, &bufferLock.cs, INFINITE);
+ }
+
+ Gentry *e = entry[ptr++];
+ --entries;
+ if (MAX_ENTRIES == ptr)
+ ptr = 0;
+
+ return e;
+}
+
+void Buffer::free(Gentry *e) {
+ delete[] e->data;
+ delete e;
+}
57 foo_input_spotify/util.h
View
@@ -0,0 +1,57 @@
+#pragma once
+
+#define MYVERSION "0.1"
+
+#define _WIN32_WINNT 0x0600
+
+#include <windows.h>
+
+struct Gentry {
+ void *data;
+ size_t size;
+ int sampleRate;
+ int channels;
+};
+
+struct CriticalSection {
+ CRITICAL_SECTION cs;
+ CriticalSection() {
+ InitializeCriticalSection(&cs);
+ }
+
+ ~CriticalSection() {
+ DeleteCriticalSection(&cs);
+ }
+};
+
+struct LockedCS {
+ CRITICAL_SECTION &cs;
+ LockedCS(CriticalSection &o) : cs(o.cs) {
+ EnterCriticalSection(&cs);
+ }
+
+ ~LockedCS() {
+ LeaveCriticalSection(&cs);
+ }
+};
+
+struct Buffer {
+
+ size_t entries;
+ size_t ptr;
+
+ static const size_t MAX_ENTRIES = 255;
+
+ Gentry *entry[MAX_ENTRIES];
+
+ CONDITION_VARIABLE bufferNotEmpty;
+ CriticalSection bufferLock;
+
+ Buffer();
+ ~Buffer();
+ void add(void *data, size_t size, int sampleRate, int channels);
+ bool isFull();
+ void flush();
+ Gentry *take();
+ void free(Gentry *e);
+};
Please sign in to comment.
Something went wrong with that request. Please try again.