/***************************************************************************
                          recording-monitor.cpp  -  description
                             -------------------
    begin                : Mo Sep 1 2003
    copyright            : (C) 2003 by Martin Witte
    email                : witte@kawo1.rwth-aachen.de
 ***************************************************************************/

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

#include "recording-monitor.h"
#include "recording-datamonitor.h"
#include "../../src/include/aboutwidget.h"

#include <tqlabel.h>
#include <tqpushbutton.h>
#include <tqlayout.h>
#include <tqcheckbox.h>
#include <kcombobox.h>

#include <tdelocale.h>
#include <tdeconfig.h>
#include <tdeaboutdata.h>

RecordingMonitor::RecordingMonitor(const TQString &name)
  : TQWidget(NULL, name.ascii()),
    WidgetPluginBase(name, i18n("Recording Monitor")),
    m_recording(false),
    m_defaultStreamDescription(TQString())
{
    setCaption(i18n("TDERadio Recording Monitor"));

    TQVBoxLayout *l = new TQVBoxLayout(this, 10, 4);
    TQGridLayout *l0 = new TQGridLayout(l, 6, 2);

    l0->addWidget(                      new TQLabel(i18n("SoundStream"),    this), 0, 0);
    l0->addWidget(m_comboSoundStreamSelector = new KComboBox(              this), 0, 1);
    l0->addWidget(                      new TQLabel(i18n("Status"),         this), 1, 0);
    l0->addWidget(m_labelStatus       = new TQLabel(i18n("<undefined>"),    this), 1, 1);
    l0->addWidget(                      new TQLabel(i18n("Recording File"), this), 2, 0);
    l0->addWidget(m_labelFileName     = new TQLabel(i18n("<undefined>"),    this), 2, 1);
    l0->addWidget(                      new TQLabel(i18n("File Size"),      this), 3, 0);
    l0->addWidget(m_labelSize         = new TQLabel(i18n("<undefined>"),    this), 3, 1);
    l0->addWidget(                      new TQLabel(i18n("Recording Time"), this), 4, 0);
    l0->addWidget(m_labelTime         = new TQLabel(i18n("<undefined>"),    this), 4, 1);
    l0->addWidget(                      new TQLabel(i18n("Sample Rate"),    this), 5, 0);
    l0->addWidget(m_labelRate         = new TQLabel(i18n("<undefined>"),    this), 5, 1);

    TQPushButton *close     = new TQPushButton(i18n("&Close"), this);
    m_btnStartStop         = new TQPushButton(i18n("&Record"), this);
    TQObject::connect(close, TQ_SIGNAL(clicked()), this, TQ_SLOT(hide()));
    TQObject::connect(m_btnStartStop, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotStartStopRecording()));

    m_dataMonitor = new RecordingDataMonitor(this, NULL);
    m_dataMonitor->setEnabled(false);

    TQHBoxLayout *hl0 = new TQHBoxLayout(l);
    hl0->addWidget(m_dataMonitor);

    TQHBoxLayout *hl2 = new TQHBoxLayout(l);
    hl2->addItem(new TQSpacerItem(10, 1));
    hl2->addWidget(close);
    hl2->addWidget(m_btnStartStop);
    hl2->addItem(new TQSpacerItem(10, 1));


    m_comboSoundStreamSelector->insertItem(i18n("nothing"));
    TQObject::connect(m_comboSoundStreamSelector, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotStreamSelected(int)));

    updateRecordingButton();
}


RecordingMonitor::~RecordingMonitor()
{
}

// WidgetPluginBase

void   RecordingMonitor::saveState (TDEConfig *config) const
{
    config->setGroup(TQString("recordingmonitor-") + name());

    WidgetPluginBase::saveState(config);
}


void   RecordingMonitor::restoreState (TDEConfig *config)
{
    config->setGroup(TQString("recordingmonitor-") + name());

    WidgetPluginBase::restoreState(config, false);
}


bool   RecordingMonitor::connectI(Interface *i)
{
    bool a = ISoundStreamClient::connectI(i);
    bool b = WidgetPluginBase::connectI(i);
    return a || b;
}

bool   RecordingMonitor::disconnectI(Interface *i)
{
    bool a = ISoundStreamClient::disconnectI(i);
    bool b = WidgetPluginBase::disconnectI(i);
    if (a) {
        m_comboSoundStreamSelector->clear();
        m_SoundStreamID2idx.clear();
        m_idx2SoundStreamID.clear();
        m_comboSoundStreamSelector->insertItem(i18n("nothing"));
    }
    return a || b;
}


