|
Packit |
427e91 |
/*****************************************************************************
|
|
Packit |
427e91 |
levelmeters.c - Stereo level meters
|
|
Packit |
427e91 |
Copyright (C) 2000 by Jaroslav Kysela <perex@perex.cz>
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
This program is free software; you can redistribute it and/or
|
|
Packit |
427e91 |
modify it under the terms of the GNU General Public License
|
|
Packit |
427e91 |
as published by the Free Software Foundation; either version 2
|
|
Packit |
427e91 |
of the License, or (at your option) any later version.
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
427e91 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
427e91 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
427e91 |
GNU General Public License for more details.
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
You should have received a copy of the GNU General Public License
|
|
Packit |
427e91 |
along with this program; if not, write to the Free Software
|
|
Packit |
427e91 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
427e91 |
******************************************************************************/
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
#include "envy24control.h"
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
static GdkGC *penGreenShadow[21] = { NULL, };
|
|
Packit |
427e91 |
static GdkGC *penGreenLight[21] = { NULL, };
|
|
Packit |
427e91 |
static GdkGC *penOrangeShadow[21] = { NULL, };
|
|
Packit |
427e91 |
static GdkGC *penOrangeLight[21] = { NULL, };
|
|
Packit |
427e91 |
static GdkGC *penRedShadow[21] = { NULL, };
|
|
Packit |
427e91 |
static GdkGC *penRedLight[21] = { NULL, };
|
|
Packit |
427e91 |
static GdkPixmap *pixmap[21] = { NULL, };
|
|
Packit |
427e91 |
static snd_ctl_elem_value_t *peaks;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
extern int input_channels, output_channels, pcm_output_channels, spdif_channels, view_spdif_playback;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
static void update_peak_switch(void)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
int err;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
if ((err = snd_ctl_elem_read(ctl, peaks)) < 0)
|
|
Packit |
427e91 |
g_print("Unable to read peaks: %s\n", snd_strerror(err));
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
static void get_levels(int idx, int *l1, int *l2)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
*l1 = *l2 = 0;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
if (idx == 0) {
|
|
Packit |
427e91 |
*l1 = snd_ctl_elem_value_get_integer(peaks, 20);
|
|
Packit |
427e91 |
*l2 = snd_ctl_elem_value_get_integer(peaks, 21);
|
|
Packit |
427e91 |
} else {
|
|
Packit |
427e91 |
*l1 = *l2 = snd_ctl_elem_value_get_integer(peaks, idx - 1);
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
static GdkGC *get_pen(int idx, int nRed, int nGreen, int nBlue)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
GdkColor *c;
|
|
Packit |
427e91 |
GdkGC *gc;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
c = (GdkColor *)g_malloc(sizeof(GdkColor));
|
|
Packit |
427e91 |
c->red = nRed;
|
|
Packit |
427e91 |
c->green = nGreen;
|
|
Packit |
427e91 |
c->blue = nBlue;
|
|
Packit |
427e91 |
gdk_color_alloc(gdk_colormap_get_system(), c);
|
|
Packit |
427e91 |
gc = gdk_gc_new(pixmap[idx]);
|
|
Packit |
427e91 |
gdk_gc_set_foreground(gc, c);
|
|
Packit |
427e91 |
return gc;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
static int get_index(gchar *name)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
int result;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
if (!strcmp(name, "DigitalMixer"))
|
|
Packit |
427e91 |
return 0;
|
|
Packit |
427e91 |
result = atoi(name + 5);
|
|
Packit |
427e91 |
if (result < 1 || result > 20) {
|
|
Packit |
427e91 |
g_print("Wrong drawing area ID: %s\n", name);
|
|
Packit |
427e91 |
gtk_main_quit();
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
return result;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
static void redraw_meters(int idx, int width, int height, int level1, int level2)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
int stereo = idx == 0;
|
|
Packit |
427e91 |
int segment_width = stereo ? (width / 2) - 8 : width - 12;
|
|
Packit |
427e91 |
int segments = (height - 6) / 4;
|
|
Packit |
427e91 |
int green_segments = (segments / 4) * 3;
|
|
Packit |
427e91 |
int red_segments = 2;
|
|
Packit |
427e91 |
int orange_segments = segments - green_segments - red_segments;
|
|
Packit |
427e91 |
int seg;
|
|
Packit |
427e91 |
int segs_on1 = ((segments * level1) + 128) / 255;
|
|
Packit |
427e91 |
int segs_on2 = ((segments * level2) + 128) / 255;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
// g_print("segs_on1 = %i (%i), segs_on2 = %i (%i)\n", segs_on1, level1, segs_on2, level2);
|
|
Packit |
427e91 |
for (seg = 0; seg < green_segments; seg++) {
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
segs_on1 > 0 ? penGreenLight[idx] : penGreenShadow[idx],
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
6, 3 + ((segments - seg - 1) * 4),
|
|
Packit |
427e91 |
segment_width,
|
|
Packit |
427e91 |
3);
|
|
Packit |
427e91 |
if (stereo)
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
segs_on2 > 0 ? penGreenLight[idx] : penGreenShadow[idx],
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
2 + (width / 2),
|
|
Packit |
427e91 |
3 + ((segments - seg - 1) * 4),
|
|
Packit |
427e91 |
segment_width,
|
|
Packit |
427e91 |
3);
|
|
Packit |
427e91 |
segs_on1--;
|
|
Packit |
427e91 |
segs_on2--;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
for (seg = green_segments; seg < green_segments + orange_segments; seg++) {
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
segs_on1 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx],
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
6, 3 + ((segments - seg - 1) * 4),
|
|
Packit |
427e91 |
segment_width,
|
|
Packit |
427e91 |
3);
|
|
Packit |
427e91 |
if (stereo)
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
segs_on2 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx],
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
2 + (width / 2),
|
|
Packit |
427e91 |
3 + ((segments - seg - 1) * 4),
|
|
Packit |
427e91 |
segment_width,
|
|
Packit |
427e91 |
3);
|
|
Packit |
427e91 |
segs_on1--;
|
|
Packit |
427e91 |
segs_on2--;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
for (seg = green_segments + orange_segments; seg < segments; seg++) {
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
segs_on1 > 0 ? penRedLight[idx] : penRedShadow[idx],
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
6, 3 + ((segments - seg - 1) * 4),
|
|
Packit |
427e91 |
segment_width,
|
|
Packit |
427e91 |
3);
|
|
Packit |
427e91 |
if (stereo)
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
segs_on2 > 0 ? penRedLight[idx] : penRedShadow[idx],
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
2 + (width / 2),
|
|
Packit |
427e91 |
3 + ((segments - seg - 1) * 4),
|
|
Packit |
427e91 |
segment_width,
|
|
Packit |
427e91 |
3);
|
|
Packit |
427e91 |
segs_on1--;
|
|
Packit |
427e91 |
segs_on2--;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
int idx = get_index(gtk_widget_get_name(widget));
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
if (pixmap[idx] != NULL)
|
|
Packit |
427e91 |
gdk_pixmap_unref(pixmap[idx]);
|
|
Packit |
427e91 |
pixmap[idx] = gdk_pixmap_new(widget->window,
|
|
Packit |
427e91 |
widget->allocation.width,
|
|
Packit |
427e91 |
widget->allocation.height,
|
|
Packit |
427e91 |
-1);
|
|
Packit |
427e91 |
penGreenShadow[idx] = get_pen(idx, 0, 0x77ff, 0);
|
|
Packit |
427e91 |
penGreenLight[idx] = get_pen(idx, 0, 0xffff, 0);
|
|
Packit |
427e91 |
penOrangeShadow[idx] = get_pen(idx, 0xddff, 0x55ff, 0);
|
|
Packit |
427e91 |
penOrangeLight[idx] = get_pen(idx, 0xffff, 0x99ff, 0);
|
|
Packit |
427e91 |
penRedShadow[idx] = get_pen(idx, 0xaaff, 0, 0);
|
|
Packit |
427e91 |
penRedLight[idx] = get_pen(idx, 0xffff, 0, 0);
|
|
Packit |
427e91 |
gdk_draw_rectangle(pixmap[idx],
|
|
Packit |
427e91 |
widget->style->black_gc,
|
|
Packit |
427e91 |
TRUE,
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
widget->allocation.width,
|
|
Packit |
427e91 |
widget->allocation.height);
|
|
Packit |
427e91 |
// g_print("configure: %i:%i\n", widget->allocation.width, widget->allocation.height);
|
|
Packit |
427e91 |
redraw_meters(idx, widget->allocation.width, widget->allocation.height, 0, 0);
|
|
Packit |
427e91 |
return TRUE;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
gint level_meters_expose_event(GtkWidget *widget, GdkEventExpose *event)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
int idx = get_index(gtk_widget_get_name(widget));
|
|
Packit |
427e91 |
int l1, l2;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
get_levels(idx, &l1, &l2;;
|
|
Packit |
427e91 |
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
|
|
Packit |
427e91 |
gdk_draw_pixmap(widget->window,
|
|
Packit |
427e91 |
widget->style->black_gc,
|
|
Packit |
427e91 |
pixmap[idx],
|
|
Packit |
427e91 |
event->area.x, event->area.y,
|
|
Packit |
427e91 |
event->area.x, event->area.y,
|
|
Packit |
427e91 |
event->area.width, event->area.height);
|
|
Packit |
427e91 |
return FALSE;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
gint level_meters_timeout_callback(gpointer data)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
GtkWidget *widget;
|
|
Packit |
427e91 |
int idx, l1, l2;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
update_peak_switch();
|
|
Packit |
427e91 |
for (idx = 0; idx <= pcm_output_channels; idx++) {
|
|
Packit |
427e91 |
get_levels(idx, &l1, &l2;;
|
|
Packit |
427e91 |
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
|
|
Packit |
427e91 |
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
|
|
Packit |
427e91 |
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
|
|
Packit |
427e91 |
gdk_draw_pixmap(widget->window,
|
|
Packit |
427e91 |
widget->style->black_gc,
|
|
Packit |
427e91 |
pixmap[idx],
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
widget->allocation.width, widget->allocation.height);
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
if (view_spdif_playback) {
|
|
Packit |
427e91 |
for (idx = MAX_PCM_OUTPUT_CHANNELS + 1; idx <= MAX_OUTPUT_CHANNELS + spdif_channels; idx++) {
|
|
Packit |
427e91 |
get_levels(idx, &l1, &l2;;
|
|
Packit |
427e91 |
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
|
|
Packit |
427e91 |
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
|
|
Packit |
427e91 |
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
|
|
Packit |
427e91 |
gdk_draw_pixmap(widget->window,
|
|
Packit |
427e91 |
widget->style->black_gc,
|
|
Packit |
427e91 |
pixmap[idx],
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
widget->allocation.width, widget->allocation.height);
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
for (idx = MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + 1; idx <= input_channels + MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS; idx++) {
|
|
Packit |
427e91 |
get_levels(idx, &l1, &l2;;
|
|
Packit |
427e91 |
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
|
|
Packit |
427e91 |
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
|
|
Packit |
427e91 |
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
|
|
Packit |
427e91 |
gdk_draw_pixmap(widget->window,
|
|
Packit |
427e91 |
widget->style->black_gc,
|
|
Packit |
427e91 |
pixmap[idx],
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
widget->allocation.width, widget->allocation.height);
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
for (idx = MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + MAX_INPUT_CHANNELS + 1; \
|
|
Packit |
427e91 |
idx <= spdif_channels + MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + MAX_INPUT_CHANNELS; idx++) {
|
|
Packit |
427e91 |
get_levels(idx, &l1, &l2;;
|
|
Packit |
427e91 |
widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1];
|
|
Packit |
427e91 |
if (GTK_WIDGET_VISIBLE(widget) && (pixmap[idx] != NULL)) {
|
|
Packit |
427e91 |
redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2);
|
|
Packit |
427e91 |
gdk_draw_pixmap(widget->window,
|
|
Packit |
427e91 |
widget->style->black_gc,
|
|
Packit |
427e91 |
pixmap[idx],
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
0, 0,
|
|
Packit |
427e91 |
widget->allocation.width, widget->allocation.height);
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
return TRUE;
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
void level_meters_reset_peaks(GtkButton *button, gpointer data)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
void level_meters_init(void)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
int err;
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
snd_ctl_elem_value_malloc(&peaks);
|
|
Packit |
427e91 |
snd_ctl_elem_value_set_interface(peaks, SND_CTL_ELEM_IFACE_PCM);
|
|
Packit |
427e91 |
snd_ctl_elem_value_set_name(peaks, "Multi Track Peak");
|
|
Packit |
427e91 |
if ((err = snd_ctl_elem_read(ctl, peaks)) < 0)
|
|
Packit |
427e91 |
/* older ALSA driver, using MIXER type */
|
|
Packit |
427e91 |
snd_ctl_elem_value_set_interface(peaks,
|
|
Packit |
427e91 |
SND_CTL_ELEM_IFACE_MIXER);
|
|
Packit |
427e91 |
}
|
|
Packit |
427e91 |
|
|
Packit |
427e91 |
void level_meters_postinit(void)
|
|
Packit |
427e91 |
{
|
|
Packit |
427e91 |
level_meters_timeout_callback(NULL);
|
|
Packit |
427e91 |
}
|