The Event Loop
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:
_67int has_logged_in = 0;_67int has_logged_out = 0;_67_67static 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_67int 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.