diff options
| author | Přemysl Janouch <p@janouch.name> | 2018-10-28 17:49:46 +0100 | 
|---|---|---|
| committer | Přemysl Janouch <p@janouch.name> | 2018-10-28 19:04:51 +0100 | 
| commit | 1f36351ab7cbded30f44f83ce6cdba414aa540c7 (patch) | |
| tree | 322e75c22a68db4c922829383f4aa704f76a202d | |
| parent | bdacb48fb922c51c213b0b9798a23b1d5292e6ee (diff) | |
| download | desktop-tools-1f36351ab7cbded30f44f83ce6cdba414aa540c7.tar.gz desktop-tools-1f36351ab7cbded30f44f83ce6cdba414aa540c7.tar.xz desktop-tools-1f36351ab7cbded30f44f83ce6cdba414aa540c7.zip | |
paswitch: avoid information duplication
And miscellaneous cleanup.
| -rw-r--r-- | LICENSE | 2 | ||||
| -rw-r--r-- | README.adoc | 2 | ||||
| -rw-r--r-- | paswitch.c | 85 | 
3 files changed, 56 insertions, 33 deletions
| @@ -1,4 +1,4 @@ -Copyright (c) 2015 - 2016, Přemysl Janouch <p@janouch.name> +Copyright (c) 2015 - 2018, Přemysl Janouch <p@janouch.name>  Permission to use, copy, modify, and/or distribute this software for any  purpose with or without fee is hereby granted. diff --git a/README.adoc b/README.adoc index 5bb70e3..3c3d4d3 100644 --- a/README.adoc +++ b/README.adoc @@ -8,6 +8,8 @@ to other people as well:   - 'wmstatus' does literally everything my i3 doesn't but I'd like it to. It     includes PulseAudio volume management and hand-written NUT and MPD clients,     all in the name of liberation from GPL-licensed software of course + - 'paswitch' displays a list of all PulseAudio sinks and ports and allows +   switching between them, moving all playing inputs   - 'brightness' allows me to change the brightness of w/e display device I have   - 'input-switch' likewise switches the input source of external displays   - 'fancontrol-ng' is a clone of fancontrol that can handle errors on resume @@ -154,6 +154,9 @@ struct app_context  	pa_context *context;                ///< PulseAudio connection context  	bool failed;                        ///< General PulseAudio failure +	bool reset_sinks;                   ///< Flag for info callback +	bool reset_inputs;                  ///< Flag for info callback +  	char *default_sink;                 ///< Name of the default sink  	struct sink *sinks;                 ///< PulseAudio sinks  	struct sink *sinks_tail;            ///< Tail of PulseAudio sinks @@ -234,7 +237,13 @@ make_inputs_status (struct app_context *ctx, struct sink *sink)  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define DEFAULT_SINK "@DEFAULT_SINK@" +static void +forget_sinks (struct app_context *ctx) +{ +	LIST_FOR_EACH (struct sink, iter, ctx->sinks) +		sink_destroy (iter); +	ctx->sinks = ctx->sinks_tail = NULL; +}  static void  on_sink_info (pa_context *context, const pa_sink_info *info, int eol, @@ -242,6 +251,13 @@ on_sink_info (pa_context *context, const pa_sink_info *info, int eol,  {  	(void) context;  	struct app_context *ctx = userdata; + +	// Assuming replies cannot overlap +	if (ctx->reset_sinks) +	{ +		forget_sinks (ctx); +		ctx->reset_sinks = false; +	}  	if (!info || eol)  	{  		// TODO: handle the case of when sinks disappear @@ -249,6 +265,7 @@ on_sink_info (pa_context *context, const pa_sink_info *info, int eol,  			ctx->selected_sink = ctx->sinks->index;  		poller_idle_set (&ctx->redraw_event); +		ctx->reset_sinks = true;  		return;  	} @@ -281,23 +298,18 @@ on_sink_info (pa_context *context, const pa_sink_info *info, int eol,  }  static void -forget_sinks (struct app_context *ctx) +update_sinks (struct app_context *ctx)  { -	LIST_FOR_EACH (struct sink, iter, ctx->sinks) -		sink_destroy (iter); -	ctx->sinks = ctx->sinks_tail = NULL; +	pa_operation_unref (pa_context_get_sink_info_list +		(ctx->context, on_sink_info, ctx));  }  static void -update_sinks (struct app_context *ctx) +forget_sink_inputs (struct app_context *ctx)  { -	// It shouldn't matter much if we interrupt this operation in the middle -	// since we request new information right away.  At least so long as -	// replies can't overlap.  Though even then we're safe, at least. -	forget_sinks (ctx); - -	pa_operation_unref (pa_context_get_sink_info_list -		(ctx->context, on_sink_info, ctx)); +	LIST_FOR_EACH (struct sink_input, iter, ctx->inputs) +		free (iter); +	ctx->inputs = ctx->inputs_tail = NULL;  }  static void @@ -306,9 +318,17 @@ on_sink_input_info (pa_context *context, const struct pa_sink_input_info *info,  {  	(void) context;  	struct app_context *ctx = userdata; + +	// Assuming replies cannot overlap +	if (ctx->reset_inputs) +	{ +		forget_sink_inputs (ctx); +		ctx->reset_inputs = false; +	}  	if (!info || eol)  	{  		poller_idle_set (&ctx->redraw_event); +		ctx->reset_inputs = true;  		return;  	} @@ -319,21 +339,8 @@ on_sink_input_info (pa_context *context, const struct pa_sink_input_info *info,  }  static void -forget_sink_inputs (struct app_context *ctx) -{ -	LIST_FOR_EACH (struct sink_input, iter, ctx->inputs) -		free (iter); -	ctx->inputs = ctx->inputs_tail = NULL; -} - -static void  update_sink_inputs (struct app_context *ctx)  { -	// It shouldn't matter much if we interrupt this operation in the middle -	// since we request new information right away.  At least so long as -	// replies can't overlap.  Though even then we're safe, at least. -	forget_sink_inputs (ctx); -  	pa_operation_unref (pa_context_get_sink_input_info_list  		(ctx->context, on_sink_input_info, ctx));  } @@ -352,6 +359,13 @@ on_server_info (pa_context *context, const struct pa_server_info *info,  }  static void +update_server_info (struct app_context *ctx) +{ +	pa_operation_unref (pa_context_get_server_info (ctx->context, +		on_server_info, ctx)); +} + +static void  on_event (pa_context *context, pa_subscription_event_type_t event,  	uint32_t index, void *userdata)  { @@ -368,8 +382,7 @@ on_event (pa_context *context, pa_subscription_event_type_t event,  		update_sink_inputs (ctx);  		break;  	case PA_SUBSCRIPTION_EVENT_SERVER: -		pa_operation_unref (pa_context_get_server_info (context, -			on_server_info, userdata)); +		update_server_info (ctx);  	}  } @@ -401,11 +414,13 @@ on_context_state_change (pa_context *context, void *userdata)  		ctx->context = NULL;  		forget_sinks (ctx); +		forget_sink_inputs (ctx);  		cstr_set (&ctx->default_sink, NULL);  		// Retry after an arbitrary delay of 5 seconds  		poller_timer_set (&ctx->make_context, 5000);  		return; +  	case PA_CONTEXT_READY:  		ctx->failed = false;  		poller_idle_set (&ctx->redraw_event); @@ -415,11 +430,12 @@ on_context_state_change (pa_context *context, void *userdata)  			PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SINK_INPUT |  			PA_SUBSCRIPTION_MASK_SERVER, on_subscribe_finish, userdata)); +		ctx->reset_sinks = true; +		ctx->reset_inputs = true; +  		update_sinks (ctx);  		update_sink_inputs (ctx); - -		pa_operation_unref (pa_context_get_server_info (context, -			on_server_info, userdata)); +		update_server_info (ctx);  	default:  		return;  	} @@ -520,7 +536,8 @@ on_redraw (struct app_context *ctx)  	printf ("\x1b[H");   // Cursor to home  	printf ("\x1b[2J");  // Clear the whole screen -	// TODO: see if we can reduce flickering.  Buffering doesn't help much. +	// TODO: see if we can reduce flickering in rxvt-unicode. +	//   Buffering doesn't help, we have to do something more sophisticated.  	// TODO: try not to write more lines than g_terminal_lines for starters  	if (ctx->failed)  	{ @@ -682,7 +699,11 @@ g_key_handlers[] =  	{ "k",       ACTION_UP       },  	{ "j",       ACTION_DOWN     }, +	{ "\x10",    ACTION_UP       }, +	{ "\x0e",    ACTION_DOWN     },  	{ "\r",      ACTION_SELECT   }, +	{ "+",       ACTION_VOLUP    }, +	{ "-",       ACTION_VOLDOWN  },  	{ "\x1b[5~", ACTION_VOLUP    },  	{ "\x1b[6~", ACTION_VOLDOWN  },  	{ "m",       ACTION_MUTE     }, | 
