diff options
-rw-r--r-- | src/command.c | 53 | ||||
-rw-r--r-- | src/interface.c | 180 | ||||
-rw-r--r-- | src/interface.h | 31 | ||||
-rw-r--r-- | src/pa-sink-ctl.c | 36 | ||||
-rw-r--r-- | src/pa-sink-ctl.h | 26 |
5 files changed, 171 insertions, 155 deletions
diff --git a/src/command.c b/src/command.c index 312e8a3..ddb0816 100644 --- a/src/command.c +++ b/src/command.c @@ -40,39 +40,41 @@ sink_input_len(struct context *ctx, struct sink_info *sink) static void up(struct context *ctx, int key) { + struct interface *ifc = &ctx->interface; struct sink_info *sink = NULL; if (!ctx->context_ready) return; - if (ctx->chooser_input == SELECTED_SINK && - ctx->chooser_sink > 0) { - sink = g_list_nth_data(ctx->sink_list, --ctx->chooser_sink); + if (ifc->chooser_input == SELECTED_SINK && + ifc->chooser_sink > 0) { + sink = g_list_nth_data(ctx->sink_list, --ifc->chooser_sink); /* autoassigment to SELECTED_SINK (=-1) if length = 0 */ - ctx->chooser_input = sink_input_len(ctx, sink) - 1; - } else if (ctx->chooser_input >= 0) - --ctx->chooser_input; + ifc->chooser_input = sink_input_len(ctx, sink) - 1; + } else if (ifc->chooser_input >= 0) + --ifc->chooser_input; - interface_redraw(ctx); + interface_redraw(ifc); } static void down(struct context *ctx, int key) { + struct interface *ifc = &ctx->interface; struct sink_info *sink; if (!ctx->context_ready) return; - sink = g_list_nth_data(ctx->sink_list, ctx->chooser_sink); - if (ctx->chooser_input == (sink_input_len(ctx, sink) - 1) && - ctx->chooser_sink < (gint) g_list_length(ctx->sink_list)-1) { - ++ctx->chooser_sink; - ctx->chooser_input = SELECTED_SINK; - } - else if (ctx->chooser_input < (sink_input_len(ctx, sink) - 1)) - ++ctx->chooser_input; - interface_redraw(ctx); + sink = g_list_nth_data(ctx->sink_list, ifc->chooser_sink); + if (ifc->chooser_input == (sink_input_len(ctx, sink) - 1) && + ifc->chooser_sink < (gint) g_list_length(ctx->sink_list)-1) { + ++ifc->chooser_sink; + ifc->chooser_input = SELECTED_SINK; + } else if (ifc->chooser_input < (sink_input_len(ctx, sink) - 1)) + ++ifc->chooser_input; + + interface_redraw(ifc); } static void @@ -86,7 +88,7 @@ volume_change(struct context *ctx, gboolean volume_increment) if (!ctx->context_ready) return; - ctl = interface_get_current_ctl(ctx, NULL); + ctl = interface_get_current_ctl(&ctx->interface, NULL); if (!ctl) return; @@ -129,7 +131,7 @@ toggle_mute(struct context *ctx, int key) if (!ctx->context_ready) return; - ctl = interface_get_current_ctl(ctx, NULL); + ctl = interface_get_current_ctl(&ctx->interface, NULL); if (!ctl) return; @@ -140,6 +142,7 @@ toggle_mute(struct context *ctx, int key) static void switch_sink(struct context *ctx, int key) { + struct interface *ifc = &ctx->interface; struct sink_input_info *t; struct vol_ctl *input, *sink; pa_operation *o; @@ -149,19 +152,19 @@ switch_sink(struct context *ctx, int key) return; - input = interface_get_current_ctl(ctx, &sink); + input = interface_get_current_ctl(&ctx->interface, &sink); if (!input || !sink) return; if (g_list_length(ctx->sink_list) <= 1) return; - if (ctx->chooser_sink < (gint) g_list_length(ctx->sink_list) - 1) - ctx->chooser_sink++; + if (ifc->chooser_sink < (gint) g_list_length(ctx->sink_list) - 1) + ifc->chooser_sink++; else - ctx->chooser_sink = 0; + ifc->chooser_sink = 0; - sink = g_list_nth_data(ctx->sink_list, ctx->chooser_sink); + sink = g_list_nth_data(ctx->sink_list, ifc->chooser_sink); /* chooser_input needs to be derived from $selected_index */ o = pa_context_move_sink_input_by_index(ctx->context, input->index, sink->index, @@ -169,11 +172,11 @@ switch_sink(struct context *ctx, int key) pa_operation_unref(o); /* get new chooser_input, if non, select sink as fallback */ - ctx->chooser_input = SELECTED_SINK; + ifc->chooser_input = SELECTED_SINK; i = -1; list_foreach(ctx->input_list, t) { if (t->base.index == input->index) { - ctx->chooser_input = ++i; + ifc->chooser_input = ++i; break; } if (t->sink == sink->index) diff --git a/src/interface.c b/src/interface.c index 7a3952d..d6fa085 100644 --- a/src/interface.c +++ b/src/interface.c @@ -55,22 +55,23 @@ sink_get_nth_input(struct context *ctx, struct sink_info *sink, int n) } struct vol_ctl * -interface_get_current_ctl(struct context *ctx, struct vol_ctl **parent) +interface_get_current_ctl(struct interface *ifc, struct vol_ctl **parent) { + struct context *ctx = container_of(ifc, struct context, interface); struct sink_info *sink; struct sink_input_info *input; if (parent) *parent = NULL; - sink = g_list_nth_data(ctx->sink_list, ctx->chooser_sink); + sink = g_list_nth_data(ctx->sink_list, ifc->chooser_sink); if (sink == NULL) return NULL; - if (ctx->chooser_input == SELECTED_SINK) + if (ifc->chooser_input == SELECTED_SINK) return &sink->base; - else if (ctx->chooser_input >= 0) { - input = sink_get_nth_input(ctx, sink, ctx->chooser_input); + else if (ifc->chooser_input >= 0) { + input = sink_get_nth_input(ctx, sink, ifc->chooser_input); if (input == NULL) return NULL; if (parent) @@ -83,102 +84,105 @@ interface_get_current_ctl(struct context *ctx, struct vol_ctl **parent) } static void -allocate_volume_bar(struct context *ctx) +allocate_volume_bar(struct interface *ifc) { gint x, y, max_x, max_y; - if (ctx->volume_bar) + if (ifc->volume_bar) return; - getyx(ctx->menu_win, y, x); - getmaxyx(ctx->menu_win, max_y, max_x); - ctx->volume_bar_len = max_x - x - 8; - ctx->volume_bar = g_new(char, ctx->volume_bar_len+1); - /* FIXME: if (ctx->volume_bar == NULL) */ - memset(ctx->volume_bar, '=', ctx->volume_bar_len); - ctx->volume_bar[ctx->volume_bar_len] = '\0'; + getyx(ifc->menu_win, y, x); + getmaxyx(ifc->menu_win, max_y, max_x); + ifc->volume_bar_len = max_x - x - 8; + ifc->volume_bar = g_new(char, ifc->volume_bar_len+1); + /* FIXME: if (ifc->volume_bar == NULL) */ + memset(ifc->volume_bar, '=', ifc->volume_bar_len); + ifc->volume_bar[ifc->volume_bar_len] = '\0'; } static void -print_volume(struct context *ctx, struct vol_ctl *ctl) +print_volume(struct interface *ifc, struct vol_ctl *ctl) { gint vol; - allocate_volume_bar(ctx); - vol = (gint) (ctx->volume_bar_len * ctl->vol / PA_VOLUME_NORM); - wprintw(ctx->menu_win, " [%c][%-*.*s]", - ctl->mute ? 'M':' ', ctx->volume_bar_len, vol, ctx->volume_bar); + allocate_volume_bar(ifc); + vol = (gint) (ifc->volume_bar_len * ctl->vol / PA_VOLUME_NORM); + wprintw(ifc->menu_win, " [%c][%-*.*s]", + ctl->mute ? 'M':' ', ifc->volume_bar_len, vol, ifc->volume_bar); } static void print_vol_ctl(gpointer data, gpointer user_data) { struct vol_ctl *ctl = data; - struct context *ctx = user_data; + struct interface *ifc = user_data; gint x, y; - gboolean selected = (ctl == interface_get_current_ctl(ctx, NULL)); + gboolean selected = (ctl == interface_get_current_ctl(ifc, NULL)); - getyx(ctx->menu_win, y, x); + getyx(ifc->menu_win, y, x); if (selected) - wattron(ctx->menu_win, A_REVERSE); + wattron(ifc->menu_win, A_REVERSE); if (!ctl->hide_index) - wprintw(ctx->menu_win, "%2u ", ctl->index); - wprintw(ctx->menu_win, "%*s%-*s", + wprintw(ifc->menu_win, "%2u ", ctl->index); + wprintw(ifc->menu_win, "%*s%-*s", ctl->indent + (ctl->hide_index ? 2+1 : 0), "", - ctx->max_name_len - ctl->indent, ctl->name); + ifc->max_name_len - ctl->indent, ctl->name); if (selected) - wattroff(ctx->menu_win, A_REVERSE); - print_volume(ctx, ctl); - wmove(ctx->menu_win, y+1, x); + wattroff(ifc->menu_win, A_REVERSE); + print_volume(ifc, ctl); + wmove(ifc->menu_win, y+1, x); if (ctl->childs_foreach) - ctl->childs_foreach(ctl, print_vol_ctl, ctx); + ctl->childs_foreach(ctl, print_vol_ctl, ifc); } static void max_name_len_helper(gpointer data, gpointer user_data) { struct vol_ctl *ctl = data; - struct context *ctx = user_data; + struct interface *ifc = user_data; guint len; len = ctl->indent + strlen(ctl->name); - if (len > ctx->max_name_len) - ctx->max_name_len = len; + if (len > ifc->max_name_len) + ifc->max_name_len = len; if (ctl->childs_foreach) - ctl->childs_foreach(ctl, max_name_len_helper, ctx); + ctl->childs_foreach(ctl, max_name_len_helper, ifc); } void -interface_redraw(struct context *ctx) +interface_redraw(struct interface *ifc) { - werase(ctx->menu_win); - box(ctx->menu_win, 0, 0); - - wmove(ctx->menu_win, 2, 2); /* set initial cursor offset */ - ctx->max_name_len = 0; - if (ctx->volume_bar) { - g_free(ctx->volume_bar); - ctx->volume_bar = NULL; + struct context *ctx = container_of(ifc, struct context, interface); + + werase(ifc->menu_win); + box(ifc->menu_win, 0, 0); + + wmove(ifc->menu_win, 2, 2); /* set initial cursor offset */ + ifc->max_name_len = 0; + if (ifc->volume_bar) { + g_free(ifc->volume_bar); + ifc->volume_bar = NULL; } - g_list_foreach(ctx->sink_list, max_name_len_helper, ctx); - g_list_foreach(ctx->sink_list, print_vol_ctl, ctx); + g_list_foreach(ctx->sink_list, max_name_len_helper, ifc); + g_list_foreach(ctx->sink_list, print_vol_ctl, ifc); - wrefresh(ctx->menu_win); + wrefresh(ifc->menu_win); } static gboolean interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data) { - struct context *ctx = data; + struct interface *ifc = data; + struct context *ctx = container_of(ifc, struct context, interface); struct command_cb_descriptor *cmd; gint c; - c = wgetch(ctx->menu_win); + c = wgetch(ifc->menu_win); cmd = g_hash_table_lookup(ctx->config.keymap, GINT_TO_POINTER(c)); if (cmd) @@ -188,28 +192,28 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data) } void -interface_set_status(struct context *ctx, const gchar *msg, ...) +interface_set_status(struct interface *ifc, const gchar *msg, ...) { va_list ap; if (msg != NULL) { - g_free(ctx->status); + g_free(ifc->status); va_start(ap, msg); - ctx->status = g_strdup_vprintf(msg, ap); + ifc->status = g_strdup_vprintf(msg, ap); va_end(ap); } - werase(ctx->msg_win); - box(ctx->msg_win, 0, 0); - if (ctx->status != NULL) - mvwprintw(ctx->msg_win, 1, 1, ctx->status); - wrefresh(ctx->msg_win); + werase(ifc->msg_win); + box(ifc->msg_win, 0, 0); + if (ifc->status != NULL) + mvwprintw(ifc->msg_win, 1, 1, ifc->status); + wrefresh(ifc->msg_win); refresh(); } static gboolean interface_resize(gpointer data) { - struct context *ctx = data; + struct interface *ifc = data; struct winsize wsize; gint height = 80; gint width = 24; @@ -223,13 +227,13 @@ interface_resize(gpointer data) clear(); refresh(); - wresize(ctx->menu_win, height - H_MSG_BOX, width); - wresize(ctx->msg_win, H_MSG_BOX, width); - mvwin(ctx->msg_win, height - H_MSG_BOX, 0); + wresize(ifc->menu_win, height - H_MSG_BOX, width); + wresize(ifc->msg_win, H_MSG_BOX, width); + mvwin(ifc->msg_win, height - H_MSG_BOX, 0); /* NULL := display old status */ - interface_set_status(ctx, NULL); - interface_redraw(ctx); + interface_set_status(ifc, NULL); + interface_redraw(ifc); return TRUE; } @@ -238,30 +242,30 @@ interface_resize(gpointer data) static gboolean resize_gio(GIOChannel *source, GIOCondition condition, gpointer data) { - struct context *ctx = data; + struct interface *ifc = data; struct signalfd_siginfo fdsi; ssize_t s; g_assert(condition & G_IO_IN); - s = read(ctx->signal_fd, &fdsi, sizeof fdsi); + s = read(ifc->signal_fd, &fdsi, sizeof fdsi); if (s != sizeof fdsi || fdsi.ssi_signo != SIGWINCH) return FALSE; - return interface_resize(ctx); + return interface_resize(ifc); } #endif int -interface_init(struct context *ctx) +interface_init(struct interface *ifc) { GIOChannel *input_channel; /* Selected sink-device. 0 is the first device */ - ctx->chooser_sink = 0; + ifc->chooser_sink = 0; /* Selected input of the current sink-device. */ /* SELECTED_SINK refers to sink-device itself */ - ctx->chooser_input = SELECTED_SINK; + ifc->chooser_input = SELECTED_SINK; initscr(); clear(); @@ -272,14 +276,14 @@ interface_init(struct context *ctx) curs_set(0); /* 0,0,0,0 := fullscreen */ - ctx->menu_win = newwin(0, 0, 0, 0); - ctx->msg_win = newwin(0, 0, 0, 0); + ifc->menu_win = newwin(0, 0, 0, 0); + ifc->msg_win = newwin(0, 0, 0, 0); /* multichar keys are mapped to one char */ - keypad(ctx->menu_win, TRUE); + keypad(ifc->menu_win, TRUE); /* "resizing" here is for initial box positioning and layout */ - interface_resize(ctx); + interface_resize(ifc); #ifdef HAVE_SIGNALFD { @@ -291,22 +295,22 @@ interface_init(struct context *ctx) if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) return -1; - ctx->signal_fd = signalfd(-1, &mask, 0); - channel = g_io_channel_unix_new(ctx->signal_fd); - ctx->resize_source_id = - g_io_add_watch(channel, G_IO_IN, resize_gio, ctx); + ifc->signal_fd = signalfd(-1, &mask, 0); + channel = g_io_channel_unix_new(ifc->signal_fd); + ifc->resize_source_id = + g_io_add_watch(channel, G_IO_IN, resize_gio, ifc); g_io_channel_unref(channel); } #else /* register event handler for resize and input */ - ctx->resize_source_id = unix_signal_add(SIGWINCH, - interface_resize, ctx); + ifc->resize_source_id = unix_signal_add(SIGWINCH, + interface_resize, ifc); #endif input_channel = g_io_channel_unix_new(STDIN_FILENO); if (!input_channel) return -1; - ctx->input_source_id = g_io_add_watch(input_channel, G_IO_IN, - interface_get_input, ctx); + ifc->input_source_id = g_io_add_watch(input_channel, G_IO_IN, + interface_get_input, ifc); g_io_channel_unref(input_channel); refresh(); @@ -315,19 +319,19 @@ interface_init(struct context *ctx) } void -interface_clear(struct context *ctx) +interface_clear(struct interface *ifc) { - g_source_remove(ctx->resize_source_id); - g_source_remove(ctx->input_source_id); + g_source_remove(ifc->resize_source_id); + g_source_remove(ifc->input_source_id); #ifdef HAVE_SIGNALFD - close(ctx->signal_fd); + close(ifc->signal_fd); #endif clear(); refresh(); - delwin(ctx->menu_win); - delwin(ctx->msg_win); + delwin(ifc->menu_win); + delwin(ifc->msg_win); endwin(); delscreen(NULL); - if (ctx->status) - g_free(ctx->status); + if (ifc->status) + g_free(ifc->status); } diff --git a/src/interface.h b/src/interface.h index 28f5276..da52be6 100644 --- a/src/interface.h +++ b/src/interface.h @@ -22,25 +22,44 @@ #include <glib.h> #include <pulse/pulseaudio.h> +#include <ncurses.h> #define SELECTED_SINK -1 #define H_MSG_BOX 3 -struct context; +struct interface { + WINDOW *menu_win; + WINDOW *msg_win; + gint volume_bar_len; + gchar *volume_bar; + + guint resize_source_id; +#ifdef HAVE_SIGNALFD + int signal_fd; +#endif + guint input_source_id; + + gint chooser_sink; + gint chooser_input; + + guint max_name_len; + + gchar *status; +}; struct vol_ctl * -interface_get_current_ctl(struct context *ctx, struct vol_ctl **parent); +interface_get_current_ctl(struct interface *ifc, struct vol_ctl **parent); void -interface_redraw(struct context *ctx); +interface_redraw(struct interface *ifc); int -interface_init(struct context *ctx); +interface_init(struct interface *ifc); void -interface_clear(struct context *ctx); +interface_clear(struct interface *ifc); void -interface_set_status(struct context *ctx, const gchar *, ...); +interface_set_status(struct interface *ifc, const gchar *, ...); #endif diff --git a/src/pa-sink-ctl.c b/src/pa-sink-ctl.c index b22230b..b1c7620 100644 --- a/src/pa-sink-ctl.c +++ b/src/pa-sink-ctl.c @@ -93,14 +93,14 @@ sink_info_cb(pa_context *c, const pa_sink_info *i, if (is_last < 0) { if (pa_context_errno(c) == PA_ERR_NOENTITY) return; - interface_set_status(ctx, + interface_set_status(&ctx->interface, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); return; } if (is_last) { - interface_redraw(ctx); + interface_redraw(&ctx->interface); return; } @@ -140,14 +140,14 @@ sink_input_info_cb(pa_context *c, const pa_sink_input_info *i, if (is_last < 0) { if (pa_context_errno(c) == PA_ERR_NOENTITY) return; - interface_set_status(ctx, + interface_set_status(&ctx->interface, "Failed to get sink input info: %s\n", pa_strerror(pa_context_errno(c))); return; } if (is_last) { - interface_redraw(ctx); + interface_redraw(&ctx->interface); return; } @@ -245,7 +245,7 @@ subscribe_cb(pa_context *c, pa_subscription_event_type_t t, default: return; } - interface_redraw(ctx); + interface_redraw(&ctx->interface); break; default: break; @@ -264,13 +264,13 @@ context_state_callback(pa_context *c, gpointer userdata) ctx->context_ready = FALSE; switch (pa_context_get_state(c)) { case PA_CONTEXT_CONNECTING: - interface_set_status(ctx, "connecting..."); + interface_set_status(&ctx->interface, "connecting..."); break; case PA_CONTEXT_AUTHORIZING: - interface_set_status(ctx, "authorizing..."); + interface_set_status(&ctx->interface, "authorizing..."); break; case PA_CONTEXT_SETTING_NAME: - interface_set_status(ctx, "setting name..."); + interface_set_status(&ctx->interface, "setting name..."); break; case PA_CONTEXT_READY: @@ -289,20 +289,21 @@ context_state_callback(pa_context *c, gpointer userdata) NULL, NULL))); } ctx->context_ready = TRUE; - interface_set_status(ctx, "ready to process events."); + interface_set_status(&ctx->interface, + "ready to process events."); break; case PA_CONTEXT_FAILED: - interface_set_status(ctx, "connection lost!"); + interface_set_status(&ctx->interface, "connection lost!"); break; case PA_CONTEXT_TERMINATED: g_assert(ctx->op != NULL); pa_operation_cancel(ctx->op); pa_operation_unref(ctx->op); ctx->op = NULL; - interface_set_status(ctx, "connection terminated."); + interface_set_status(&ctx->interface, "connection terminated."); break; default: - interface_set_status(ctx, "unknown state"); + interface_set_status(&ctx->interface, "unknown state"); break; } } @@ -325,7 +326,6 @@ main(int argc, char** argv) ctx.sink_list = NULL; ctx.input_list = NULL; - ctx.max_name_len = 0; ctx.context_ready = FALSE; ctx.return_value = 1; @@ -336,7 +336,7 @@ main(int argc, char** argv) if (config_init(&ctx.config) < 0) goto cleanup_loop; - if (interface_init(&ctx) < 0) + if (interface_init(&ctx.interface) < 0) goto cleanup_config; if (!(m = pa_glib_mainloop_new(NULL))) { @@ -346,7 +346,8 @@ main(int argc, char** argv) mainloop_api = pa_glib_mainloop_get_api(m); if (!(ctx.context = pa_context_new(mainloop_api, "pa-sink-ctl"))) { - interface_set_status(&ctx, "pa_context_new failed: %s\n", + interface_set_status(&ctx.interface, + "pa_context_new failed: %s\n", pa_strerror(pa_context_errno(ctx.context))); } @@ -355,7 +356,8 @@ main(int argc, char** argv) context_state_callback, &ctx); if (pa_context_connect(ctx.context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL)) { - interface_set_status(&ctx, "pa_context_connect failed: %s\n", + interface_set_status(&ctx.interface, + "pa_context_connect failed: %s\n", pa_strerror(pa_context_errno(ctx.context))); } @@ -368,7 +370,7 @@ main(int argc, char** argv) pa_context_unref(ctx.context); pa_glib_mainloop_free(m); cleanup_interface: - interface_clear(&ctx); + interface_clear(&ctx.interface); cleanup_config: config_uninit(&ctx.config); cleanup_loop: diff --git a/src/pa-sink-ctl.h b/src/pa-sink-ctl.h index bc93ccb..e3eebdd 100644 --- a/src/pa-sink-ctl.h +++ b/src/pa-sink-ctl.h @@ -22,38 +22,22 @@ #include <glib.h> #include <pulse/pulseaudio.h> -#include <ncurses.h> +#include <stddef.h> #include "config.h" +#include "interface.h" struct context { pa_context *context; pa_operation *op; gboolean context_ready; - WINDOW *menu_win; - WINDOW *msg_win; - gint volume_bar_len; - gchar *volume_bar; - - guint resize_source_id; -#ifdef HAVE_SIGNALFD - int signal_fd; -#endif - guint input_source_id; - - gint chooser_sink; - gint chooser_input; - - guint max_name_len; - GMainLoop *loop; GList *sink_list; GList *input_list; - gchar *status; - + struct interface interface; struct config config; int return_value; }; @@ -70,4 +54,8 @@ quit(struct context *ctx); #define list_foreach(list, el) \ for (GList *__l = (list); __l && ((el) = __l->data); __l = __l->next) +#define container_of(ptr, type, member) \ + (type *)(((char *) ((const __typeof__( ((type *)0)->member ) *)(ptr))) \ + - offsetof(type,member) ) + #endif |