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:

int has_logged_in = 0;
int has_logged_out = 0;

static void CallbackConnectionNotify(enum SpConnectionNotification event,
                              void *context) {
  switch (event) {
  case kSpConnectionNotifyLoggedIn:
    LOG("Logged in\n");
    has_logged_in = 1;
    break;
  case kSpConnectionNotifyLoggedOut:
    LOG("Logged out\n");
    has_logged_in = 0;
    has_logged_out = 1;
    break;
...

  default:
    break;
  }
}
...

int main(int argc, char *argv[]) {
  SpError err;
  struct SpConnectionCallbacks connection_callbacks;

  memset(&connection_callbacks, 0, sizeof(connection_callbacks));
  connection_callbacks.on_notify = CallbackConnectionNotify;

...

  if (kSpErrorOk != (err = SpInit(&conf)))
    LOG("Error %d\n", err);
    return 0;
  }

  SpRegisterConnectionCallbacks(&connection_callbacks, NULL);

  err = SpConnectionLoginPassword(YOUR_USERNAME, YOUR_PASSWORD);
  if (err != kSpErrorOk) {
    LOG("Error %d\n", err);
    SpFree();
    return 0;
  }

  while (1) {
    err =  SpPumpEvents();
    if (kSpErrorOk != err || error_occurred) {
      goto end;
    }

    if (has_logged_in) {
      LOG("Login was successful. Logging out again.\n");
      has_logged_in = 0;
      SpConnectionLogout();
    }
    if (has_logged_out) {
      LOG("Logged out. Exiting.\n");
      break;
    }
  }

  SpFree();

  return 0;
}

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.