Exemple #1
0
static void playlistcontainer_loaded(sp_playlistcontainer *pc, void *userdata) {
  syslog(LOG_DEBUG, "playlistcontainer_loaded\n");
  sp_session *session = userdata;
  struct state *state = sp_session_userdata(session);

  sp_playlistcontainer_remove_callbacks(pc, &playlistcontainer_callbacks, session);

  state->http = evhttp_new(state->event_base);
  evhttp_set_timeout(state->http, 60);
  evhttp_set_gencb(state->http, &handle_request, state);

  // Bind HTTP server
  int bind = evhttp_bind_socket(state->http, state->http_host,
                                state->http_port);

  if (bind == -1) {
    syslog(LOG_WARNING, "Could not bind HTTP server socket to %s:%d",
           state->http_host, state->http_port);
    sp_session_logout(session);
    return;
  }

  syslog(LOG_DEBUG, "HTTP server listening on %s:%d", state->http_host,
         state->http_port);
}
Exemple #2
0
static void
connection_error(sp_session * session, sp_error error)
{
    PyGILState_STATE gstate;
    PyObject *res, *err, *method;

#ifdef DEBUG
        fprintf(stderr, "[DEBUG]-session- >> connection_error called\n");
#endif
    gstate = PyGILState_Ensure();
    Session *psession =
        (Session *) PyObject_CallObject((PyObject *)&SessionType, NULL);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);

    err = error_message(error);
    method = PyObject_GetAttrString(client, "connection_error");
    res = PyObject_CallFunctionObjArgs(method, psession, err, NULL);
    if (!res)
        PyErr_WriteUnraisable(method);
    Py_DECREF(psession);
    Py_DECREF(err);
    Py_XDECREF(res);
    Py_DECREF(method);
    PyGILState_Release(gstate);
}
Exemple #3
0
static void
notify_main_thread(sp_session * session)
{
    PyGILState_STATE gstate;
    PyObject *res, *method;

#ifdef DEBUG
        fprintf(stderr, "[DEBUG]-session- >> notify_main_thread called\n");
#endif
    if (!session_constructed)
        return;
    gstate = PyGILState_Ensure();
    Session *psession =
        (Session *) PyObject_CallObject((PyObject *)&SessionType, NULL);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);

    if (client != NULL) {
        method = PyObject_GetAttrString(client, "wake");
        res = PyObject_CallFunctionObjArgs(method, psession, NULL);
        if (!res)
            PyErr_WriteUnraisable(method);
        Py_XDECREF(res);
        Py_DECREF(method);
    }
    Py_DECREF(psession);
    PyGILState_Release(gstate);
}
Exemple #4
0
static void
log_message(sp_session * session, const char *data)
{
    PyGILState_STATE gstate;
    PyObject *res, *method, *msg;

#ifdef DEBUG
        fprintf(stderr, "[DEBUG]-session- >> log message: %s\n", data);
#endif
    gstate = PyGILState_Ensure();
    Session *psession =
        (Session *) PyObject_CallObject((PyObject *)&SessionType, NULL);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);

    msg = PyUnicode_FromString(data);
    method = PyObject_GetAttrString(client, "log_message");
    res = PyObject_CallFunctionObjArgs(method, psession, msg, NULL);
    if (!res)
        PyErr_WriteUnraisable(method);
    Py_DECREF(psession);
    Py_XDECREF(res);
    Py_DECREF(msg);
    Py_DECREF(method);
    PyGILState_Release(gstate);
}
int
SpotifyPlayback::musicDelivery(sp_session *session, const sp_audioformat *format, const void *frames, int numFrames_)
{
    SpotifySession* _session = reinterpret_cast<SpotifySession*>(sp_session_userdata(session));
    Q_ASSERT (_session);

    QMutex &m = _session->Playback()->dataMutex();

    _session->Playback()->m_currChannels = format->channels;
    _session->Playback()->m_currFrames = numFrames_;
    _session->Playback()->m_currSamples = format->sample_rate;

    if (numFrames_ == 0) // flush caches
    {
        QMutexLocker l(&m);
        _session->Playback()->clearData();
        return 0;
    }

    m.lock();
    // libspotify v11 bug, seems to retry to push the last batch of audio no matter what. short-circuit to ignore
    if ( _session->Playback()->trackIsOver() ) {
        m.unlock();
        return numFrames_;
    }

    const QByteArray data( (const char*)frames, numFrames_ * 4 ); // 4 == channels * ( bits per sample / 8 ) == 2 * ( 16 / 8 ) == 2 * 2
    _session->Playback()->queueData( data );
    m.unlock();

    return numFrames_; // num frames read, not bytes read. we always read all the frames
}
void SpotifyClient::LoggedInCallback(sp_session* session, sp_error error) {
  SpotifyClient* me = reinterpret_cast<SpotifyClient*>(sp_session_userdata(session));
  const bool success = error == SP_ERROR_OK;
  spotify_pb::LoginResponse_Error error_code = spotify_pb::LoginResponse_Error_Other;

  if (!success) {
    qLog(Warning) << "Failed to login" << sp_error_message(error);
  }

  switch (error) {
  case SP_ERROR_BAD_USERNAME_OR_PASSWORD:
    error_code = spotify_pb::LoginResponse_Error_BadUsernameOrPassword;
    break;
  case SP_ERROR_USER_BANNED:
    error_code = spotify_pb::LoginResponse_Error_UserBanned;
    break;
  case SP_ERROR_USER_NEEDS_PREMIUM :
    error_code = spotify_pb::LoginResponse_Error_UserNeedsPremium;
    break;
  }

  me->SendLoginCompleted(success, sp_error_message(error), error_code);

  if (success) {
    sp_playlistcontainer_add_callbacks(
          sp_session_playlistcontainer(session),
          &me->playlistcontainer_callbacks_, me);
  }
}
Exemple #7
0
static void logged_out(sp_session *session) {
  fprintf(stderr, "logged_out\n");
  struct state *state = sp_session_userdata(session);
  event_del(state->async);
  event_del(state->timer);
  event_del(state->sigint);
  event_base_loopbreak(state->event_base);
  apr_pool_destroy(state->pool);
}
void
SpotifyPlayback::endOfTrack(sp_session *session)
{
    SpotifySession* _session = reinterpret_cast<SpotifySession*>( sp_session_userdata( session ) );
//     qDebug() << "Got spotify end of track callback!";
    if ( !_session->Playback()->trackIsOver() )
        _session->Playback()->endTrack();

}
Exemple #9
0
static void logged_out_callback(sp_session *session) {
    TRACE("logged_out_callback\n");

    struct owl_state* state = sp_session_userdata(session);

    state->state = OWL_STATE_INITIALIZED;
    INFO("Logged out from Spotify\n");

    respond_success(state->http_request);
}
Exemple #10
0
void logged_out(sp_session *session) {
  syslog(LOG_DEBUG, "logged_out\n");
  struct state *state = sp_session_userdata(session);
  event_del(state->async);
  event_del(state->timer);
  event_del(state->sigint);
  event_base_loopbreak(state->event_base);
  apr_pool_destroy(state->pool);
  closelog();
}
Exemple #11
0
static void connection_error(sp_session *session, sp_error error) {
    // fprintf(stderr, "----------> connection_error called\n");
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    Session *psession = (Session *)PyObject_CallObject((PyObject *)&SessionType, NULL);
    Py_INCREF(psession);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    PyObject_CallMethod(client, "connection_error", "Oi", psession, error);
    Py_DECREF(psession);
    PyGILState_Release(gstate);
}
Exemple #12
0
static void log_message(sp_session *session, const char *data) {
    // fprintf(stderr, "----------> log_message called: %s\n", data);
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    Session *psession = (Session *)PyObject_CallObject((PyObject *)&SessionType, NULL);
    Py_INCREF(psession);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    PyObject_CallMethod(client, "log_message", "Os", psession, data);
    Py_DECREF(psession);
    PyGILState_Release(gstate);
}
Exemple #13
0
static void end_of_track(sp_session *session) {
    // fprintf(stderr, "----------> end_of_track called\n");
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    Session *psession = (Session *)PyObject_CallObject((PyObject *)&SessionType, NULL);
    Py_INCREF(psession);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    PyObject_CallMethod(client, "end_of_track", "O", psession);
    Py_DECREF(psession);
    PyGILState_Release(gstate);
}
Exemple #14
0
static void message_to_user(sp_session *session, const char *message) {
    // fprintf(stderr, "----------> message to user: %s\n", message);
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    Session *psession = (Session *)PyObject_CallObject((PyObject *)&SessionType, NULL);
    Py_INCREF(psession);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    PyObject_CallMethod(client, "message_to_user", "Os", psession, message);
    Py_DECREF(psession);
    PyGILState_Release(gstate);
}
/**
  credentialsBlobUpdated
  callback from login when we get the blob, used instead of plain password
  will send blob to application to storage
  @note its up the the application to store it
  @note2: it will be fired more than once, always store latest blob
  @note3: if user have no cache, it will fire once, if cache it will (maybe) update current blob
  **/
