Skip to content

The Event Loop

Warning: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 SpConnectionLoginPassword() 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 username and password to SpConnectionLoginPassword(). Register a callback of type SpCallbackConnectionNotify() by calling SpRegisterConnectionCallbacks() to receive the notification kSpConnectionNotifyLoggedIn when 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:


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

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.