2016-04-05 17 views
0

Bu, günlerce anlamaya çalıştığım çok tuhaf bir sorundur. Bununla ilgili garip olan şey, bu sadece belli kullanıcı hesapları için geçerli. Bu bir Windows uygulamasıdır ve Jukebox örneğini başlangıç ​​noktası olarak kullandım.sp_session_process_events, sp_session_login çağrısının ardından Erişim İhlaline neden oluyor

  • Sp_session_login() yöntemini arıyorum.
  • Oturum açma_in() için geri çağrı alıyorum.
  • Notify_main_thread geri aramasını görüyorum.
  • sp_session_process_events() birtakım olayları ve ardından Erişim İhlali'ni işler.

Bunu bir kaç kez izledim ve çökmelere neden olan hesaplarda, userinfo_updated() 8 kez geri çağırıyorum. Kilitlenmeyen hesaplar Sadece bir veya iki kez görüyorum. Geri aramada hiçbir şey yapmıyorum. Vermediğim geri aramalardan birine ihtiyacım olup olmadığını görmeye çalışıyordum.

Kilitlenmesini engelleyebileceğimin bir yolu var. Eğer hemen bir parça yüklüyorsam ve log_in() geri aramada iken (Jukebox örneğinde olduğu gibi) çalarsam çalmaz.

Hata ayıklama işleminde herhangi bir yardım büyük ölçüde takdir edilecektir.

-Tommy

GÜNCELLEME: 2016/04/07 İşte günlük dosyası çıkıştır. Birini umursama, bunun anlamını anlamama yardımcı olabilir. Ayrıca, onun Playlist ile ilgili olduğunu düşünüyorum. Çalma listesi geri çağrılarının kurulmasını istiyorum.

14: 57: 57:

14 tgsource kullanıcı 47,735 sp_session_login Günlüğü Oturum sp_session_login 47,788 bulundu: SP_ERROR_OK

14: 57: 47,859 log_message 21: 57: 47,859 I [user_cache: 135] UserCache 57: 47,906 log_message 21: 57: Ben [ap: 1752] 47,906 AP bağlanma

14:57 ap.gslb.spotify.com:4070 :: initiateGetUsers() 1 kullanıcı

14 için sorgular : 47.937 login_in login_in kullanıcısı: tgsource

14: 57: 47,937 log_message 21: 57: 47,937 I [çevrimdışı mgr: 2084]: 57: 47,984 log_message 21: 57: Depolama

14 temizlenmiş 47,984 I [ap: 1226] bağlantılı AP: 194.68.29.165:4070

14: 57: 48,405

credentials_blob_updated credentials_blob_updated

14: 57: 57: 48,452 userinfo_updated Userinfo

adı Userinfo userinfo_updated 48,405

14 olarak adlandırılan

14: 57: 57: çalma listesi 48,920 PlaylistContainerLoaded sayısı: 8

14: 57: 49,107 log_message 21:57:49 48,452 Userinfo userinfo_updated

14 olarak adlandırılan.107 E [ap: 4172] ChannelError (3, 1, çalma listesi)

14: 57: 49,139 log_message 21: 57: 49,139 W [çekirdek/çalma/playlist.h: 45]

güncellenirken gözlemci ekleme 14: 57: 49.139 log_message 21: 57: 49.139 W [core/playlist/playlist.h: 45] Güncelleme sırasında gözlemci eklenirken

14: 57: 49.154 log_message 21: 57: 49.154 W [çekirdek/çalma listesi/çalma listesi. 57: s:

14 güncellenirken 45] gözlemci ekleme 49,154 log_message 21: 57: 49,154 W [çekirdek/çalma/playlist.h: 45]

güncellenirken gözlemci ekleme

14: 57: 49,295 log_message 21: 57: 49,295 I [user_cache: 135]: 57: 49,295 log_message 21: 57: 49,295 W [çekirdek/UserCache :: initiateGetUsers() 1 kullanıcıyla

14 için sorgular 57: çalma listesi/playlist.h:

14 güncellenirken 45] gözlemci ekleme 49,295 log_message 21: 57: 49,295 W [çekirdek/çalma/playlist.h: 45]