void SpotifySession::credentialsBlobUpdated(sp_session *session, const char *blob)
{

    SpotifySession* _session = reinterpret_cast<SpotifySession*>(sp_session_userdata(session));
#if SPOTIFY_API_VERSION >= 12
    const char* username = sp_session_user_name( session );
#else
    const char* username = sp_user_canonical_name( sp_session_user( session ) );
#endif
    _session->m_blob = QByteArray(blob);
    qDebug() << " ==== Got blob update for " << QString::fromUtf8(username, strlen(username) ) << " ==== ";
    emit _session->blobUpdated( username, QByteArray(blob).constData() );
}
Exemple #16
0
static void logged_in(sp_session *session, sp_error error)
{
	spotify_object *p = sp_session_userdata(session);
	p->is_logged_in = 1;

	if (SP_ERROR_OK != error) {
		p->is_logged_out = 1;
		sp_session_release(session);

		char *errMsg;
		spprintf(&errMsg, 0, "login failed: %s", sp_error_message(error));
		zend_throw_exception((zend_class_entry*)zend_exception_get_default(), errMsg, 0 TSRMLS_CC);
	}
}
Exemple #17
0
static void notify_main_thread(sp_session *session) {
    // fprintf(stderr, "----------> notify_main_thread\n");
    if(!session_constructed) return;
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    Session *psession = (Session *)PyObject_CallObject((PyObject *)&SessionType, NULL);
    Py_INCREF(psession);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    if(client != NULL) {
        PyObject_CallMethod(client, "wake", "O", psession);
    }
    Py_DECREF(psession);
    PyGILState_Release(gstate);
}
Exemple #18
0
static int
music_delivery(sp_session * session, const sp_audioformat * format,
               const void *frames, int num_frames)
{
    /* TODO: This is called _all_ the time, make it faster? */

    // Note that we do not try to shoe horn this into session_callback as it is
    // quite different in that this needs to handle return values and much more
    // complicated arguments.

    debug_printf(">> music_delivery called: frames %d", num_frames);

    int consumed = num_frames;  // assume all consumed
    int size = frame_size(format);

    PyObject *callback, *client, *py_frames, *py_session, *result;
    PyGILState_STATE gstate = PyGILState_Ensure();

    /* TODO: check if session creations succeeds. */
    py_frames = PyBuffer_FromMemory((void *)frames, num_frames * size);
    py_session = Session_FromSpotify(session);

    /* TODO: check if callback get succeeds. */
    client = (PyObject *)sp_session_userdata(session);
    callback = PyObject_GetAttrString(client, "music_delivery");

    result = PyObject_CallFunction(callback, "NNiiiii", py_session, py_frames,
                                   size, num_frames, format->sample_type,
                                   format->sample_rate, format->channels);

    if (result == NULL)
        PyErr_WriteUnraisable(callback);
    else {
        if (PyInt_Check(result))
            consumed = (int)PyInt_AsLong(result);
        else if (PyLong_Check(result))
            consumed = (int)PyLong_AsLong(result);
        else {
            PyErr_SetString(PyExc_TypeError,
                            "music_delivery must return an integer");
            PyErr_WriteUnraisable(callback);
        }
        Py_DECREF(result);
    }
    Py_XDECREF(callback);
    PyGILState_Release(gstate);
    return consumed;
}
Exemple #19
0
//
// -- Spotify callbacks ---------------------------------------------------------------------------
//
static void logged_in_callback(sp_session *session, sp_error error) {
    TRACE("logged_in_callback\n");
    struct owl_state* state = sp_session_userdata(session);

    if(error == SP_ERROR_OK) {
        state->state = OWL_STATE_IDLE;
        INFO("Logged in to Spotify!\n");
        respond_success(state->http_request);
    }
    else {
        state->state = OWL_STATE_INITIALIZED;
        ERROR("Failed to login to Spotify: %s\n", sp_error_message(error));

        respond_error(state->http_request, OWL_HTTP_ERROR_LOGIN, sp_error_message(error));
    }
}
Exemple #20
0
static void logged_in(sp_session *session, sp_error error) {
  if (error != SP_ERROR_OK) {
    fprintf(stderr, "%s\n", sp_error_message(error));
    exit_status = EXIT_FAILURE;
    logged_out(session);
    return;
  }

  struct state *state = sp_session_userdata(session);
  state->session = session;
  evsignal_add(state->sigint, NULL);

  sp_playlistcontainer *pc = sp_session_playlistcontainer(session);
  sp_playlistcontainer_add_callbacks(pc, &playlistcontainer_callbacks,
                                     session);
}
/**
  loggedout
  callback
  will relogin if true
  **/
