Compare commits

..

No commits in common. "7143225fc582084630693ad6f9e455b3206f4fff" and "bdacb48fb922c51c213b0b9798a23b1d5292e6ee" have entirely different histories.

4 changed files with 42 additions and 79 deletions

View File

@ -96,8 +96,8 @@ if (WITH_GDM)
install (TARGETS gdm-switch-user DESTINATION ${CMAKE_INSTALL_BINDIR}) install (TARGETS gdm-switch-user DESTINATION ${CMAKE_INSTALL_BINDIR})
endif (WITH_GDM) endif (WITH_GDM)
install (TARGETS wmstatus paswitch brightness input-switch fancontrol-ng priod install (TARGETS wmstatus brightness input-switch fancontrol-ng priod iexec
iexec siprandom DESTINATION ${CMAKE_INSTALL_BINDIR}) siprandom DESTINATION ${CMAKE_INSTALL_BINDIR})
install (PROGRAMS shellify DESTINATION ${CMAKE_INSTALL_BINDIR}) install (PROGRAMS shellify DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})

View File

@ -1,4 +1,4 @@
Copyright (c) 2015 - 2018, Přemysl Janouch <p@janouch.name> Copyright (c) 2015 - 2016, Přemysl Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.

View File

@ -8,8 +8,6 @@ to other people as well:
- 'wmstatus' does literally everything my i3 doesn't but I'd like it to. It - '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, includes PulseAudio volume management and hand-written NUT and MPD clients,
all in the name of liberation from GPL-licensed software of course 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 - 'brightness' allows me to change the brightness of w/e display device I have
- 'input-switch' likewise switches the input source of external displays - 'input-switch' likewise switches the input source of external displays
- 'fancontrol-ng' is a clone of fancontrol that can handle errors on resume - 'fancontrol-ng' is a clone of fancontrol that can handle errors on resume

View File

