#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include <qapplication.h>

#ifdef QTOPIA
#include <qpe/config.h>
#include <qpe/qcopenvelope_qws.h>
#endif

#ifdef __linux__
#include <linux/soundcard.h>
#endif

#include "system_volume.h"

SystemVolume & SystemVolume::singleton()
{
	static SystemVolume instance;
	return instance;
}

SystemVolume::SystemVolume()
	: 	internalVolume_(100),
		useInternalVolume_(false)
{
#ifndef __linux__
	useInternalVolume_ = true;
#endif
}

SystemVolume::~SystemVolume()
{
}

bool SystemVolume::setLevel(int level, bool publish)
{
#ifdef __linux__
	if (!useInternalVolume_)
	{
		int iDevice, isetlv = (level + (level << 8));
		
		// Set value
		if ((iDevice = open("/dev/mixer", O_RDONLY)) == -1) {
			qDebug("Could not open the mixer device.\n");
			return false;
		}
	
		if (ioctl(iDevice, MIXER_WRITE(0), &isetlv) == -1) {
			close(iDevice);
			qDebug("Could not set the volume.\n");
			return false;
		}
		
	#ifdef QTOPIA
		// Update applet
		if (publish)
		{
			QCopEnvelope e("QPE/System", "volumeChange(bool)");
			e << FALSE;
		}
	#endif
		
		close(iDevice);
	}
	else
#endif
	{
		internalVolume_ = level;
		emit levelChanged(level);
	}
	
	return true;	
}

int SystemVolume::getCurrentLevel()
{
#ifdef __linux__
	if (!useInternalVolume_)
	{
		int iDevice;
	
		// Set value
		if ((iDevice = open("/dev/mixer", O_RDONLY)) == -1) {
			qDebug("Could not open the mixer device, trying QPE directly instead.\n");
	
	#ifdef QTOPIA		
			Config cfg("qpe");
			cfg.setGroup("Volume");
			return cfg.readNumEntry("VolumePercent", 0);
	#else
			return 100;
	#endif		
		}
	
		int level = 0;
		if (ioctl(iDevice, MIXER_READ(0), &level) == -1) {
			qDebug("Could not read the volume.\n");
		}
		close(iDevice);
		
		return level >> 8;
	}
	else
#endif
		return internalVolume_;
}

