@@ -94,13 +94,13 @@ int get_max_elem_by_name(GArray *elems, char *prefix, char *needle) {
|
||||
return max;
|
||||
}
|
||||
|
||||
// return true if the element is an routing destination enum, e.g.:
|
||||
// return true if the element is an routing sink enum, e.g.:
|
||||
// PCM xx Capture Enum
|
||||
// Mixer Input xx Capture Enum
|
||||
// Analogue Output xx Playback Enum
|
||||
// S/PDIF Output xx Playback Enum
|
||||
// ADAT Output xx Playback Enum
|
||||
int is_elem_routing_dst(struct alsa_elem *elem) {
|
||||
int is_elem_routing_snk(struct alsa_elem *elem) {
|
||||
if (strstr(elem->name, "Capture Enum") &&
|
||||
!strstr(elem->name, "Level"))
|
||||
return 1;
|
||||
|
||||
24
src/alsa.h
24
src/alsa.h
@@ -19,7 +19,7 @@ struct alsa_card;
|
||||
// notifies of a change
|
||||
typedef void (AlsaElemCallback)(struct alsa_elem *);
|
||||
|
||||
// port categories for routing_src and routing_dst entries
|
||||
// port categories for routing_src and routing_snk entries
|
||||
// must match the level meter ordering from the driver
|
||||
enum {
|
||||
// Hardware inputs/outputs
|
||||
@@ -39,11 +39,11 @@ enum {
|
||||
extern const char *port_category_names[PC_COUNT];
|
||||
|
||||
// is a drag active, and whether dragging from a routing source or a
|
||||
// routing destination
|
||||
// routing sink
|
||||
enum {
|
||||
DRAG_TYPE_NONE = 0,
|
||||
DRAG_TYPE_SRC = 1,
|
||||
DRAG_TYPE_DST = 2,
|
||||
DRAG_TYPE_SNK = 2,
|
||||
};
|
||||
|
||||
// entry in alsa_card routing_srcs (routing sources) array
|
||||
@@ -76,12 +76,12 @@ struct routing_src {
|
||||
GtkWidget *widget2;
|
||||
};
|
||||
|
||||
// entry in alsa_card routing_dsts (routing destinations) array
|
||||
// for alsa elements that are routing destinations like Analogue
|
||||
// Output 01 Playback Enum
|
||||
// entry in alsa_card routing_snks (routing sinks) array for alsa
|
||||
// elements that are routing sinks like Analogue Output 01 Playback
|
||||
// Enum
|
||||
// port_category is set to PC_MIX, PC_PCM, PC_HW
|
||||
// port_num is a count (0-based) within that category
|
||||
struct routing_dst {
|
||||
struct routing_snk {
|
||||
|
||||
// location within the array
|
||||
int idx;
|
||||
@@ -95,7 +95,7 @@ struct routing_dst {
|
||||
// 0-based count within port_category
|
||||
int port_num;
|
||||
|
||||
// the mixer label widgets for this destination
|
||||
// the mixer label widgets for this sink
|
||||
GtkWidget *mixer_label_top;
|
||||
GtkWidget *mixer_label_bottom;
|
||||
};
|
||||
@@ -113,7 +113,7 @@ struct alsa_elem {
|
||||
int count;
|
||||
|
||||
// for the number (or translated letter; A = 1) in the item name
|
||||
// TODO: move this to struct routing_dst?
|
||||
// TODO: move this to struct routing_snk?
|
||||
int lr_num;
|
||||
|
||||
// the primary GTK widget and callback function for this ALSA
|
||||
@@ -149,7 +149,7 @@ struct alsa_card {
|
||||
struct alsa_elem *sample_capture_elem;
|
||||
struct alsa_elem *level_meter_elem;
|
||||
GArray *routing_srcs;
|
||||
GArray *routing_dsts;
|
||||
GArray *routing_snks;
|
||||
GIOChannel *io_channel;
|
||||
guint event_source_id;
|
||||
GtkWidget *window_main;
|
||||
@@ -176,7 +176,7 @@ struct alsa_card {
|
||||
GtkWidget *drag_line;
|
||||
int drag_type;
|
||||
struct routing_src *src_drag;
|
||||
struct routing_dst *dst_drag;
|
||||
struct routing_snk *snk_drag;
|
||||
double drag_x, drag_y;
|
||||
};
|
||||
|
||||
@@ -190,7 +190,7 @@ void fatal_alsa_error(const char *msg, int err);
|
||||
struct alsa_elem *get_elem_by_name(GArray *elems, char *name);
|
||||
struct alsa_elem *get_elem_by_prefix(GArray *elems, char *prefix);
|
||||
int get_max_elem_by_name(GArray *elems, char *prefix, char *needle);
|
||||
int is_elem_routing_dst(struct alsa_elem *elem);
|
||||
int is_elem_routing_snk(struct alsa_elem *elem);
|
||||
|
||||
// alsa snd_ctl_elem_*() functions
|
||||
int alsa_get_elem_type(struct alsa_elem *elem);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "alsa.h"
|
||||
#include "routing-lines.h"
|
||||
|
||||
// dotted dash when a destination is going to be removed by a drag
|
||||
// dotted dash when a sink is going to be removed by a drag
|
||||
static const double dash_dotted[] = { 1, 10 };
|
||||
|
||||
// dash when dragging and not connected
|
||||
@@ -12,7 +12,7 @@ static const double dash[] = { 4 };
|
||||
|
||||
static void choose_line_colour(
|
||||
struct routing_src *r_src,
|
||||
struct routing_dst *r_dst,
|
||||
struct routing_snk *r_snk,
|
||||
double *r,
|
||||
double *g,
|
||||
double *b
|
||||
@@ -20,21 +20,21 @@ static void choose_line_colour(
|
||||
// left channels have odd numbers
|
||||
// right channels have even numbers
|
||||
int odd_src = r_src->lr_num & 1;
|
||||
int odd_dst = r_dst->elem->lr_num & 1;
|
||||
int odd_snk = r_snk->elem->lr_num & 1;
|
||||
|
||||
// for colouring, pair channels up
|
||||
// 0 for odd pairs, 1 for even pairs
|
||||
int src2 = ((r_src->lr_num - 1) / 2 & 1);
|
||||
int dst2 = ((r_dst->elem->lr_num - 1) / 2 & 1);
|
||||
int snk2 = ((r_snk->elem->lr_num - 1) / 2 & 1);
|
||||
|
||||
// left -> left, black
|
||||
if (odd_src && odd_dst) {
|
||||
if (odd_src && odd_snk) {
|
||||
*r = 0;
|
||||
*g = 0;
|
||||
*b = 0;
|
||||
|
||||
// right -> right, red
|
||||
} else if (!odd_src && !odd_dst) {
|
||||
} else if (!odd_src && !odd_snk) {
|
||||
*r = 1;
|
||||
*g = 0;
|
||||
*b = 0;
|
||||
@@ -54,7 +54,7 @@ static void choose_line_colour(
|
||||
|
||||
// mix <-> non-mix, add blue
|
||||
if ((r_src->port_category == PC_MIX) !=
|
||||
(r_dst->port_category == PC_MIX)) {
|
||||
(r_snk->port_category == PC_MIX)) {
|
||||
*b = 0.5;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ static void choose_line_colour(
|
||||
}
|
||||
|
||||
// even output pairs, lighten blue component
|
||||
if (dst2) {
|
||||
if (snk2) {
|
||||
*b = (*b + 1) / 2;
|
||||
}
|
||||
}
|
||||
@@ -160,8 +160,8 @@ static void arrow(
|
||||
cairo_close_path(cr);
|
||||
}
|
||||
|
||||
// draw a nice curved line connecting a source at (x1, y1) and a
|
||||
// destination at (x2, y2)
|
||||
// draw a nice curved line connecting a source at (x1, y1) and a sink
|
||||
// at (x2, y2)
|
||||
static void draw_connection(
|
||||
cairo_t *cr,
|
||||
double x1,
|
||||
@@ -169,7 +169,7 @@ static void draw_connection(
|
||||
int src_is_mixer,
|
||||
double x2,
|
||||
double y2,
|
||||
int dst_is_mixer,
|
||||
int snk_is_mixer,
|
||||
double r,
|
||||
double g,
|
||||
double b,
|
||||
@@ -178,7 +178,7 @@ static void draw_connection(
|
||||
double x3 = x1, y3 = y1, x4 = x2, y4 = y2;
|
||||
|
||||
// vertical/horizontal?
|
||||
if (src_is_mixer == dst_is_mixer) {
|
||||
if (src_is_mixer == snk_is_mixer) {
|
||||
double f1 = 0.3;
|
||||
double f2 = 1 - f1;
|
||||
|
||||
@@ -222,7 +222,7 @@ static void draw_connection(
|
||||
|
||||
// locate the center of a widget in the parent coordinates
|
||||
// used for drawing lines to/from the "socket" widget of routing
|
||||
// sources and destinations
|
||||
// sources and sinks
|
||||
static void get_widget_center(
|
||||
GtkWidget *w,
|
||||
GtkWidget *parent,
|
||||
@@ -245,19 +245,18 @@ static void get_src_center(
|
||||
(*y)++;
|
||||
}
|
||||
|
||||
static void get_dst_center(
|
||||
struct routing_dst *r_dst,
|
||||
static void get_snk_center(
|
||||
struct routing_snk *r_snk,
|
||||
GtkWidget *parent,
|
||||
double *x,
|
||||
double *y
|
||||
) {
|
||||
get_widget_center(r_dst->elem->widget2, parent, x, y);
|
||||
if (r_dst->port_category == PC_MIX)
|
||||
get_widget_center(r_snk->elem->widget2, parent, x, y);
|
||||
if (r_snk->port_category == PC_MIX)
|
||||
(*y)++;
|
||||
}
|
||||
|
||||
// redraw the overlay lines between the routing sources and
|
||||
// destinations
|
||||
// redraw the overlay lines between the routing sources and sinks
|
||||
void draw_routing_lines(
|
||||
GtkDrawingArea *drawing_area,
|
||||
cairo_t *cr,
|
||||
@@ -272,22 +271,22 @@ void draw_routing_lines(
|
||||
|
||||
int dragging = card->drag_type != DRAG_TYPE_NONE;
|
||||
|
||||
// go through all the routing destinations
|
||||
for (int i = 0; i < card->routing_dsts->len; i++) {
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, i
|
||||
// go through all the routing sinks
|
||||
for (int i = 0; i < card->routing_snks->len; i++) {
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, i
|
||||
);
|
||||
|
||||
// if dragging and a routing destination is being reconnected then
|
||||
// draw it with dots
|
||||
int dragging_this = dragging && card->dst_drag == r_dst;
|
||||
// if dragging and a routing sink is being reconnected then draw
|
||||
// it with dots
|
||||
int dragging_this = dragging && card->snk_drag == r_snk;
|
||||
if (dragging_this)
|
||||
cairo_set_dash(cr, dash_dotted, 2, 0);
|
||||
else
|
||||
cairo_set_dash(cr, NULL, 0, 0);
|
||||
|
||||
// get the destination and skip if it's "Off"
|
||||
int r_src_idx = alsa_get_elem_value(r_dst->elem);
|
||||
// get the sink and skip if it's "Off"
|
||||
int r_src_idx = alsa_get_elem_value(r_snk->elem);
|
||||
if (!r_src_idx)
|
||||
continue;
|
||||
|
||||
@@ -296,14 +295,14 @@ void draw_routing_lines(
|
||||
card->routing_srcs, struct routing_src, r_src_idx
|
||||
);
|
||||
|
||||
// locate the source and destination coordinates
|
||||
// locate the source and sink coordinates
|
||||
double x1, y1, x2, y2;
|
||||
get_src_center(r_src, parent, &x1, &y1);
|
||||
get_dst_center(r_dst, parent, &x2, &y2);
|
||||
get_snk_center(r_snk, parent, &x2, &y2);
|
||||
|
||||
// pick a colour
|
||||
double r, g, b;
|
||||
choose_line_colour(r_src, r_dst, &r, &g, &b);
|
||||
choose_line_colour(r_src, r_snk, &r, &g, &b);
|
||||
|
||||
// make the colour lighter if it's being shown dotted
|
||||
if (dragging_this) {
|
||||
@@ -316,7 +315,7 @@ void draw_routing_lines(
|
||||
draw_connection(
|
||||
cr,
|
||||
x1, y1, r_src->port_category == PC_MIX,
|
||||
x2, y2, r_dst->port_category == PC_MIX,
|
||||
x2, y2, r_snk->port_category == PC_MIX,
|
||||
r, g, b, 2
|
||||
);
|
||||
}
|
||||
@@ -333,19 +332,19 @@ void draw_drag_line(
|
||||
struct alsa_card *card = user_data;
|
||||
GtkWidget *parent = card->drag_line;
|
||||
|
||||
// if not dragging or routing src & dst not specified or drag out of
|
||||
// if not dragging or routing src & snk not specified or drag out of
|
||||
// bounds then do nothing
|
||||
if (card->drag_type == DRAG_TYPE_NONE ||
|
||||
(!card->src_drag && !card->dst_drag) ||
|
||||
(!card->src_drag && !card->snk_drag) ||
|
||||
card->drag_x < 0 ||
|
||||
card->drag_y < 0)
|
||||
return;
|
||||
|
||||
// the drag mouse position is relative to card->routing_grid
|
||||
// translate it to the overlay card->drag_line
|
||||
// (don't need to do this if both src_drag and dst_drag are set)
|
||||
// (don't need to do this if both src_drag and snk_drag are set)
|
||||
double drag_x, drag_y;
|
||||
if (!card->src_drag || !card->dst_drag)
|
||||
if (!card->src_drag || !card->snk_drag)
|
||||
gtk_widget_translate_coordinates(
|
||||
card->routing_grid, parent,
|
||||
card->drag_x, card->drag_y,
|
||||
@@ -362,23 +361,23 @@ void draw_drag_line(
|
||||
y1 = drag_y;
|
||||
}
|
||||
|
||||
// get the line end position; either a routing destination socket
|
||||
// widget or the drag mouse position
|
||||
// get the line end position; either a routing sink socket widget or
|
||||
// the drag mouse position
|
||||
double x2, y2;
|
||||
if (card->dst_drag) {
|
||||
get_dst_center(card->dst_drag, parent, &x2, &y2);
|
||||
if (card->snk_drag) {
|
||||
get_snk_center(card->snk_drag, parent, &x2, &y2);
|
||||
} else {
|
||||
x2 = drag_x;
|
||||
y2 = drag_y;
|
||||
}
|
||||
|
||||
// if routing src & dst both specified then draw a curved line as if
|
||||
// if routing src & snk both specified then draw a curved line as if
|
||||
// it was connected (except black)
|
||||
if (card->src_drag && card->dst_drag) {
|
||||
if (card->src_drag && card->snk_drag) {
|
||||
draw_connection(
|
||||
cr,
|
||||
x1, y1, card->src_drag->port_category == PC_MIX,
|
||||
x2, y2, card->dst_drag->port_category == PC_MIX,
|
||||
x2, y2, card->snk_drag->port_category == PC_MIX,
|
||||
0, 0, 0, 2
|
||||
);
|
||||
|
||||
|
||||
@@ -8,18 +8,18 @@
|
||||
#include "widget-gain.h"
|
||||
#include "window-mixer.h"
|
||||
|
||||
static struct routing_dst *get_mixer_r_dst(
|
||||
static struct routing_snk *get_mixer_r_snk(
|
||||
struct alsa_card *card,
|
||||
int input_num
|
||||
) {
|
||||
for (int i = 0; i < card->routing_dsts->len; i++) {
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, i
|
||||
for (int i = 0; i < card->routing_snks->len; i++) {
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, i
|
||||
);
|
||||
if (r_dst->port_category != PC_MIX)
|
||||
if (r_snk->port_category != PC_MIX)
|
||||
continue;
|
||||
if (r_dst->elem->lr_num == input_num)
|
||||
return r_dst;
|
||||
if (r_snk->elem->lr_num == input_num)
|
||||
return r_snk;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -76,21 +76,21 @@ GtkWidget *create_mixer_controls(struct alsa_card *card) {
|
||||
GtkWidget *w = make_gain_alsa_elem(elem);
|
||||
gtk_grid_attach(GTK_GRID(mixer_top), w, input_num + 1, mix_num + 2, 1, 1);
|
||||
|
||||
// look up the r_dst entry for the mixer input number
|
||||
struct routing_dst *r_dst = get_mixer_r_dst(card, input_num + 1);
|
||||
if (!r_dst) {
|
||||
// look up the r_snk entry for the mixer input number
|
||||
struct routing_snk *r_snk = get_mixer_r_snk(card, input_num + 1);
|
||||
if (!r_snk) {
|
||||
printf("missing mixer input %d\n", input_num);
|
||||
continue;
|
||||
}
|
||||
|
||||
// lookup the top label for the mixer input
|
||||
GtkWidget *l_top = r_dst->mixer_label_top;
|
||||
GtkWidget *l_top = r_snk->mixer_label_top;
|
||||
|
||||
// if the top label doesn't already exist the bottom doesn't
|
||||
// either; create them both and attach to the grid
|
||||
if (!l_top) {
|
||||
l_top = r_dst->mixer_label_top = gtk_label_new("");
|
||||
GtkWidget *l_bottom = r_dst->mixer_label_bottom = gtk_label_new("");
|
||||
l_top = r_snk->mixer_label_top = gtk_label_new("");
|
||||
GtkWidget *l_bottom = r_snk->mixer_label_bottom = gtk_label_new("");
|
||||
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(mixer_top), l_top,
|
||||
@@ -109,15 +109,15 @@ GtkWidget *create_mixer_controls(struct alsa_card *card) {
|
||||
}
|
||||
|
||||
void update_mixer_labels(struct alsa_card *card) {
|
||||
for (int i = 0; i < card->routing_dsts->len; i++) {
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, i
|
||||
for (int i = 0; i < card->routing_snks->len; i++) {
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, i
|
||||
);
|
||||
|
||||
if (r_dst->port_category != PC_MIX)
|
||||
if (r_snk->port_category != PC_MIX)
|
||||
continue;
|
||||
|
||||
struct alsa_elem *elem = r_dst->elem;
|
||||
struct alsa_elem *elem = r_snk->elem;
|
||||
|
||||
int routing_src_idx = alsa_get_elem_value(elem);
|
||||
|
||||
@@ -125,9 +125,9 @@ void update_mixer_labels(struct alsa_card *card) {
|
||||
card->routing_srcs, struct routing_src, routing_src_idx
|
||||
);
|
||||
|
||||
if (r_dst->mixer_label_top) {
|
||||
gtk_label_set_text(GTK_LABEL(r_dst->mixer_label_top), r_src->name);
|
||||
gtk_label_set_text(GTK_LABEL(r_dst->mixer_label_bottom), r_src->name);
|
||||
if (r_snk->mixer_label_top) {
|
||||
gtk_label_set_text(GTK_LABEL(r_snk->mixer_label_top), r_src->name);
|
||||
gtk_label_set_text(GTK_LABEL(r_snk->mixer_label_bottom), r_src->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,19 +47,19 @@ static void get_routing_srcs(struct alsa_card *card) {
|
||||
assert(card->routing_in_count[PC_MIX] <= MAX_MIX_OUT);
|
||||
}
|
||||
|
||||
static void get_routing_dsts(struct alsa_card *card) {
|
||||
static void get_routing_snks(struct alsa_card *card) {
|
||||
GArray *elems = card->elems;
|
||||
|
||||
int count = 0;
|
||||
|
||||
// count and label routing dsts
|
||||
// count and label routing snks
|
||||
for (int i = 0; i < elems->len; i++) {
|
||||
struct alsa_elem *elem = &g_array_index(elems, struct alsa_elem, i);
|
||||
|
||||
if (!elem->card)
|
||||
continue;
|
||||
|
||||
if (!is_elem_routing_dst(elem))
|
||||
if (!is_elem_routing_snk(elem))
|
||||
continue;
|
||||
|
||||
int i = get_num_from_string(elem->name);
|
||||
@@ -70,13 +70,13 @@ static void get_routing_dsts(struct alsa_card *card) {
|
||||
count++;
|
||||
}
|
||||
|
||||
// create an array of routing dsts pointing to those elements
|
||||
card->routing_dsts = g_array_new(
|
||||
FALSE, TRUE, sizeof(struct routing_dst)
|
||||
// create an array of routing snks pointing to those elements
|
||||
card->routing_snks = g_array_new(
|
||||
FALSE, TRUE, sizeof(struct routing_snk)
|
||||
);
|
||||
g_array_set_size(card->routing_dsts, count);
|
||||
g_array_set_size(card->routing_snks, count);
|
||||
|
||||
// count through card->rounting_dsts
|
||||
// count through card->rounting_snks
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < elems->len; i++) {
|
||||
@@ -85,8 +85,8 @@ static void get_routing_dsts(struct alsa_card *card) {
|
||||
if (!elem->lr_num)
|
||||
continue;
|
||||
|
||||
struct routing_dst *r = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, j
|
||||
struct routing_snk *r = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, j
|
||||
);
|
||||
r->idx = j;
|
||||
j++;
|
||||
@@ -113,14 +113,14 @@ static void routing_grid_label(char *s, GtkGrid *g, GtkAlign align) {
|
||||
gtk_grid_attach(g, l, 0, 0, 1, 1);
|
||||
}
|
||||
|
||||
// clear all the routing destinations
|
||||
// clear all the routing sinks
|
||||
static void routing_preset_clear(struct alsa_card *card) {
|
||||
for (int i = 0; i < card->routing_dsts->len; i++) {
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, i
|
||||
for (int i = 0; i < card->routing_snks->len; i++) {
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, i
|
||||
);
|
||||
|
||||
alsa_set_elem_value(r_dst->elem, 0);
|
||||
alsa_set_elem_value(r_snk->elem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ static void routing_preset_link(
|
||||
struct alsa_card *card,
|
||||
int src_port_category,
|
||||
int src_mod,
|
||||
int dst_port_category
|
||||
int snk_port_category
|
||||
) {
|
||||
|
||||
// find the first src port with the selected port category
|
||||
@@ -144,16 +144,16 @@ static void routing_preset_link(
|
||||
break;
|
||||
}
|
||||
|
||||
// find the first dst port with the selected port category
|
||||
int dst_idx;
|
||||
for (dst_idx = 0;
|
||||
dst_idx < card->routing_dsts->len;
|
||||
dst_idx++) {
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, dst_idx
|
||||
// find the first snk port with the selected port category
|
||||
int snk_idx;
|
||||
for (snk_idx = 0;
|
||||
snk_idx < card->routing_snks->len;
|
||||
snk_idx++) {
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, snk_idx
|
||||
);
|
||||
|
||||
if (r_dst->port_category == dst_port_category)
|
||||
if (r_snk->port_category == snk_port_category)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ static void routing_preset_link(
|
||||
int src_idx = start_src_idx;
|
||||
int src_count = 0;
|
||||
while (src_idx < card->routing_srcs->len &&
|
||||
dst_idx < card->routing_dsts->len) {
|
||||
snk_idx < card->routing_snks->len) {
|
||||
|
||||
// stop if no more of the selected src port category
|
||||
struct routing_src *r_src = &g_array_index(
|
||||
@@ -170,20 +170,20 @@ static void routing_preset_link(
|
||||
if (r_src->port_category != src_port_category)
|
||||
break;
|
||||
|
||||
// stop if no more of the selected dst port category
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, dst_idx
|
||||
// stop if no more of the selected snk port category
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, snk_idx
|
||||
);
|
||||
if (r_dst->port_category != dst_port_category)
|
||||
if (r_snk->port_category != snk_port_category)
|
||||
break;
|
||||
|
||||
// do the assignment
|
||||
alsa_set_elem_value(r_dst->elem, r_src->id);
|
||||
alsa_set_elem_value(r_snk->elem, r_src->id);
|
||||
|
||||
// get the next index
|
||||
src_idx++;
|
||||
src_count++;
|
||||
dst_idx++;
|
||||
snk_idx++;
|
||||
|
||||
if (src_count == src_mod) {
|
||||
src_idx = start_src_idx;
|
||||
@@ -337,9 +337,9 @@ static void create_routing_grid(struct alsa_card *card) {
|
||||
gtk_label_set_justify(GTK_LABEL(src_label), GTK_JUSTIFY_CENTER);
|
||||
gtk_grid_attach(GTK_GRID(routing_grid), src_label, 0, 3, 1, 1);
|
||||
|
||||
GtkWidget *dst_label = gtk_label_new("← Destinations\n↓");
|
||||
gtk_label_set_justify(GTK_LABEL(dst_label), GTK_JUSTIFY_CENTER);
|
||||
gtk_grid_attach(GTK_GRID(routing_grid), dst_label, 2, 0, 1, 1);
|
||||
GtkWidget *snk_label = gtk_label_new("← Sinks\n↓");
|
||||
gtk_label_set_justify(GTK_LABEL(snk_label), GTK_JUSTIFY_CENTER);
|
||||
gtk_grid_attach(GTK_GRID(routing_grid), snk_label, 2, 0, 1, 1);
|
||||
}
|
||||
|
||||
static GtkWidget *make_socket_widget(void) {
|
||||
@@ -359,30 +359,30 @@ static gboolean dropped_on_src(
|
||||
gpointer data
|
||||
) {
|
||||
struct routing_src *src = data;
|
||||
int dst_id = g_value_get_int(value);
|
||||
int snk_id = g_value_get_int(value);
|
||||
|
||||
// don't accept src -> src drops
|
||||
if (!(dst_id & 0x8000))
|
||||
if (!(snk_id & 0x8000))
|
||||
return FALSE;
|
||||
|
||||
// convert the int to a r_dst_idx
|
||||
int r_dst_idx = dst_id & ~0x8000;
|
||||
// convert the int to a r_snk_idx
|
||||
int r_snk_idx = snk_id & ~0x8000;
|
||||
|
||||
// check the index is in bounds
|
||||
GArray *r_dsts = src->card->routing_dsts;
|
||||
if (r_dst_idx < 0 || r_dst_idx >= r_dsts->len)
|
||||
GArray *r_snks = src->card->routing_snks;
|
||||
if (r_snk_idx < 0 || r_snk_idx >= r_snks->len)
|
||||
return FALSE;
|
||||
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
r_dsts, struct routing_dst, r_dst_idx
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
r_snks, struct routing_snk, r_snk_idx
|
||||
);
|
||||
alsa_set_elem_value(r_dst->elem, src->id);
|
||||
alsa_set_elem_value(r_snk->elem, src->id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// something was dropped on a routing destination
|
||||
static gboolean dropped_on_dst(
|
||||
// something was dropped on a routing sink
|
||||
static gboolean dropped_on_snk(
|
||||
GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
@@ -392,7 +392,7 @@ static gboolean dropped_on_dst(
|
||||
struct alsa_elem *elem = data;
|
||||
int src_id = g_value_get_int(value);
|
||||
|
||||
// don't accept dst -> dst drops
|
||||
// don't accept snk -> snk drops
|
||||
if (src_id & 0x8000)
|
||||
return FALSE;
|
||||
|
||||
@@ -409,20 +409,20 @@ static void src_routing_clicked(
|
||||
) {
|
||||
struct alsa_card *card = r_src->card;
|
||||
|
||||
// go through all the routing destinations
|
||||
for (int i = 0; i < card->routing_dsts->len; i++) {
|
||||
struct routing_dst *r_dst = &g_array_index(
|
||||
card->routing_dsts, struct routing_dst, i
|
||||
// go through all the routing sinks
|
||||
for (int i = 0; i < card->routing_snks->len; i++) {
|
||||
struct routing_snk *r_snk = &g_array_index(
|
||||
card->routing_snks, struct routing_snk, i
|
||||
);
|
||||
|
||||
int r_src_idx = alsa_get_elem_value(r_dst->elem);
|
||||
int r_src_idx = alsa_get_elem_value(r_snk->elem);
|
||||
|
||||
if (r_src_idx == r_src->id)
|
||||
alsa_set_elem_value(r_dst->elem, 0);
|
||||
alsa_set_elem_value(r_snk->elem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void dst_routing_clicked(
|
||||
static void snk_routing_clicked(
|
||||
GtkWidget *widget,
|
||||
int n_press,
|
||||
double x,
|
||||
@@ -444,16 +444,16 @@ static void src_drag_begin(
|
||||
card->src_drag = r_src;
|
||||
}
|
||||
|
||||
static void dst_drag_begin(
|
||||
static void snk_drag_begin(
|
||||
GtkDragSource *source,
|
||||
GdkDrag *drag,
|
||||
gpointer user_data
|
||||
) {
|
||||
struct routing_dst *r_dst = user_data;
|
||||
struct alsa_card *card = r_dst->elem->card;
|
||||
struct routing_snk *r_snk = user_data;
|
||||
struct alsa_card *card = r_snk->elem->card;
|
||||
|
||||
card->drag_type = DRAG_TYPE_DST;
|
||||
card->dst_drag = r_dst;
|
||||
card->drag_type = DRAG_TYPE_SNK;
|
||||
card->snk_drag = r_snk;
|
||||
}
|
||||
|
||||
static void src_drag_end(
|
||||
@@ -471,17 +471,17 @@ static void src_drag_end(
|
||||
gtk_widget_queue_draw(card->routing_lines);
|
||||
}
|
||||
|
||||
static void dst_drag_end(
|
||||
static void snk_drag_end(
|
||||
GtkDragSource *source,
|
||||
GdkDrag *drag,
|
||||
gboolean delete_data,
|
||||
gpointer user_data
|
||||
) {
|
||||
struct routing_dst *r_dst = user_data;
|
||||
struct alsa_card *card = r_dst->elem->card;
|
||||
struct routing_snk *r_snk = user_data;
|
||||
struct alsa_card *card = r_snk->elem->card;
|
||||
|
||||
card->drag_type = DRAG_TYPE_NONE;
|
||||
card->dst_drag = NULL;
|
||||
card->snk_drag = NULL;
|
||||
gtk_widget_queue_draw(card->drag_line);
|
||||
gtk_widget_queue_draw(card->routing_lines);
|
||||
}
|
||||
@@ -494,16 +494,16 @@ static gboolean src_drop_accept(
|
||||
struct routing_src *r_src = user_data;
|
||||
struct alsa_card *card = r_src->card;
|
||||
|
||||
return card->drag_type == DRAG_TYPE_DST;
|
||||
return card->drag_type == DRAG_TYPE_SNK;
|
||||
}
|
||||
|
||||
static gboolean dst_drop_accept(
|
||||
static gboolean snk_drop_accept(
|
||||
GtkDropTarget *source,
|
||||
GdkDrop *drop,
|
||||
gpointer user_data
|
||||
) {
|
||||
struct routing_dst *r_dst = user_data;
|
||||
struct alsa_card *card = r_dst->elem->card;
|
||||
struct routing_snk *r_snk = user_data;
|
||||
struct alsa_card *card = r_snk->elem->card;
|
||||
|
||||
return card->drag_type == DRAG_TYPE_SRC;
|
||||
}
|
||||
@@ -517,7 +517,7 @@ static GdkDragAction src_drop_enter(
|
||||
struct routing_src *r_src = user_data;
|
||||
struct alsa_card *card = r_src->card;
|
||||
|
||||
if (card->drag_type != DRAG_TYPE_DST)
|
||||
if (card->drag_type != DRAG_TYPE_SNK)
|
||||
return 0;
|
||||
|
||||
card->src_drag = r_src;
|
||||
@@ -525,19 +525,19 @@ static GdkDragAction src_drop_enter(
|
||||
return GDK_ACTION_COPY;
|
||||
}
|
||||
|
||||
static GdkDragAction dst_drop_enter(
|
||||
static GdkDragAction snk_drop_enter(
|
||||
GtkDropTarget *dest,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gpointer user_data
|
||||
) {
|
||||
struct routing_dst *r_dst = user_data;
|
||||
struct alsa_card *card = r_dst->elem->card;
|
||||
struct routing_snk *r_snk = user_data;
|
||||
struct alsa_card *card = r_snk->elem->card;
|
||||
|
||||
if (card->drag_type != DRAG_TYPE_SRC)
|
||||
return 0;
|
||||
|
||||
card->dst_drag = r_dst;
|
||||
card->snk_drag = r_snk;
|
||||
|
||||
return GDK_ACTION_COPY;
|
||||
}
|
||||
@@ -549,23 +549,23 @@ static void src_drop_leave(
|
||||
struct routing_src *r_src = user_data;
|
||||
struct alsa_card *card = r_src->card;
|
||||
|
||||
if (card->drag_type != DRAG_TYPE_DST)
|
||||
if (card->drag_type != DRAG_TYPE_SNK)
|
||||
return;
|
||||
|
||||
card->src_drag = NULL;
|
||||
}
|
||||
|
||||
static void dst_drop_leave(
|
||||
static void snk_drop_leave(
|
||||
GtkDropTarget *dest,
|
||||
gpointer user_data
|
||||
) {
|
||||
struct routing_dst *r_dst = user_data;
|
||||
struct alsa_card *card = r_dst->elem->card;
|
||||
struct routing_snk *r_snk = user_data;
|
||||
struct alsa_card *card = r_snk->elem->card;
|
||||
|
||||
if (card->drag_type != DRAG_TYPE_SRC)
|
||||
return;
|
||||
|
||||
card->dst_drag = NULL;
|
||||
card->snk_drag = NULL;
|
||||
}
|
||||
|
||||
static void setup_src_drag(struct routing_src *r_src) {
|
||||
@@ -601,14 +601,14 @@ static void setup_src_drag(struct routing_src *r_src) {
|
||||
g_signal_connect(dest, "leave", G_CALLBACK(src_drop_leave), r_src);
|
||||
}
|
||||
|
||||
static void setup_dst_drag(struct routing_dst *r_dst) {
|
||||
struct alsa_elem *elem = r_dst->elem;
|
||||
static void setup_snk_drag(struct routing_snk *r_snk) {
|
||||
struct alsa_elem *elem = r_snk->elem;
|
||||
GtkWidget *box = elem->widget;
|
||||
|
||||
// handle drags on the box
|
||||
GtkDragSource *source = gtk_drag_source_new();
|
||||
g_signal_connect(source, "drag-begin", G_CALLBACK(dst_drag_begin), r_dst);
|
||||
g_signal_connect(source, "drag-end", G_CALLBACK(dst_drag_end), r_dst);
|
||||
g_signal_connect(source, "drag-begin", G_CALLBACK(snk_drag_begin), r_snk);
|
||||
g_signal_connect(source, "drag-end", G_CALLBACK(snk_drag_end), r_snk);
|
||||
|
||||
// set the box as a drag source
|
||||
gtk_drag_source_set_actions(source, GDK_ACTION_COPY);
|
||||
@@ -617,7 +617,7 @@ static void setup_dst_drag(struct routing_dst *r_dst) {
|
||||
// set the content
|
||||
// 0x8000 flag indicates alsa_elem numid value
|
||||
GdkContentProvider *content = gdk_content_provider_new_typed(
|
||||
G_TYPE_INT, 0x8000 | r_dst->idx
|
||||
G_TYPE_INT, 0x8000 | r_snk->idx
|
||||
);
|
||||
gtk_drag_source_set_content(source, content);
|
||||
g_object_unref(content);
|
||||
@@ -630,10 +630,10 @@ static void setup_dst_drag(struct routing_dst *r_dst) {
|
||||
// set the box as a drop target
|
||||
GtkDropTarget *dest = gtk_drop_target_new(G_TYPE_INT, GDK_ACTION_COPY);
|
||||
gtk_widget_add_controller(box, GTK_EVENT_CONTROLLER(dest));
|
||||
g_signal_connect(dest, "drop", G_CALLBACK(dropped_on_dst), elem);
|
||||
g_signal_connect(dest, "accept", G_CALLBACK(dst_drop_accept), r_dst);
|
||||
g_signal_connect(dest, "enter", G_CALLBACK(dst_drop_enter), r_dst);
|
||||
g_signal_connect(dest, "leave", G_CALLBACK(dst_drop_leave), r_dst);
|
||||
g_signal_connect(dest, "drop", G_CALLBACK(dropped_on_snk), elem);
|
||||
g_signal_connect(dest, "accept", G_CALLBACK(snk_drop_accept), r_snk);
|
||||
g_signal_connect(dest, "enter", G_CALLBACK(snk_drop_enter), r_snk);
|
||||
g_signal_connect(dest, "leave", G_CALLBACK(snk_drop_leave), r_snk);
|
||||
}
|
||||
|
||||
static void make_src_routing_widget(
|
||||
@@ -698,13 +698,13 @@ static GtkWidget *make_talkback_mix_widget(
|
||||
return make_boolean_alsa_elem(talkback_elem, name, name);
|
||||
}
|
||||
|
||||
static void make_dst_routing_widget(
|
||||
struct routing_dst *r_dst,
|
||||
static void make_snk_routing_widget(
|
||||
struct routing_snk *r_snk,
|
||||
char *name,
|
||||
GtkOrientation orientation
|
||||
) {
|
||||
|
||||
struct alsa_elem *elem = r_dst->elem;
|
||||
struct alsa_elem *elem = r_snk->elem;
|
||||
|
||||
// create a box, a "socket", and a label
|
||||
GtkWidget *box = elem->widget = gtk_box_new(orientation, 5);
|
||||
@@ -727,14 +727,14 @@ static void make_dst_routing_widget(
|
||||
// handle clicks on the box
|
||||
GtkGesture *gesture = gtk_gesture_click_new();
|
||||
g_signal_connect(
|
||||
gesture, "released", G_CALLBACK(dst_routing_clicked), elem
|
||||
gesture, "released", G_CALLBACK(snk_routing_clicked), elem
|
||||
);
|
||||
gtk_widget_add_controller(
|
||||
GTK_WIDGET(box), GTK_EVENT_CONTROLLER(gesture)
|
||||
);
|
||||
|
||||
// handle dragging to or from the box
|
||||
setup_dst_drag(r_dst);
|
||||
setup_snk_drag(r_snk);
|
||||
}
|
||||
|
||||
static void routing_updated(struct alsa_elem *elem) {
|
||||
@@ -744,26 +744,26 @@ static void routing_updated(struct alsa_elem *elem) {
|
||||
gtk_widget_queue_draw(card->routing_lines);
|
||||
}
|
||||
|
||||
static void make_routing_alsa_elem(struct routing_dst *r_dst) {
|
||||
struct alsa_elem *elem = r_dst->elem;
|
||||
static void make_routing_alsa_elem(struct routing_snk *r_snk) {
|
||||
struct alsa_elem *elem = r_snk->elem;
|
||||
struct alsa_card *card = elem->card;
|
||||
|
||||
// "Mixer Input X Capture Enum" controls (Mixer Inputs) go along
|
||||
// the top, in card->routing_mixer_in_grid
|
||||
if (r_dst->port_category == PC_MIX) {
|
||||
if (r_snk->port_category == PC_MIX) {
|
||||
|
||||
char name[10];
|
||||
|
||||
snprintf(name, 10, "%d", elem->lr_num);
|
||||
make_dst_routing_widget(r_dst, name, GTK_ORIENTATION_VERTICAL);
|
||||
make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_VERTICAL);
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(card->routing_mixer_in_grid), elem->widget,
|
||||
r_dst->port_num + 1, 0, 1, 1
|
||||
r_snk->port_num + 1, 0, 1, 1
|
||||
);
|
||||
|
||||
// "PCM X Capture Enum" controls (PCM Inputs) go along the right,
|
||||
// in card->routing_pcm_out_grid
|
||||
} else if (r_dst->port_category == PC_PCM) {
|
||||
} else if (r_snk->port_category == PC_PCM) {
|
||||
char *name = strdup(elem->name);
|
||||
char *name_end = strchr(name, ' ');
|
||||
|
||||
@@ -771,17 +771,17 @@ static void make_routing_alsa_elem(struct routing_dst *r_dst) {
|
||||
if (name_end)
|
||||
snprintf(name_end, strlen(name_end) + 1, " %d", elem->lr_num);
|
||||
|
||||
make_dst_routing_widget(r_dst, name, GTK_ORIENTATION_HORIZONTAL);
|
||||
make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_HORIZONTAL);
|
||||
free(name);
|
||||
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(card->routing_pcm_out_grid), elem->widget,
|
||||
0, r_dst->port_num + 1, 1, 1
|
||||
0, r_snk->port_num + 1, 1, 1
|
||||
);
|
||||
|
||||
// "* Output X Playback Enum" controls go along the right, in
|
||||
// card->routing_hw_out_grid
|
||||
} else if (r_dst->port_category == PC_HW) {
|
||||
} else if (r_snk->port_category == PC_HW) {
|
||||
|
||||
// Convert "Analogue 01 Output Playback Enum" to "Analogue 1"
|
||||
char *name = strdup(elem->name);
|
||||
@@ -791,15 +791,15 @@ static void make_routing_alsa_elem(struct routing_dst *r_dst) {
|
||||
if (name_end)
|
||||
snprintf(name_end, strlen(name_end) + 1, " %d", elem->lr_num);
|
||||
|
||||
make_dst_routing_widget(r_dst, name, GTK_ORIENTATION_HORIZONTAL);
|
||||
make_snk_routing_widget(r_snk, name, GTK_ORIENTATION_HORIZONTAL);
|
||||
free(name);
|
||||
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(card->routing_hw_out_grid), elem->widget,
|
||||
0, r_dst->port_num + 1, 1, 1
|
||||
0, r_snk->port_num + 1, 1, 1
|
||||
);
|
||||
} else {
|
||||
printf("invalid port category %d\n", r_dst->port_category);
|
||||
printf("invalid port category %d\n", r_snk->port_category);
|
||||
}
|
||||
|
||||
elem->widget_callback = routing_updated;
|
||||
@@ -809,13 +809,13 @@ static void add_routing_widgets(
|
||||
struct alsa_card *card,
|
||||
GtkWidget *routing_overlay
|
||||
) {
|
||||
GArray *r_dsts = card->routing_dsts;
|
||||
GArray *r_snks = card->routing_snks;
|
||||
|
||||
// go through each routing destination and create its control
|
||||
for (int i = 0; i < r_dsts->len; i++) {
|
||||
struct routing_dst *r_dst = &g_array_index(r_dsts, struct routing_dst, i);
|
||||
// go through each routing sink and create its control
|
||||
for (int i = 0; i < r_snks->len; i++) {
|
||||
struct routing_snk *r_snk = &g_array_index(r_snks, struct routing_snk, i);
|
||||
|
||||
make_routing_alsa_elem(r_dst);
|
||||
make_routing_alsa_elem(r_snk);
|
||||
}
|
||||
|
||||
if (!card->routing_out_count[PC_MIX]) {
|
||||
@@ -920,7 +920,7 @@ GtkWidget *create_routing_controls(struct alsa_card *card) {
|
||||
}
|
||||
|
||||
get_routing_srcs(card);
|
||||
get_routing_dsts(card);
|
||||
get_routing_snks(card);
|
||||
|
||||
create_routing_grid(card);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user