e16-epplets/epplets/Emix.c

191 lines
4.4 KiB
C

/*
Emix - A small audio mixer Epplet
Roberto Machorro <rmach@bigfoot.com>
This is a GPL Licensed program, you know the deal.
*/
#include "config.h"
#include "epplet.h"
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef __FreeBSD__
#include <machine/soundcard.h>
#else
#include <sys/soundcard.h>
#endif
static Epplet_gadget vs_master, vs_pcm, vs_lin, vs_cda, b_close, b_help;
#define MIXER_DEV "/dev/mixer"
#if 0
#define debug
#endif
typedef struct {
int id;
int value;
} MIX_CHANNEL;
static int fd_mixer = 0;
static int msk_mixerdevs = 0;
static MIX_CHANNEL channels[4];
static int mute_status = 0;
static Epplet_gadget b_mute;
static void
cb_close(void *data __UNUSED__)
{
Epplet_unremember();
close(fd_mixer);
Esync();
exit(0);
}
static void
cb_help(void *data __UNUSED__)
{
Epplet_show_about("Emix");
}
static void
toggle_mute(void *data)
{
unsigned char lrvl[4];
MIX_CHANNEL *dev = (MIX_CHANNEL *) data;
if (mute_status)
{
lrvl[0] = lrvl[1] = 0;
}
else
{
lrvl[0] = (20 - (unsigned char)dev->value) * 5;
lrvl[1] = lrvl[0];
}
lrvl[2] = lrvl[3] = 0;
ioctl(fd_mixer, MIXER_WRITE(dev->id), lrvl);
}
static int
open_mixer(void)
{
if ((fd_mixer = open(MIXER_DEV, O_RDWR)) < 0)
{
fprintf(stderr, "Mixer device (%s) open failed.\n", MIXER_DEV);
return 0;
}
if (ioctl(fd_mixer, SOUND_MIXER_READ_DEVMASK, &msk_mixerdevs) == -1)
{
fprintf(stderr, "Mixer device (%s) mask read failed.\n", MIXER_DEV);
return 0;
}
return 1;
}
static int
read_volume(int channel)
{
unsigned char lrvl[4];
if (ioctl(fd_mixer, MIXER_READ(channels[channel].id), lrvl) == -1)
{
#ifdef debug
fprintf(stderr, "Error reading volume for channel #%d\n", channel);
#endif
return 0;
}
channels[channel].value = (100 - (lrvl[0] + lrvl[1]) / 2) / 5;
return channels[channel].value;
}
static void
set_volume(void *data __UNUSED__)
{
unsigned char lrvl[4];
MIX_CHANNEL *dev = (MIX_CHANNEL *) data;
if (mute_status)
{
mute_status = 0;
toggle_mute(&channels[0]);
Epplet_gadget_data_changed(b_mute);
}
lrvl[0] = (20 - (unsigned char)dev->value) * 5;
lrvl[1] = lrvl[0];
lrvl[2] = lrvl[3] = 0;
ioctl(fd_mixer, MIXER_WRITE(dev->id), lrvl);
}
static void
initialize_channels(void)
{
channels[0].id = SOUND_MIXER_VOLUME;
channels[0].value = read_volume(0);
channels[1].id = SOUND_MIXER_SYNTH;
channels[1].value = read_volume(1);
channels[2].id = SOUND_MIXER_PCM;
channels[2].value = read_volume(2);
channels[3].id = SOUND_MIXER_LINE;
channels[3].value = read_volume(3);
}
/* callback_function to update the volumes with a timer */
static void
update_volumes_callback(void *data __UNUSED__)
{
channels[0].value = read_volume(0);
channels[1].value = read_volume(1);
channels[2].value = read_volume(2);
channels[3].value = read_volume(3);
Epplet_gadget_data_changed(vs_master);
Epplet_gadget_data_changed(vs_pcm);
Epplet_gadget_data_changed(vs_lin);
Epplet_gadget_data_changed(vs_cda);
Epplet_timer(update_volumes_callback, NULL, 0.5, "TIMER");
}
int
main(int argc, char *argv[])
{
if (!open_mixer())
return 1;
initialize_channels();
atexit(Epplet_cleanup);
Epplet_Init("Emix", "0.9", "Audio mixer Epplet", 3, 3, argc, argv, 0);
vs_master = Epplet_create_vslider(2, 2, 44, 0, 20, 1, 5,
&channels[0].value, set_volume,
&channels[0]);
vs_pcm =
Epplet_create_vslider(10, 2, 44, 0, 20, 1, 5, &channels[1].value,
set_volume, &channels[1]);
vs_lin =
Epplet_create_vslider(18, 2, 44, 0, 20, 1, 5, &channels[2].value,
set_volume, &channels[2]);
vs_cda =
Epplet_create_vslider(26, 2, 44, 0, 20, 1, 5, &channels[3].value,
set_volume, &channels[3]);
b_close =
Epplet_create_button(NULL, NULL, 34, 3, 0, 0, "CLOSE", 0, NULL, cb_close,
NULL);
b_mute =
Epplet_create_togglebutton("M", NULL, 34, 18, 12, 12, &mute_status,
toggle_mute, &channels[0]);
b_help =
Epplet_create_button(NULL, NULL, 34, 33, 0, 0, "HELP", 0, NULL, cb_help,
NULL);
Epplet_gadget_show(vs_master);
Epplet_gadget_show(vs_pcm);
Epplet_gadget_show(vs_lin);
Epplet_gadget_show(vs_cda);
Epplet_gadget_show(b_close);
Epplet_gadget_show(b_mute);
Epplet_gadget_show(b_help);
Epplet_show();
Epplet_timer(update_volumes_callback, NULL, 0.5, "TIMER");
Epplet_Loop();
return 0;
}