Beispiel #1
0
int cmd_playlist_add_track(int argc, char **argv)
{
	sp_link *plink, *tlink;
	sp_track *t;
	sp_playlist *pl;
	int i;
	struct pl_update_work *puw;

	if(argc < 4) {
		printf("add [playlist uri] [position] [track uri] <[track uri]>...\n");
		return 1;
	}

	plink = sp_link_create_from_string(argv[1]);
	if (!plink) {
		fprintf(stderr, "%s is not a spotify link\n", argv[1]);
		return -1;
	}

	if(sp_link_type(plink) != SP_LINKTYPE_PLAYLIST) {
		fprintf(stderr, "%s is not a playlist link\n", argv[1]);
		sp_link_release(plink);
		return -1;
	}

	puw = malloc(sizeof(struct pl_update_work));
	puw->position = atoi(argv[2]);
	puw->tracks = malloc(sizeof(sp_track *) * argc - 3);
	puw->num_tracks = 0;
	for(i = 0; i < argc - 3; i++) {
		tlink = sp_link_create_from_string(argv[i + 3]);
		if(tlink == NULL) {
			fprintf(stderr, "%s is not a spotify link, skipping\n", argv[i + 3]);
			continue;
		}
		if(sp_link_type(tlink) != SP_LINKTYPE_TRACK) {
			fprintf(stderr, "%s is not a track link, skipping\n", argv[i + 3]);
			continue;
		}
		t = sp_link_as_track(tlink);
		sp_track_add_ref(t);
		puw->tracks[puw->num_tracks++] = t;
		sp_link_release(tlink);
	}

	pl = sp_playlist_create(g_session, plink);
	if(!apply_changes(pl, puw)) {
		// Changes applied directly, we're done
		sp_playlist_release(pl);
		sp_link_release(plink);
		return 1;
	}

	fprintf(stderr, "Playlist not yet loaded, waiting...\n");
	sp_playlist_add_callbacks(pl, &pl_update_callbacks, puw);
	sp_link_release(plink);
	return 0;
}
Beispiel #2
0
  bool Codec::Init(const CStdString & strFile, unsigned int filecache) {
    m_bufferSize = 2048 * sizeof(int16_t) * 50;
    m_buffer = new char[m_bufferSize];
    CStdString uri = URIUtils::GetFileName(strFile);
    CStdString extension = uri.Right(uri.GetLength() - uri.Find('.') - 1);
    if (extension.Left(12) == "spotifyradio") {
      //if its a radiotrack the radionumber and tracknumber is secretly encoded at the end of the extension
      CStdString trackStr = extension.Right(
          extension.GetLength() - extension.ReverseFind('#') - 1);
      Logger::printOut(extension);
      CStdString radioNumber = extension.Left(uri.Find('#'));
      Logger::printOut(radioNumber);
      radioNumber = radioNumber.Right(
          radioNumber.GetLength() - radioNumber.Find('#') - 1);
      Logger::printOut("loading codec radio");
      RadioHandler::getInstance()->pushToTrack(atoi(radioNumber),
          atoi(trackStr));
    }
    //we have a non legit extension so remove it manually
    uri = uri.Left(uri.Find('.'));

    Logger::printOut("trying to load track:");
    Logger::printOut(uri);
    sp_link *spLink = sp_link_create_from_string(uri);
    m_currentTrack = sp_link_as_track(spLink);
    sp_track_add_ref(m_currentTrack);
    sp_link_release(spLink);
    m_endOfTrack = false;
    m_bufferPos = 0;
    m_startStream = false;
    m_isPlayerLoaded = false;
    m_TotalTime = sp_track_duration(m_currentTrack);

    //prefetch the next track!

	  CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC);
	  int nextSong = g_playlistPlayer.GetNextSong();

	  if (nextSong >= 0 && nextSong < playlist.size()){
	  	CFileItemPtr song = playlist[nextSong];
	  	if (song != NULL){
	  		CStdString uri = song->GetPath();
	  		if (uri.Left(7).Equals("spotify")){
	  			uri = uri.Left(uri.Find('.'));
	  	    Logger::printOut("prefetching track:");
	  	    Logger::printOut(uri);
	  	    sp_link *spLink = sp_link_create_from_string(uri);
	  	    sp_track* track = sp_link_as_track(spLink);
	  	    sp_session_player_prefetch(getSession(), track);
	  	    sp_link_release(spLink);
	  		}
	  	}
	  }

    return true;
  }