void RecordingMonitor::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
{
    ISoundStreamClient::noticeConnectedI(s, pointer_valid);
    if (s && pointer_valid) {
        s->register4_notifySoundStreamCreated(this);
        s->register4_notifySoundStreamClosed(this);
        s->register4_notifySoundStreamChanged(this);
        s->register4_notifySoundStreamData(this);
        s->register4_sendStartRecordingWithFormat(this);
        s->register4_sendStopRecording(this);

        TQMap<TQString, SoundStreamID> tmp;
        queryEnumerateSoundStreams(tmp);

        m_comboSoundStreamSelector->clear();
        m_SoundStreamID2idx.clear();
        m_idx2SoundStreamID.clear();
        m_comboSoundStreamSelector->insertItem(i18n("nothing"));
        TQMapConstIterator<TQString, SoundStreamID> end = tmp.end();
        for (TQMapConstIterator<TQString, SoundStreamID> it = tmp.begin(); it != end; ++it) {
            int idx = m_comboSoundStreamSelector->count();
            m_comboSoundStreamSelector->insertItem(it.key());
            m_idx2SoundStreamID[idx] = *it;
            m_SoundStreamID2idx[*it] = idx;
        }
    }
}

ConfigPageInfo  RecordingMonitor::createConfigurationPage()
{
    return ConfigPageInfo();
}

AboutPageInfo   RecordingMonitor::createAboutPage()
{
/*    TDEAboutData aboutData("tderadio",
                         NULL,
                         NULL,
                         I18N_NOOP("Recording Monitor Plugin for TDERadio"),
                         TDEAboutData::License_GPL,
                         "(c) 2002-2005 Martin Witte",
                         0,
                         "http://sourceforge.net/projects/tderadio",
                         0);
    aboutData.addAuthor("Martin Witte",  "", "witte@kawo1.rwth-aachen.de");

    return AboutPageInfo(
              new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
              i18n("Recording Monitor"),
              i18n("Recording Monitor Plugin"),
              "goto"
           );
*/
    return AboutPageInfo();
}


void RecordingMonitor::show()
{
    WidgetPluginBase::pShow();
    TQWidget::show();
}


void RecordingMonitor::showOnOrgDesktop()
{
    WidgetPluginBase::pShowOnOrgDesktop();
    //TQWidget::show();
}

void RecordingMonitor::hide()
{
    WidgetPluginBase::pHide();
    TQWidget::hide();
}


void RecordingMonitor::showEvent(TQShowEvent *e)
{
    TQWidget::showEvent(e);
    WidgetPluginBase::pShowEvent(e);
    //m_comboSoundStreamSelector->setCurrentItem(1);
    //slotStreamSelected(1);
}


void RecordingMonitor::hideEvent(TQHideEvent *e)
{
    TQWidget::hideEvent(e);
    WidgetPluginBase::pHideEvent(e);
    m_comboSoundStreamSelector->setCurrentItem(0);
    slotStreamSelected(0);
}


void RecordingMonitor::slotStartStopRecording()
{
    if (m_currentStream.isValid()) {
        if (m_recording) {
            sendStopRecording(m_currentStream);
        } else {
            sendStartRecording(m_currentStream);
        }
    }
    updateRecordingButton();
}


bool RecordingMonitor::noticeSoundStreamCreated(SoundStreamID id)
{
    TQString tmp = TQString();
    querySoundStreamDescription(id, tmp);

    int idx = m_comboSoundStreamSelector->count();
    m_comboSoundStreamSelector->insertItem(tmp);
    m_idx2SoundStreamID[idx] = id;
    m_SoundStreamID2idx[id]  = idx;

    if (tmp == m_defaultStreamDescription) {
        m_comboSoundStreamSelector->setCurrentItem(idx);
        slotStreamSelected(idx);
    }
    return true;
}


bool RecordingMonitor::noticeSoundStreamClosed(SoundStreamID id)
{
    if (m_SoundStreamID2idx.contains(id)) {
        int idx = m_SoundStreamID2idx[id];
        m_idx2SoundStreamID.clear();
        m_SoundStreamID2idx.remove(id);
        TQMapIterator<SoundStreamID, int> end = m_SoundStreamID2idx.end();
        for (TQMapIterator<SoundStreamID, int> it = m_SoundStreamID2idx.begin(); it != end; ++it) {
            if (*it > idx) {
                (*it)--;
            }
            m_idx2SoundStreamID[*it] = it.key();
        }
        m_comboSoundStreamSelector->removeItem(idx);
        slotStreamSelected(m_comboSoundStreamSelector->currentItem());
        return true;
    }
    return false;
}


