// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
/*
   This file is part of the KDE project

   Copyright (c) 2003 Willi Richert <w.richert@gmx.net>
   Pretty much ripped off from :
	 George Staikos <staikos@kde.org> :)

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

*/

#include <kgenericfactory.h>
#include <kdebug.h>

#include <sys/types.h>
#include <unistd.h>

#include "generic_monitor.h"
#include "kmilointerface.h"
#include <qmessagebox.h>
#include <qfile.h>


// FIXME: use DCOPRef where possible instead of hand-rolled DCOP calls.

using namespace KMilo;

GenericMonitor::GenericMonitor(QObject *parent, const char *name, const QStringList& args)
: Monitor(parent, name, args)
{
	_poll = false;
	m_displayType = Monitor::None;

	m_mute = false;
	m_progress = 0;
	m_minVolume = 0;
	m_maxVolume = 100;
	m_volume = 50;
}

GenericMonitor::~GenericMonitor()
{
}

bool GenericMonitor::init()
{
	static const ShortcutInfo shortcuts[] = {
		{ "FastVolumeUp", Qt::Key_VolumeUp, SLOT(fastVolumeUp()) },
		{ "FastVolumeDown", Qt::Key_VolumeDown, SLOT(fastVolumeDown()) },
		{ "SlowVolumeUp", Qt::CTRL+Qt::Key_VolumeUp, SLOT(slowVolumeUp()) },
		{ "SlowVolumeDown", Qt::CTRL+Qt::Key_VolumeDown, SLOT(slowVolumeDown()) },
		{ "Mute", KShortcut("XF86AudioMute"), SLOT(mute()) }
	};

	ga = new KGlobalAccel(this, "miloGenericAccel");

	ShortcutInfo si;
	int len = (int)sizeof(shortcuts)/sizeof(ShortcutInfo);
	for (int i = 0; i < len; i++) {
		si = shortcuts[i];

		ga->insert(si.name, QString::null, QString::null,
							 si.symbol, si.symbol,
							 this,
							 si.slot, false);
	}

	ga->readSettings();
	ga->updateConnections();

	kmixClient = new DCOPRef("kmix", "Mixer0");
	kmixWindow = new DCOPRef("kmix", "kmix-mainwindow#1");

	return true;
}

bool GenericMonitor::retrieveVolume() 
{
	bool kmix_error = false;

	DCOPReply reply = kmixClient->call("volume", 0);
	if (reply.isValid())
		m_volume = reply;
	else
		kmix_error = true;

	if (kmix_error) // maybe the error occurred because kmix wasn't running
	{
		_interface->displayText(i18n("Starting KMix..."));
		if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix
		{
			// trying again
			reply = kmixClient->call("volume", 0);
			if (reply.isValid()) 
			{
				m_volume = reply;
				kmix_error = false;
				kmixWindow->send("minimize");
			}
		}
	}
		
	if (kmix_error)
	{
		kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" 
							<< endl;
		_interface->displayText(i18n("It seems that KMix is not running."));
		
		return false;
	} else {
		return true;
	}
}

void GenericMonitor::volumeUp(int step) 
{	
	if (!retrieveVolume())
		return;

	// FIXME if the mixer doesn't support steps of the specified size it
	// could get stuck at one position
	m_volume += step;
	if (m_volume > m_maxVolume)
		m_volume = m_maxVolume;

	displayVolume();
}

void GenericMonitor::volumeDown(int step)
{
	if (!retrieveVolume())
		return;

	m_volume -= step;
	if (m_volume < m_minVolume)
		m_volume = m_minVolume;
							 
	displayVolume();
}

void GenericMonitor::slowVolumeUp() {	volumeUp(1); }
void GenericMonitor::slowVolumeDown() {	volumeDown(1); }
void GenericMonitor::fastVolumeUp() {	volumeUp(10); }
void GenericMonitor::fastVolumeDown() {	volumeDown(10); }

void GenericMonitor::displayVolume()
{
	_interface->displayProgress(i18n("Volume"), m_volume);

	// If we got this far, the DCOP communication with kmix works,
  // so we don't have to test the result.
	kmixClient->send("setVolume", 0, m_volume);

	// if mute then unmute
	if (m_mute)
	{
		m_mute = false;
		kmixClient->send("setMute",  0, m_mute);
	}
}

bool GenericMonitor::retrieveMute() 
{
	bool kmix_error = false;

	DCOPReply reply = kmixClient->call("mute", 0);
	if (reply.isValid())
		m_volume = reply;
	else
		kmix_error = true;

	if (kmix_error)
	{
		// maybe the error occurred because kmix wasn't running
		_interface->displayText(i18n("Starting KMix..."));
		if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix
		{
			// trying again
			reply = kmixClient->call("mute", 0);
			if (reply.isValid()) 
			{
				m_mute = reply;
				kmix_error = false;
				kmixWindow->send("minimize");
			}
		}	else 
		{
			kmixWindow->send("minimize");
			kmix_error = true;
		}
	}

	if (kmix_error)
	{
		kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" 
							<< endl;
		_interface->displayText(i18n("It seems that KMix is not running."));
		
		return false;
	} else {
		return true;
	}
}

void GenericMonitor::mute() 
{
	if (!retrieveMute())
		return;

	m_mute = !m_mute;
	int newVolume;
	QString muteText;
	if (m_mute)
	{
		m_oldVolume = m_volume;
		newVolume = 0;
		muteText = i18n("Mute on");
	} else {
		newVolume = m_oldVolume;
		muteText = i18n("Mute off");
	}

	kmixClient->send("setMute",  0, m_mute);

	_interface->displayText(muteText);
}

int GenericMonitor::progress() const 
{
	return m_progress;
}

Monitor::DisplayType GenericMonitor::poll() 
{
	return m_displayType;
}


K_EXPORT_COMPONENT_FACTORY(kmilo_generic, KGenericFactory<GenericMonitor>("kmilo_generic"))

#include "generic_monitor.moc"