void SpotifySession::loggedOut(sp_session *session)
{
    SpotifySession* _session = reinterpret_cast<SpotifySession*>(sp_session_userdata(session));
    _session->setLoggedIn( false );
    qDebug() << "Logging out";

    /// @note: This will login the user after previous user
    ///        was properly logged out.
    if(_session->m_relogin)
    {
        _session->m_relogin = false;
        _session->login( _session->m_username, _session->m_password, _session->m_blob.constData() );
    }


}
static void playlistcontainer_loaded(sp_playlistcontainer *pc, void *userdata) {
  syslog(LOG_DEBUG, "playlistcontainer_loaded\n");
  sp_session *session = userdata;
  struct state *state = sp_session_userdata(session);

  sp_playlistcontainer_remove_callbacks(pc, &playlistcontainer_callbacks, session);

  state->http = evhttp_new(state->event_base);
  evhttp_set_timeout(state->http, 60);
  evhttp_set_gencb(state->http, &handle_request, state);

  // TODO(liesen): Make address and port configurable
  if (evhttp_bind_socket(state->http, "0.0.0.0", 1337) == -1) {
    syslog(LOG_WARNING, "Could not bind HTTP server socket");
    sp_session_logout(session);
  }
}
Exemple #23
0
void logged_in(sp_session *session, sp_error error) {
  struct state *state = sp_session_userdata(session);

  if (error != SP_ERROR_OK) {
    syslog(LOG_CRIT, "Error logging in to Spotify: %s",
           sp_error_message(error));
    state->exit_status = EXIT_FAILURE;
    logged_out(session);
    return;
  }

  state->session = session;
  evsignal_add(state->sigint, NULL);

  sp_playlistcontainer *pc = sp_session_playlistcontainer(session);
  sp_playlistcontainer_add_callbacks(pc, &playlistcontainer_callbacks,
                                     session);
}
/**
  loggedin
  callback from spotify
  also initilizes the playlistcontainer and callbacks
  **/
