2

我正在围绕 libspotfiy 编写 C# 包装器,并且在播放曲目时遇到问题。据我所知,当我想在会话中第一次开始流式传输曲目时,我应该打电话

sp_session_player_load(sessionHandle, trackHandle)
sp_session_player_play(sessionHandle, true);

这就是我正在做的,它工作正常。当我想玩别的东西时,问题就开始了。有一首曲目仍在播放,我该怎么做才能播放新曲目?我应该打电话

sp_session_player_play(sessionHandle, false);
sp_session_player_unload(sessionHandle);

在此之前调用新一轮的加载/播放?我问是因为当我这样做时,我经常看到我的程序在我调用卸载时挂起,或者使用 false 参数调用 play。我正在使用 get_audio_buffer_stats 回调。我有适当的线程同步,所以我想知道我是否错误地唱了 api?

4

2 回答 2

4

这正是 Mac 和 iOS 官方库所做的,并且运行良好:

第一次玩时:

sp_session_player_load(sessionHandle, trackHandle)
sp_session_player_play(sessionHandle, true);

再次播放时:

sp_session_player_play(sessionHandle, false);
sp_session_player_unload(sessionHandle);
sp_session_player_load(sessionHandle, trackHandle)
sp_session_player_play(sessionHandle, true);

不过,您可以检查几件事:

  • 我见过的最常见的挂起是由于程序如何实现notify_main_thread回调。当你得到这个时,你必须以非阻塞的sp_session_process_events方式在主线程上安排一个调用。即,您的实现应该在另一个线程上调用之前返回。notify_main_threadsp_session_process_events

  • 尝试取出你的get_audio_buffer_stats实现。这个 Mac/iOS 库根本没有实现这一点 - 它不是必需的。

如果这还不够,请尝试获取挂起的堆栈跟踪。如果你在调试器中捕获它,点击暂停通常就足够了。

于 2012-11-05T10:48:22.693 回答
0

我的代码通过简单地向另一个线程发出信号来对 notify_main_thread 回调做出反应,因此它完全是非阻塞的。

我似乎已经解决了一些问题,但我仍然有些困惑。我确实删除了 get_audio_buffer_stats 回调。但是,似乎有帮助的是在调用 sp_session_player_unload 之前停止在 music_delivery 回调中执行任何操作。

我锁定了我在 music_delivery 回调中所做的一切,以及保护 sp_session_player_unload 的相同锁定。因此,似乎在执行 sp_session_player_unload 时,libspotify 中的另一个线程会触发 music_delivery 回调,这自然要等待 sp_session_player_unload 完成。看来这可能会导致死锁。

我认为我通过确保music_delivery 回调和其他libspotify 函数(即sp_session_player_unload)应该受到同一个互斥锁保护来做正确的事情?也许在 music_delivery 中正确的做法是立即返回,如果尝试获取锁失败,则报告没有采样?(那么对于在 process_events 线程之外进行的所有回调,情况是否如此?)

于 2012-11-05T17:50:32.067 回答