/*
* IceWM
*
* Copyright (C) 2005 Igor Stirbu
*
* Derived from aapm by Andreas Hinz and aclock by Marko Macek
*
* Sound mixer
*/
#define NEED_TIME_H
#include "config.h"
#include "amixer.h"
#ifdef CONFIG_APPLET_MIXER
#include "ylib.h"
#include "sysdep.h"
#include "aclock.h"
#include "yapp.h"
#include "prefs.h"
#include "intl.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/soundcard.h>
#include <errno.h>
#if USE_PIXMAP
int step;
#endif
YColor *YMixer::mixerBg = 0;
static YColor *taskBarBg = 0;
YMixer::YMixer(YWindow *aParent): YWindow(aParent) {
if (taskBarBg == 0) {
taskBarBg = new YColor(clrDefaultTaskBar);
}
#if USE_PIXMAP
init_pixmaps();
#endif
mixer_init();
muted = !mixer_read();
mixerTimer = new YTimer(500);
mixerTimer->setTimerListener(this);
mixerTimer->startTimer();
setSize(MIXER_WIDTH, 20);
updateToolTip();
}
#if USE_PIXMAP
int YMixer::init_pixmaps()
{
YResourcePaths const paths;
char const *base("mixer/");
YResourcePaths subdirs(paths, base);
subdirs.init(paths, base);
PixMute = subdirs.loadPixmap(base, "volume-mute.xpm");
PixMix[0] = subdirs.loadPixmap(base, "volume-zero.xpm");
PixMix[1] = subdirs.loadPixmap(base, "volume-min.xpm");
PixMix[2] = subdirs.loadPixmap(base, "volume-medium.xpm");
PixMix[3] = subdirs.loadPixmap(base, "volume-max.xpm");
PixMix[4] = PixMix[3];
step = 100/PIX_NUM;
return 0;
}
#endif
int YMixer::mixer_write(int height)
{
int value;
value = height | (height << 8);
if (ioctl(mixer_fd, SOUND_MIXER_WRITE_PCM, &value) == -1) {
fprintf(stderr, "Could not write volume\n");
}
return 0;
}
int YMixer::mixer_read()
{
int value;
if (ioctl(mixer_fd, SOUND_MIXER_READ_PCM, &value) == -1) {
fprintf(stderr, "Could not read volume\n");
}
return (value & 0xFF);
}
int YMixer::mixer_init()
{
mixer_fd = open(mixerDEV, 2, 0); // O_RDWR == 2
if (mixer_fd < 0) {
fprintf(stderr, "Could not open %s\n", mixerDEV);
}
return 0;
}
int YMixer::mixer_mute()
{
muted = 1;
muted_state = mixer_read();
return mixer_write(0);
}
int YMixer::mixer_unmute()
{
muted = 0;
return mixer_write(muted_state);
}
void YMixer::handleButton(const XButtonEvent &button) {
int val = mixer_read();
YWindow::handleButton(button);
if (button.type == ButtonPress) {
if (muted) {
if (val)
muted = 0;
if (button.button == 2) {
mixer_unmute();
}
} else {
if (button.button == 2) {
mixer_mute();
} else {
if (button.button == 4) {
if ((val += 5) > 100)
val = 100;
}
if (button.button == 5) {
if ((val -= 5) < 0)
val = 0;
}
mixer_write(val);
}
}
repaint();
}
}
YMixer::~YMixer() {
close(mixer_fd);
}
void YMixer::updateToolTip() {
char s[100];
if (muted) {
sprintf(s, "Volume: mute");
} else {
int vol;
vol = mixer_read();
sprintf(s, "Volume: %d", vol);
}
setToolTip(s);
}
void YMixer::paint(Graphics &g, const YRect &/*r*/) {
#if USE_PIXMAP
ref<YPixmap> pix;
#endif
// fill in the blank
g.setColor(taskBarBg);
g.fillRect(0, 0, width(), height());
#if USE_PIXMAP
if (muted) {
g.drawPixmap(PixMute, 0, 0);
} else {
int index = mixer_read();
index /= step;
pix = PixMix[index];
g.drawPixmap(pix, 0, 0);
}
#endif
}
bool YMixer::handleTimer(YTimer *t) {
if (t != mixerTimer) return false;
if (muted && mixer_read()) // reload settings if modified
muted = 0; // from elsewhere
if (toolTipVisible())
updateToolTip();
repaint();
return true;
}
#endif