void SpotifySession::loggedIn(sp_session *session, sp_error error)
{
   SpotifySession* _session = reinterpret_cast<SpotifySession*>(sp_session_userdata(session));
    if (error == SP_ERROR_OK) {

        qDebug() << "Logged in successfully!!";

        _session->setSession(session);
        _session->setLoggedIn(true);
        _session->setPlaylistContainer( sp_session_playlistcontainer(session) );

        sp_playlistcontainer_add_ref( _session->PlaylistContainer() );
        sp_playlistcontainer_add_callbacks(_session->PlaylistContainer(), &SpotifyCallbacks::containerCallbacks, _session);
    }

    qDebug() << Q_FUNC_INFO << "==== " << sp_error_message( error ) << " ====";
    const QString msg = QString::fromUtf8( sp_error_message( error ) );
    emit _session->loginResponse( error == SP_ERROR_OK, msg );
}
Exemple #25
0
static int music_delivery(sp_session *session, const sp_audioformat *format, const void *frames, int num_frames) {
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    int siz = frame_size(format);
    PyObject *pyframes = PyBuffer_FromMemory((void *)frames, num_frames * siz);
    Py_INCREF(pyframes);
    Session *psession = (Session *)PyObject_CallObject((PyObject *)&SessionType, NULL);
    Py_INCREF(psession);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    PyObject *c= PyObject_CallMethod(client, "music_delivery", "OOiiiii", psession, pyframes, siz, num_frames, format->sample_type, format->sample_rate, format->channels);
    int consumed = num_frames; // assume all consumed
    if(PyObject_TypeCheck(c, &PyInt_Type)) {
        consumed = (int)PyInt_AsLong(c);
    }
    Py_DECREF(pyframes);
    Py_DECREF(psession);
    PyGILState_Release(gstate);
    return consumed;
}
Exemple #26
0
static int
music_delivery(sp_session * session, const sp_audioformat * format,
               const void *frames, int num_frames)
{
    PyGILState_STATE gstate;
    PyObject *res, *method;

#ifdef DEBUG
        fprintf(stderr, "[DEBUG]-session- >> music_delivery called\n");
#endif
    gstate = PyGILState_Ensure();
    int siz = frame_size(format);
    PyObject *pyframes = PyBuffer_FromMemory((void *)frames, num_frames * siz);
    Session *psession =
        (Session *) PyObject_CallObject((PyObject *)&SessionType, NULL);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);
    method = PyObject_GetAttrString(client, "music_delivery");
    res =
        PyObject_CallFunction(method, "OOiiiii", psession,
                              pyframes, siz, num_frames, format->sample_type,
                              format->sample_rate, format->channels);
    int consumed = num_frames;  // assume all consumed
    if (!res)
        PyErr_WriteUnraisable(method);
    if (PyInt_Check(res))
        consumed = (int)PyInt_AsLong(res);
    else if (PyLong_Check(res))
        consumed = (int)PyLong_AsLong(res);
    else {
        PyErr_SetString(PyExc_TypeError,
                        "music_delivery must return an integer");
        PyErr_WriteUnraisable(method);
    }
    Py_DECREF(pyframes);
    Py_DECREF(psession);
    Py_XDECREF(res);
    Py_DECREF(method);
    PyGILState_Release(gstate);
    return consumed;
}
Exemple #27
0
void credentials_blob_updated(sp_session *session, const char *blob) {
  syslog(LOG_DEBUG, "credentials_blob_updated");
  struct state *state = sp_session_userdata(session);

  if (state->credentials_blob_filename == NULL) {
    syslog(LOG_DEBUG, "Not configured to store credentials");
    return;
  }

  FILE *fp = fopen(state->credentials_blob_filename, "w+");

  if (!fp) {
    syslog(LOG_DEBUG, "Could not open credentials file for writing");
    return;
  }

  size_t blob_size = strlen(blob);
  fwrite(blob, 1, blob_size, fp);
  fclose(fp);
  syslog(LOG_DEBUG, "Wrote new credentials to %s",
         state->credentials_blob_filename);
}
Exemple #28
0
/* TODO: convert to Py_VaBuildValue based solution so we can support
 *   music_delivery?
 * TODO: could we avoid having to pass session into the python callbacks, or
 *   could we at least store a g_py_session to save us reconstructing it all
 *   the time? Or would that break in unexpected ways if the session gets
 *   modified? Measuring the affect of changing say music_delivery to not
 *   waste time contructing the session would be a good place to start.
 * TODO: could we avoid having to lookup the attr for the callback on every
 *   single callback? Would that break cases where people change the config
 *   later, does that matter?
 */
