summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-10-21 11:53:39 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-10-21 23:13:11 +0200
commit2310d43d6410de464dbd5ffa7edc7fd2785f21d3 (patch)
treed6a888b1b973b829a87bad67d210eb3b3d633ed6
parent478d7fe56a9927133b87b80e21d507c90bd8800d (diff)
downloadpa-sink-ctl-2310d43d6410de464dbd5ffa7edc7fd2785f21d3.tar.gz
pa-sink-ctl-2310d43d6410de464dbd5ffa7edc7fd2785f21d3.tar.bz2
pa-sink-ctl-2310d43d6410de464dbd5ffa7edc7fd2785f21d3.zip
Use a GList instead of GArray for sinks.
This lets us drop our ugly GArray wrappers sink.c and sink_input.c. It will make gradual updates of sinks easier, since elements can be added and dropped everywhere in the list easily.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/interface.c90
-rw-r--r--src/pa-sink-ctl.c45
-rw-r--r--src/sink.c54
-rw-r--r--src/sink.h14
-rw-r--r--src/sink_input.c23
-rw-r--r--src/sink_input.h3
7 files changed, 84 insertions, 147 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 863fea4..327376b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
bin_PROGRAMS = pa-sink-ctl
-pa_sink_ctl_SOURCES = interface.c pa-sink-ctl.c sink.c sink_input.c
+pa_sink_ctl_SOURCES = interface.c pa-sink-ctl.c
EXTRA_pa_sink_ctl_SOURCES = unix_signal.c
if !HAVE_SIGNALFD
diff --git a/src/interface.c b/src/interface.c
index d4b94be..11238df 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -40,6 +40,8 @@ static guint32 selected_index;
guint max_name_len = 0;
+extern GList *sink_list;
+
static gboolean
interface_resize(gpointer data)
{
@@ -88,29 +90,30 @@ print_volume(pa_volume_t volume, int mute, int y)
}
static void
-print_input_list(gint sink_num)
+print_input_list(GList *input_list, gint sink_num)
{
+ GList *l;
gint offset = sink_num + 3 /* win border + empty line + 1th sink */;
+ gint i;
- for (gint i = 0; i < sink_num; ++i)
- offset += sink_list_get(i)->input_list->len;
+ for (l = sink_list, i = 0; l && i < sink_num; l = l->next,i++)
+ offset += g_list_length(((sink_info *)l->data)->input_list);
- for (gint i = 0; i < sink_list_get(sink_num)->input_list->len; ++i) {
+ for (l = input_list, i = 0; l; l = l->next,++i) {
+ sink_input_info *input = l->data;
gboolean selected = (chooser_sink == sink_num && chooser_input == i);
if (selected)
wattron(menu_win, A_REVERSE);
mvwprintw(menu_win, offset + i, 2, "%*s%-*s",
- 2+1+1, "", /* space for index number + indentation*/
- max_name_len - 1,
- sink_input_get(sink_num, i)->name);
+ 2+1+1, "", /* space for index number + indentation*/
+ max_name_len - 1, input->name);
if (selected)
wattroff(menu_win, A_REVERSE);
- print_volume(sink_input_get(sink_num, i)->vol,
- sink_input_get(sink_num, i)->mute, offset + i);
+ print_volume(input->vol, input->mute, offset + i);
}
}
@@ -118,24 +121,22 @@ print_input_list(gint sink_num)
static void
set_max_name_len(void)
{
+ GList *l,*k;
guint len = 0;
max_name_len = len;
- for (gint sink_num = 0; sink_num < sink_list->len; ++sink_num) {
-
- len = strlen(sink_list_get(sink_num)->device != NULL ?
- sink_list_get(sink_num)->device :
- sink_list_get(sink_num)->name);
+ for (l = sink_list; l; l = l->next) {
+ sink_info *sink = l->data;
+
+ len = strlen(sink->device != NULL ? sink->device : sink->name);
if (len > max_name_len)
max_name_len = len;
- for (gint input_num = 0;
- input_num < sink_list_get(sink_num)->input_list->len;
- ++input_num) {
+ for (k = sink->input_list; k; k = k->next) {
+ sink_input_info *input = k->data;
- len = strlen(sink_input_get(sink_num, input_num)->name)
- + 1 /* indentation */;
+ len = strlen(input->name) + 1 /* indentation */;
if (len > max_name_len)
max_name_len = len;
@@ -150,6 +151,7 @@ print_sink_list(void)
gint x = 2;
gint y = 2;
gint offset = 0;
+ GList *l;
/* looking for the longest name for right indentation */
set_max_name_len();
@@ -162,32 +164,34 @@ print_sink_list(void)
/* if index is will not be found (in the loop), select the sink itself */
chooser_input = SELECTED_SINK;
/* step through inputs for current sink and find the selected */
- for (i = 0; i < sink_list_get(chooser_sink)->input_list->len; ++i) {
- if (selected_index == sink_input_get(chooser_sink, i)->index) {
+ sink_info *sink = g_list_nth_data(sink_list, chooser_sink);
+ for (l = sink->input_list, i = 0; l; l = l->next,++i) {
+ sink_input_info *input = l->data;
+ if (selected_index == input->index) {
chooser_input = i;
break;
}
}
}
- for (i = 0; i < sink_list->len; ++i) {
+ for (l = sink_list, i = 0; l; l = l->next,++i) {
+ sink_info *sink = l->data;
gboolean selected = (i == chooser_sink && chooser_input == SELECTED_SINK);
if (selected)
wattron(menu_win, A_REVERSE);
mvwprintw(menu_win, y+i+offset, x, "%2u %-*s",
- sink_list_get(i)->index,
- max_name_len,
- sink_list_get(i)->device != NULL ? sink_list_get(i)->device : sink_list_get(i)->name);
+ sink->index, max_name_len,
+ sink->device != NULL ? sink->device : sink->name);
if (selected)
wattroff(menu_win, A_REVERSE);
- print_volume(sink_list_get(i)->vol, sink_list_get(i)->mute, y+i+offset);
+ print_volume(sink->vol, sink->mute, y+i+offset);
- print_input_list(i);
+ print_input_list(sink->input_list, i);
- offset += sink_list_get(i)->input_list->len;
+ offset += g_list_length(sink->input_list);
}
wrefresh(menu_win);
}
@@ -197,6 +201,7 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
{
gint c;
gboolean volume_increment = TRUE;
+ sink_info *sink = NULL;
if (!context_ready)
return TRUE;
@@ -207,8 +212,9 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
case 'w':
case KEY_UP:
if (chooser_input == SELECTED_SINK && chooser_sink > 0) {
- --chooser_sink;
- chooser_input = (gint)sink_list_get(chooser_sink)->input_list->len - 1;
+ sink = g_list_nth_data(sink_list, --chooser_sink);
+ /* automatic SELECTED_SINK (=-1) assignment if length = 0 */
+ chooser_input = (gint)g_list_length(sink->input_list) - 1;
}
else if (chooser_input >= 0)
@@ -219,11 +225,12 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
case 'j':
case 's':
case KEY_DOWN:
- if (chooser_input == ((gint)sink_list_get(chooser_sink)->input_list->len - 1) && chooser_sink < (gint)sink_list->len - 1) {
+ sink = g_list_nth_data(sink_list, chooser_sink);
+ if (chooser_input == ((gint)g_list_length(sink->input_list) - 1) && chooser_sink < (gint)g_list_length(sink_list) - 1) {
++chooser_sink;
chooser_input = SELECTED_SINK;
}
- else if (chooser_input < ((gint)sink_list_get(chooser_sink)->input_list->len - 1))
+ else if (chooser_input < ((gint)g_list_length(sink->input_list) - 1))
++chooser_input;
print_sink_list();
break;
@@ -243,8 +250,9 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
pa_operation* (*volume_set) (pa_context*, guint32, const pa_cvolume*, pa_context_success_cb_t, gpointer);
} tmp;
+ sink = g_list_nth_data(sink_list, chooser_sink);
if (chooser_input >= 0) {
- sink_input_info *input = sink_input_get(chooser_sink, chooser_input);
+ sink_input_info *input = g_list_nth_data(sink->input_list, chooser_input);
tmp = (struct tmp_t) {
.index = input->index,
.volume = (pa_cvolume) {.channels = input->channels},
@@ -252,7 +260,6 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
.volume_set = pa_context_set_sink_input_volume
};
} else if (chooser_input == SELECTED_SINK) {
- sink_info *sink = sink_list_get(chooser_sink);
tmp = (struct tmp_t) {
.index = sink->index,
.volume = (pa_cvolume) {.channels = sink->channels},
@@ -288,15 +295,15 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
pa_operation* (*mute_set) (pa_context*, guint32, int, pa_context_success_cb_t, void*);
} tmp;
+ sink = g_list_nth_data(sink_list, chooser_sink);
if (chooser_input >= 0) {
- sink_input_info *input = sink_input_get(chooser_sink, chooser_input);
+ sink_input_info *input = g_list_nth_data(sink->input_list, chooser_input);
tmp = (struct tmp_t) {
.index = input->index,
.mute = input->mute,
.mute_set = pa_context_set_sink_input_mute
};
} else if (chooser_input == SELECTED_SINK) {
- sink_info *sink = sink_list_get(chooser_sink);
tmp = (struct tmp_t) {
.index = sink->index,
.mute = sink->mute,
@@ -314,17 +321,20 @@ interface_get_input(GIOChannel *source, GIOCondition condition, gpointer data)
case ' ':
if (chooser_input == SELECTED_SINK)
break;
- selected_index = sink_input_get(chooser_sink, chooser_input)->index;
- if (chooser_sink < (gint)sink_list->len - 1)
+ sink = g_list_nth_data(sink_list, chooser_sink);
+ sink_input_info *input = g_list_nth_data(sink->input_list, chooser_input);
+ selected_index = input->index;
+ if (chooser_sink < (gint)g_list_length(sink_list) - 1)
chooser_sink++;
else
chooser_sink = 0;
+ sink = g_list_nth_data(sink_list, chooser_sink);
/* chooser_input needs to be derived from $selected_index */
chooser_input = SELECTED_UNKNOWN;
pa_operation_unref(pa_context_move_sink_input_by_index(context, selected_index,
- sink_list_get(chooser_sink)->index,
- change_callback, NULL));
+ sink->index,
+ change_callback, NULL));
break;
case 'q':
diff --git a/src/pa-sink-ctl.c b/src/pa-sink-ctl.c
index e9f9c23..3591df3 100644
--- a/src/pa-sink-ctl.c
+++ b/src/pa-sink-ctl.c
@@ -13,13 +13,25 @@ gboolean context_ready = FALSE;
static gboolean info_callbacks_finished = TRUE;
static gboolean info_callbacks_blocked = FALSE;
+struct fetch_ctx {
+ GList *sinks;
+};
+
+GList *sink_list;
+
+#define list_append_struct(list, data) \
+ do { \
+ (list) = g_list_append((list), \
+ g_memdup(&(data), sizeof(data))); \
+ } while (0)
+
int
main(int argc, char** argv)
{
pa_mainloop_api *mainloop_api = NULL;
pa_glib_mainloop *m = NULL;
- sink_list = sink_list_alloc();
+ sink_list = NULL;
GMainLoop *g_loop = g_main_loop_new(NULL, FALSE);
@@ -49,7 +61,7 @@ main(int argc, char** argv)
g_main_loop_run(g_loop);
interface_clear();
- sink_list_free(sink_list);
+ g_list_free(sink_list);
pa_glib_mainloop_free(m);
g_main_loop_unref(g_loop);
@@ -112,6 +124,7 @@ context_state_callback(pa_context *c, gpointer userdata)
}
}
+
/*
* the begin of the callback loops
*/
@@ -119,7 +132,7 @@ void
get_sink_info_callback(pa_context *c, const pa_sink_info *i, gint is_last, gpointer userdata)
{
g_assert(userdata != NULL);
- GArray *sink_list_tmp = userdata;
+ struct fetch_ctx *fetch_ctx = userdata;
if (is_last < 0) {
g_printerr("Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -127,11 +140,11 @@ get_sink_info_callback(pa_context *c, const pa_sink_info *i, gint is_last, gpoin
}
if (is_last) {
- pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, sink_list_tmp));
+ pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, fetch_ctx));
return;
}
- g_array_append_val(sink_list_tmp, ((sink_info) {
+ sink_info sink = {
.index = i->index,
.mute = i->mute,
.vol = pa_cvolume_avg(&i->volume),
@@ -139,8 +152,10 @@ get_sink_info_callback(pa_context *c, const pa_sink_info *i, gint is_last, gpoin
.name = g_strdup(i->name),
.device = pa_proplist_contains(i->proplist, "device.product.name") ?
g_strdup(pa_proplist_gets(i->proplist, "device.product.name")) : NULL,
- .input_list = sink_input_list_alloc()
- }));
+ .input_list = NULL
+ };
+
+ list_append_struct(fetch_ctx->sinks, sink);
}
/*
@@ -150,7 +165,7 @@ void
get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, gint is_last, gpointer userdata)
{
g_assert(userdata != NULL);
- GArray *sink_list_tmp = userdata;
+ struct fetch_ctx *fetch_ctx = userdata;
if (is_last < 0) {
g_printerr("Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -159,8 +174,9 @@ get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, gint is
if (is_last) {
info_callbacks_finished = TRUE;
- sink_list_free(sink_list);
- sink_list = sink_list_tmp;
+ g_list_free_full(sink_list, g_free);
+ sink_list = fetch_ctx->sinks;
+ g_free(fetch_ctx);
print_sink_list();
@@ -173,7 +189,7 @@ get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, gint is
if (!(i->client != PA_INVALID_INDEX)) return;
- g_array_append_val(g_array_index(sink_list_tmp, sink_info, i->sink).input_list, ((sink_input_info) {
+ sink_input_info sink_input = {
.index = i->index,
.sink = i->sink,
.name = pa_proplist_contains(i->proplist, "application.name") ?
@@ -183,7 +199,10 @@ get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, gint is
.channels = i->volume.channels,
.vol = pa_cvolume_avg(&i->volume),
.pid = NULL /* maybe obsolete */
- }));
+ };
+
+ sink_info *sink = g_list_nth_data(fetch_ctx->sinks, i->sink);
+ list_append_struct(sink->input_list, sink_input);
}
void
@@ -207,5 +226,5 @@ collect_all_info(void)
if (!info_callbacks_finished)
return;
info_callbacks_finished = FALSE;
- pa_operation_unref(pa_context_get_sink_info_list(context, get_sink_info_callback, sink_list_alloc()));
+ pa_operation_unref(pa_context_get_sink_info_list(context, get_sink_info_callback, g_new0(struct fetch_ctx, 1)));
}
diff --git a/src/sink.c b/src/sink.c
deleted file mode 100644
index 090659f..0000000
--- a/src/sink.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <glib.h>
-
-#define SINK_C
-#include "sink.h"
-#include "sink_input.h"
-
-/*
- * init a sink list
- */
-GArray *
-sink_list_alloc(void)
-{
- return g_array_sized_new(FALSE, FALSE, sizeof(sink_info), 16);
-}
-
-/*
- * frees all dynamic allocated components of a sink
- */
-static void
-sink_clear(sink_info* sink)
-{
- g_free(sink->name);
- g_free(sink->device);
- sink_input_list_free(sink->input_list);
-}
-
-/*
- * frees a complete sink array
- */
-void
-sink_list_free(GArray *sink_list)
-{
- for (int i = 0; i < sink_list->len; ++i)
- sink_clear(&g_array_index(sink_list, sink_info, i));
- g_array_free(sink_list, TRUE);
-}
-
-/*
- * get sink at index from sink_list
- */
-sink_info *
-sink_list_get(gint index)
-{
- return &g_array_index(sink_list, sink_info, index);
-}
-
-/*
- * get an input association to an sink by their indizes
- */
-sink_input_info *
-sink_input_get(gint sink_list_index, gint index)
-{
- return &g_array_index(sink_list_get(sink_list_index)->input_list, sink_input_info, index);
-}
diff --git a/src/sink.h b/src/sink.h
index cccbe1b..083f0d8 100644
--- a/src/sink.h
+++ b/src/sink.h
@@ -1,12 +1,6 @@
#ifndef SINK_H
#define SINK_H
-#ifdef SINK_C
-GArray *sink_list;
-#else
-extern GArray *sink_list;
-#endif
-
#include <glib.h>
#include <pulse/pulseaudio.h>
@@ -19,13 +13,7 @@ typedef struct _sink_info {
gint mute;
guint8 channels;
pa_volume_t vol;
- GArray *input_list;
+ GList *input_list;
} sink_info;
-GArray *sink_list_alloc(void);
-void sink_list_free(GArray *sink_list);
-
-sink_info *sink_list_get(gint index);
-sink_input_info *sink_input_get(gint sink_list_index, gint index);
-
#endif
diff --git a/src/sink_input.c b/src/sink_input.c
deleted file mode 100644
index 6dd292a..0000000
--- a/src/sink_input.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <glib.h>
-#include "sink_input.h"
-
-GArray *
-sink_input_list_alloc(void)
-{
- return g_array_sized_new(FALSE, FALSE, sizeof(sink_input_info), 8);
-}
-
-static void
-sink_input_clear(sink_input_info* sink_input)
-{
- g_free(sink_input->name);
- g_free(sink_input->pid);
-}
-
-void
-sink_input_list_free(GArray *sink_input_list)
-{
- for (int i = 0; i < sink_input_list->len; ++i)
- sink_input_clear(&g_array_index(sink_input_list, sink_input_info, i));
- g_array_free(sink_input_list, TRUE);
-}
diff --git a/src/sink_input.h b/src/sink_input.h
index a62a00b..82797c0 100644
--- a/src/sink_input.h
+++ b/src/sink_input.h
@@ -14,7 +14,4 @@ typedef struct _sink_input_info {
pa_volume_t vol; // TOTO: exchange with the channel-list
} sink_input_info;
-GArray *sink_input_list_alloc(void);
-void sink_input_list_free(GArray *sink_input_list);
-
#endif