bool RecordingMonitor::noticeSoundStreamChanged(SoundStreamID id)
{
    if (m_SoundStreamID2idx.contains(id)) {
        int idx = m_SoundStreamID2idx[id];
        TQString tmp = TQString();
        querySoundStreamDescription(id, tmp);
        m_comboSoundStreamSelector->changeItem(tmp, idx);
        if (idx == m_comboSoundStreamSelector->currentItem()) {
            m_defaultStreamDescription = tmp;
        }
        return true;
    }
    return false;
}

bool RecordingMonitor::startRecordingWithFormat(SoundStreamID id, const SoundFormat &/*sf*/, SoundFormat &/*real_format*/)
{
    if (id == m_currentStream) {
        m_recording = true;
        updateRecordingButton();
    }
    return false;
}

bool RecordingMonitor::stopRecording(SoundStreamID id)
{
    if (id == m_currentStream) {
        m_recording = false;
        updateRecordingButton();
    }
    return false;
}

bool RecordingMonitor::noticeSoundStreamData(SoundStreamID id,
    const SoundFormat &sf, const char *data, size_t size, size_t &consumed_size,
    const SoundMetaData &md
)
{
    if (m_idx2SoundStreamID[m_comboSoundStreamSelector->currentItem()] == id) {

        m_labelFileName->setText(md.url().url());

        double B = (double)md.position() + (double)size;

        double s = md.relativeTimestamp();

        int m = (int)(s / 60);   s -= 60 * m;
        int h = m / 60;   m %= 60;
        int d = h / 24;   h %= 24;
        TQString time;
        if (d) {
            time.sprintf("%dd - %02d:%02d:%05.2f", d, h, m, s);
        } else {
            time.sprintf("%02d:%02d:%05.2f", h, m, s);
        }
        m_labelTime->setText(time);

        if (sf.m_Encoding == "raw") {
            m_dataMonitor->setEnabled(true);
            m_dataMonitor->noticeSoundStreamData(id, sf, data, size, consumed_size, md);
        } else {
            m_dataMonitor->setEnabled(false);
        }

        double kB = B  / 1024;
        double MB = kB / 1024;
        double GB = MB / 1024;
        TQString str_size;
        str_size = i18n("%1 Byte").arg(TDEGlobal::locale()->formatNumber((int)B, 0));
        if (kB > 1) str_size = i18n("%1 kB").arg(TDEGlobal::locale()->formatNumber(kB, 3));
        if (MB > 1) str_size = i18n("%1 MB").arg(TDEGlobal::locale()->formatNumber(MB, 3));
        if (GB > 1) str_size = i18n("%1 GB").arg(TDEGlobal::locale()->formatNumber(GB, 3));
        m_labelSize->setText(str_size);

        m_labelRate->setText(i18n("%1 Hz").arg(sf.m_SampleRate));
        return true;
    }
    return false;
}


void RecordingMonitor::slotStreamSelected(int idx)
{
    SoundStreamID old_id = m_currentStream;
    if (old_id.isValid()) {
        sendStopCapture(old_id);
    }

    SoundStreamID id = m_idx2SoundStreamID.contains(idx) ? m_idx2SoundStreamID[idx] : SoundStreamID::InvalidID;
    if (id.isValid()) {

        m_defaultStreamDescription = m_comboSoundStreamSelector->text(idx);

        SoundFormat sf;
        sendStartCaptureWithFormat(id, sf, sf);
        m_dataMonitor   ->setEnabled(true);
        m_labelSize     ->setEnabled(true);
        m_labelSize     ->setEnabled(true);
        m_labelTime     ->setEnabled(true);
        m_labelRate     ->setEnabled(true);
        m_labelFileName ->setEnabled(true);
        m_labelStatus   ->setEnabled(true);
    } else {
        m_dataMonitor   ->setEnabled(false);
        m_labelSize     ->setEnabled(false);
        m_labelSize     ->setEnabled(false);
        m_labelTime     ->setEnabled(false);
        m_labelRate     ->setEnabled(false);
        m_labelFileName ->setEnabled(false);
        m_labelStatus   ->setEnabled(false);
    }
    m_currentStream = id;
    m_recording = false;
    SoundFormat sf;
    queryIsRecordingRunning(m_currentStream, m_recording, sf);
    updateRecordingButton();
}


void RecordingMonitor::updateRecordingButton()
{
    if (m_currentStream.isValid()) {
        m_btnStartStop->setText(!m_recording ? i18n("&Record") : i18n("&Stop Recording"));
        m_btnStartStop->setEnabled(true);
    } else {
        m_btnStartStop->setText(i18n("&Record"));
        m_btnStartStop->setEnabled(false);
    }
}


#include "recording-monitor.moc"
