我正在尝试为包装libspotify的nodeJS编写一个模块。目标是编写一个webapp,允许远程控制从spotify播放音乐的设备。
我已决定使用spshell示例来确保线程安全,并在plain C中编写一个“Spotify Service”,它启动一个调用所有API函数的单独线程。
nodeJS模块然后只调用一些提供的函数来与spotify交互。可以在此处找到服务的代码:http://pastebin.com/KB6uwSC8新线程从底部开始。
现在,如果我在这样一个简单的程序中调用它(fget只是为了让登录完成一个简单的方法)。我使用c ++来接近node-gyp编译代码。
#include <stdio.h>
extern "C" {
#include "objects/SpotifyService.h"
}
int main(int argc, char** argv) {
login();
char string[100];
fgets(string, 100, stdin);
fprintf(stdout, "Got: %s", string);
logout();
fgets(string, 100, stdin);
fprintf(stdout, "Got: %s", string);
return 0;
}
工作正常。我无法让它崩溃。
如果我在nodeJS中使用相同的“服务”(意味着我只是致电login()
和logout()
而不执行任何操作),则在退出时会崩溃 ,喜欢7-8 / 10次。我尝试了很多东西,包括:
无济于事。它只是崩溃了。从gdb中调用时似乎崩溃较少,但这可能是随机的。
来自gdb的堆栈跟踪显示以下内容:
Thread 3 (Thread 0x7ffff65fd700 (LWP 21838)):
#0 0x00007ffff678f746 in ?? () from /usr/local/lib/libspotify.so.12
#1 0x00007ffff6702289 in ?? () from /usr/local/lib/libspotify.so.12
#2 0x00007ffff6702535 in ?? () from /usr/local/lib/libspotify.so.12
#3 0x00007ffff6703b5a in ?? () from /usr/local/lib/libspotify.so.12
#4 0x00007ffff6703c86 in ?? () from /usr/local/lib/libspotify.so.12
#5 0x00007ffff66c5c8b in ?? () from /usr/local/lib/libspotify.so.12
#6 0x00007ffff679a5b3 in sp_session_process_events () from /usr/local/lib/libspotify.so.12
#7 0x00007ffff6aa7839 in spotifyLoop (nervNicht=<value optimized out>) at ../src/SpotifyService.c:103
#8 0x00007ffff70118ca in start_thread () from /lib/libpthread.so.0
#9 0x00007ffff6d78b6d in clone () from /lib/libc.so.6
#10 0x0000000000000000 in ?? ()
(在OSX中,gdb显示libspotify中调用的函数称为“process_title”。)
由于到目前为止没有任何帮助我只是不知道我是否可以使这个工作,或者它是libspotify中与nodeJS不兼容的东西。我不明白node-gyp如何链接.o文件,也许出了点问题?
我在github上发现了另外两个尝试这样做的项目,但是其中一个项目将spotify主循环实际放在Javascript中,另一个使用节点0.1.100和libspotify 0.0.4并且未在2中更新年份。我无法从他们两个身上学到任何东西。
答案 0 :(得分:1)
好的,我已经玩了一些。我只是忽略了注销错误并继续实现其他功能。
我在logged_in回调中添加了一个新的sp_playlist_container创建,显然有帮助。之后,节点模块不再崩溃(或尚未崩溃)。
static sp_playlistcontainer_callbacks pc_callbacks = {
.container_loaded = &rootPlaylistContainerLoaded,
};
static void rootPlaylistContainerLoaded(sp_playlistcontainer* pc, void* userdata) {
int numPlaylists = sp_playlistcontainer_num_playlists(pc);
fprintf(stdout, "Root playlist synchronized, number of Playlists: %d\n", numPlaylists);
}
static void loggedIn(sp_session* session, sp_error error) {
if(SP_ERROR_OK != error) {
fprintf(stderr, "Error logging in: %s\n", sp_error_message(error));
} else {
fprintf(stdout, "Service is logged in!\n");
}
//This is absolutely necessary here, otherwise following callbacks can crash.
sp_playlistcontainer *pc = sp_session_playlistcontainer(spotifySession);
sp_playlistcontainer_add_callbacks(pc, &pc_callbacks, NULL);
}
但sp_playlist_container创建必须在logged_in回调中,如果我在另一个函数(例如“getPlaylistNames”)中调用它,程序也会崩溃。
我会看看它是否会继续发挥作用,并希望这个答案可以帮助其他人。