QString Spotify::songNameFromUri(const QString &uriString)
{
    const char * uri = uriString.toLocal8Bit().constData();
    sp_link * link = sp_link_create_from_string(uri);
    if (!link) {
        fprintf(stderr, "Spotify: failed to parse URI (%s)\n", uri);
        return QString();
    }

    sp_track * track;
    QString song;

    switch (sp_link_type(link)) {
    case SP_LINKTYPE_LOCALTRACK:
    case SP_LINKTYPE_TRACK:
        track = sp_link_as_track(link);
        if (!track) {
            fprintf(stderr, "Link is not a track\n");
            break;
        }

        song = QString(sp_track_name(track));
        break;

    default:
        qDebug() << "URI is not a track:" << uriString;
        break;
    }

    sp_link_release(link);

    return song;
}
Beispiel #4
0
JNIEXPORT jobject JNICALL Java_jahspotify_impl_JahSpotifyImpl_retrieveTrack ( JNIEnv *env, jobject obj, jstring uri)
{
    jobject trackInstance;
    uint8_t *nativeUri = NULL;

    nativeUri = ( uint8_t * ) ( *env )->GetStringUTFChars ( env, uri, NULL );

    sp_link *link = sp_link_create_from_string(nativeUri);
    if (!link)
    {
        // hmm
        fprintf ( stderr, "jahspotify::Java_jahspotify_impl_JahSpotifyImpl_retrieveTrack: Could not create link!\n" );
        return JNI_FALSE;
    }

    sp_track *track = sp_link_as_track(link);

    while (!sp_track_is_loaded(track))
    {
        fprintf ( stderr, "jahspotify::Java_jahspotify_impl_JahSpotifyImpl_retrieveTrack: Waiting for track to be loaded ...\n" );
        sleep(1);
    }

    trackInstance = createJTrackInstance(env, track);

    if (track)
        sp_track_release(track);
    if (link)
        sp_link_release(link);
    if (nativeUri)
        free(nativeUri);

    return trackInstance;
}
void Spotify::changeCurrentlyPlayingSong()
{
    sp_track * track;
    const char * uri = currentURI.toLocal8Bit().constData();
    fprintf(stderr, "Spotify: Playing %s\n", uri);

    sp_link * link = sp_link_create_from_string(uri);
    if (!link) {
        fprintf(stderr, "Spotify: failed to parse URI (%s)\n", uri);
        currentURI.clear();
        return;
    }

    switch (sp_link_type(link)) {
    case SP_LINKTYPE_LOCALTRACK:
    case SP_LINKTYPE_TRACK:
        track = sp_link_as_track(link);
        if (!track) {
            fprintf(stderr, "Link is not a track\n");
            break;
        }
        nextTrack = track;
        sp_track_add_ref(track);
        tryLoadTrack();
        break;

    default:
        qDebug() << "URI is not a track:" << currentURI;
        break;
    }

    sp_link_release(link);
}
Beispiel #6
0
//----------------------------------------------
//	get track info from URI
//----------------------------------------------
TRef TLSpotify::TSession::FindTrack(const TString& URI)
{
	THeapArray<char> UriString;
	URI.GetAnsi( UriString );
	
	//	find link
	sp_link *link = sp_link_create_from_string( UriString.GetData() );
    if (!link) 
		return TRef();
	
	//	get track from the link
	sp_track* pTrack = sp_link_as_track( link );
	if ( !pTrack )
	{
		TDebugString Debug_String;
		Debug_String << "URI " << URI << " is not a track";
		TLDebug_Print( Debug_String );
		return TRef();
	}
	
	//	create new track info
	TRef TrackRef = AddTrack( *pTrack );
	
	const char* TrackName = sp_track_name( pTrack );
	
    //	The create function will have increased the reference count for us so release
    sp_link_release(link);
	
	return TrackRef;
}
Beispiel #7
0
JNIEXPORT jobject JNICALL Java_jahspotify_impl_JahSpotifyImpl_retrievePlaylist ( JNIEnv *env, jobject obj, jstring uri)
{
    jobject playlistInstance;
    uint8_t *nativeUri = NULL;

    nativeUri = ( uint8_t * ) ( *env )->GetStringUTFChars ( env, uri, NULL );

    sp_link *link = sp_link_create_from_string(nativeUri);
    if (!link)
    {
        // hmm
        fprintf ( stderr, "jahspotify::Java_jahspotify_impl_JahSpotifyImpl_retrievePlaylist: Could not create link!\n" );
        return JNI_FALSE;
    }

    sp_playlist *playlist = sp_playlist_create(g_sess,link);

    while (!sp_playlist_is_loaded(playlist))
    {
        fprintf ( stderr, "jahspotify::Java_jahspotify_impl_JahSpotifyImpl_retrievePlaylist: Waiting for playlist to be loaded ...\n" );
        sleep(1);
    }

    playlistInstance = createJPlaylist(env, playlist);

    if (playlist)
        sp_playlist_release(playlist);
    if (link)
        sp_link_release(link);
    if (nativeUri)
        free(nativeUri);

    return playlistInstance;

}
Beispiel #8
0
JNIEXPORT jobject JNICALL Java_jahspotify_impl_JahSpotifyImpl_retrieveAlbum ( JNIEnv *env, jobject obj, jstring uri)
{
    jobject albumInstance;
    uint8_t *nativeUri = NULL;

    nativeUri = ( uint8_t * ) ( *env )->GetStringUTFChars ( env, uri, NULL );

    sp_link *link = sp_link_create_from_string(nativeUri);
    if (link)
    {
        sp_album *album= sp_link_as_album(link);

        if (album)
        {
            sp_album_add_ref(album);
            
            albumInstance = createJAlbumInstance(env, album);
	    
            sp_album_release(album);
        }
        sp_link_release(link);
    }

    if (nativeUri)
        (*env)->ReleaseStringUTFChars(env, uri,nativeUri);

    return albumInstance;
}
Beispiel #9
0
/**
 * This callback is called when an attempt to login has succeeded or failed.
 *
 * @sa sp_session_callbacks#logged_in
 */
