summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.c34
-rw-r--r--src/interface.c51
-rw-r--r--src/pa-sink-ctl.c2
-rw-r--r--src/sink.h15
4 files changed, 80 insertions, 22 deletions
diff --git a/src/command.c b/src/command.c
index eb671ca..a883685 100644
--- a/src/command.c
+++ b/src/command.c
@@ -25,13 +25,13 @@
#include "command.h"
static int
-sink_input_len(struct context *ctx, struct sink *sink)
+main_ctl_childs_len(struct context *ctx, struct main_ctl *ctl)
{
- struct sink_input *input;
+ struct slave_ctl *sctl;
int len = 0;
- list_foreach(ctx->input_list, input)
- if (input->sink == sink->base.index)
+ list_foreach(*ctl->childs_list, sctl)
+ if (sctl->parent_index == ctl->base.index)
len++;
return len;
@@ -50,7 +50,7 @@ up(struct context *ctx, int key)
ifc->chooser_sink > 0) {
sink = g_list_nth_data(ctx->sink_list, --ifc->chooser_sink);
/* autoassigment to SELECTED_SINK (=-1) if length = 0 */
- ifc->chooser_input = sink_input_len(ctx, sink) - 1;
+ ifc->chooser_input = main_ctl_childs_len(ctx, (struct main_ctl *) sink) - 1;
} else if (ifc->chooser_input >= 0)
--ifc->chooser_input;
@@ -61,17 +61,27 @@ static void
down(struct context *ctx, int key)
{
struct interface *ifc = &ctx->interface;
- struct sink *sink;
+ int max_input;
+ struct vol_ctl *ctl, *parent;
+ int max_len;
if (!ctx->context_ready)
return;
- 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))
+ max_len = g_list_length(ctx->sink_list) + g_list_length(ctx->source_list);
+
+ ctl = interface_get_current_ctl(&ctx->interface, &parent);
+ if (parent)
+ ctl = parent;
+
+ max_input = main_ctl_childs_len(ctx, (struct main_ctl *) ctl) -1;
+
+ if (ifc->chooser_input == max_input) {
+ if (ifc->chooser_sink < max_len -1) {
+ ++ifc->chooser_sink;
+ ifc->chooser_input = SELECTED_SINK;
+ }
+ } else if (ifc->chooser_input < max_input)
++ifc->chooser_input;
interface_redraw(ifc);
diff --git a/src/interface.c b/src/interface.c
index f6fdc8a..3247aaa 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -54,29 +54,60 @@ sink_get_nth_input(struct context *ctx, struct sink *sink, int n)
return NULL;
}
+static struct source_output *
+source_get_nth_output(struct context *ctx, struct source *source, int n)
+{
+ struct source_output *output;
+ int i = 0;
+
+ list_foreach(ctx->output_list, output) {
+ if (output->source != source->base.index)
+ continue;
+ if (i++ == n)
+ return output;
+ }
+
+ return NULL;
+}
+
struct vol_ctl *
interface_get_current_ctl(struct interface *ifc, struct vol_ctl **parent)
{
struct context *ctx = container_of(ifc, struct context, interface);
- struct sink *sink;
+ struct vol_ctl *main_ctl, *ctl;
struct sink_input *input;
+ struct source_output *output;
+ int is_sink = 1;
if (parent)
*parent = NULL;
- sink = g_list_nth_data(ctx->sink_list, ifc->chooser_sink);
- if (sink == NULL)
- return NULL;
+ main_ctl = g_list_nth_data(ctx->sink_list, ifc->chooser_sink);
+ if (main_ctl == NULL) {
+ main_ctl = g_list_nth_data(ctx->source_list,
+ ifc->chooser_sink - g_list_length(ctx->sink_list));
+ is_sink = 0;
+ if (main_ctl == NULL)
+ return NULL;
+ }
if (ifc->chooser_input == SELECTED_SINK)
- return &sink->base;
+ return main_ctl;
else if (ifc->chooser_input >= 0) {
- input = sink_get_nth_input(ctx, sink, ifc->chooser_input);
- if (input == NULL)
- return NULL;
+ if (is_sink) {
+ input = sink_get_nth_input(ctx, (struct sink *) main_ctl, ifc->chooser_input);
+ if (input == NULL)
+ return NULL;
+ ctl = &input->base;
+ } else {
+ output = source_get_nth_output(ctx, (struct source *) main_ctl, ifc->chooser_input);
+ if (output == NULL)
+ return NULL;
+ ctl = &output->base;
+ }
if (parent)
- *parent = &sink->base;
- return &input->base;
+ *parent = main_ctl;
+ return ctl;
}
g_assert(0);
diff --git a/src/pa-sink-ctl.c b/src/pa-sink-ctl.c
index 690368e..38a5913 100644
--- a/src/pa-sink-ctl.c
+++ b/src/pa-sink-ctl.c
@@ -113,6 +113,7 @@ sink_info_cb(pa_context *c, const pa_sink_info *i,
sink->base.volume_set = pa_context_set_sink_volume_by_index;
sink->base.childs_foreach = sink_childs_foreach;
sink->ctx = ctx;
+ sink->childs_list = &ctx->input_list;
sink->priority = get_priority(ctx, i->proplist);
ctx->sink_list = g_list_insert_sorted(ctx->sink_list, sink,
@@ -172,6 +173,7 @@ source_info_cb(pa_context *c, const pa_source_info *i,
source->base.volume_set = pa_context_set_source_volume_by_index;
source->base.childs_foreach = source_childs_foreach;
source->ctx = ctx;
+ source->childs_list = &ctx->output_list;
source->priority = get_priority(ctx, i->proplist);
ctx->source_list = g_list_insert_sorted(ctx->source_list,
diff --git a/src/sink.h b/src/sink.h
index d3a9362..15c51c9 100644
--- a/src/sink.h
+++ b/src/sink.h
@@ -44,10 +44,19 @@ struct vol_ctl {
void (*childs_foreach)(struct vol_ctl *ctx, GFunc func, gpointer udata);
};
+struct main_ctl {
+ struct vol_ctl base;
+ gint priority;
+ struct context *ctx;
+
+ GList **childs_list;
+};
+
struct sink {
struct vol_ctl base;
gint priority;
struct context *ctx;
+ GList **childs_list;
};
struct sink_input {
@@ -55,6 +64,11 @@ struct sink_input {
guint32 sink;
};
+struct slave_ctl {
+ struct vol_ctl base;
+ guint32 parent_index;
+};
+
struct source_output {
struct vol_ctl base;
guint32 source;
@@ -64,6 +78,7 @@ struct source {
struct vol_ctl base;
gint priority;
struct context *ctx;
+ GList **childs_list;
};
#endif