static void
session_callback(sp_session * session, const char *attr, PyObject *extra)
{
    PyObject *callback, *client, *py_session, *result;
    py_session = Session_FromSpotify(session);
    if (py_session != NULL) {

        client = (PyObject *)sp_session_userdata(session);
        callback = PyObject_GetAttrString(client, attr);

        if (callback != NULL) {
            result = PyObject_CallFunctionObjArgs(callback, py_session, extra, NULL);

            if (result == NULL)
                PyErr_WriteUnraisable(callback);
            else
                Py_DECREF(result);

            Py_DECREF(callback);
        }
        Py_DECREF(py_session);
    }
}
Exemple #29
0
static void
play_token_lost(sp_session * session)
{
    PyGILState_STATE gstate;
    PyObject *res, *method;

#ifdef DEBUG
        fprintf(stderr, "[DEBUG]-session- >> play_token_lost called\n");
#endif
    gstate = PyGILState_Ensure();
    Session *psession =
        (Session *) PyObject_CallObject((PyObject *)&SessionType, NULL);
    psession->_session = session;
    PyObject *client = (PyObject *)sp_session_userdata(session);

    method = PyObject_GetAttrString(client, "play_token_lost");
    res = PyObject_CallFunctionObjArgs(method, psession, NULL);
    if (!res)
        PyErr_WriteUnraisable(method);
    Py_DECREF(psession);
    Py_XDECREF(res);
    Py_DECREF(method);
    PyGILState_Release(gstate);
}
/** sp_session_userdata is assumed to be thread safe. */
SpotifySession *from(sp_session *sess) {
	return static_cast<SpotifySession *>(sp_session_userdata(sess));
}