14:57 güncellenirken gözlemci ekleme : 49.327 userinfo_updated Userinfo aradı

14: 57: 49.467 userinfo_updated Userinfo aradı

** Çökme **

Güncelleme 2016/04/11: Burada sorun reproduces kaynak kodudur. Jukebox örneğinden playtrack.c dosyasının bir portu. Parça yüklemesini kaldırdım ve aynı soruna neden oluyor.

/** 
* Copyright (c) 2006-2010 Spotify Ltd 
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy 
* of this software and associated documentation files (the "Software"), to deal 
* in the Software without restriction, including without limitation the rights 
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions: 
* 
* The above copyright notice and this permission notice shall be included in 
* all copies or substantial portions of the Software. 
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
* THE SOFTWARE. 
* 
* 
* This example application is the most minimal way to just play a spotify URI. 
* 
* This file is part of the libspotify examples suite. Jukebox - playtrack.c 
*/ 
#include <errno.h> 
#include "stdint.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include "../libspotify/api.h" 
#include "audio.h" 
#include <windows.h> 

/* --- Data --- */ 
extern const uint8_t g_appkey[]; 
extern const size_t g_appkey_size; 
static audio_fifo_t g_audiofifo; 
static HANDLE g_notify_mutex; 
static HANDLE g_notify_cond; 
static int g_notify_do; 
int g_playback_done; 
sp_session *g_sess; 
static sp_track *g_currenttrack; 
const char *g_trackurl; 
static bool is_logged_out = FALSE; 
static HANDLE events; 



/* --------------------------- PLAYLIST CALLBACKS ------------------------- */ 
/** 
* Playlist container callbacks. 
* If some callbacks should not be of interest, set them to NULL. 
* 
*/ 
static void SP_CALLCONV PlaylistContainerLoaded(sp_playlistcontainer* pc, void* userdata) 
{ 
    int numPlaylists = sp_playlistcontainer_num_playlists(pc); 
    printf("Number of playlists: %d", numPlaylists);     
} 

static sp_playlistcontainer_callbacks pc_callbacks = 
{ 
    NULL, 
    NULL, 
    NULL, 
    &PlaylistContainerLoaded 
}; 

/* --------------------------- SESSION CALLBACKS ------------------------- */ 
/** 
* This callback is called when an attempt to login has succeeded or failed. 
* 
* @sa sp_session_callbacks#logged_in 
*/ 
static void SP_CALLCONV 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); 
    } 

    sp_playlistcontainer *pc = sp_session_playlistcontainer(sess); 
    sp_playlistcontainer_add_callbacks(pc, &pc_callbacks, NULL); 


// Note: Removing the track start will cause this to crash 
#if 0 

    printf("Loading track\n"); 


    link = sp_link_create_from_string("spotify:track:0W4Kpfp1w2xkY3PrV714B7"); 

    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)); 


     printf("Duration: %d\n", sp_track_duration(g_currenttrack)); 
     fflush(stdout); 

     sp_session_player_load(g_sess, g_currenttrack); 
     sp_session_player_play(g_sess, 1); 
     } 
#endif 

    /* Track not loaded? Then we need to wait for the metadata to 
      load before we can start playback (see metadata_updated below) */ 
} 

/** 
* Callback called when libspotify has new metadata available 
* 
* @sa sp_session_callbacks#metadata_updated 
*/ 
static void SP_CALLCONV metadata_updated(sp_session *sess) 
{ 
    puts("Metadata updated, trying to start playback"); 

    if (sp_track_error(g_currenttrack) != SP_ERROR_OK) 
     return; 

    sp_session_player_load(g_sess, g_currenttrack); 
    sp_session_player_play(g_sess, 1); 
} 

/** 
* This callback is called from an internal libspotify thread to ask 
* us to reiterate the main loop. 
* 
* We notify the main thread using a condition variable and a protected variable. 
* 
* @sa sp_session_callbacks#notify_main_thread 
*/ 
static void SP_CALLCONV notify_main_thread(sp_session *sess) 
{ 
    g_notify_do = 1; 
    SetEvent(events); 
} 

