summaryrefslogtreecommitdiffstats
path: root/parecord/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'parecord/device.c')
-rw-r--r--parecord/device.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/parecord/device.c b/parecord/device.c
new file mode 100644
index 0000000..24f94ba
--- /dev/null
+++ b/parecord/device.c
@@ -0,0 +1,142 @@
+#include <string.h>
+#include <pulse/pulseaudio.h>
+#include <stdio.h>
+
+#include "device.h"
+
+static struct list_devices *g_input; // struct array
+static int input_idx;
+static int input_num; // size of struct array
+
+static void context_state_callback(pa_context *c, void *userdata)
+{
+ int *ready = userdata;
+
+ switch(pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY: {
+ *ready = 1;
+ break;
+ }
+
+ case PA_CONTEXT_TERMINATED:
+ case PA_CONTEXT_FAILED:
+ default: {
+ *ready = 2;
+ // error
+ break;
+ }
+ }
+}
+
+static void context_sourcelist_callback(pa_context *c,
+ const pa_source_info *i, int eol, void *userdata)
+{
+ // end of list
+ if(eol > 0)
+ return;
+
+ if(input_idx >= input_num)
+ {
+ int i;
+ struct list_devices *tmp = malloc(
+ sizeof(struct list_devices) * (input_num+1));
+
+ for(i = 0; i < input_num; i++) {
+ tmp[i].name = g_input[i].name;
+ tmp[i].description = g_input[i].description;
+ }
+ input_num++;
+ free(g_input);
+ g_input = tmp;
+ }
+ g_input[input_idx].name
+ = malloc((strlen(i->name)+1)*sizeof(char));
+ strcpy(g_input[input_idx].name, i->name);
+
+ g_input[input_idx].description
+ = malloc((strlen(i->description)+1)*sizeof(char));
+ strcpy(g_input[input_idx].description, i->description);
+
+ input_idx++;
+}
+
+struct list_devices *getInputDeviceList(int *len)
+{
+ pa_mainloop *ml;
+ pa_mainloop_api *ml_api;
+ pa_context *context;
+ pa_operation *operation;
+ int state = 0;
+ int ready = 0;
+
+ if(!(ml = pa_mainloop_new()))
+ return NULL;
+ ml_api = pa_mainloop_get_api(ml);
+ context = pa_context_new(ml_api, NULL);
+
+ // Connect the context
+ if(pa_context_connect(context, NULL, 0, NULL) < 0)
+ return NULL;
+ pa_context_set_state_callback(context, context_state_callback, &ready);
+
+ input_idx = 0;
+ input_num = 3;
+ g_input = malloc(
+ sizeof(struct list_devices) * input_num);
+
+ for(;;) {
+ if(ready == 0) {
+ pa_mainloop_iterate(ml, 1, NULL);
+ continue;
+ }
+ if(ready == 2) {
+ pa_context_disconnect(context);
+ pa_context_unref(context);
+ pa_mainloop_free(ml);
+ return NULL;
+ }
+
+ switch(state) {
+ case 0: {
+ operation = pa_context_get_source_info_list(
+ context, context_sourcelist_callback, NULL);
+
+ state++;
+ break;
+ }
+ case 1: {
+ if(pa_operation_get_state(operation) == PA_OPERATION_DONE) {
+ pa_operation_unref(operation);
+ pa_context_disconnect(context);
+ pa_context_unref(context);
+ pa_mainloop_free(ml);
+ *len = input_num;
+ return g_input;
+ }
+ break;
+ }
+ default: {
+ pa_mainloop_free(ml);
+ return NULL;
+ }
+ }
+ pa_mainloop_iterate(ml, 1, NULL);
+ }
+}
+
+void freeDeviceList(struct list_devices *list, int len)
+{
+ int i;
+ for(i = 0; i < len; i++)
+ {
+ free(list[i].name);
+ free(list[i].description);
+ }
+ free(list);
+}
+