/*
 * 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
