Skip to content

The Event Loop

Commercial Hardware tools and the eSDK are available only for approved partners

In order to do work, the library function SpPumpEvents() must be called periodically. This is where the library performs all asynchronous operations, and this is where it invokes the callback functions that the application registers (such as the error callback that is specified in SpConfig::error_callback).

There are two major ways to write the main event loop:

  • Call SpPumpEvents() from the application's main event loop
  • Call SpPumpEvents() from a separate thread and communicate with the application's main thread

In both cases, you must make sure that you never invoke Spotify Embedded APIs from different threads. The Spotify Embedded SDK is not thread-safe, and will typically refuse to execute APIs called from another thread. See Threading for details.

Logging In And Logging Out

Note: The following example uses SpConnectionLoginOauthToken() to log in. This API exists for testing purposes only.

In order to be certified, hardware devices must either enable the internal ZeroConf implementation (see SpConfig::zeroconf_serve), or implement the ZeroConf in the eSDK integration and use the function SpConnectionLoginZeroConf() to log in.

Change the code from the previous example so that it passes a valid Spotify OAuth access token (see Authorization Guide) to SpConnectionLoginOauthToken(). Register a callback of type SpCallbackConnectionNotify() by calling SpRegisterConnectionCallbacks() to receive the notification kSpConnectionNotifyLoggedInwhen login is successful.

As soon as the example application has logged in successfully, it will log out again using SpConnectionLogout() and wait for the notification kSpConnectionNotifyLoggedOut.

Here is the new code:


_68
int has_logged_in = 0;
_68
int has_logged_out = 0;
_68
_68
static void CallbackConnectionNotify(enum SpConnectionNotification event,
_68
void *context) {
_68
switch (event) {
_68
case kSpConnectionNotifyLoggedIn:
_68
LOG("Logged in\n");
_68
has_logged_in = 1;
_68
break;
_68
case kSpConnectionNotifyLoggedOut:
_68
LOG("Logged out\n");
_68
has_logged_in = 0;
_68
has_logged_out = 1;
_68
break;
_68
...
_68
_68
default:
_68
break;
_68
}
_68
}
_68
_68
...
_68
_68
int main(int argc, char *argv[]) {
_68
SpError err;
_68
struct SpConnectionCallbacks connection_callbacks;
_68
_68
memset(&connection_callbacks, 0, sizeof(connection_callbacks));
_68
connection_callbacks.on_notify = CallbackConnectionNotify;
_68
_68
...
_68
_68
if (kSpErrorOk != (err = SpInit(&conf)))
_68
LOG("Error %d\n", err);
_68
return 0;
_68
}
_68
_68
SpRegisterConnectionCallbacks(&connection_callbacks, NULL);
_68
_68
err = SpConnectionLoginOauthToken(YOUR_OAUTH_TOKEN);
_68
if (err != kSpErrorOk) {
_68
LOG("Error %d\n", err);
_68
SpFree();
_68
return 0;
_68
}
_68
_68
while (1) {
_68
err = SpPumpEvents();
_68
if (kSpErrorOk != err || error_occurred) {
_68
goto end;
_68
}
_68
_68
if (has_logged_in) {
_68
LOG("Login was successful. Logging out again.\n");
_68
has_logged_in = 0;
_68
SpConnectionLogout();
_68
}
_68
if (has_logged_out) {
_68
LOG("Logged out. Exiting.\n");
_68
break;
_68
}
_68
}
_68
_68
SpFree();
_68
_68
return 0;
_68
}

Writing Callbacks

The application should not perform time-consuming tasks in any of the callbacks. Try to return from the callback as quickly as possible. If a time-consuming operation needs to be performed as a reaction to an event, the callback should trigger an asynchronous task.

Note: Only Spotify Embedded API functions that are explicitly marked as such are allowed to be invoked from callbacks.