node-pulseaudio-control/main.c

179 lines
4.7 KiB
C
Raw Normal View History

2018-04-20 17:29:09 +00:00
#include <node/node_api.h>
2018-04-20 04:01:34 +00:00
#include <stdio.h>
2018-04-20 17:29:09 +00:00
#include <execinfo.h>
#include <signal.h>
#include <unistd.h>
2018-04-20 04:01:34 +00:00
#include <pulse/pulseaudio.h>
2018-04-12 17:30:06 +00:00
2018-04-20 04:01:34 +00:00
struct PACBData {
2018-04-16 23:42:55 +00:00
pa_context *context;
pa_mainloop *mainloop;
2018-04-20 04:01:34 +00:00
};
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
struct NapiCBData {
napi_value *cb;
napi_env *env;
napi_ref *cbRef;
};
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
const char *NAME = "miccontrol";
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
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);
2018-04-12 17:30:06 +00:00
2018-04-20 04:01:34 +00:00
napi_value connectToPulse(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
struct PACBData *paCBData;
napi_status status;
2018-04-20 17:29:09 +00:00
struct NapiCBData *napiCBData = malloc(sizeof(struct NapiCBData));
napiCBData->cbRef = malloc(sizeof(napi_ref));
2018-04-20 04:01:34 +00:00
status = napi_get_cb_info(env, info, &argc, args, NULL, (void**)&paCBData);
2018-04-20 17:29:09 +00:00
assert(argc == 1);
2018-04-20 04:01:34 +00:00
assert(status == napi_ok);
2018-04-20 17:29:09 +00:00
printf("finished getting calback info... \n");
2018-04-20 04:01:34 +00:00
napiCBData->env = &env;
2018-04-16 23:42:55 +00:00
2018-04-20 17:29:09 +00:00
status = napi_create_reference(env, *args, 1, napiCBData->cbRef);
2018-04-20 04:01:34 +00:00
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);
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
pa_context_unref(paCBData->context);
pa_mainloop_free(paCBData->mainloop);
//free(napiCBData);
return NULL;
}
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
void connectToPulseCB(pa_context *context, void *userdata) {
2018-04-20 17:29:09 +00:00
printf("Callback called... \n");
2018-04-20 04:01:34 +00:00
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 {
2018-04-20 17:29:09 +00:00
return;
2018-04-20 04:01:34 +00:00
//eventually need to look into reconnecting on disconnections and handling
//connection failures.
2018-04-12 17:30:06 +00:00
}
2018-04-20 04:01:34 +00:00
napi_value global;
status = napi_get_global(*(napiCBData->env), &global);
assert(status == napi_ok);
napi_value result;
napi_value cb;
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
status = napi_get_reference_value(*(napiCBData->env), *(napiCBData->cbRef), &cb);
assert(status == napi_ok);
2018-04-20 17:29:09 +00:00
printf("Calling callback from native... \n");
2018-04-20 04:01:34 +00:00
status = napi_call_function(*(napiCBData->env), global, cb, 1, argv, &result);
assert(status == napi_ok);
2018-04-16 23:42:55 +00:00
}
2018-04-20 04:01:34 +00:00
//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;
//}
2018-04-20 17:29:09 +00:00
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);
}
2018-04-16 23:42:55 +00:00
napi_value init(napi_env env, napi_value exports) {
2018-04-20 17:29:09 +00:00
signal(SIGSEGV, handler);
2018-04-20 04:01:34 +00:00
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);
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
struct PACBData *paCBData = malloc(sizeof(*paCBData));
2018-04-16 23:42:55 +00:00
2018-04-20 04:01:34 +00:00
paCBData->context = context;
paCBData->mainloop = mainloop;
2018-04-16 23:42:55 +00:00
napi_status status;
napi_value fn;
2018-04-20 04:01:34 +00:00
status = napi_create_function(
env,
"connectToPulse",
NAPI_AUTO_LENGTH,
connectToPulse,
paCBData,
&fn);
2018-04-16 23:42:55 +00:00
if(status != napi_ok) {
2018-04-20 04:01:34 +00:00
return NULL;
2018-04-16 23:42:55 +00:00
}
status = napi_set_named_property(env, exports, "connectToPulse", fn);
if(status != napi_ok) {
2018-04-20 04:01:34 +00:00
return NULL;
2018-04-16 23:42:55 +00:00
}
2018-04-20 04:01:34 +00:00
// 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;
// }
2018-04-16 23:42:55 +00:00
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, init);