22
USAGE.md
22
USAGE.md
@@ -217,17 +217,15 @@ inputs/outputs.
|
|||||||
|
|
||||||
To manage the routing connections:
|
To manage the routing connections:
|
||||||
|
|
||||||
- Click and drag from a source to a destination or a destination to a
|
- Click and drag from a source to a sink or a sink to a source to
|
||||||
source to connect them. Audio from the source will then be sent to
|
connect them. Audio from the source will then be sent to that sink.
|
||||||
that destination.
|
|
||||||
|
|
||||||
- Click on a source or a destination to clear the links connected to
|
- Click on a source or a sink to clear the links connected to that
|
||||||
that source/destination.
|
source/sink.
|
||||||
|
|
||||||
Note that a destination can only be connected to one source, but one
|
Note that a sink can only be connected to one source, but one source
|
||||||
source can be connected to many destinations. If you want a
|
can be connected to many sinks. If you want a sink to receive input
|
||||||
destination to receive input from more than one source, use the mixer
|
from more than one source, use the mixer inputs and outputs.
|
||||||
inputs and outputs.
|
|
||||||
|
|
||||||
The Presets menu can be used to clear all connections, or to set up
|
The Presets menu can be used to clear all connections, or to set up
|
||||||
common configurations:
|
common configurations:
|
||||||
@@ -270,9 +268,9 @@ to a PCM Input.
|
|||||||
### Mixer
|
### Mixer
|
||||||
|
|
||||||
If you use the Routing window to connect Sources to Mixer Inputs and
|
If you use the Routing window to connect Sources to Mixer Inputs and
|
||||||
Mixer Outputs to Destinations, then you can use the Mixer window to
|
Mixer Outputs to Sinks, then you can use the Mixer window to set the
|
||||||
set the amount of each Mixer Input that is sent to each Mixer Output
|
amount of each Mixer Input that is sent to each Mixer Output using a
|
||||||
using a matrix of controls:
|
matrix of controls:
|
||||||
|
|
||||||

|

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