static void logged_in(sp_session *sess, sp_error error)
{
	sp_link *link;

	if (SP_ERROR_OK != error) {
		fprintf(stderr, "Login failed: %s\n",
			sp_error_message(error));
		exit(2);
	}

	printf("Loading track\n");
	link = sp_link_create_from_string("spotify:track:5W3cjX2J3tjhG8zb6u0qHn");
        sp_track_add_ref(g_currenttrack = sp_link_as_track(link));
	sp_link_release(link);

	if (sp_track_error(g_currenttrack) == SP_ERROR_OK) {
		printf("Now playing \"%s\"...\n", sp_track_name(g_currenttrack));
		fflush(stdout);
		
		sp_session_player_load(g_sess, g_currenttrack);
		sp_session_player_play(g_sess, 1);
        }

	/* Track not loaded? Then we need to wait for the metadata to
           load before we can start playback (see below) */
}
Beispiel #10
0
PHP_METHOD(Spotify, getArtistByURI)
{
        zval *uri, temp, *object = getThis();
        int timeout = 0;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &uri) == FAILURE) {
                return;
        }

        spotify_object *p = (spotify_object*)zend_object_store_get_object(object TSRMLS_CC);

        sp_link *link = sp_link_create_from_string(Z_STRVAL_P(uri));
        if (NULL == link) {
                RETURN_FALSE;
        }

        if (SP_LINKTYPE_ARTIST != sp_link_type(link)) {
                RETURN_FALSE;
        }

        sp_artist *artist = sp_link_as_artist(link);

        object_init_ex(return_value, spotifyartist_ce);
        SPOTIFY_METHOD2(SpotifyArtist, __construct, &temp, return_value, object, artist);

        sp_link_release(link);
}
Beispiel #11
0
PHP_METHOD(Spotify, getAlbumByURI)
{
	zval *uri, temp, *object = getThis();
	int timeout = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &uri) == FAILURE) {
		return;
	}

	spotify_object *p = (spotify_object*)zend_object_store_get_object(object TSRMLS_CC);

	sp_link *link = sp_link_create_from_string(Z_STRVAL_P(uri));
	if (NULL == link) {
		RETURN_FALSE;
	}

	if (SP_LINKTYPE_ALBUM != sp_link_type(link)) {
		RETURN_FALSE;
	}

	sp_album *album = sp_link_as_album(link);

	while (!sp_album_is_loaded(album)) {
		sp_session_process_events(p->session, &timeout);
	}

	object_init_ex(return_value, spotifyalbum_ce);
	SPOTIFY_METHOD2(SpotifyAlbum, __construct, &temp, return_value, object, album);

	sp_link_release(link);
}
Beispiel #12
0
void upvoteHelper(const char* s)
{
	// turns s into sp_link
	sp_link* temp = sp_link_create_from_string(s);
	upvote(temp);
	// calls upvote
}
Beispiel #13
0
sp_link *
sp_link_create_from_search(sp_search *search)
{
  char *uri_encoded = url_encode(search->query);
  char *uri = ALLOC_STR(strlen("spotify:search:") + strlen(uri_encoded));
  sprintf(uri, "spotify:search:%s", uri_encoded);
  return sp_link_create_from_string(uri);
}
Beispiel #14
0
int createTrackFromUri( char *uri , char *name )
{
    TRACE_2( PLAYERMANAGER , "createTrackFromUri( %s , __track__ )" , uri );

    sp_link *link;
    sp_error error;

    if( playing == FALSE && hasNextTrack() == FALSE )
        createFile( name );

    TRACE_1( PLAYERMANAGER , "Creating URI : %s" , uri );

    link = sp_link_create_from_string( uri );

    if( link == NULL )
    {
        TRACE_ERROR( PLAYERMANAGER , "Fail to create link.");

        return PC_ERROR;
    }
    else
    {
        TRACE_1( PLAYERMANAGER , "Success to create link.");
    }

    TRACE_3( PLAYERMANAGER , "Construct track...");

    currentTrack = sp_link_as_track( link );

    if( currentTrack == NULL )
    {
        TRACE_ERROR( PLAYERMANAGER , "Fail to create track.");

        return PC_ERROR;
    }
    else
    {
        TRACE_1( PLAYERMANAGER , "Success to create track.");
    }

    error = sp_track_add_ref( currentTrack );

    if( error != SP_ERROR_OK )
    {
        TRACE_ERROR( PLAYERMANAGER , "Cannot add ref track, reason: %s" , sp_error_message( error ) );

        return PC_ERROR;
    }

    sp_link_release( link );

    running = TRUE;
//    playing = FALSE;

    return PC_SUCCESS;
}
Beispiel #15
0
  bool Codec::Init(const CStdString & strFile, unsigned int filecache) {
    m_bufferSize = 2048 * sizeof(int16_t) * 50;
    m_buffer = new char[m_bufferSize];
    CStdString uri = URIUtils::GetFileName(strFile);
    CStdString extension = uri.Right(uri.GetLength() - uri.Find('.') - 1);
    //we have a non legit extension so remove it manually
    uri = uri.Left(uri.Find('.'));

    Logger::printOut("trying to load track:");
    Logger::printOut(uri);
    sp_link *spLink = sp_link_create_from_string(uri);
    m_currentTrack = sp_link_as_track(spLink);
    sp_track_add_ref(m_currentTrack);
    sp_link_release(spLink);
    m_endOfTrack = false;
    m_bufferPos = 0;
    m_startStream = false;
    m_isPlayerLoaded = false;
    m_TotalTime = sp_track_duration(m_currentTrack);

    //prefetch the next track!

	  CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC);
	  int nextSong = g_playlistPlayer.GetNextSong();

	  if (nextSong >= 0 && nextSong < playlist.size()){
	  	CFileItemPtr song = playlist[nextSong];
	  	if (song != NULL){
	  		CStdString uri = song->GetPath();
	  		if (uri.Left(7).Equals("spotify")){
	  			uri = uri.Left(uri.Find('.'));
	  	    Logger::printOut("prefetching track:");
	  	    Logger::printOut(uri);
	  	    sp_link *spLink = sp_link_create_from_string(uri);
	  	    sp_track* track = sp_link_as_track(spLink);
	  	    sp_session_player_prefetch(getSession(), track);
	  	    sp_link_release(spLink);
	  		}
	  	}
	  }

    return true;
  }
