aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pulsemix.c130
1 files changed, 103 insertions, 27 deletions
diff --git a/pulsemix.c b/pulsemix.c
index bd565ca..6741a09 100644
--- a/pulsemix.c
+++ b/pulsemix.c
@@ -116,6 +116,12 @@ int xstrtol(const char *str, long *out)
return 0;
}
+static void populate(struct io_t *node)
+{
+ node->volume_percent = (int)(((double)pa_cvolume_avg(&node->volume) * 100)
+ / PA_VOLUME_NORM);
+}
+
static struct io_t *sink_new(const pa_sink_info *info)
{
struct io_t *sink = calloc(1, sizeof(struct io_t));
@@ -126,16 +132,34 @@ static struct io_t *sink_new(const pa_sink_info *info)
sink->desc = strdup(info->description);
sink->pp_name = "sink";
memcpy(&sink->volume, &info->volume, sizeof(pa_cvolume));
- sink->volume_percent = (int)(((double)pa_cvolume_avg(&sink->volume) * 100)
- / PA_VOLUME_NORM);
sink->mute = info->mute;
sink->fn_mute = pa_context_set_sink_mute_by_index;
sink->fn_setvol = pa_context_set_sink_volume_by_index;
+ populate(sink);
return sink;
}
+static struct io_t *source_new(const pa_source_info *info)
+{
+ struct io_t *source = calloc(1, sizeof(struct io_t));
+
+ source->type = TYPE_SOURCE;
+ source->idx = info->index;
+ source->name = strdup(info->name);
+ source->desc = strdup(info->description);
+ source->pp_name = "source";
+ memcpy(&source->volume, &info->volume, sizeof(pa_cvolume));
+ source->mute = info->mute;
+
+ source->fn_mute = pa_context_set_source_mute_by_index;
+ source->fn_setvol = pa_context_set_source_volume_by_index;
+
+ populate(source);
+ return source;
+}
+
static void sink_add_cb(pa_context UNUSED *c, const pa_sink_info *i, int eol,
void *raw)
{
@@ -146,12 +170,23 @@ static void sink_add_cb(pa_context UNUSED *c, const pa_sink_info *i, int eol,
return;
sink = sink_new(i);
-
- if (pulse->head != NULL)
- sink->next = pulse->head;
+ sink->next = pulse->head;
pulse->head = sink;
}
+static void source_add_cb(pa_context UNUSED *c, const pa_source_info *i, int eol, void *raw)
+{
+ struct pulseaudio_t *pulse = raw;
+ struct io_t *source;
+
+ if (eol)
+ return;
+
+ source = source_new(i);
+ source->next = pulse->head;
+ pulse->head = source;
+}
+
static void server_info_cb(pa_context UNUSED *c, const pa_server_info *i,
void *raw)
{
@@ -160,6 +195,13 @@ static void server_info_cb(pa_context UNUSED *c, const pa_server_info *i,
*sink_name = i->default_sink_name;
}
+static void source_info_cb(pa_context UNUSED *c, const pa_server_info *i, void *raw)
+{
+ const char **source_name = (const char **)raw;
+
+ *source_name = i->default_source_name;
+}
+
static void state_cb(pa_context UNUSED *c, void *raw)
{
struct pulseaudio_t *pulse = raw;
@@ -286,6 +328,25 @@ static void get_default_sink(struct pulseaudio_t *pulse)
get_sink_by_name(pulse, sink_name);
}
+static void get_source_by_name(struct pulseaudio_t *pulse, const char *name)
+{
+ pa_operation *op = pa_context_get_source_info_by_name(pulse->cxt, name,
+ source_add_cb, pulse);
+ pulse_async_wait(pulse, op);
+ pa_operation_unref(op);
+}
+
+static void get_default_source(struct pulseaudio_t *pulse)
+{
+ const char *source_name;
+ pa_operation *op = pa_context_get_server_info(pulse->cxt, source_info_cb,
+ &source_name);
+ pulse_async_wait(pulse, op);
+ pa_operation_unref(op);
+
+ get_source_by_name(pulse, source_name);
+}
+
static int set_default_sink(struct pulseaudio_t *pulse, const char *sinkname)
{
pa_operation *op;
@@ -360,19 +421,20 @@ void usage(FILE *out)
{
fprintf(out, "usage: %s [options] <command>...\n", program_invocation_short_name);
fputs("\nOptions:\n", out);
- fputs(" -h, --help, display this help and exit\n", out);
- fputs(" -s, --sink <name> control a sink other than the default\n", out);
+ fputs(" -h, --help, display this help and exit\n", out);
+ fputs(" -o, --sink <name> control a sink other than the default\n", out);
+ fputs(" -i, --source <name> control a source\n", out);
fputs("\nCommands:\n", out);
- fputs(" list list available sinks\n", out);
- fputs(" get-volume get volume for sink\n", out);
- fputs(" set-volume VALUE set volume for sink\n", out);
- fputs(" increase VALUE increase volume\n", out);
- fputs(" decrease VALUE decrease volume\n", out);
- fputs(" mute mute active sink\n", out);
- fputs(" unmute unmute active sink\n", out);
- fputs(" toggle toggle mute\n", out);
- fputs(" set-sink SINKNAME set default sink\n", out);
+ fputs(" list list available sinks\n", out);
+ fputs(" get-volume get volume for sink\n", out);
+ fputs(" set-volume VALUE set volume for sink\n", out);
+ fputs(" increase VALUE increase volume\n", out);
+ fputs(" decrease VALUE decrease volume\n", out);
+ fputs(" mute mute active sink\n", out);
+ fputs(" unmute unmute active sink\n", out);
+ fputs(" toggle toggle mute\n", out);
+ fputs(" set-sink SINKNAME set default sink\n", out);
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
@@ -405,26 +467,40 @@ int main(int argc, char *argv[])
{
struct pulseaudio_t pulse;
enum action verb;
- char *sink = NULL;
+ char *id = NULL;
union arg_t value;
int rc = 0;
+ const char *pp_name = "sink";
+ void (*fn_get_default)(struct pulseaudio_t *) = get_default_sink;
+ void (*fn_get_by_name)(struct pulseaudio_t *, const char*) = get_sink_by_name;
+
static const struct option opts[] = {
{ "help", no_argument, 0, 'h' },
- { "sink", required_argument, 0, 's' },
+ { "sink", optional_argument, 0, 'o' },
+ { "source", optional_argument, 0, 'i' },
{ 0, 0, 0, 0 },
};
for (;;) {
- int opt = getopt_long(argc, argv, "hs:", opts, NULL);
+ int opt = getopt_long(argc, argv, "ho:i:", opts, NULL);
if (opt == -1)
break;
switch (opt) {
case 'h':
usage(stdout);
- case 's':
- sink = optarg;
+ case 'o':
+ id = optarg;
+ fn_get_default = get_default_sink;
+ fn_get_by_name = get_sink_by_name;
+ pp_name = "sink";
+ break;
+ case 'i':
+ id = optarg;
+ fn_get_default = get_default_source;
+ fn_get_by_name = get_source_by_name;
+ pp_name = "source";
break;
default:
exit(1);
@@ -465,13 +541,13 @@ int main(int argc, char *argv[])
print_all(&pulse);
} else {
/* determine sink */
- if (sink) {
- get_sink_by_name(&pulse, sink);
- } else
- get_default_sink(&pulse);
+ if (id && fn_get_by_name)
+ fn_get_by_name(&pulse, id);
+ else if (fn_get_default)
+ fn_get_default(&pulse);
- if(pulse.head == NULL)
- errx(EXIT_FAILURE, "sink not found: %s", sink ? sink : "default");
+ if (pulse.head == NULL)
+ errx(EXIT_FAILURE, "%s not found: %s", pp_name, id ? id : "default");
switch (verb) {
case ACTION_GETVOL: