//=========================================================
//  MusE
//  Linux Music Editor
//    $Id: waveedit.cpp,v 1.1.1.1 2003/10/29 10:06:14 wschweer Exp $
//  (C) Copyright 2000 Werner Schweer (ws@seh.de)
//=========================================================

#include "xml.h"
#include "waveedit.h"
#include "mtscale.h"
#include "scrollscale.h"
#include "intlabel.h"
#include "waveview.h"
#include "ttoolbar.h"
#include "globals.h"
#include "waveview.h"
#include "utils.h"
#include "song.h"
#include "poslabel.h"

#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qaccel.h>
#include <qlayout.h>
#include <qhbox.h>
#include <qsizegrip.h>
#include <qscrollbar.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qbuttongroup.h>
#include <qlistbox.h>
#include <qcombobox.h>
#include <qheader.h>
#include <qpopupmenu.h>
#include <qmenubar.h>

extern QColor readColor(Xml& xml);

QColor WaveEdit::bg = QColor(0xff,0xff,0xff);
int WaveEdit::_widthInit = 600;
int WaveEdit::_heightInit = 400;

//---------------------------------------------------------
//   setBg
//---------------------------------------------------------

void WaveEdit::setBg(QColor _bg)
      {
      bg = _bg;
      view->setBg(bg);
      }

//---------------------------------------------------------
//   closeEvent
//---------------------------------------------------------

void WaveEdit::closeEvent(QCloseEvent* e)
      {
      emit deleted((int)this);
      e->accept();
      }

//---------------------------------------------------------
//   WaveEdit
//---------------------------------------------------------

WaveEdit::WaveEdit(PartList* pl)
   : MidiEditor(1, 1, pl)
      {
      resize(_widthInit, _heightInit);

      //---------Pulldown Menu----------------------------
      QPopupMenu* menuFile = new QPopupMenu(this);
      menuBar()->insertItem(tr("&File"), menuFile);
      QPopupMenu* menuFunctions = new QPopupMenu(this);
      menuBar()->insertItem(tr("Functions"), menuFunctions);
      menuFunctions->insertItem(tr("Normalize"), 1);

      connect(menuFunctions, SIGNAL(activated(int)), SLOT(cmd(int)));
      connect(menuFile, SIGNAL(activated(int)), SLOT(cmd(int)));

      //---------ToolBar----------------------------------
      tools = new QToolBar(this, "waveedit-tools");
      undoRedo->addTo(tools);

      //--------------------------------------------------
      //    Transport Bar
      QToolBar* transport = new QToolBar(this);
      transportAction->addTo(transport);

      //--------------------------------------------------
      //    ToolBar:   Solo  Cursor1 Cursor2

      tb1 = new QToolBar(this, "pianoroll-tools");

      tb1->setLabel(tr("weTools"));
      solo = new QToolButton(tb1);
      solo->setText(tr("Solo"));
      solo->setToggleButton(true);
      connect(solo,  SIGNAL(toggled(bool)), SLOT(soloChanged(bool)));

      QLabel* label = new QLabel(tr("Cursor"), tb1, "Cursor");
      label->setAlignment(AlignRight|AlignVCenter);
      label->setIndent(3);
      pos1 = new PosLabel(tb1);
      pos2 = new PosLabel(tb1);
      pos2->setSmpte(true);

      //---------------------------------------------------
      //    Rest
      //---------------------------------------------------

      int yscale = 256;
      int xscale = -8000;

      hscroll = new ScrollScale(1, -32768, xscale, 10000, Horizontal, mainw, 0, true, 10000.0);
      view    = new WaveView(this, mainw, xscale, yscale);
      wview   = view;   // HACK!

      view->setBg(bg);

      QSizeGrip* corner    = new QSizeGrip(mainw);
      ymag                 = new QSlider(1, 256, 256, yscale, Vertical, mainw);
      time                 = new MTScale(&_raster, mainw, xscale, true);
      ymag->setFixedWidth(16);
      connect(ymag, SIGNAL(valueChanged(int)), view, SLOT(setYScale(int)));
      time->setOrigin(0, 0);

      mainGrid->setRowStretch(0, 100);
      mainGrid->setColStretch(0, 100);

      mainGrid->addMultiCellWidget(time,   0, 0, 0, 1);
      mainGrid->addMultiCellWidget(hLine(mainw),    1, 1, 0, 1);
      mainGrid->addWidget(view,    2, 0);
      mainGrid->addWidget(ymag,    2, 1);
      mainGrid->addWidget(hscroll, 3, 0);
      mainGrid->addWidget(corner,  3, 1, AlignBottom | AlignRight);

      connect(hscroll, SIGNAL(scrollChanged(int)), view, SLOT(setXPos(int)));
      connect(hscroll, SIGNAL(scaleChanged(int)),  view, SLOT(setXMag(int)));
      setCaption(view->getCaption());
      connect(view, SIGNAL(followEvent(int)), hscroll, SLOT(setOffset(int)));

      connect(hscroll, SIGNAL(scrollChanged(int)), time,  SLOT(setXPos(int)));
      connect(hscroll, SIGNAL(scaleChanged(int)),  time,  SLOT(setXMag(int)));
      connect(time,    SIGNAL(timeChanged(int)),  SLOT(setTime(int)));
      connect(view,    SIGNAL(timeChanged(int)),  SLOT(setTime(int)));

      int s, e;
      view->range(&s, &e);
      hscroll->setRange(s, e);
      }

