Add colour to GtkDial level meters
This commit is contained in:
@@ -125,6 +125,11 @@ struct _GtkDial {
|
||||
double *taper_outputs;
|
||||
int taper_breakpoints_count;
|
||||
|
||||
// level meter colour breakpoints array
|
||||
const int *level_breakpoints;
|
||||
const double *level_colours;
|
||||
int level_breakpoints_count;
|
||||
|
||||
// variables derived from the widget's dynamic properties (size and
|
||||
// configuration, excluding the value)
|
||||
int dim;
|
||||
@@ -139,6 +144,7 @@ struct _GtkDial {
|
||||
double cy;
|
||||
double zero_db_x;
|
||||
double zero_db_y;
|
||||
double *level_breakpoint_angles;
|
||||
|
||||
// cairo patterns dependent on the above
|
||||
cairo_pattern_t *fill_pattern[2][2];
|
||||
@@ -374,6 +380,21 @@ static void update_dial_properties(GtkDial *dial) {
|
||||
|
||||
dial->outline_pattern[dim] = pat;
|
||||
}
|
||||
|
||||
// calculate level meter breakpoint angles
|
||||
if (dial->level_breakpoint_angles)
|
||||
free(dial->level_breakpoint_angles);
|
||||
|
||||
if (dial->level_breakpoints_count) {
|
||||
dial->level_breakpoint_angles = malloc(
|
||||
dial->level_breakpoints_count * sizeof(double)
|
||||
);
|
||||
for (int i = 0; i < dial->level_breakpoints_count; i++) {
|
||||
double valp = calc_taper(dial, dial->level_breakpoints[i]);
|
||||
dial->level_breakpoint_angles[i] =
|
||||
calc_val(valp, ANGLE_START, ANGLE_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_dial_values(GtkDial *dial) {
|
||||
@@ -658,10 +679,60 @@ static void draw_slider(
|
||||
double thickness,
|
||||
double alpha
|
||||
) {
|
||||
cairo_arc(cr, dial->cx, dial->cy, radius, ANGLE_START, dial->angle);
|
||||
cairo_set_line_width(cr, thickness);
|
||||
cairo_set_source_rgba_dim(cr, 1, 1, 1, alpha, dial->dim);
|
||||
cairo_stroke(cr);
|
||||
|
||||
int count = dial->level_breakpoints_count;
|
||||
|
||||
if (!count) {
|
||||
cairo_arc(cr, dial->cx, dial->cy, radius, ANGLE_START, dial->angle);
|
||||
cairo_set_source_rgba_dim(cr, 1, 1, 1, alpha, dial->dim);
|
||||
cairo_stroke(cr);
|
||||
return;
|
||||
}
|
||||
|
||||
// if the last breakpoint is at the upper limit, then the maximum
|
||||
// value is displayed with the whole slider that colours
|
||||
if (dial->level_breakpoint_angles[count - 1] == ANGLE_END &&
|
||||
dial->angle == ANGLE_END) {
|
||||
const double *colours = &dial->level_colours[(count - 1) * 3];
|
||||
|
||||
cairo_set_source_rgba_dim(
|
||||
cr,
|
||||
colours[0], colours[1], colours[2],
|
||||
alpha,
|
||||
dial->dim
|
||||
);
|
||||
|
||||
cairo_arc(cr, dial->cx, dial->cy, radius, ANGLE_START, ANGLE_END);
|
||||
cairo_stroke(cr);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const double *colours = &dial->level_colours[i * 3];
|
||||
|
||||
cairo_set_source_rgba_dim(
|
||||
cr,
|
||||
colours[0], colours[1], colours[2],
|
||||
alpha,
|
||||
dial->dim
|
||||
);
|
||||
|
||||
double angle_start = dial->level_breakpoint_angles[i];
|
||||
double angle_end =
|
||||
i == count - 1
|
||||
? ANGLE_END
|
||||
: dial->level_breakpoint_angles[i + 1];
|
||||
|
||||
if (dial->angle < angle_end) {
|
||||
cairo_arc(cr, dial->cx, dial->cy, radius, angle_start, dial->angle);
|
||||
cairo_stroke(cr);
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_arc(cr, dial->cx, dial->cy, radius, angle_start, angle_end);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
}
|
||||
|
||||
static void dial_snapshot(GtkWidget *widget, GtkSnapshot *snapshot) {
|
||||
@@ -940,6 +1011,18 @@ gboolean gtk_dial_get_can_control(GtkDial *dial) {
|
||||
return dial->can_control;
|
||||
}
|
||||
|
||||
void gtk_dial_set_level_meter_colours(
|
||||
GtkDial *dial,
|
||||
const int *breakpoints,
|
||||
const double *colours,
|
||||
int count
|
||||
) {
|
||||
dial->level_breakpoints = breakpoints;
|
||||
dial->level_colours = colours;
|
||||
dial->level_breakpoints_count = count;
|
||||
dial->properties_updated = 1;
|
||||
}
|
||||
|
||||
void gtk_dial_set_adjustment(GtkDial *dial, GtkAdjustment *adj) {
|
||||
if (!(adj == NULL || GTK_IS_ADJUSTMENT(adj)))
|
||||
return;
|
||||
@@ -1217,6 +1300,8 @@ void gtk_dial_dispose(GObject *o) {
|
||||
free(dial->taper_outputs);
|
||||
dial->taper_outputs = NULL;
|
||||
dial->taper_breakpoints_count = 0;
|
||||
free(dial->level_breakpoint_angles);
|
||||
dial->level_breakpoint_angles = NULL;
|
||||
|
||||
for (int focus = 0; focus <= 1; focus++)
|
||||
for (int dim = 0; dim <= 1; dim++)
|
||||
|
||||
@@ -87,6 +87,13 @@ void gtk_dial_set_taper_linear_breakpoints(
|
||||
void gtk_dial_set_can_control(GtkDial *dial, gboolean can_control);
|
||||
gboolean gtk_dial_get_can_control(GtkDial *dial);
|
||||
|
||||
void gtk_dial_set_level_meter_colours(
|
||||
GtkDial *dial,
|
||||
const int *breakpoints,
|
||||
const double *colours,
|
||||
int count
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,20 @@
|
||||
#include "widget-gain.h"
|
||||
#include "window-levels.h"
|
||||
|
||||
static const int level_breakpoints_out[] = { -80, -18, -12, -6, -3, -1 };
|
||||
|
||||
// inputs glow all-red when limit is reached
|
||||
static const int level_breakpoints_in[] = { -80, -18, -12, -6, -3, 0 };
|
||||
|
||||
static const double level_colours[] = {
|
||||
0.00, 1.00, 0.00, // -80
|
||||
0.75, 1.00, 0.00, // -18
|
||||
1.00, 1.00, 0.00, // -12
|
||||
1.00, 0.75, 0.00, // -6
|
||||
1.00, 0.50, 0.00, // -3
|
||||
1.00, 0.00, 0.00 // -1/0
|
||||
};
|
||||
|
||||
static int update_levels_controls(void *user_data) {
|
||||
struct alsa_card *card = user_data;
|
||||
|
||||
@@ -104,6 +118,14 @@ GtkWidget *create_levels_controls(struct alsa_card *card) {
|
||||
GtkWidget *meter = gtk_dial_new_with_range(-80, 0, 0, 0);
|
||||
gtk_dial_set_taper(GTK_DIAL(meter), GTK_DIAL_TAPER_LINEAR);
|
||||
gtk_dial_set_can_control(GTK_DIAL(meter), FALSE);
|
||||
gtk_dial_set_level_meter_colours(
|
||||
GTK_DIAL(meter),
|
||||
(i == PC_DSP || i == PC_PCM)
|
||||
? level_breakpoints_in
|
||||
: level_breakpoints_out,
|
||||
level_colours,
|
||||
sizeof(level_breakpoints_out) / sizeof(int)
|
||||
);
|
||||
gtk_widget_set_sensitive(meter, FALSE);
|
||||
|
||||
// HW Output off_db is -55db; otherwise -45db
|
||||
|
||||
Reference in New Issue
Block a user