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