//---------------------------------------------------------
//   setTime
//---------------------------------------------------------

void WaveEdit::setTime(int samplepos)
      {
      int tick = tempomap.time2tick(double(samplepos) / double(sampleRate));
      pos1->setValue(tick);
      pos2->setValue(tick);
      time->setPos(3, tick, false);
      }

//---------------------------------------------------------
//   ~WaveEdit
//---------------------------------------------------------

WaveEdit::~WaveEdit()
      {
      undoRedo->removeFrom(tools);
      }

//---------------------------------------------------------
//   cmd
//---------------------------------------------------------

void WaveEdit::cmd(int n)
      {
      switch(n) {
            case 1: printf("normalize: not implemented\n"); break;
            default:
                  break;
            }
      }

//---------------------------------------------------------
//   loadConfiguration
//---------------------------------------------------------

void WaveEdit::readConfiguration(Xml& xml)
      {
      for (;;) {
            Xml::Token token = xml.parse();
            const QString& tag = xml.s1();
            switch (token) {
                  case Xml::TagStart:
                        if (tag == "bgcolor")
                              bg = readColor(xml);
                        else if (tag == "width")
                              _widthInit = xml.parseInt();
                        else if (tag == "height")
                              _heightInit = xml.parseInt();
                        else
                              xml.unknown("WaveEdit");
                        break;
                  case Xml::TagEnd:
                        if (tag == "waveedit")
                              return;
                  default:
                        break;
                  case Xml::Error:
                  case Xml::End:
                        return;
                  }
            }
      }

//---------------------------------------------------------
//   saveConfiguration
//---------------------------------------------------------

void WaveEdit::writeConfiguration(int level, Xml& xml)
      {
      xml.tag(level++, "waveedit");
      xml.put(level, "<bgcolor r=\"%d\" g=\"%d\" b=\"%d\"></bgcolor>",
         bg.red(), bg.green(), bg.blue());
      xml.intTag(level, "width", _widthInit);
      xml.intTag(level, "height", _heightInit);
      xml.tag(level, "/waveedit");
      }

//---------------------------------------------------------
//   writeStatus
//---------------------------------------------------------

void WaveEdit::writeStatus(int level, Xml& xml) const
      {
      writePartList(level, xml);
      xml.tag(level++, "waveedit");
      MidiEditor::writeStatus(level, xml);
      xml.intTag(level, "xpos", hscroll->pos());
      xml.intTag(level, "xmag", hscroll->mag());
      xml.intTag(level, "ymag", ymag->value());
      xml.tag(level, "/waveedit");
      }

//---------------------------------------------------------
//   readStatus
//---------------------------------------------------------

void WaveEdit::readStatus(Xml& xml)
      {
      for (;;) {
            Xml::Token token = xml.parse();
            if (token == Xml::Error || token == Xml::End)
                  break;
            QString tag = xml.s1();
            switch (token) {
                  case Xml::TagStart:
                        if (tag == "midieditor")
                              MidiEditor::readStatus(xml);
                        else if (tag == "xmag")
                              hscroll->setMag(xml.parseInt());
                        else if (tag == "ymag")
                              ymag->setValue(xml.parseInt());
                        else if (tag == "xpos")
                              hscroll->setPos(xml.parseInt());
                        else
                              xml.unknown("WaveEdit");
                        break;
                  case Xml::TagEnd:
                        if (tag == "waveedit")
                              return;
                  default:
                        break;
                  }
            }
      }

//---------------------------------------------------------
//   resizeEvent
//---------------------------------------------------------

void WaveEdit::resizeEvent(QResizeEvent* ev)
      {
      QWidget::resizeEvent(ev);
      _widthInit = ev->size().width();
      _heightInit = ev->size().height();
      }

//---------------------------------------------------------
//   soloChanged
//    signal from "song"
//---------------------------------------------------------

void WaveEdit::soloChanged(SNode*/* s*/)
      {
      WavePart* part = (WavePart*)(parts()->begin()->second);
      solo->setOn(part->track()->solo());
      }

//---------------------------------------------------------
//   soloChanged
//    signal from solo button
//---------------------------------------------------------

void WaveEdit::soloChanged(bool flag)
      {
      WavePart* part = (WavePart*)(parts()->begin()->second);
      part->track()->node()->setSolo(flag);
      }
