diff options
| -rw-r--r-- | pulsemix.c | 130 | 
1 files changed, 103 insertions, 27 deletions
| @@ -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: | 