/** 
* This callback is used from libspotify whenever there is PCM data available. 
* 
* @sa sp_session_callbacks#music_delivery 
*/ 
static int SP_CALLCONV music_delivery(sp_session *sess, const sp_audioformat *format, 
          const void *frames, int num_frames) 
{ 
    audio_fifo_t *af = &g_audiofifo; 
    audio_fifo_data_t *afd; 
    size_t s; 

    if (num_frames == 0) 
     return 0; // Audio discontinuity, do nothing 

    WaitForSingleObject(af->mutex, INFINITE); 

    /* Buffer one second of audio */ 
    if (af->qlen > format->sample_rate) { 
     ReleaseMutex(af->mutex); 

     return 0; 
    } 

    s = num_frames * sizeof(int16_t) * format->channels; 

    afd = malloc(sizeof(audio_fifo_data_t) + s); 
    memcpy(afd->samples, frames, s); 

    afd->nsamples = num_frames; 

    afd->rate = format->sample_rate; 
    afd->channels = format->channels; 

    TAILQ_INSERT_TAIL(&af->q, afd, link); 
    af->qlen += num_frames; 

    PulseEvent(af->cond); 
    ReleaseMutex(af->mutex); 

    return num_frames; 
} 


/** 
* This callback is used from libspotify when the current track has ended 
* 
* @sa sp_session_callbacks#end_of_track 
*/ 
static void SP_CALLCONV end_of_track(sp_session *sess) 
{ 
    printf("end_of_track\n"); 
    g_playback_done = 1; 
} 

/** 
* Notification that some other connection has started playing on this account. 
* Playback has been stopped. 
* 
* @sa sp_session_callbacks#play_token_lost 
*/ 
static void SP_CALLCONV play_token_lost(sp_session *sess) 
{ 
    printf("play_token_lost\n"); 
    audio_fifo_flush(&g_audiofifo); 

    if (g_currenttrack != NULL) { 
     sp_session_player_unload(g_sess); 
     g_currenttrack = NULL; 
    } 
} 

static void SP_CALLCONV log_message(sp_session *session, const char *msg) 
{ 
    puts(msg); 
} 

static void SP_CALLCONV userinfo_updated(sp_session *session) 
{ 
    printf("Userinfo called.\n"); 

} 

static void SP_CALLCONV offline_status_updated(sp_session *sess) 
{ 
    sp_offline_sync_status status; 
    sp_offline_sync_get_status(sess, &status); 
    if(status.syncing) { 
     printf("Offline status: queued:%d:%zd done:%d:%zd copied:%d:%zd nocopy:%d err:%d\n", 
      status.queued_tracks, 
      (size_t)status.queued_bytes, 
      status.done_tracks, 
      (size_t)status.done_bytes, 
      status.copied_tracks, 
      (size_t)status.copied_bytes, 
      status.willnotcopy_tracks, 
      status.error_tracks); 
    } else { 
     printf("Offline status: Idle\n"); 
    } 
} 

/** 
* The session callbacks 
*/ 
static sp_session_callbacks session_callbacks = { 
    &logged_in, 
    NULL, 
    &metadata_updated, 
    NULL, 
    NULL, 
    &notify_main_thread, 
    &music_delivery, 
    &play_token_lost, 
    &log_message, 
    &end_of_track, 
    NULL, 
    &userinfo_updated, 
    NULL, 
    NULL, 
    NULL, 
    &offline_status_updated, 
    NULL, 
    NULL, 
    NULL, 
    NULL, 
    NULL, 
}; 


/** 
* The session configuration. Note that application_key_size is an 
* external, so we set it in main() instead. 
*/ 
static sp_session_config spconfig = { 
    SPOTIFY_API_VERSION, 
    "tmp", 
    "tmp", 
    g_appkey, 
    0, // Set in main() 
    "spotify-jukebox-playtrack", 
    &session_callbacks, 
    NULL, 
}; 
/* ------------------------- END SESSION CALLBACKS ----------------------- */ 


