/*  This file is part of the KDE project.

    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2.1 or 3 of the License.

    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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#import <QTKit/QTMovie.h>

#include "mediaobjectaudionode.h"
#include "quicktimeaudioplayer.h"
#include "quicktimevideoplayer.h"
#include "audiomixer.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace QT7
{

MediaObjectAudioNode::MediaObjectAudioNode(QuickTimeAudioPlayer *player1, QuickTimeAudioPlayer *player2) : AudioNode(0, 1)
{
    m_mute = false;
    m_player1 = player1;
    m_player2 = player2;
    m_mixer = new AudioMixerAudioNode();

    m_connection1 = new AudioConnection(m_player1, 0, m_mixer, 0);
    m_connection2 = new AudioConnection(m_player2, 0, m_mixer, 1);

    m_fadeDuration = 0;
}

MediaObjectAudioNode::~MediaObjectAudioNode()
{
    setGraph(0);
    delete m_player1;
    delete m_player2;
    delete m_mixer;
    delete m_connection1;
    delete m_connection2;
}

void MediaObjectAudioNode::createAndConnectAUNodes()
{
    DEBUG_AUDIO_GRAPH("(MediaObjectAudioNode" << int(this) << "createAndConnectAUNodes called)" )
    m_player1->createAndConnectAUNodes();
    m_player2->createAndConnectAUNodes();
    m_mixer->createAndConnectAUNodes();

    m_connection1->connect(m_audioGraph);
    m_connection2->connect(m_audioGraph);
}

void MediaObjectAudioNode::createAudioUnits()
{
    DEBUG_AUDIO_GRAPH("(MediaObjectAudioNode" << int(this) << "createAudioUnits called)" )
    m_player1->createAudioUnits();
    m_player2->createAudioUnits();
    m_mixer->createAudioUnits();
}

void MediaObjectAudioNode::setGraph(AudioGraph *audioGraph)
{
    DEBUG_AUDIO_GRAPH("MediaObjectAudioNode" << int(this) << "is setting graph:" << int(audioGraph))
    m_audioGraph = audioGraph;
    m_player1->setGraph(audioGraph);
    m_player2->setGraph(audioGraph);
    m_mixer->setGraph(audioGraph);
}

AUNode MediaObjectAudioNode::getOutputAUNode()
{
    return m_mixer->getOutputAUNode();
}

bool MediaObjectAudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
{
    if (side == Source){
        DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "fillInStreamSpecification called, role = source)")
        return m_mixer->fillInStreamSpecification(connection, side);
    } else {
        DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "fillInStreamSpecification called, role = sink)")
        return (m_connection2->updateStreamSpecification() && m_connection1->updateStreamSpecification());
    }
}

bool MediaObjectAudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side)
{
    if (side == Source){
        DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "setStreamSpecification called, role = source)")
        return m_mixer->setStreamSpecification(connection, side);
    }
    return true;
}

void MediaObjectAudioNode::setMute(bool mute)
{
    m_mute = mute;
    m_mixer->setVolume(m_mute ? 0 : m_volume1, m_connection1->m_sinkInputBus);
    m_mixer->setVolume(m_mute ? 0 : m_volume2, m_connection2->m_sinkInputBus);
}

void MediaObjectAudioNode::updateVolume()
{
    if (m_mute)
        return;
        
    QuickTimeVideoPlayer *player1 = static_cast<QuickTimeAudioPlayer *>(m_connection1->m_sourceAudioNode)->videoPlayer();
    QuickTimeVideoPlayer *player2 = static_cast<QuickTimeAudioPlayer *>(m_connection2->m_sourceAudioNode)->videoPlayer();
    if (player1)
        player1->setRelativeVolume(m_volume1);
    if (player2)
        player2->setRelativeVolume(m_volume2);

    m_mixer->setVolume(m_volume1, m_connection1->m_sinkInputBus);
    m_mixer->setVolume(m_volume2, m_connection2->m_sinkInputBus);
}

void MediaObjectAudioNode::startCrossFade(qint64 duration)
{
    m_fadeDuration = duration;

    // Swap:
    AudioConnection *tmp = m_connection1;
    m_connection1 = m_connection2;
    m_connection2 = tmp;

    // Init volume:
    if (m_fadeDuration > 0){
        m_volume1 = 0;
        m_volume2 = 1;
    } else {
        m_volume1 = 1;
        m_volume2 = 0;
    }
    updateVolume();
}

float MediaObjectAudioNode::applyCurve(float volume)
{
    float newValue = 0;
    if (volume > 0)
        newValue = float(0.5f * (2 + log10(volume)));
    return newValue;
}

void MediaObjectAudioNode::updateCrossFade(qint64 currentTime)
{
    // Assume that currentTime starts at 0 and progress.
    if (m_fadeDuration > 0){
        float volume = float(currentTime) / float(m_fadeDuration);
        if (volume >= 1){
            volume = 1;
            m_fadeDuration = 0;
        }
        m_volume1 = applyCurve(volume);
        m_volume2 = 1 - volume;
        updateVolume();
    }
}

bool MediaObjectAudioNode::isCrossFading()
{
    return (m_fadeDuration > 0);
}

void MediaObjectAudioNode::cancelCrossFade()
{
    m_fadeDuration = 0;
    m_volume1 = 1;
    m_volume2 = 0;
    updateVolume();
}

void MediaObjectAudioNode::mediaNodeEvent(const MediaNodeEvent *event)
{
    switch (event->type()){
    case MediaNodeEvent::AudioGraphAboutToBeDeleted:
        m_connection1->invalidate();
        m_connection2->invalidate();
        break;
    case MediaNodeEvent::AudioGraphCannotPlay:
    case MediaNodeEvent::AudioGraphInitialized:
        updateVolume();
        break;
    default:
        break;
    }

    m_player1->mediaNodeEvent(event);
    m_player2->mediaNodeEvent(event);
    m_mixer->mediaNodeEvent(event);
}

}} //namespace Phonon::QT7

QT_END_NAMESPACE