@ -154,9 +154,6 @@ struct app_context
pa_context *context; ///< PulseAudio connection context pa_context *context; ///< PulseAudio connection context
bool failed; ///< General PulseAudio failure 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 char *default_sink; ///< Name of the default sink
struct sink *sinks; ///< PulseAudio sinks struct sink *sinks; ///< PulseAudio sinks
struct sink *sinks_tail; ///< Tail of PulseAudio sinks struct sink *sinks_tail; ///< Tail of PulseAudio sinks
@ -196,15 +193,6 @@ app_context_free (struct app_context *self)
poller_free (&self->poller); poller_free (&self->poller);
} }
static struct sink *
current_sink (struct app_context *ctx)
{
LIST_FOR_EACH (struct sink, iter, ctx->sinks)
if (iter->index == ctx->selected_sink)
return iter;
return NULL;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define VOLUME_PERCENT(x) (((x) * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM) #define VOLUME_PERCENT(x) (((x) * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM)
@ -246,13 +234,7 @@ make_inputs_status (struct app_context *ctx, struct sink *sink)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void #define DEFAULT_SINK "@DEFAULT_SINK@"
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 static void
on_sink_info (pa_context *context, const pa_sink_info *info, int eol, on_sink_info (pa_context *context, const pa_sink_info *info, int eol,
@ -260,26 +242,13 @@ on_sink_info (pa_context *context, const pa_sink_info *info, int eol,
{ {
(void) context; (void) context;
struct app_context *ctx = userdata; struct app_context *ctx = userdata;
// Assuming replies cannot overlap
if (ctx->reset_sinks)
{
forget_sinks (ctx);
ctx->reset_sinks = false;
}
if (!info || eol) if (!info || eol)
{ {
struct sink *sink = current_sink (ctx); // TODO: handle the case of when sinks disappear
if (!sink && ctx->sinks) if (ctx->selected_sink == PA_INVALID_INDEX && ctx->sinks)
{
ctx->selected_sink = ctx->sinks->index; ctx->selected_sink = ctx->sinks->index;
ctx->selected_port = -1;
}
else if (sink && ctx->selected_port >= (ssize_t) sink->ports_len)
ctx->selected_port = -1;
poller_idle_set (&ctx->redraw_event); poller_idle_set (&ctx->redraw_event);
ctx->reset_sinks = true;
return; return;
} }
@ -312,20 +281,23 @@ on_sink_info (pa_context *context, const pa_sink_info *info, int eol,
} }
static void static void
update_sinks (struct app_context *ctx) forget_sinks (struct app_context *ctx)
{ {
pa_operation_unref (pa_context_get_sink_info_list LIST_FOR_EACH (struct sink, iter, ctx->sinks)
(ctx->context, on_sink_info, ctx)); sink_destroy (iter);
ctx->sinks = ctx->sinks_tail = NULL;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void static void
forget_sink_inputs (struct app_context *ctx) update_sinks (struct app_context *ctx)
{ {
LIST_FOR_EACH (struct sink_input, iter, ctx->inputs) // It shouldn't matter much if we interrupt this operation in the middle
free (iter); // since we request new information right away. At least so long as
ctx->inputs = ctx->inputs_tail = NULL; // 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));
} }
static void static void
@ -334,17 +306,9 @@ on_sink_input_info (pa_context *context, const struct pa_sink_input_info *info,
{ {
(void) context; (void) context;
struct app_context *ctx = userdata; struct app_context *ctx = userdata;
// Assuming replies cannot overlap
if (ctx->reset_inputs)
{
forget_sink_inputs (ctx);
ctx->reset_inputs = false;
}
if (!info || eol) if (!info || eol)
{ {
poller_idle_set (&ctx->redraw_event); poller_idle_set (&ctx->redraw_event);
ctx->reset_inputs = true;
return; return;
} }
@ -354,9 +318,22 @@ on_sink_input_info (pa_context *context, const struct pa_sink_input_info *info,
LIST_APPEND_WITH_TAIL (ctx->inputs, ctx->inputs_tail, input); LIST_APPEND_WITH_TAIL (ctx->inputs, ctx->inputs_tail, input);
} }
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 static void
update_sink_inputs (struct app_context *ctx) 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 pa_operation_unref (pa_context_get_sink_input_info_list
(ctx->context, on_sink_input_info, ctx)); (ctx->context, on_sink_input_info, ctx));
} }
@ -374,15 +351,6 @@ on_server_info (pa_context *context, const struct pa_server_info *info,
cstr_set (&ctx->default_sink, NULL); cstr_set (&ctx->default_sink, NULL);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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 static void
on_event (pa_context *context, pa_subscription_event_type_t event, on_event (pa_context *context, pa_subscription_event_type_t event,
uint32_t index, void *userdata) uint32_t index, void *userdata)
@ -400,7 +368,8 @@ on_event (pa_context *context, pa_subscription_event_type_t event,
update_sink_inputs (ctx); update_sink_inputs (ctx);
break; break;
case PA_SUBSCRIPTION_EVENT_SERVER: case PA_SUBSCRIPTION_EVENT_SERVER:
update_server_info (ctx); pa_operation_unref (pa_context_get_server_info (context,
on_server_info, userdata));
} }
} }
@ -432,13 +401,11 @@ on_context_state_change (pa_context *context, void *userdata)
ctx->context = NULL; ctx->context = NULL;
forget_sinks (ctx); forget_sinks (ctx);
forget_sink_inputs (ctx);
cstr_set (&ctx->default_sink, NULL); cstr_set (&ctx->default_sink, NULL);
// Retry after an arbitrary delay of 5 seconds // Retry after an arbitrary delay of 5 seconds
poller_timer_set (&ctx->make_context, 5000); poller_timer_set (&ctx->make_context, 5000);
return; return;
case PA_CONTEXT_READY: case PA_CONTEXT_READY:
ctx->failed = false; ctx->failed = false;
poller_idle_set (&ctx->redraw_event); poller_idle_set (&ctx->redraw_event);
@ -448,12 +415,11 @@ on_context_state_change (pa_context *context, void *userdata)
PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SINK_INPUT |
PA_SUBSCRIPTION_MASK_SERVER, on_subscribe_finish, userdata)); PA_SUBSCRIPTION_MASK_SERVER, on_subscribe_finish, userdata));
ctx->reset_sinks = true;
ctx->reset_inputs = true;
update_sinks (ctx); update_sinks (ctx);
update_sink_inputs (ctx); update_sink_inputs (ctx);
update_server_info (ctx);
pa_operation_unref (pa_context_get_server_info (context,
on_server_info, userdata));
default: default:
return; return;
} }
@ -554,8 +520,7 @@ on_redraw (struct app_context *ctx)
printf ("\x1b[H"); // Cursor to home printf ("\x1b[H"); // Cursor to home
printf ("\x1b[2J"); // Clear the whole screen printf ("\x1b[2J"); // Clear the whole screen
// TODO: see if we can reduce flickering in rxvt-unicode. // TODO: see if we can reduce flickering. Buffering doesn't help much.
// Buffering doesn't help, we have to do something more sophisticated.
// TODO: try not to write more lines than g_terminal_lines for starters // TODO: try not to write more lines than g_terminal_lines for starters
if (ctx->failed) if (ctx->failed)
{ {
@ -618,7 +583,11 @@ on_action (struct app_context *ctx, enum action action)
{ {
poller_idle_set (&ctx->redraw_event); poller_idle_set (&ctx->redraw_event);
struct sink *sink = current_sink (ctx); struct sink *sink = NULL;
LIST_FOR_EACH (struct sink, iter, ctx->sinks)
if (iter->index == ctx->selected_sink)
sink = iter;
switch (action) switch (action)
{ {
case ACTION_UP: case ACTION_UP:
@ -713,11 +682,7 @@ g_key_handlers[] =
{ "k", ACTION_UP }, { "k", ACTION_UP },
{ "j", ACTION_DOWN }, { "j", ACTION_DOWN },
{ "\x10", ACTION_UP },
{ "\x0e", ACTION_DOWN },
{ "\r", ACTION_SELECT }, { "\r", ACTION_SELECT },
{ "+", ACTION_VOLUP },
{ "-", ACTION_VOLDOWN },
{ "\x1b[5~", ACTION_VOLUP }, { "\x1b[5~", ACTION_VOLUP },
{ "\x1b[6~", ACTION_VOLDOWN }, { "\x1b[6~", ACTION_VOLDOWN },
{ "m", ACTION_MUTE }, { "m", ACTION_MUTE },