// -*- c++ -*-
/***************************************************************************
                           volumecontroller.cpp
                           --------------------
    begin                : Sun May 9 2004
    copyright            : (C) 2004 by Dirk Ziegelmeier
    email                : dziegel@gmx.de
 ***************************************************************************/

/*
 * 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., 51 Franklin Steet, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <qtimer.h>

#include <kdebug.h>

#include "volumecontroller.h"
#include "sourcemanager.h"
#include "audiomanager.h"

VolumeController::VolumeController(AudioManager* am, SourceManager* srcm,
                                   bool preferAudioManager, int amVol, int srcmVol,
                                   QObject* parent, const char* name)
    : QObject(parent, name),
      _am(am),
      _srcm(srcm),
      _preferAudioManager(preferAudioManager),
      _amVol(amVol),
      _srcmVol(srcmVol),
      _pre(100),
      _post(100),
      _left(0),
      _right(0),
      _muted(true)
{
    _preTimer  = new QTimer(this, "PreTimer");
    connect(_preTimer, SIGNAL( timeout() ),
            this,      SLOT( preTimerExpired() ));

    _postTimer = new QTimer(this, "PostTimer");
    connect(_postTimer, SIGNAL( timeout() ),
            this,       SLOT( applyVolumeSettings() ));

    connect(_srcm, SIGNAL( deviceChanged(const QString&) ),
            this, SLOT( applyVolumeSettings() ));

    connect(_am, SIGNAL( mixerAvailable(bool) ),
            this, SLOT( applyVolumeSettings() ));
}

VolumeController::~VolumeController()
{
    delete _preTimer;
    delete _postTimer;
}

void VolumeController::setConfig(bool preferAudioManager, int amVol, int srcmVol)
{
    _preferAudioManager = preferAudioManager;
    _amVol              = amVol;
    _srcmVol            = srcmVol;
}

void VolumeController::volumeUp(int step)
{
    setVolume(QMIN(_left+step, 100), QMIN(_right+step, 100));
}

void VolumeController::volumeDown(int step)
{
    setVolume(QMAX(_left-step, 0), QMAX(_right-step, 0));
}

void VolumeController::setVolume(int left, int right)
{
    static bool inhibitRecursion = false;

    if(!inhibitRecursion) {
        inhibitRecursion = true;
        if( (_left != left) || (_right != right) ) {
            emit volumeChanged(left, right);
            emit volumeChanged((left+right)/2);
        }
        _left  = left;
        _right = right;
        
        if(!_preTimer->isActive() && !_postTimer->isActive()) {
            if(_muted) {
                mute(false);
            } else {
                doSetVolume(_left, _right);
            }
        }
        inhibitRecursion = false;
    }
}

void VolumeController::mute(bool mute)
{
    if(mute != _muted) {
        emit muted(mute);
    }
    _muted = mute;

    if(!_preTimer->isActive() && !_postTimer->isActive()) {
        doMute(_muted);
        if(!_muted) {
            doSetVolume(_left, _right);
        }
    }
}

void VolumeController::toggleMute()
{
    mute(!_muted);
}

void VolumeController::prepareChannelChange()
{
    if(_postTimer->isActive()) {
        emit setChannel();
        _postTimer->start(_pre, true);
    } else if(!_preTimer->isActive()) {
        doMute(true);
        _preTimer->start(_pre, true);
    }
}

void VolumeController::preTimerExpired()
{
    emit setChannel();
    _postTimer->start(_pre, true);
}

void VolumeController::applyVolumeSettings()
{
    doMute(_muted);
    if(!_muted) {
        doSetVolume(_left, _right);
    }
}

void VolumeController::doSetVolume(int left, int right)
{
    if(_preferAudioManager) {
        if(_am->setVolume(left, right) == 0) {
            _srcm->setVolume(_srcmVol, _srcmVol);
        } else {
            // Audiomanager didn't work, try SourceManager
            kdWarning() << "VolumeController::doSetVolume: AudioManager failed, trying SourceManager" << endl;
            _srcm->setVolume(left, right);
        }
    } else {
        if(_srcm->setVolume(left, right)) {
            _am->setVolume(_amVol, _amVol);
        } else {
            // Sourcemanager didn't work, try Audiomanager
            kdWarning() << "VolumeController::doSetVolume: SourceManager failed, trying AudioManager" << endl;
            _am->setVolume(left, right);
        }
    }
}

void VolumeController::doMute(bool mute)
{
    _srcm->setMuted(mute);
    _am->setMuted(mute);
}

void VolumeController::setTiming(unsigned int pre, unsigned int post)
{
    _pre  = pre;
    _post = post;
}

#include "volumecontroller.moc"

// vim: sw=4 ts=4 noet
