//=============================================================================
//  MusE
//  Linux Music Editor
//  $Id:$
//
//  Copyright (C) 2006 by Werner Schweer
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License version 2.
//
//  This program 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 General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================

#include "splitlayergui.h"
#include "splitlayer.h"
#include "gui.h"

//---------------------------------------------------------
//   SplitLayerGui
//---------------------------------------------------------

SplitLayerGui::SplitLayerGui(SplitLayer* f, QWidget* parent)
  : QWidget(parent)
      {
      sl = f;
      QGridLayout* grid = new QGridLayout;
      grid->setSpacing(1);
      setLayout(grid);
      QSignalMapper* m1 = new QSignalMapper(this);
      QSignalMapper* m2 = new QSignalMapper(this);
      QSignalMapper* m3 = new QSignalMapper(this);
      QSignalMapper* m4 = new QSignalMapper(this);
      QSignalMapper* m5 = new QSignalMapper(this);
      QSignalMapper* m6 = new QSignalMapper(this);
      connect(m1, SIGNAL(mapped(int)), SLOT(startPitchChanged(int)));
      connect(m2, SIGNAL(mapped(int)), SLOT(endPitchChanged(int)));
      connect(m3, SIGNAL(mapped(int)), SLOT(pitchOffsetChanged(int)));
      connect(m4, SIGNAL(mapped(int)), SLOT(startVeloChanged(int)));
      connect(m5, SIGNAL(mapped(int)), SLOT(endVeloChanged(int)));
      connect(m6, SIGNAL(mapped(int)), SLOT(veloOffsetChanged(int)));
      for (int i = 0; i < MIDI_CHANNELS; ++i) {
            QLabel* l = new QLabel(QString("Ch %1").arg(i+1));
            grid->addWidget(l, i, 0);

            p1[i] = new Awl::PitchEdit(0);
            p1[i]->setToolTip(tr("start pitch for split"));
            connect(p1[i], SIGNAL(valueChanged(int)), m1, SLOT(map()));
            m1->setMapping(p1[i], i);

            a1[i] = new QAction(this);
            a1[i]->setToolTip(tr("enable learn mode for start pitch"));
            a1[i]->setCheckable(true);
            QIcon icon;
            icon.addFile(":/xpm/recordOn.svg",  ICON_SIZE, QIcon::Normal, QIcon::On);
            icon.addFile(":/xpm/recordOff.svg", ICON_SIZE, QIcon::Normal, QIcon::Off);
            a1[i]->setIcon(icon);
            a1[i]->setData(i);
            QToolButton* rb1  = new QToolButton;
            rb1->setDefaultAction(a1[i]);
            connect(rb1, SIGNAL(triggered(QAction*)), SLOT(learnStartPitch(QAction*)));

            p2[i] = new Awl::PitchEdit(0);
            p2[i]->setToolTip(tr("end pitch for split"));
            connect(p2[i], SIGNAL(valueChanged(int)), m2, SLOT(map()));
            m2->setMapping(p2[i], i);

            a2[i] = new QAction(this);
            a2[i]->setToolTip(tr("enable learn mode for end pitch"));
            a2[i]->setCheckable(true);
            a2[i]->setIcon(icon);
            a2[i]->setData(i);
            QToolButton* rb2  = new QToolButton;
            rb2->setDefaultAction(a2[i]);
            connect(rb2, SIGNAL(triggered(QAction*)), SLOT(learnEndPitch(QAction*)));

            p3[i] = new Awl::PitchEdit(0);
            p3[i]->setToolTip(tr("pitch offset for split"));
            p3[i]->setDeltaMode(true);
            connect(p3[i], SIGNAL(valueChanged(int)), m3, SLOT(map()));
            m3->setMapping(p3[i], i);

            p4[i] = new QSpinBox;
            p4[i]->setRange(0, 127);
            p4[i]->setToolTip(tr("start velocity for split"));
            connect(p4[i], SIGNAL(valueChanged(int)), m4, SLOT(map()));
            m4->setMapping(p4[i], i);

            p5[i] = new QSpinBox;
            p5[i]->setRange(0, 127);
            p5[i]->setToolTip(tr("end velocity for split"));
            connect(p5[i], SIGNAL(valueChanged(int)), m5, SLOT(map()));
            m5->setMapping(p5[i], i);

            p6[i] = new QSpinBox;
            p6[i]->setRange(-127, 127);
            p6[i]->setToolTip(tr("velocity offset for split"));
            connect(p6[i], SIGNAL(valueChanged(int)), m6, SLOT(map()));
            m6->setMapping(p6[i], i);

            grid->addWidget(p1[i], i, 1);
            grid->addWidget(rb1,   i, 2);
            grid->addWidget(p2[i], i, 3);
            grid->addWidget(rb2,   i, 4);
            grid->addWidget(p3[i], i, 5);
            grid->addWidget(p4[i], i, 7);
            grid->addWidget(p5[i], i, 8);
            grid->addWidget(p6[i], i, 9);
            }
      QFrame* fr = new QFrame;
      fr->setFrameStyle(QFrame::VLine | QFrame::Raised);
      fr->setLineWidth(4);
      grid->addWidget(fr, 0, 6, MIDI_CHANNELS, 1);

      int filedes[2];         // 0 - reading   1 - writing
      if (pipe(filedes) == -1) {
            perror("SplitLayerGui:creating pipe");
            exit(-1);
            }
      fd2 = filedes[0];
      fd1 = filedes[1];
      
      QSocketNotifier* socket = new QSocketNotifier(fd2, 
         QSocketNotifier::Read, this);
      connect(socket, SIGNAL(activated(int)), SLOT(resetLearnMode(int)));
      init();
      }