/** 
* A track has ended. Remove it from the playlist. 
* 
* Called from the main loop when the music_delivery() callback has set g_playback_done. 
*/ 
static void SP_CALLCONV track_ended(void) 
{ 
    printf("track_ended\n"); 

    if (g_currenttrack) { 
     sp_track_release(g_currenttrack); 
     g_currenttrack = NULL; 
     sp_session_player_unload(g_sess); 
     exit(0); 
    } 
} 

/** 
* Show usage information 
* 
* @param progname The program name 
*/ 
static void usage(const char *progname) 
{ 
    fprintf(stderr, "usage: %s <username> <password> <trackurl>\n", progname); 
} 


/************************************************* 
* app main 
* 
*************************************************/ 
int main(int argc, char **argv) 
{ 
    sp_session *sp; 
    sp_error err; 
    int next_timeout = 0; 
    DWORD ev; 

    const char* username_default = "username"; 
    const char* password_default = "login"; 

    const char *username = argc > 1 ? argv[1] : NULL; 
    const char *password = argc > 2 ? argv[2] : NULL; 
    g_trackurl = argc > 3 ? argv[3] : NULL; 


    if (!username || !password) { 
     username = username_default; 
     password = password_default; 
    } 

    events = CreateEvent(NULL, FALSE, FALSE, NULL); 
    audio_init(&g_audiofifo); 

    /* Create session */ 
    spconfig.application_key_size = g_appkey_size; 


    err = sp_session_create(&spconfig, &sp); 

    if (SP_ERROR_OK != err) { 
     fprintf(stderr, "Unable to create session: %s\n", 
      sp_error_message(err)); 
     exit(1); 
    } 

    g_sess = sp; 

// Q: Why a mutex and cond here??? 

// pthread_mutex_init(&g_notify_mutex, NULL); 
// pthread_cond_init(&g_notify_cond, NULL); 

    err = sp_session_login(sp, username, password, 0, NULL); 
// pthread_mutex_lock(&g_notify_mutex); 

    if (SP_ERROR_OK != err) { 
     fprintf(stderr, "Unable to create session: %s\n", 
      sp_error_message(err)); 
     exit(1); 
    } 

    while(!is_logged_out) 
    { 
     ev = WaitForSingleObject(events, next_timeout > 0 ? next_timeout : INFINITE); 

     switch (ev) 
     { 
      case WAIT_OBJECT_0: 
      case WAIT_TIMEOUT: 
       do { 
        sp_session_process_events(g_sess, &next_timeout); 
       } while (next_timeout == 0); 
       break; 
     } 

     if(g_playback_done) 
     { 
      track_ended(); 
      break; 
     } 
    } 

    audio_free(&g_audiofifo); 

    printf("Logged out\n"); 
    sp_session_release(g_sess); 
    printf("Exiting...\n"); 

    return 0; 
} 

cevap

0

Bu sorun hala var, ancak bu konuda çalışmayı başardım.

Sorun, Çalma Listesi ile ilgilidir, ancak nerede ve nasıl olduğunu çözemedim. Sp_playlistcontainer_callbacks uygulamasının yanı sıra sp_playlist_callbacks var. 57: 49,107 E [ap: 4172]

Ben log_message 21 almaya devam ChannelError (3, 1, çalma listesi) ama bu hata ne anlama geldiğini bilmiyorum.

Gözönünde bulundurduğum başka bir şey, libspotify c lib ve C++ uygulamamın karıştırılması nedeniyle derleme ve bağlama sırasında bazı bayt hizalaması veya paketleme sorunu olabileceğidir. Bir dizi farklı ayar denedim. Çalıştırmak için sürüm oluşturmada optimizasyonu da kapatmak zorunda kaldım. en iyi iş çevresinde bulabildiğim

sp_session_config.dont_save_metadata_for_playlists için sp_session_config belirlemekti = DOĞRU sp_session_config.initially_unload_playlists = Bu şimdilik sorunu giderir ama bu sadece bir gizleme hissetmek

DOĞRU daha derin bir sorun. libspotify lib artık desteklenmediği için

hata ayıklama için kaynak kodunu almanın bir yolu yoktur. Tracefile çıktısı için sp_session_config.tracefile param ayarlamayı denedim, ancak hiçbir şey yapmıyor gibi görünüyor.

İlgili konular