envy24control: port to GTK 3

Closes: https://github.com/alsa-project/alsa-tools/pull/35
Signed-off-by: Andreas Persson <andreasp56@outlook.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Andreas Persson 2025-04-09 12:25:09 +02:00 committed by Jaroslav Kysela
parent 32495631b1
commit ddc93b66b4
12 changed files with 541 additions and 534 deletions

View file

@ -19,13 +19,13 @@
#include "envy24control.h"
static GdkGC *penGreenShadow[21] = { NULL, };
static GdkGC *penGreenLight[21] = { NULL, };
static GdkGC *penOrangeShadow[21] = { NULL, };
static GdkGC *penOrangeLight[21] = { NULL, };
static GdkGC *penRedShadow[21] = { NULL, };
static GdkGC *penRedLight[21] = { NULL, };
static GdkPixmap *pixmap[21] = { NULL, };
static GdkRGBA *penGreenShadow = NULL;
static GdkRGBA *penGreenLight = NULL;
static GdkRGBA *penOrangeShadow = NULL;
static GdkRGBA *penOrangeLight = NULL;
static GdkRGBA *penRedShadow = NULL;
static GdkRGBA *penRedLight = NULL;
static int level[22] = { 0 };
static snd_ctl_elem_value_t *peaks;
extern int input_channels, output_channels, pcm_output_channels, spdif_channels, view_spdif_playback;
@ -50,19 +50,16 @@ static void get_levels(int idx, int *l1, int *l2)
}
}
static GdkGC *get_pen(int idx, int nRed, int nGreen, int nBlue)
static GdkRGBA *get_pen(int nRed, int nGreen, int nBlue)
{
GdkColor *c;
GdkGC *gc;
GdkRGBA *c;
c = (GdkColor *)g_malloc(sizeof(GdkColor));
c->red = nRed;
c->green = nGreen;
c->blue = nBlue;
gdk_color_alloc(gdk_colormap_get_system(), c);
gc = gdk_gc_new(pixmap[idx]);
gdk_gc_set_foreground(gc, c);
return gc;
c = (GdkRGBA *)g_malloc(sizeof(GdkRGBA));
c->red = nRed / 65535.0;
c->green = nGreen / 65535.0;
c->blue = nBlue / 65535.0;
c->alpha = 1.0;
return c;
}
static int get_index(const gchar *name)
@ -79,7 +76,7 @@ static int get_index(const gchar *name)
return result;
}
static void redraw_meters(int idx, int width, int height, int level1, int level2)
static void redraw_meters(int idx, int width, int height, int level1, int level2, cairo_t *cr)
{
int stereo = idx == 0;
int segment_width = stereo ? (width / 2) - 8 : width - 12;
@ -90,167 +87,156 @@ static void redraw_meters(int idx, int width, int height, int level1, int level2
int seg;
int segs_on1 = ((segments * level1) + 128) / 255;
int segs_on2 = ((segments * level2) + 128) / 255;
int end_seg;
GdkRectangle clip;
// g_print("segs_on1 = %i (%i), segs_on2 = %i (%i)\n", segs_on1, level1, segs_on2, level2);
for (seg = 0; seg < green_segments; seg++) {
gdk_draw_rectangle(pixmap[idx],
segs_on1 > 0 ? penGreenLight[idx] : penGreenShadow[idx],
TRUE,
6, 3 + ((segments - seg - 1) * 4),
segment_width,
3);
if (stereo)
gdk_draw_rectangle(pixmap[idx],
segs_on2 > 0 ? penGreenLight[idx] : penGreenShadow[idx],
TRUE,
2 + (width / 2),
3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
gdk_cairo_get_clip_rectangle(cr, &clip);
seg = segments - (clip.y + clip.height) / 4;
if (seg < 0)
seg = 0;
segs_on1 -= seg;
segs_on2 -= seg;
end_seg = segments - (clip.y - 2) / 4;
for (; seg < green_segments && seg < end_seg; seg++) {
gdk_cairo_set_source_rgba(cr,
segs_on1 > 0 ? penGreenLight : penGreenShadow);
cairo_rectangle(cr,
6, 3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_fill(cr);
if (stereo) {
gdk_cairo_set_source_rgba(cr,
segs_on2 > 0 ? penGreenLight : penGreenShadow);
cairo_rectangle(cr,
2 + (width / 2),
3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_fill(cr);
}
segs_on1--;
segs_on2--;
}
for (seg = green_segments; seg < green_segments + orange_segments; seg++) {
gdk_draw_rectangle(pixmap[idx],
segs_on1 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx],
TRUE,
6, 3 + ((segments - seg - 1) * 4),
segment_width,
3);
if (stereo)
gdk_draw_rectangle(pixmap[idx],
segs_on2 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx],
TRUE,
2 + (width / 2),
3 + ((segments - seg - 1) * 4),
segment_width,
3);
for (; seg < green_segments + orange_segments && seg < end_seg; seg++) {
gdk_cairo_set_source_rgba(cr,
segs_on1 > 0 ? penOrangeLight : penOrangeShadow);
cairo_rectangle(cr,
6, 3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_fill(cr);
if (stereo) {
gdk_cairo_set_source_rgba(cr,
segs_on2 > 0 ? penOrangeLight : penOrangeShadow);
cairo_rectangle(cr,
2 + (width / 2),
3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_fill(cr);
}
segs_on1--;
segs_on2--;
}
for (seg = green_segments + orange_segments; seg < segments; seg++) {
gdk_draw_rectangle(pixmap[idx],
segs_on1 > 0 ? penRedLight[idx] : penRedShadow[idx],
TRUE,
6, 3 + ((segments - seg - 1) * 4),
segment_width,
3);
if (stereo)
gdk_draw_rectangle(pixmap[idx],
segs_on2 > 0 ? penRedLight[idx] : penRedShadow[idx],
TRUE,
2 + (width / 2),
3 + ((segments - seg - 1) * 4),
segment_width,
3);
for (; seg < segments && seg < end_seg; seg++) {
gdk_cairo_set_source_rgba(cr,
segs_on1 > 0 ? penRedLight : penRedShadow);
cairo_rectangle(cr,
6, 3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_fill(cr);
if (stereo) {
gdk_cairo_set_source_rgba(cr,
segs_on2 > 0 ? penRedLight : penRedShadow);
cairo_rectangle(cr,
2 + (width / 2),
3 + ((segments - seg - 1) * 4),
segment_width,
3);
cairo_fill(cr);
}
segs_on1--;
segs_on2--;
}
}
gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event)
{
int idx = get_index(gtk_widget_get_name(widget));
if (pixmap[idx] != NULL)
gdk_pixmap_unref(pixmap[idx]);
pixmap[idx] = gdk_pixmap_new(widget->window,
widget->allocation.width,
widget->allocation.height,
-1);
penGreenShadow[idx] = get_pen(idx, 0, 0x77ff, 0);
penGreenLight[idx] = get_pen(idx, 0, 0xffff, 0);
penOrangeShadow[idx] = get_pen(idx, 0xddff, 0x55ff, 0);
penOrangeLight[idx] = get_pen(idx, 0xffff, 0x99ff, 0);
penRedShadow[idx] = get_pen(idx, 0xaaff, 0, 0);
penRedLight[idx] = get_pen(idx, 0xffff, 0, 0);
gdk_draw_rectangle(pixmap[idx],
widget->style->black_gc,
TRUE,
0, 0,
widget->allocation.width,
widget->allocation.height);
// g_print("configure: %i:%i\n", widget->allocation.width, widget->allocation.height);
redraw_meters(idx, widget->allocation.width, widget->allocation.height, 0, 0);
return TRUE;
}
gint level_meters_expose_event(GtkWidget *widget, GdkEventExpose *event)
gboolean level_meters_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data)
{
int idx = get_index(gtk_widget_get_name(widget));
int l1, l2;
get_levels(idx, &l1, &l2);
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
gdk_draw_pixmap(widget->window,
widget->style->black_gc,
pixmap[idx],
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
redraw_meters(idx, gtk_widget_get_allocated_width(widget), gtk_widget_get_allocated_height(widget), l1, l2, cr);
return FALSE;
}
static void update_meter(int idx)
{
int stereo = idx == 0;
GtkWidget *widget = stereo ? mixer_mix_drawing : mixer_drawing[idx - 1];
int width = gtk_widget_get_allocated_width(widget);
int height = gtk_widget_get_allocated_height(widget);
int segments = (height - 6) / 4;
int level_idx = stereo ? 20 : idx - 1;
int l1, l2, segs_on, old_segs_on, h;
get_levels(idx, &l1, &l2);
segs_on = ((segments * l1) + 128) / 255;
old_segs_on = ((segments * level[level_idx]) + 128) / 255;
h = abs(old_segs_on - segs_on);
level[level_idx] = l1;
if (h > 0) {
int y = segments - MAX(old_segs_on, segs_on);
gtk_widget_queue_draw_area(widget,
6, 4 * y + 3,
stereo ? (width / 2) - 8 : width - 12,
4 * h - 1);
}
if (stereo) {
level_idx++;
segs_on = ((segments * l2) + 128) / 255;
old_segs_on = ((segments * level[level_idx]) + 128) / 255;
h = abs(old_segs_on - segs_on);
level[level_idx] = l2;
if (h > 0) {
int y = segments - MAX(old_segs_on, segs_on);
gtk_widget_queue_draw_area(widget,
2 + (width / 2), 4 * y + 3,
(width / 2) - 8,
4 * h - 1);
}
}
}
gint level_meters_timeout_callback(gpointer data)
{
GtkWidget *widget;
int idx, l1, l2;
int idx;
update_peak_switch();
for (idx = 0; idx <= pcm_output_channels; idx++) {
get_levels(idx, &l1, &l2);
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
gdk_draw_pixmap(widget->window,
widget->style->black_gc,
pixmap[idx],
0, 0,
0, 0,
widget->allocation.width, widget->allocation.height);
}
update_meter(idx);
}
if (view_spdif_playback) {
for (idx = MAX_PCM_OUTPUT_CHANNELS + 1; idx <= MAX_OUTPUT_CHANNELS + spdif_channels; idx++) {
get_levels(idx, &l1, &l2);
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
gdk_draw_pixmap(widget->window,
widget->style->black_gc,
pixmap[idx],
0, 0,
0, 0,
widget->allocation.width, widget->allocation.height);
}
update_meter(idx);
}
}
for (idx = MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + 1; idx <= input_channels + MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS; idx++) {
get_levels(idx, &l1, &l2);
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
gdk_draw_pixmap(widget->window,
widget->style->black_gc,
pixmap[idx],
0, 0,
0, 0,
widget->allocation.width, widget->allocation.height);
}
update_meter(idx);
}
for (idx = MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + MAX_INPUT_CHANNELS + 1; \
idx <= spdif_channels + MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + MAX_INPUT_CHANNELS; idx++) {
get_levels(idx, &l1, &l2);
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
gdk_draw_pixmap(widget->window,
widget->style->black_gc,
pixmap[idx],
0, 0,
0, 0,
widget->allocation.width, widget->allocation.height);
}
update_meter(idx);
}
return TRUE;
}
@ -270,6 +256,13 @@ void level_meters_init(void)
/* older ALSA driver, using MIXER type */
snd_ctl_elem_value_set_interface(peaks,
SND_CTL_ELEM_IFACE_MIXER);
penGreenShadow = get_pen(0, 0x77ff, 0);
penGreenLight = get_pen(0, 0xffff, 0);
penOrangeShadow = get_pen(0xddff, 0x55ff, 0);
penOrangeLight = get_pen(0xffff, 0x99ff, 0);
penRedShadow = get_pen(0xaaff, 0, 0);
penRedLight = get_pen(0xffff, 0, 0);
}
void level_meters_postinit(void)