Beispiel #16
0
void start_playlist(char *uri)
{
	printf("Start playlist: %s\n", uri);
	sp_link *link = sp_link_create_from_string(uri);
	sp_playlist *pl = sp_playlist_create(g_sess, link);
	sp_playlist_add_callbacks(pl, &pl_callbacks, NULL);
	sprintf(g_last_playlist_name, sp_playlist_name(pl));
	// hardware_banner(sp_playlist_name(pl), 200);
	g_jukeboxlist = pl;
	try_jukebox_start();
}
Beispiel #17
0
static void get_album_tracks(){
    
    sp_link * new_link;
    new_link = sp_link_create_from_string(g_guid);
    
    sp_album * new_album;
    new_album = sp_link_as_album(new_link);
    
    sp_albumbrowse* albumbrowser;
    albumbrowser = sp_albumbrowse_create(g_sess,new_album,albumbrowser_callback,NULL);
}
Beispiel #18
0
sp_link *
sp_link_create_from_artistbrowse_portrait(sp_artistbrowse *artistbrowse, int index)
{
  const byte *image_id = sp_artistbrowse_portrait(artistbrowse, index);

  if ( ! image_id)
  {
    return NULL;
  }

  return sp_link_create_from_string(image_id_to_uri(image_id));
}
Beispiel #19
0
sp_link *
sp_link_create_from_album_cover(sp_album *album, sp_image_size size)
{
  const byte *image_id = sp_album_cover(album, size);

  if ( ! image_id)
  {
    return NULL;
  }

  return sp_link_create_from_string(image_id_to_uri(image_id));
}
Beispiel #20
0
sp_link *
sp_link_create_from_artist_portrait(sp_artist *artist, sp_image_size size)
{
  const byte *image_id = sp_artist_portrait(artist, size);

  if ( ! image_id)
  {
    return NULL;
  }

  return sp_link_create_from_string(image_id_to_uri(image_id));
}
Beispiel #21
0
static void _spotify_play(sp_session *session, std::string uri)
{
    assert(pthread_equal(pthread_self(),g_spotify_tid));
    sp_link *l = sp_link_create_from_string(uri.c_str());
    sp_error err;
    int offset;
    if(!l || sp_link_type(l) != SP_LINKTYPE_TRACK) {
        return;
    }
    sp_track *t = sp_link_as_track_and_offset(l,&offset);
    try_play(session,t,offset);
    sp_link_release(l);
    return;
}
Beispiel #22
0
void QSpotifySession::handleUri(QString uri) {
    qDebug() << "QSpotifySession::handleUri";
    if (!m_isLoggedIn) {
        m_uriToOpen = uri;
        return;
    }
    sp_link *link = sp_link_create_from_string(uri.toLatin1().data());
    sp_linktype link_type = sp_link_type(link);
    if (link_type == SP_LINKTYPE_TRACK) {
        sp_track *track = sp_link_as_track(link);
        std::shared_ptr<QSpotifyTrack> q_track(new QSpotifyTrack(track, nullptr));
        enqueue(q_track);
        play(q_track, true);
    }
}
Beispiel #23
0
sp_link *
sp_link_create_from_track(sp_track *track, int offset)
{
  const char *link = registry_reverse_find((void *) track);
  int mins = 0, secs = 0;
  char *link_with_offset = NULL;

  if (offset > 0)
  {
    link_with_offset = ALLOC_STR(strlen(link) + strlen("#00:00"));

    offset = offset / 1000;
    mins = (offset / 60) % 60;
    secs = (offset - mins * 60) % 60;

    sprintf(link_with_offset, "%s", link);
    sprintf(link_with_offset + strlen(link), "#%02d:%02d", mins, secs);
    return sp_link_create_from_string(link_with_offset);
  }
  else
  {
    return sp_link_create_from_string(link);
  }
}
Beispiel #24
0
bool json_to_track(json_t *json, sp_track **track) {
  if (!json_is_string(json))
    return false;

  sp_link *link = sp_link_create_from_string(json_string_value(json));

  if (link == NULL)
    return false;

  if (sp_link_type(link) != SP_LINKTYPE_TRACK) {
    sp_link_release(link);
    return false;
  }

  *track = sp_link_as_track(link);
  return *track != NULL;
}
Beispiel #25
0
int cmd_browse(int argc, char **argv)
{
	sp_link *link;

	if (argc != 2) {
		browse_usage();
		return -1;
	}

	
	link = sp_link_create_from_string(argv[1]);
	
	if (!link) {
		fprintf(stderr, "Not a spotify link\n");
		return -1;
	}

	switch(sp_link_type(link)) {
	default:
		fprintf(stderr, "Can not handle link");
		sp_link_release(link);
		return -1;

	case SP_LINKTYPE_ALBUM:
		sp_albumbrowse_create(g_session, sp_link_as_album(link), browse_album_callback, NULL);
		break;

	case SP_LINKTYPE_ARTIST:
		sp_artistbrowse_create(g_session, sp_link_as_artist(link), browse_artist_callback, NULL);
		break;

	case SP_LINKTYPE_TRACK:
		track_browse = sp_link_as_track(link);
		metadata_updated_fn = track_browse_try;
		sp_track_add_ref(track_browse);
		track_browse_try();
		break;

	case SP_LINKTYPE_PLAYLIST:
		browse_playlist(sp_playlist_create(g_session, link));
		break;
	}

	sp_link_release(link);
	return 0;
}
Beispiel #26
0
int luasp_link_create_from_string(lua_State *L) {
  // link = spotify.link_create_from_string(uri)
  
  if (lua_gettop(L) != 1 || !lua_isstring(L, 1))
  {
    lua_pushstring(L, "incorrect argument to link_create_from_string(...)");
		lua_error(L);
  }
  
  sp_link* t_link = sp_link_create_from_string(lua_tostring(L, 1));
  
  if (t_link)
    lua_pushlightuserdata(L,  t_link);
  else
    lua_pushnil(L);
  
  return 1;
}
Beispiel #27
0
// Loads track if metadata exists, otherwise load the metadata
static void load_track_or_metadata(sp_session *session, sp_track *track, const char *uri) {
	if (track != NULL) {
		if (s_is_playing)
			sp_session_player_play(session, false);
		sp_session_player_unload(session);
		sp_track_release(track);
	}
	track = sp_link_as_track(sp_link_create_from_string(uri));
	set_track(track);
	sp_track_add_ref(track);
	s_player_position = 0;
	s_current_uri = uri;

	// either the track is already cached and can be used or we need to wait for the metadata callback
	if (sp_track_is_loaded(track))
		load_and_play_track(session, track);
	else
		s_is_waiting_for_metadata = true;
}
Beispiel #28
0
static PyObject *
Link_from_string(Link * self, PyObject *args)
{
    char *s, *s2;
    PyObject *plink;

    if (!PyArg_ParseTuple(args, "s", &s))
        return NULL;
    s2 = malloc(strlen(s) + 1);
    strcpy(s2, s);
    sp_link *link = sp_link_create_from_string(s2);

    if (!link) {
        PyErr_SetString(SpotifyError, "Failed to get link from a Spotify URI");
        return NULL;
    }
    plink = Link_FromSpotify(link);
    return plink;
}
Beispiel #29
0
void QSpotifySession::sendImageRequest(const QString &id)
{
    qDebug() << "QSpotifySession::sendImageRequest" << id;
    sp_image *image = nullptr;
    byte *idPtr = QSpotifyPlaylist::getImageIdPtr(id);
    if(idPtr)
        image = sp_image_create(m_sp_session, idPtr);
    else {
        sp_link *link = sp_link_create_from_string(id.toUtf8().constData());
        if(link) {
            image = sp_image_create_from_link(m_sp_session, link);
            sp_link_release(link);
        }
    }

    if (image) {
        g_imageRequestObject.insert(image, id);
        sp_image_add_load_callback(image, callback_image_loaded, nullptr);
    }
}
Beispiel #30
0
/**
 * This callback is called when an attempt to login has succeeded or failed.
 *
 * @sa sp_session_callbacks#logged_in
 */
static void logged_in(sp_session *session, sp_error error)
{
	sp_user *me;
	const char *my_name;

	if (SP_ERROR_OK != error) {
		fprintf(stderr, "failed to log in to Spotify: %s\n",
		                sp_error_message(error));
		sp_session_release(session);
		exit(4);
	}

	// Let us print the nice message...
	me = sp_session_user(session);
	my_name = (sp_user_is_loaded(me) ? sp_user_display_name(me) : sp_user_canonical_name(me));

	fprintf(stderr, "Logged in to Spotify as user %s\n", my_name);
    sp_playlist *pl = sp_playlist_create(session, sp_link_create_from_string("spotify:user:devnevyn:playlist:44ZXlJstDZrwuQvWPOo7KX"));
    empty_callbacks.playlist_state_changed = foo;
    sp_playlist_add_callbacks(pl, &empty_callbacks, NULL);
}