Blame envy24control/levelmeters.c

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
}