//---------------------------------------------------------
//   init
//---------------------------------------------------------

void SplitLayerGui::init()
      {
      for (int i = 0; i < MIDI_CHANNELS; ++i) {
            p1[i]->setValue(sl->data.startPitch[i]);
            p2[i]->setValue(sl->data.endPitch[i]);
            p3[i]->setValue(sl->data.pitchOffset[i]);
            p4[i]->setValue(sl->data.startVelo[i]);
            p5[i]->setValue(sl->data.endVelo[i]);
            p6[i]->setValue(sl->data.veloOffset[i]);
            }
      }

//---------------------------------------------------------
//   learnStartPitch
//---------------------------------------------------------

void SplitLayerGui::learnStartPitch(QAction* a)
      {
      sl->learnChannel = a->data().toInt();
      sl->learnStartPitch = true;
      sl->learnMode = true;
      for (int i = 0; i < MIDI_CHANNELS; ++i) {
            if (a != a1[i])
                  a1[i]->setChecked(false);
            if (a != a2[i])
                  a2[i]->setChecked(false);
            }
      }

//---------------------------------------------------------
//   learnEndPitch
//---------------------------------------------------------

void SplitLayerGui::learnEndPitch(QAction* a)
      {
      sl->learnChannel = a->data().toInt();
      sl->learnStartPitch = false;
      sl->learnMode = true;
      for (int i = 0; i < MIDI_CHANNELS; ++i) {
            if (a != a1[i])
                  a1[i]->setChecked(false);
            if (a != a2[i])
                  a2[i]->setChecked(false);
            }
      }

//---------------------------------------------------------
//   startPitchChanged
//---------------------------------------------------------

void SplitLayerGui::startPitchChanged(int n)
      {
      sl->data.startPitch[n] = p1[n]->value();
      }

//---------------------------------------------------------
//   endPitchChanged
//---------------------------------------------------------

void SplitLayerGui::endPitchChanged(int n)
      {
      sl->data.endPitch[n] = p2[n]->value();
      }

//---------------------------------------------------------
//   pitchOffsetChanged
//---------------------------------------------------------

void SplitLayerGui::pitchOffsetChanged(int n)
      {
      sl->data.pitchOffset[n] = p3[n]->value();
      }

//---------------------------------------------------------
//   startVeloChanged
//---------------------------------------------------------

void SplitLayerGui::startVeloChanged(int n)
      {
      sl->data.startVelo[n] = p4[n]->value();
      }

//---------------------------------------------------------
//   endVeloChanged
//---------------------------------------------------------

void SplitLayerGui::endVeloChanged(int n)
      {
      sl->data.endVelo[n] = p5[n]->value();
      }

//---------------------------------------------------------
//   veloOffsetChanged
//---------------------------------------------------------

void SplitLayerGui::veloOffsetChanged(int n)
      {
      sl->data.veloOffset[n] = p6[n]->value();
      }

//---------------------------------------------------------
//   resetLearnMode
//---------------------------------------------------------

void SplitLayerGui::resetLearnMode(int fd)
      {
      char buffer[16];
      read(fd, buffer, 16);

      for (int i = 0; i < MIDI_CHANNELS; ++i) {
            a1[i]->setChecked(false);
            a2[i]->setChecked(false);
            }
      init();
      }

//---------------------------------------------------------
//   sendResetLearnMode
//---------------------------------------------------------

void SplitLayerGui::sendResetLearnMode()
      {
      write(fd1, "X", 1);
      }