#include #include #include #include #include #include struct PACBData { pa_context *context; pa_mainloop *mainloop; }; struct NapiCBData { napi_value *cb; napi_env *env; napi_ref *cbRef; }; const char *NAME = "miccontrol"; void handleSourceList(struct pa_context *c, const pa_source_info *i, int eol, void *userdata); void connectToPulseCB(pa_context *context, void *userdata); napi_value connectToPulse(napi_env env, napi_callback_info info); napi_value init(napi_env env, napi_value exports); napi_value connectToPulse(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; struct PACBData *paCBData; napi_status status; struct NapiCBData *napiCBData = malloc(sizeof(struct NapiCBData)); napiCBData->cbRef = malloc(sizeof(napi_ref)); status = napi_get_cb_info(env, info, &argc, args, NULL, (void**)&paCBData); assert(argc == 1); assert(status == napi_ok); printf("finished getting calback info... \n"); napiCBData->env = &env; status = napi_create_reference(env, *args, 1, napiCBData->cbRef); assert(status == napi_ok); int ret = 1; pa_context_set_state_callback(paCBData->context, connectToPulseCB, napiCBData); pa_context_connect(paCBData->context, NULL, 0, NULL); pa_mainloop_run(paCBData->mainloop, &ret); pa_context_unref(paCBData->context); pa_mainloop_free(paCBData->mainloop); //free(napiCBData); return NULL; } void connectToPulseCB(pa_context *context, void *userdata) { printf("Callback called... \n"); napi_status status; napi_value argv[1]; struct NapiCBData *napiCBData = (struct NapiCBData*)userdata; pa_context_state_t pa_state = pa_context_get_state(context); napi_value errorString; if(pa_state == PA_CONTEXT_READY) { status = napi_get_undefined(*(napiCBData->env), &argv[0]); } else if(pa_state == PA_CONTEXT_FAILED) { status = napi_create_string_utf8( *(napiCBData->env), "Error connecting to Pulse Audio", NAPI_AUTO_LENGTH, &errorString); assert(status == napi_ok); status = napi_create_error(*(napiCBData->env), NULL, errorString, &argv[0]); assert(status == napi_ok); } else { return; //eventually need to look into reconnecting on disconnections and handling //connection failures. } napi_value global; status = napi_get_global(*(napiCBData->env), &global); assert(status == napi_ok); napi_value result; napi_value cb; status = napi_get_reference_value(*(napiCBData->env), *(napiCBData->cbRef), &cb); assert(status == napi_ok); printf("Calling callback from native... \n"); status = napi_call_function(*(napiCBData->env), global, cb, 1, argv, &result); assert(status == napi_ok); } //napi_value getSources() { // pa_operation *getSourceOp = NULL; // getSourceOp = pa_context_get_source_info_list(context, handleSourceList, NULL); // if(!getSourceOp) { // } else { // pa_operation_state_t state = pa_operation_get_state(getSourceOp); // switch(state) { // case PA_OPERATION_RUNNING: // break; // case PA_OPERATION_DONE: // break; // case PA_OPERATION_CANCELLED: // } // } //} // //void handleSourceList(pa_context *c, const pa_source_info *i, int eol, void *userdata) { // printf("Callback called...\n"); // printf("eol is %d\n", eol); // printf(i->description); // printf("\n"); // // return; //} void handler(int sig) { void *array[10]; size_t size; size = backtrace(array, 10); fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, STDERR_FILENO); exit(1); } napi_value init(napi_env env, napi_value exports) { signal(SIGSEGV, handler); pa_mainloop *mainloop = pa_mainloop_new(); pa_mainloop_api *mainloop_api = pa_mainloop_get_api(mainloop); pa_context *context = pa_context_new(mainloop_api, NULL); struct PACBData *paCBData = malloc(sizeof(*paCBData)); paCBData->context = context; paCBData->mainloop = mainloop; napi_status status; napi_value fn; status = napi_create_function( env, "connectToPulse", NAPI_AUTO_LENGTH, connectToPulse, paCBData, &fn); if(status != napi_ok) { return NULL; } status = napi_set_named_property(env, exports, "connectToPulse", fn); if(status != napi_ok) { return NULL; } // status = napi_create_function(env, NULL, NAPI_AUTO_LENGTH, getSources, paCBData, &fn); // // if(status != napi_ok) { // return NULL; // } // // status = napi_set_named_property(env, exports, "getSources", fn); // // if(status != napi_ok) { // return NULL; // } return exports; } NAPI_MODULE(NODE_GYP_MODULE_NAME, init);