diff options
| author | Tim E. Real <termtech@rogers.com> | 2012-08-15 00:24:29 +0000 | 
|---|---|---|
| committer | Tim E. Real <termtech@rogers.com> | 2012-08-15 00:24:29 +0000 | 
| commit | 6c642a1cff928c183d80af7ab4fad6910466a091 (patch) | |
| tree | ab534d2203486d681398b7197635861ae65160c1 /muse2/muse | |
| parent | 345fb0cc41b94b08134dc1f40020b4bf26e1d46b (diff) | |
Introducing: Improved Wave Editor. Class WaveView is replaced by WaveCanvas. 
Wave Events can be selected, added, moved and deleted.
TODO: Bunch o' stuff, but currently it should be as good or better than the old editor.
Diffstat (limited to 'muse2/muse')
| -rw-r--r-- | muse2/muse/functions.cpp | 12 | ||||
| -rw-r--r-- | muse2/muse/midiedit/ecanvas.h | 16 | ||||
| -rw-r--r-- | muse2/muse/midieditor.cpp | 22 | ||||
| -rw-r--r-- | muse2/muse/midieditor.h | 5 | ||||
| -rw-r--r-- | muse2/muse/waveedit/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | muse2/muse/waveedit/wavecanvas.cpp | 2422 | ||||
| -rw-r--r-- | muse2/muse/waveedit/wavecanvas.h | 185 | ||||
| -rw-r--r-- | muse2/muse/waveedit/waveedit.cpp | 401 | ||||
| -rw-r--r-- | muse2/muse/waveedit/waveedit.h | 27 | ||||
| -rw-r--r-- | muse2/muse/widgets/canvas.cpp | 2 | ||||
| -rw-r--r-- | muse2/muse/widgets/canvas.h | 2 | ||||
| -rw-r--r-- | muse2/muse/widgets/poslabel.cpp | 24 | 
12 files changed, 3027 insertions, 95 deletions
| diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index 1a6927e8..da5826e5 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -1286,12 +1286,22 @@ void schedule_resize_all_same_len_clone_parts(Part* part, unsigned new_len, Undo  		if (op_it->type==UndoOp::ModifyPart || op_it->type==UndoOp::DeletePart)  			already_done.insert(op_it->nPart); -	unsigned old_len=part->lenTick(); +	unsigned old_len= part->type() == Pos::FRAMES ? part->lenFrame() : part->lenTick();  	if (old_len!=new_len)  	{  		Part* part_it=part;  		do  		{ +			if (part->type() == Pos::FRAMES) +			{ +			  if (part_it->lenFrame()==old_len && !already_done.contains(part_it)) +			  { +				  WavePart* new_part = new WavePart(*(WavePart*)part_it); +				  new_part->setLenFrame(new_len); +				  operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, new_part, true, false)); +			  } +			} +			else  			if (part_it->lenTick()==old_len && !already_done.contains(part_it))  			{  				MidiPart* new_part = new MidiPart(*(MidiPart*)part_it); diff --git a/muse2/muse/midiedit/ecanvas.h b/muse2/muse/midiedit/ecanvas.h index 7847e88a..400072dc 100644 --- a/muse2/muse/midiedit/ecanvas.h +++ b/muse2/muse/midiedit/ecanvas.h @@ -87,22 +87,22 @@ class EventCanvas : public Canvas {     signals:        void pitchChanged(int);       // current cursor position        void timeChanged(unsigned); -      void selectionChanged(int /*tick*/ , MusECore::Event&, MusECore::Part*, bool /*update*/); +      void selectionChanged(int /*tick or frame*/ , MusECore::Event&, MusECore::Part*, bool /*update*/);        void enterCanvas();     public:        EventCanvas(MidiEditor*, QWidget*, int, int, const char* name = 0);        MusECore::MidiTrack* track() const; -      unsigned start() const       { return start_tick; } -      unsigned end() const         { return end_tick; } +      virtual unsigned start() const       { return start_tick; } +      virtual unsigned end() const         { return end_tick; }        bool midiin() const     { return _midiin; }        bool steprec() const    { return _steprec; } -      QString getCaption() const; -      void songChanged(MusECore::SongChangedFlags_t); -      void range(int* s, int* e) const { *s = start_tick; *e = end_tick; } +      virtual QString getCaption() const; +      virtual void songChanged(MusECore::SongChangedFlags_t); +      virtual void range(int* s, int* e) const { *s = start_tick; *e = end_tick; }        void playEvents(bool flag) { _playEvents = flag; } -      void selectAtTick(unsigned int tick); -      void viewDropEvent(QDropEvent* event); +      virtual void selectAtTick(unsigned int tick); +      virtual void viewDropEvent(QDropEvent* event);        virtual void modifySelected(NoteInfo::ValType, int /*val*/, bool /*delta_mode*/ = true) {}        virtual void keyPress(QKeyEvent*);        }; diff --git a/muse2/muse/midieditor.cpp b/muse2/muse/midieditor.cpp index b4830c21..c00a7049 100644 --- a/muse2/muse/midieditor.cpp +++ b/muse2/muse/midieditor.cpp @@ -50,7 +50,7 @@ MidiEditor::MidiEditor(ToplevelType t, int r, MusECore::PartList* pl,                    _parts.insert(i->second->sn());        _raster  = r;        canvas   = 0; -      wview    = 0; +      //wview    = 0;        _curDrumInstrument = -1;        mainw    = new QWidget(this); @@ -194,8 +194,8 @@ void MidiEditor::songChanged(MusECore::SongChangedFlags_t type)                    }              if (canvas)                    canvas->songChanged(type); -            else if (wview) -                  wview->songChanged(type); +            //else if (wview) +            //      wview->songChanged(type);              if (type & (SC_PART_REMOVED | SC_PART_MODIFIED                 | SC_PART_INSERTED | SC_TRACK_REMOVED)) { @@ -204,8 +204,8 @@ void MidiEditor::songChanged(MusECore::SongChangedFlags_t type)                    if (canvas)                          setWindowTitle(canvas->getCaption()); -                  else if (wview) -                        setWindowTitle(wview->getCaption()); +                  //else if (wview) +                  //      setWindowTitle(wview->getCaption());                    if (type & SC_SIG)                          time->update(); @@ -236,18 +236,6 @@ MusECore::Part* MidiEditor::curCanvasPart()  }  //--------------------------------------------------------- -//   curWavePart -//--------------------------------------------------------- - -MusECore::WavePart* MidiEditor::curWavePart()  -{  -  if(wview)  -    return wview->part();  -  else  -    return 0;  -} - -//---------------------------------------------------------  //   setCurCanvasPart  //--------------------------------------------------------- diff --git a/muse2/muse/midieditor.h b/muse2/muse/midieditor.h index fd6d255b..541e4e0c 100644 --- a/muse2/muse/midieditor.h +++ b/muse2/muse/midieditor.h @@ -46,7 +46,7 @@ class CtrlEdit;  class EventCanvas;  class MTScale;  class ScrollScale; -class WaveView; +//class WaveView;  //---------------------------------------------------------  //   MidiEditor @@ -64,7 +64,7 @@ class MidiEditor : public TopWin  {        MusEGui::ScrollScale* vscroll;        MusEGui::MTScale* time;        EventCanvas* canvas; -      WaveView* wview; +      //WaveView* wview;        std::list<CtrlEdit*> ctrlEditList;        int _raster; @@ -102,7 +102,6 @@ class MidiEditor : public TopWin  {        MusECore::PartList* parts()            { return _pl;  }        int curDrumInstrument() const  { return _curDrumInstrument; }        MusECore::Part* curCanvasPart(); -      MusECore::WavePart* curWavePart();        void setCurCanvasPart(MusECore::Part*);         void addPart(MusECore::Part*);        }; diff --git a/muse2/muse/waveedit/CMakeLists.txt b/muse2/muse/waveedit/CMakeLists.txt index f32eb6e1..920c7068 100644 --- a/muse2/muse/waveedit/CMakeLists.txt +++ b/muse2/muse/waveedit/CMakeLists.txt @@ -27,7 +27,7 @@  QT4_WRAP_CPP ( waveedit_mocs        editgain.h        waveedit.h -      waveview.h +      wavecanvas.h        )  ## @@ -44,7 +44,7 @@ QT4_WRAP_UI (waveedit_ui_headers ${waveedit_ui_files} )  file (GLOB waveedit_source_files        editgain.cpp        waveedit.cpp -      waveview.cpp +      wavecanvas.cpp        )  ## diff --git a/muse2/muse/waveedit/wavecanvas.cpp b/muse2/muse/waveedit/wavecanvas.cpp new file mode 100644 index 00000000..220c2804 --- /dev/null +++ b/muse2/muse/waveedit/wavecanvas.cpp @@ -0,0 +1,2422 @@ +//========================================================= +//  MusE +//  Linux Music Editor +//    wavecanvas.cpp +//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +//  Based on WaveView.cpp and PianoCanvas.cpp +//  (C) Copyright 2000 Werner Schweer (ws@seh.de) +//   and others. +// +//  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; version 2 of +//  the License, or (at your option) any later version. +// +//  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. +// +//========================================================= + + +#include <QApplication> +#include <QClipboard> +#include <QPainter> +#include <QDrag> +#include <QDragLeaveEvent> +#include <QDragEnterEvent> +#include <QDragMoveEvent> +#include <QDropEvent> +#include <QMouseEvent> +#include <QList> +#include <QPair> +#include <QMessageBox> +#include <QDir> + +#include <set> + +#include <limits.h> +#include <stdio.h> +#include <math.h> +#include <errno.h> +#include <sys/wait.h> + +#include "xml.h" +#include "wavecanvas.h" +#include "event.h" +#include "globals.h" +#include "cmd.h" +#include "song.h" +#include "audio.h" +#include "functions.h" +#include "gconfig.h" +#include "shortcuts.h" +#include "editgain.h" +#include "wave.h" +#include "waveedit.h" +#include "fastlog.h" +#include "utils.h" +#include "tools.h" + +namespace MusEGui { + +//--------------------------------------------------------- +//   WEvent +//--------------------------------------------------------- + +WEvent::WEvent(MusECore::Event& e, MusECore::Part* p, int height) : MusEGui::CItem(e, p) +      { +      unsigned frame = e.frame() + p->frame(); +      setPos(QPoint(frame, 0)); +      unsigned len = e.lenFrame(); +      if(e.frame() + e.lenFrame() >= p->lenFrame()) +        len = p->lenFrame() - e.frame(); +      setBBox(QRect(frame, 0, len, height));     +      } + +//--------------------------------------------------------- +//   addItem +//--------------------------------------------------------- + +CItem* WaveCanvas::addItem(MusECore::Part* part, MusECore::Event& event) +      { +      if (signed(event.frame())<0) { +            printf("ERROR: trying to add event before current part!\n"); +            return NULL; +      } + +      WEvent* ev = new WEvent(event, part, height());   +      items.add(ev); + +      int diff = event.frame()-part->lenFrame(); +      if (diff > 0)  {// too short part? extend it +            part->setLenFrame(part->lenFrame()+diff); +            } +       +      return ev; +      } + +//--------------------------------------------------------- +//   WaveCanvas +//--------------------------------------------------------- + +WaveCanvas::WaveCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy) +   : EventCanvas(pr, parent, sx, 1) +      { +      colorMode = 0; +      button = 0; +       +      editor = pr; +      setVirt(true); +       +      setBg(QColor()); +       +      pos[0] = MusEGlobal::tempomap.tick2frame(MusEGlobal::song->cpos()); +      pos[1] = MusEGlobal::tempomap.tick2frame(MusEGlobal::song->lpos()); +      pos[2] = MusEGlobal::tempomap.tick2frame(MusEGlobal::song->rpos()); +      yScale = sy; +      mode = NORMAL; +      selectionStart = 0; +      selectionStop  = 0; +      lastGainvalue = 100; + +      songChanged(SC_TRACK_INSERTED); +      } + +WaveCanvas::~WaveCanvas() +{ +  //delete steprec; +} + +//--------------------------------------------------------- +//   songChanged(type) +//--------------------------------------------------------- + +void WaveCanvas::songChanged(MusECore::SongChangedFlags_t flags) +      { +      // Is it simply a midi controller value adjustment? Forget it. +      if(flags == SC_MIDI_CONTROLLER) +        return; +     +      if (flags & ~SC_SELECTION) { +            // TODO FIXME: don't we actually only want SC_PART_*, and maybe SC_TRACK_DELETED? +            //             (same in waveview.cpp) +            bool curItemNeedsRestore=false; +            MusECore::Event storedEvent; +            int partSn; +            if (curItem) +            { +              curItemNeedsRestore=true; +              storedEvent=curItem->event(); +              partSn=curItem->part()->sn(); +            } +            curItem=NULL; +             +            items.clearDelete(); +            startSample  = INT_MAX; +            endSample    = 0; +            curPart = 0; +            for (MusECore::iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) { +                  MusECore::WavePart* part = (MusECore::WavePart*)(p->second); +                  if (part->sn() == curPartId) +                        curPart = part; +                  unsigned ssample = part->frame(); +                  unsigned len = part->lenFrame(); +                  unsigned esample = ssample + len; +                  if (ssample < startSample) +                        startSample = ssample; +                  if (esample > endSample) +                        endSample = esample; + +                  MusECore::EventList* el = part->events(); +                  for (MusECore::iEvent i = el->begin(); i != el->end(); ++i) { +                        MusECore::Event e = i->second; +                        // Do not add events which are past the end of the part. +                        if(e.frame() > len)       +                          break; +                         +                        if (e.type() == MusECore::Wave) { +                              CItem* temp = addItem(part, e); +                               +                              if (temp && curItemNeedsRestore && e==storedEvent && part->sn()==partSn) +                              { +                                  if (curItem!=NULL) +                                    printf("THIS SHOULD NEVER HAPPEN: curItemNeedsRestore=true, event fits, but there was already a fitting event!?\n"); +                                   +                                  curItem=temp; +                                  } +                              } +                        } +                  } +            } + +      MusECore::Event event; +      MusECore::WavePart* part   = 0; +      int x            = 0; +      CItem*   nevent  = 0; + +      int n  = 0;       // count selections +      for (iCItem k = items.begin(); k != items.end(); ++k) { +            MusECore::Event ev = k->second->event(); +            bool selected = ev.selected(); +            if (selected) { +                  k->second->setSelected(true); +                  ++n; +                  if (!nevent) { +                        nevent   =  k->second; +                        MusECore::Event mi = nevent->event(); +                        } +                  } +            } +       +      if (flags & SC_CLIP_MODIFIED) { +            redraw(); // Boring, but the only thing possible to do +            } +      if (flags & SC_TEMPO) { +            setPos(0, MusEGlobal::song->cpos(), false); +            setPos(1, MusEGlobal::song->lpos(), false); +            setPos(2, MusEGlobal::song->rpos(), false); +            } +       +      if (n >= 1)     +      { +            x     = nevent->x(); +            event = nevent->event(); +            part  = (MusECore::WavePart*)nevent->part(); +            if (_setCurPartIfOnlyOneEventIsSelected && n == 1 && curPart != part) { +                  curPart = part; +                  curPartId = curPart->sn(); +                  curPartChanged(); +                  } +      } +       +      bool f1 = flags & (SC_EVENT_INSERTED | SC_EVENT_MODIFIED | SC_EVENT_REMOVED |  +                         SC_PART_INSERTED | SC_PART_MODIFIED | SC_PART_REMOVED | +                         SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED | +                         SC_SIG | SC_TEMPO | SC_KEY | SC_MASTER | SC_CONFIG | SC_DRUMMAP);  +      bool f2 = flags & SC_SELECTION; +      if(f1 || f2)   // Try to avoid all unnecessary emissions. +        emit selectionChanged(x, event, part, !f1); +       +      if (curPart == 0) +            curPart = (MusECore::WavePart*)(editor->parts()->begin()->second); +      redraw(); +      } + +//--------------------------------------------------------- +//   selectAtTick +//--------------------------------------------------------- + +void WaveCanvas::selectAtTick(unsigned int tick) +      { +      selectAtFrame(MusEGlobal::tempomap.tick2frame(tick)); +      } + +//--------------------------------------------------------- +//   selectAtFrame +//--------------------------------------------------------- + +void WaveCanvas::selectAtFrame(unsigned int frame) +      { +      //Select event nearest frame, if none selected and there are any +      if (!items.empty() && selectionSize() == 0) { +            iCItem i = items.begin(); +            CItem* nearest = i->second; + +            while (i != items.end()) { +                CItem* cur=i->second;                 +                unsigned int curf=abs(cur->x() + cur->part()->frame() - frame); +                unsigned int nearf=abs(nearest->x() + nearest->part()->frame() - frame); + +                if (curf < nearf) { +                    nearest=cur; +                    } + +                i++; +                } + +            if (!nearest->isSelected()) { +                  selectItem(nearest, true); +                  songChanged(SC_SELECTION); +                  } +            } +      } + +//--------------------------------------------------------- +//   getCaption +//--------------------------------------------------------- + +QString WaveCanvas::getCaption() const +      { +      int bar1, bar2, xx; +      unsigned x; +      AL::sigmap.tickValues(curPart->tick(), &bar1, &xx, &x); +      AL::sigmap.tickValues(curPart->tick() + curPart->lenTick(), &bar2, &xx, &x); + +      return QString("MusE: Part <") + curPart->name() +         + QString("> %1-%2").arg(bar1+1).arg(bar2+1); +      } + +//--------------------------------------------------------- +//   track +//--------------------------------------------------------- + +MusECore::WaveTrack* WaveCanvas::track() const +      { +      return ((MusECore::WavePart*)curPart)->track(); +      } + + +//--------------------------------------------------------- +//   keyPress +//--------------------------------------------------------- + +void WaveCanvas::keyPress(QKeyEvent* event) +      { +      int key = event->key(); +      if (((QInputEvent*)event)->modifiers() & Qt::ShiftModifier) +            key += Qt::SHIFT; +      if (((QInputEvent*)event)->modifiers() & Qt::AltModifier) +            key += Qt::ALT; +      if (((QInputEvent*)event)->modifiers() & Qt::ControlModifier) +            key+= Qt::CTRL; + +      // TODO: New WaveCanvas: Convert these to frames, and remove unneeded functions. +             +      // +      //  Shortcut for DrumEditor & PianoRoll +      //  Sets locators to selected events +      // +      if (key == shortcuts[SHRT_LOCATORS_TO_SELECTION].key) { +            int tick_max = 0; +            int tick_min = INT_MAX; +            bool found = false; + +            for (iCItem i= items.begin(); i != items.end(); i++) { +                  if (!i->second->isSelected()) +                        continue; + +                  int tick = i->second->x(); +                  int len = i->second->event().lenTick(); +                  found = true; +                  if (tick + len > tick_max) +                        tick_max = tick + len; +                  if (tick < tick_min) +                        tick_min = tick; +                  } +            if (found) { +                  MusECore::Pos p1(tick_min, true); +                  MusECore::Pos p2(tick_max, true); +                  MusEGlobal::song->setPos(1, p1); +                  MusEGlobal::song->setPos(2, p2); +                  } +            } +      // Select items by key (PianoRoll & DrumEditor) +      else if (key == shortcuts[SHRT_SEL_RIGHT].key || key == shortcuts[SHRT_SEL_RIGHT_ADD].key) { +              rciCItem i; + +              if (items.empty()) +                  return; +              for (i = items.rbegin(); i != items.rend(); ++i)  +                if (i->second->isSelected())  +                  break; + +              if(i == items.rend()) +                i = items.rbegin(); +               +              if(i != items.rbegin()) +                --i; +              if(i->second) +              { +                if (key != shortcuts[SHRT_SEL_RIGHT_ADD].key) +                      deselectAll(); +                CItem* sel = i->second; +                sel->setSelected(true); +                updateSelection(); +                if (sel->x() + sel->width() > mapxDev(width()))  +                {   +                  int mx = rmapx(sel->x());   +                  int newx = mx + rmapx(sel->width()) - width(); +                  // Leave a bit of room for the specially-drawn drum notes. But good for piano too. +                  emit horizontalScroll( (newx > mx ? mx - 10: newx + 10) - rmapx(xorg) ); +                }   +              } +            } +      //Select items by key: (PianoRoll & DrumEditor) +      else if (key == shortcuts[SHRT_SEL_LEFT].key || key == shortcuts[SHRT_SEL_LEFT_ADD].key) { +              ciCItem i; +              if (items.empty()) +                  return; +              for (i = items.begin(); i != items.end(); ++i) +                if (i->second->isSelected())  +                  break; + +              if(i == items.end()) +                i = items.begin(); +               +              if(i != items.begin()) +                --i; +              if(i->second) +              { +                if (key != shortcuts[SHRT_SEL_LEFT_ADD].key) +                      deselectAll(); +                CItem* sel = i->second; +                sel->setSelected(true); +                updateSelection(); +                if (sel->x() <= mapxDev(0))  +                  emit horizontalScroll(rmapx(sel->x() - xorg) - 10);  // Leave a bit of room. +              } +            } +      //else if (key == shortcuts[SHRT_INC_PITCH].key) { +      //      modifySelected(NoteInfo::VAL_PITCH, 1); +      //      } +      //else if (key == shortcuts[SHRT_DEC_PITCH].key) { +      //      modifySelected(NoteInfo::VAL_PITCH, -1); +      //      } +      else if (key == shortcuts[SHRT_INC_POS].key) { +            // TODO: Check boundaries +            modifySelected(NoteInfo::VAL_TIME, editor->raster()); +            } +      else if (key == shortcuts[SHRT_DEC_POS].key) { +            // TODO: Check boundaries +            modifySelected(NoteInfo::VAL_TIME, 0 - editor->raster()); +            } + +      else if (key == shortcuts[SHRT_INCREASE_LEN].key) { +            // TODO: Check boundaries +            modifySelected(NoteInfo::VAL_LEN, editor->raster()); +            } +      else if (key == shortcuts[SHRT_DECREASE_LEN].key) { +            // TODO: Check boundaries +            modifySelected(NoteInfo::VAL_LEN, 0 - editor->raster()); +            } + +      else +            event->ignore(); +      } + + +//--------------------------------------------------------- +//   setPos +//    set one of three markers +//    idx   - 0-cpos  1-lpos  2-rpos +//    flag  - emit followEvent() +//--------------------------------------------------------- + +void WaveCanvas::setPos(int idx, unsigned val, bool adjustScrollbar) +      { +      val = MusEGlobal::tempomap.tick2frame(val); +      if (pos[idx] == val) +            return; +      int opos = mapx(pos[idx]); +      int npos = mapx(val); + +      if (adjustScrollbar && idx == 0) { +            switch (MusEGlobal::song->follow()) { +                  case  MusECore::Song::NO: +                        break; +                  case MusECore::Song::JUMP: +                        if (npos >= width()) { +                              int ppos =  val - xorg - rmapxDev(width()/4); +                              if (ppos < 0) +                                    ppos = 0; +                              emit followEvent(ppos); +                              opos = mapx(pos[idx]); +                              npos = mapx(val); +                              } +                        else if (npos < 0) { +                              int ppos =  val - xorg - rmapxDev(width()*3/4); +                              if (ppos < 0) +                                    ppos = 0; +                              emit followEvent(ppos); +                              opos = mapx(pos[idx]); +                              npos = mapx(val); +                              } +                        break; +            case MusECore::Song::CONTINUOUS: +                        if (npos > (width()*5)/8) { +                              int ppos =  pos[idx] - xorg - rmapxDev(width()*5/8); +                              if (ppos < 0) +                                    ppos = 0; +                              emit followEvent(ppos); +                              opos = mapx(pos[idx]); +                              npos = mapx(val); +                              } +                        else if (npos < (width()*3)/8) { +                              int ppos =  pos[idx] - xorg - rmapxDev(width()*3/8); +                              if (ppos < 0) +                                    ppos = 0; +                              emit followEvent(ppos); +                              opos = mapx(pos[idx]); +                              npos = mapx(val); +                              } +                        break; +                  } +            } + +      int x; +      int w = 1; +      if (opos > npos) { +            w += opos - npos; +            x = npos; +            } +      else { +            w += npos - opos; +            x = opos; +            } +      pos[idx] = val; +      //redraw(QRect(x, 0, w, height())); +      redraw(QRect(x-1, 0, w+2, height()));    // From Canvas::draw (is otherwise identical). Fix for corruption. (TEST: New WaveCanvas: Still true?) +      } + +//--------------------------------------------------------- +//   setYScale +//--------------------------------------------------------- + +void WaveCanvas::setYScale(int val) +      { +      yScale = val; +      redraw(); +      } + +// TODO: Overridden because markers need tick2frame.  +//       After BBT/frame mode is added to Canvas, remove this override and let Canvas::draw do it. +//       Also add the drawParts calls to Canvas::draw, and add a dummy Canvas::drawParts { }. +//--------------------------------------------------------- +//   draw +//--------------------------------------------------------- + +void WaveCanvas::draw(QPainter& p, const QRect& r) +      { +      int x = r.x() < 0 ? 0 : r.x(); +      int y = r.y() < 0 ? 0 : r.y(); +      int w = r.width(); +      int h = r.height(); +      int x2 = x + w; + +      std::vector<CItem*> list1; +      std::vector<CItem*> list2; +      //std::vector<CItem*> list3; +      std::vector<CItem*> list4; + +      drawCanvas(p, r); + +      //--------------------------------------------------- +      // draw Canvas Items +      //--------------------------------------------------- + +      iCItem to(items.lower_bound(x2)); +       +      for(iCItem i = items.begin(); i != to; ++i) +      {  +        CItem* ci = i->second; +        // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents(). +        // Not required for now. +        //ci->part()->hasHiddenEvents(); +         +        // Draw items from other parts behind all others. Only for items with events (not arranger parts). +        if(!ci->event().empty() && ci->part() != curPart) +          list1.push_back(ci);     +        else if(!ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) +        { +          // Draw selected parts in front of all others. +          if(ci->isSelected())  +            list4.push_back(ci); +          // Draw clone parts, and parts with hidden events, in front of others all except selected. +          //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())) +          // Draw clone parts in front of others all except selected. +          //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1)) +          //  list3.push_back(ci); +          else   +            // Draw unselected parts. +            list2.push_back(ci); +        }   +      } + +      // Draw non-current part backgrounds behind all others: +      drawParts(p, r, false); +       +      int i; +      int sz = list1.size(); +      for(i = 0; i != sz; ++i)  +        drawItem(p, list1[i], r); +       +      // Draw current part background in front of all others: +      drawParts(p, r, true); +       +      sz = list2.size(); +      for(i = 0; i != sz; ++i)  +        drawItem(p, list2[i], r); + +      //sz = list3.size(); +      //for(i = 0; i != sz; ++i)  +      //  drawItem(p, list3[i], rect); +       +      sz = list4.size(); +      for(i = 0; i != sz; ++i)  +        drawItem(p, list4[i], r); +       +      to = moving.lower_bound(x2); +      for (iCItem i = moving.begin(); i != to; ++i)  +      { +            drawItem(p, i->second, r); +      } + +      drawTopItem(p,r); + + +      //--------------------------------------------------- +      //    draw marker +      //--------------------------------------------------- + +      bool wmtxen = p.worldMatrixEnabled(); +      p.setWorldMatrixEnabled(false); +       +      int my = mapy(y); +      int my2 = mapy(y + h); +       +      MusECore::MarkerList* marker = MusEGlobal::song->marker(); +      for (MusECore::iMarker m = marker->begin(); m != marker->end(); ++m) { +            int xp = MusEGlobal::tempomap.tick2frame(m->second.tick()); +            if (xp >= x && xp < x2) { +                  p.setPen(Qt::green); +                  p.drawLine(mapx(xp), my, mapx(xp), my2); +                  } +            } + +      //--------------------------------------------------- +      //    draw location marker +      //--------------------------------------------------- + +      // Tip: These positions are already in units of frames. +      p.setPen(Qt::blue); +      int mx; +      if (pos[1] >= unsigned(x) && pos[1] < unsigned(x2)) { +            mx = mapx(pos[1]); +            p.drawLine(mx, my, mx, my2); +            } +      if (pos[2] >= unsigned(x) && pos[2] < unsigned(x2)) { +            mx = mapx(pos[2]); +            p.drawLine(mx, my, mx, my2); +            } +      p.setPen(Qt::red); +      if (pos[0] >= unsigned(x) && pos[0] < unsigned(x2)) { +            mx = mapx(pos[0]); +            p.drawLine(mx, my, mx, my2); +            } +             +      //p.restore(); +      //p.setWorldMatrixEnabled(true); +      p.setWorldMatrixEnabled(wmtxen); +       +      //--------------------------------------------------- +      //    draw lasso +      //--------------------------------------------------- + +      if (drag == DRAG_LASSO) { +            p.setPen(Qt::blue); +            p.setBrush(Qt::NoBrush); +            p.drawRect(lasso); +            } +       +      //--------------------------------------------------- +      //    draw moving items +      //--------------------------------------------------- +       +      for(iCItem i = moving.begin(); i != moving.end(); ++i)  +        drawMoving(p, i->second, r); + +      } + +//--------------------------------------------------------- +//   drawWaveParts +//--------------------------------------------------------- + +void WaveCanvas::drawParts(QPainter& p, const QRect& r, bool do_cur_part) +{ +      //QRect rr = p.transform().mapRect(r);  // Gives inconsistent positions. Source shows wrong operation for our needs. +      QRect rr = map(r);                      // Use our own map instead.         + +      bool wmtxen = p.worldMatrixEnabled(); +      p.setWorldMatrixEnabled(false); + +      if(do_cur_part) +      { +        // Draw current part: +        if(curPart) +        { +              QRect mwpr  = map(QRect(curPart->frame(), 0, curPart->lenFrame(), height())); +              QRect mpbgr = rr & mwpr; +              if(!mpbgr.isNull()) +              { +                QColor c; +                switch(colorMode) +                { +                  default: +                  case 0: +                    c = MusEGlobal::config.partColors[curPart->colorIndex()]; +                    break; +                  case 1: +                    c = Qt::lightGray; +                    break; +                } +                c.setAlpha(MusEGlobal::config.globalAlphaBlend); +                QBrush part_bg_brush(MusECore::gGradientFromQColor(c, mwpr.topLeft(), mwpr.bottomLeft())); +                p.fillRect(mpbgr, part_bg_brush); +              } +        }      +      } +      else +      { +        // Draw non-current parts: +        for (MusECore::iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)  +        { +              MusECore::WavePart* wp = (MusECore::WavePart*)(ip->second); +              if(wp == curPart) +                continue; +               +              QRect mwpr  = map(QRect(wp->frame(), 0, wp->lenFrame(), height())); +              QRect mpbgr = rr & mwpr; +              if(!mpbgr.isNull()) +              { +                //int cidx = wp->colorIndex(); +                //QColor c(MusEGlobal::config.partColors[cidx]); +                QColor c(Qt::darkGray); +                c.setAlpha(MusEGlobal::config.globalAlphaBlend); +                QBrush part_bg_brush(MusECore::gGradientFromQColor(c, mwpr.topLeft(), mwpr.bottomLeft())); +                p.fillRect(mpbgr, part_bg_brush); +              } +        }      +      } +       +      p.setWorldMatrixEnabled(wmtxen); +} +       +// TODO: Overridden because we're in units of frames.  +//       After BBT/frame mode is added to Canvas, remove this override and let View or Canvas do it. +//--------------------------------------------------------- +//   drawTickRaster +//--------------------------------------------------------- + +void WaveCanvas::drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster) +      { +      // Changed to draw in device coordinate space instead of virtual, transformed space. Tim.  +       +      //int mx = mapx(x); +      int my = mapy(y); +      //int mw = mapx(x + w) - mx; +      //int mw = mapx(x + w) - mx - 1; +      //int mh = mapy(y + h) - my; +      //int mh = mapy(y + h) - my - 1; +       +      //p.save(); +      bool wmtxen = p.worldMatrixEnabled(); +      p.setWorldMatrixEnabled(false); +       +      int xx,bar1, bar2, beat; +      unsigned tick; +//      AL::sigmap.tickValues(x, &bar1, &beat, &tick); +//      AL::sigmap.tickValues(x+w, &bar2, &beat, &tick); +      AL::sigmap.tickValues(MusEGlobal::tempomap.frame2tick(x), &bar1, &beat, &tick); +      AL::sigmap.tickValues(MusEGlobal::tempomap.frame2tick(x+w), &bar2, &beat, &tick); +      ++bar2; +      ///int y2 = y + h; +      //int y2 = my + mh; +      int y2 = mapy(y + h) - 1; +      //printf("View::drawTickRaster x:%d y:%d w:%d h:%d mx:%d my:%d mw:%d mh:%d y2:%d bar1:%d bar2:%d\n", x, y, w, h, mx, my, mw, mh, y2, bar1, bar2);   +      //printf("View::drawTickRaster x:%d y:%d w:%d h:%d my:%d mh:%d y2:%d bar1:%d bar2:%d\n", x, y, w, h, my, mh, y2, bar1, bar2);   +      for (int bar = bar1; bar < bar2; ++bar) { +         +//            unsigned xb = AL::sigmap.bar2tick(bar, 0, 0); +            unsigned xb = AL::sigmap.bar2tick(bar, 0, 0); +            int xt = mapx(MusEGlobal::tempomap.tick2frame(xb)); +            p.setPen(Qt::black); +            p.drawLine(xt, my, xt, y2); +             +            int z, n; +            AL::sigmap.timesig(xb, z, n); +            int qq = raster; +            if (rmapx(raster) < 8)        // grid too dense +                  qq *= 2; +            p.setPen(Qt::lightGray); +            if (raster>=4) { +                        xx = xb + qq; +                        int xxx = MusEGlobal::tempomap.tick2frame(AL::sigmap.bar2tick(bar, z, 0)); +                        //while (MusEGlobal::tempomap.tick2frame(xx) <= xxx) { +                        while (1) { +                               int xxf = MusEGlobal::tempomap.tick2frame(xx); +                               if(xxf > xxx) +                                 break; +                               //int x = mapx(MusEGlobal::tempomap.tick2frame(xx)); +                               int x = mapx(xxf); +                               p.drawLine(x, my, x, y2); +                               xx += qq; +                               } +                        } +            p.setPen(Qt::gray); +            for (int beat = 1; beat < z; beat++) { +                        xx = mapx(MusEGlobal::tempomap.tick2frame(AL::sigmap.bar2tick(bar, beat, 0))); +                        //printf(" bar:%d z:%d beat:%d xx:%d\n", bar, z, beat, xx);   +                        p.drawLine(xx, my, xx, y2); +                        } + +            } +      p.setWorldMatrixEnabled(wmtxen); +      } + +// TODO: Overridden because we're in units of frames.  +//       After BBT/frame mode is added to Canvas, remove this override and let Canvas do it. +//--------------------------------------------------------- +//   raster +//--------------------------------------------------------- + +QPoint WaveCanvas::raster(const QPoint& p) const +      { +      int x = p.x(); +      if (x < 0) +            x = 0; +      //x = editor->rasterVal(x); +      x = MusEGlobal::tempomap.tick2frame(editor->rasterVal(MusEGlobal::tempomap.frame2tick(x))); +      int pitch = y2pitch(p.y()); +      int y = pitch2y(pitch); +      return QPoint(x, y); +      } + +#define WHEEL_STEPSIZE 40 +#define WHEEL_DELTA   120 +//--------------------------------------------------------- +//   wheelEvent +//--------------------------------------------------------- +void WaveCanvas::wheelEvent(QWheelEvent* ev) +{ +  int keyState = ev->modifiers(); + +  bool shift      = keyState & Qt::ShiftModifier; +  bool ctrl       = keyState & Qt::ControlModifier; + +  if (shift) { // scroll vertically +      int delta       = -ev->delta() / WHEEL_DELTA; +      int xpixelscale = 5*MusECore::fast_log10(rmapxDev(1)); + + +      if (xpixelscale <= 0) +            xpixelscale = 1; + +      int scrollstep = WHEEL_STEPSIZE * (delta); +      ///if (ev->state() == Qt::ShiftModifier) +  //      if (((QInputEvent*)ev)->modifiers() == Qt::ShiftModifier) +      scrollstep = scrollstep / 10; + +      int newXpos = xpos + xpixelscale * scrollstep; + +      if (newXpos < 0) +            newXpos = 0; + +      //setYPos(newYpos); +      emit horizontalScroll((unsigned)newXpos); + + +  } else if (ctrl) {  // zoom horizontally +    if (ev->delta()>0) +      emit horizontalZoomIn(); +    else +      emit horizontalZoomOut(); + +  } else { // scroll horizontally +      emit mouseWheelMoved(ev->delta() / 10); +  } + +} + +//--------------------------------------------------------- +//   viewMousePressEvent +//--------------------------------------------------------- + +bool WaveCanvas::mousePress(QMouseEvent* event) +      { +    if (event->modifiers() & Qt::ControlModifier) { +            return true; +            } +      button = event->button(); +      QPoint pt = event->pos(); +      //CItem* item = items.find(pt); +      unsigned x = event->x(); + +      switch (_tool) { +            default: +                  break; +             case CursorTool: +                  switch (button) { +                        case Qt::LeftButton: +                              if (mode == NORMAL) { +                                    // redraw and reset: +                                    if (selectionStart != selectionStop) { +                                          selectionStart = selectionStop = 0; +                                          redraw(); +                                          } +                                    mode = DRAG; +                                    dragstartx = x; +                                    selectionStart = selectionStop = x; +                                    drag = DRAG_LASSO_START; +                                    Canvas::start = pt; +                                    return false; +                                    } +                              break; + +                        case Qt::MidButton: +                        case Qt::RightButton: +                        default: +                              break; +                        } + +                   break; +            } +      return true; +      } + +//--------------------------------------------------------- +//   viewMouseReleaseEvent +//--------------------------------------------------------- + +void WaveCanvas::mouseRelease(const QPoint&) +      { +      button = Qt::NoButton; +      if (mode == DRAG) { +            mode = NORMAL; +            } +      } + +//--------------------------------------------------------- +//   viewMousevent +//--------------------------------------------------------- + +void WaveCanvas::mouseMove(QMouseEvent* event) +      { +      int x = event->x(); +      if (x < 0) +            x = 0; +      emit timeChanged(x); +      //emit timeChanged(editor->rasterVal(x)); +      //emit timeChanged(AL::sigmap.raster(x, *_raster)); + +      switch (button) { +            case Qt::LeftButton: +                  if (mode == DRAG) { +                        int mx      = mapx(x); +                        int mstart  = mapx(selectionStart); +                        int mstop   = mapx(selectionStop); +                        //int mdstart = mapx(dragstartx); +                        QRect r(0, 0, 0, height()); +                         +                        if (x < dragstartx) { +                              if(x < selectionStart) +                              { +                                r.setLeft(mx); +                                r.setWidth((selectionStop >= dragstartx ? mstop : mstart) - mx); +                              } +                              else +                              { +                                r.setLeft(mstart); +                                r.setWidth(mx - mstart); +                              } +                              selectionStart = x; +                              selectionStop = dragstartx; +                              } +                        else { +                              if(x >= selectionStop) +                              { +                                r.setLeft(selectionStart < dragstartx ? mstart : mstop); +                                r.setWidth(mx - (selectionStart < dragstartx ? mstart : mstop)); +                              } +                              else +                              { +                                r.setLeft(mx); +                                r.setWidth(mstop - mx); +                              } +                              selectionStart = dragstartx; +                              selectionStop = x; +                              } +                        update(r); +                        } +                  break; +            case Qt::MidButton: +                  break; +            case Qt::RightButton: +                  break; +            default: +                  return; +            } +      } +       +//--------------------------------------------------------- +//   pitch2y +//--------------------------------------------------------- + +int WaveCanvas::pitch2y(int) const +      { +      return 0; +      } + +//--------------------------------------------------------- +//   y2pitch +//--------------------------------------------------------- + +int WaveCanvas::y2pitch(int) const +      { +      return 0; +      } + +//--------------------------------------------------------- +//   drawItem +//    draws a wave +//--------------------------------------------------------- + +void WaveCanvas::drawItem(QPainter& p, const MusEGui::CItem* item, const QRect& rect) +{ +      MusECore::WavePart* wp = (MusECore::WavePart*)(item->part()); +      if(!wp || !wp->track()) +        return; + +      //QRect rr = p.transform().mapRect(rect);  // Gives inconsistent positions. Source shows wrong operation for our needs. +      QRect rr = map(rect);                      // Use our own map instead.         + +      QRect mwpr  = map(QRect(wp->frame(), 0, wp->lenFrame(), height())); +       +      QRect r = item->bbox(); +      QRect mer = map(r);                               +      QRect mr = rr & mer & mwpr; +      if(mr.isNull()) +        return; +       +      MusECore::Event event  = item->event(); +      if(event.empty()) +        return; +       +      int x1 = mr.x(); +      int x2 = mr.right() + 1; +      if (x1 < 0) +            x1 = 0; +      if (x2 > width()) +            x2 = width(); +      int hh = height(); +      int h  = hh/2; +      int y  = mr.y() + h; + +      int xScale = xmag; +      if (xScale < 0) +            xScale = -xScale; + +      //int t_channels = wp->track()->channels(); +      int px = wp->frame(); + +      bool wmtxen = p.worldMatrixEnabled(); +      p.setWorldMatrixEnabled(false); + +      int sx, ex; +       +      sx = event.frame() + px + xScale/2; +      ex = sx + event.lenFrame(); +      sx = sx / xScale - xpos; +      ex = ex / xScale - xpos; + +      if (sx < x1) +            sx = x1; +      if (ex > x2) +            ex = x2; + +      int pos = (xpos + sx) * xScale + event.spos() - event.frame() - px; +       +      //printf("pos=%d xpos=%d sx=%d ex=%d xScale=%d event.spos=%d event.frame=%d px=%d\n",    +      //      pos, xpos, sx, ex, xScale, event.spos(), event.frame(), px); + +       +      QBrush brush; +      if (item->isMoving())  +      { +            QColor c(Qt::gray); +            c.setAlpha(MusEGlobal::config.globalAlphaBlend); +            QLinearGradient gradient(r.topLeft(), r.bottomLeft()); +            gradient.setColorAt(0, c); +            gradient.setColorAt(1, c.darker()); +            brush = QBrush(gradient); +            p.fillRect(sx, 0, ex - sx, hh, brush); +      } +      else  +      if (item->isSelected())  +      { +          QColor c(Qt::black); +          c.setAlpha(MusEGlobal::config.globalAlphaBlend); +          QLinearGradient gradient(r.topLeft(), r.bottomLeft()); +          // Use a colour only about 20% lighter than black, rather than the 50% we use in MusECore::gGradientFromQColor +          //  and is used in darker()/lighter(), so that it is distinguished a bit better from grey non-part tracks. +          //c.setRgba(64, 64, 64, c.alpha());         +          gradient.setColorAt(0, QColor(51, 51, 51, MusEGlobal::config.globalAlphaBlend)); +          gradient.setColorAt(1, c); +          brush = QBrush(gradient); +          p.fillRect(sx, 0, ex - sx, hh, brush); +      } +      //else +      { +            QPen pen(Qt::DashLine); +            pen.setColor(Qt::black); +            pen.setCosmetic(true); +            p.setPen(pen); +            p.drawRect(sx, 0, ex - sx, hh); +      }   +      //p.fillRect(sx, 0, ex - sx, hh, brush); +      //p.drawRect(sx, 0, ex - sx, hh, brush); +       +      MusECore::SndFileR f = event.sndFile(); +      if(f.isNull()) +      { +        p.setWorldMatrixEnabled(wmtxen); +        return; +      } +       +      int ev_channels = f.channels(); +      if (ev_channels == 0) { +            p.setWorldMatrixEnabled(wmtxen); +            printf("WaveCnvas::drawItem: ev_channels==0! %s\n", f.name().toLatin1().constData()); +            return; +            } +                   +      h       = hh / (ev_channels * 2); +      int cc  = hh % (ev_channels * 2) ? 0 : 1; + +      unsigned peoffset = px + event.frame() - event.spos(); +       +      for (int i = sx; i < ex; i++) { +            y  = mr.y() + h; +            MusECore::SampleV sa[f.channels()]; +            f.read(sa, xScale, pos); +            pos += xScale; +            if (pos < event.spos()) +                  continue; + +            int selectionStartPos = selectionStart - peoffset; // Offset transformed to event coords +            int selectionStopPos  = selectionStop  - peoffset; + +            for (int k = 0; k < ev_channels; ++k) { +                  int kk = k % f.channels(); +                  int peak = (sa[kk].peak * (h - 1)) / yScale; +                  int rms  = (sa[kk].rms  * (h - 1)) / yScale; +                  if (peak > h) +                        peak = h; +                  if (rms > h) +                        rms = h; +                  QColor peak_color = QColor(Qt::darkGray); +                  QColor rms_color  = QColor(Qt::black); +                   +                  // Changed by T356. Reduces (but not eliminates) drawing artifacts. (TODO Cause of artifacts gone, correct this now.) +                  //if (pos > selectionStartPos && pos < selectionStopPos) { +                  if (pos > selectionStartPos && pos <= selectionStopPos) { +                         +                        peak_color = QColor(Qt::lightGray); +                        rms_color  = QColor(Qt::white); +                        // Draw inverted +                        p.setPen(QColor(Qt::black)); +                        p.drawLine(i, y - h + cc, i, y + h - cc ); +                        } +                  p.setPen(peak_color); +                  p.drawLine(i, y - peak - cc, i, y + peak); +                  p.setPen(rms_color); +                  p.drawLine(i, y - rms - cc, i, y + rms); +                  y  += 2 * h; +                  } +            } +             + +      int hn = hh / ev_channels; +      int hhn = hn / 2; +      for (int i = 0; i < ev_channels; ++i) { +            int h2     = hn * i; +            int center = hhn + h2; +            p.setPen(QColor(i & i ? Qt::red : Qt::blue)); +            p.drawLine(sx, center, ex, center); +            p.setPen(QColor(Qt::black)); +            p.drawLine(sx, h2, ex, h2); +            } +             +      p.setWorldMatrixEnabled(wmtxen); +} + +//--------------------------------------------------------- +//   drawTopItem +//--------------------------------------------------------- +void WaveCanvas::drawTopItem(QPainter& , const QRect&) +{} + +//--------------------------------------------------------- +//   drawMoving +//    draws moving items +//--------------------------------------------------------- + +void WaveCanvas::drawMoving(QPainter& p, const MusEGui::CItem* item, const QRect& rect) +    { +      QRect mr = QRect(item->mp().x(), item->mp().y(), item->width(), item->height()); +      mr = mr.intersected(rect); +      if(!mr.isValid()) +        return; +      p.setPen(Qt::black); +      p.setBrush(QColor(0, 128, 0, 128));  // TODO: Pick a better colour, or use part colours, or grey? +      p.drawRect(mr); +    } + +//--------------------------------------------------------- +//   viewMouseDoubleClickEvent +//--------------------------------------------------------- + +void WaveCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) +      { +      if ((_tool != MusEGui::PointerTool) && (event->button() != Qt::LeftButton)) { +            mousePress(event); +            return; +            } +      } + +//--------------------------------------------------------- +//   moveCanvasItems +//--------------------------------------------------------- + +MusECore::Undo WaveCanvas::moveCanvasItems(MusEGui::CItemList& items, int /*dp*/, int dx, DragType dtype) +{       +  if(editor->parts()->empty()) +    return MusECore::Undo(); //return empty list +   +  MusECore::PartsToChangeMap parts2change; +  MusECore::Undo operations;   +   +  for(MusECore::iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) +  { +    MusECore::Part* part = ip->second; +    if(!part) +      continue; +     +    int npartoffset = 0; +    for(MusEGui::iCItem ici = items.begin(); ici != items.end(); ++ici)  +    { +      MusEGui::CItem* ci = ici->second; +      if(ci->part() != part) +        continue; +       +      int x = ci->pos().x() + dx; +      //int y = pitch2y(y2pitch(ci->pos().y()) + dp); +      int y = 0; +      QPoint newpos = raster(QPoint(x, y)); +       +      // Test moving the item... +      WEvent* wevent = (WEvent*) ci; +      MusECore::Event event    = wevent->event(); +      x              = newpos.x(); +      if(x < 0) +        x = 0; +      int nframe = MusEGlobal::tempomap.tick2frame(editor->rasterVal(MusEGlobal::tempomap.frame2tick(x))) - part->frame(); +      if(nframe < 0) +        nframe = 0; +      int diff = nframe + event.lenFrame() - part->lenFrame(); +       +      // If moving the item would require a new part size... +      if(diff > npartoffset) +        npartoffset = diff; +    } +         +    if(npartoffset > 0) +    {     +      MusECore::iPartToChange ip2c = parts2change.find(part); +      if(ip2c == parts2change.end()) +      { +        MusECore::PartToChange p2c = {0, npartoffset}; +        parts2change.insert(std::pair<MusECore::Part*, MusECore::PartToChange> (part, p2c)); +      } +      else +        ip2c->second.xdiff = npartoffset; +    } +  } +   +  bool forbidden=false; +  for(MusECore::iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) +  { +    MusECore::Part* opart = ip2c->first; +    if (opart->hasHiddenEvents()) +    { +                        forbidden=true; +                        break; +                } +  }     + +         +        if (!forbidden) +        { +                std::vector< MusEGui::CItem* > doneList; +                typedef std::vector< MusEGui::CItem* >::iterator iDoneList; +                 +                for(MusEGui::iCItem ici = items.begin(); ici != items.end(); ++ici)  +                { +                        MusEGui::CItem* ci = ici->second; +                         +                        int x = ci->pos().x(); +                        //int y = ci->pos().y(); +                        int nx = x + dx; +                        //int ny = pitch2y(y2pitch(y) + dp); +                        int ny = 0; +                        QPoint newpos = raster(QPoint(nx, ny)); +                        selectItem(ci, true); +                         +                        iDoneList idl; +                        for(idl = doneList.begin(); idl != doneList.end(); ++idl) +                                // This compares EventBase pointers to see if they're the same... +                                if((*idl)->event() == ci->event()) +                                        break; +                                 +                        // Do not process if the event has already been processed (meaning it's an event in a clone part)... +                        if (idl == doneList.end()) +                        { +                                moveItem(operations, ci, newpos, dtype); // always returns true. if not, change is necessary here! +                                doneList.push_back(ci); +                        } +                        ci->move(newpos); +                                                 +                        if(moving.size() == 1)  +                                                itemReleased(curItem, newpos); + +                        if(dtype == MOVE_COPY || dtype == MOVE_CLONE) +                                                selectItem(ci, false); +                }   + +    for(MusECore::iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) +    { +      MusECore::Part* opart = ip2c->first; +      int diff = ip2c->second.xdiff; +       +      //schedule_resize_all_same_len_clone_parts(opart, opart->lenTick() + diff, operations); +      schedule_resize_all_same_len_clone_parts(opart, opart->lenFrame() + diff, operations); +    }     +                                         +        return operations; +  } +  else +  { +                return MusECore::Undo(); //return empty list +        } +} +       +//--------------------------------------------------------- +//   moveItem +//    called after moving an object +//--------------------------------------------------------- + +bool WaveCanvas::moveItem(MusECore::Undo& operations, MusEGui::CItem* item, const QPoint& pos, DragType dtype) +      { +      WEvent* wevent = (WEvent*) item; +      MusECore::Event event    = wevent->event(); +      //int npitch     = y2pitch(pos.y()); +      MusECore::Event newEvent = event.clone(); +      int x          = pos.x(); +      if (x < 0) +            x = 0; +       +      MusECore::Part* part = wevent->part(); +      int nframe = MusEGlobal::tempomap.tick2frame(editor->rasterVal(MusEGlobal::tempomap.frame2tick(x))) - part->frame(); +      if (nframe < 0) +            nframe = 0; +      newEvent.setFrame(nframe); +      newEvent.setLenFrame(event.lenFrame()); + +      // don't check, whether the new event is within the part +      // at this place. with operation groups, the part isn't +      // resized yet. (flo93) +       +      if (dtype == MOVE_COPY || dtype == MOVE_CLONE) +            operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, part, false, false)); +      else +            operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false)); +       +      return true; +} + +//--------------------------------------------------------- +//   newItem(p, state) +//--------------------------------------------------------- + +MusEGui::CItem* WaveCanvas::newItem(const QPoint& p, int) +      { +      int frame  = MusEGlobal::tempomap.tick2frame(editor->rasterVal1(MusEGlobal::tempomap.frame2tick(p.x()))); +      int len   = p.x() - frame; +      frame     -= curPart->frame(); +      if (frame < 0) +            return 0; +      MusECore::Event e =  MusECore::Event(MusECore::Wave); +      e.setFrame(frame); +      e.setLenFrame(len); +      WEvent* we = new WEvent(e, curPart, height()); +      return we; +      } + +void WaveCanvas::newItem(MusEGui::CItem* item, bool noSnap) +      { +      WEvent* wevent = (WEvent*) item; +      MusECore::Event event    = wevent->event(); +      int x = item->x(); +      if (x<0) +            x=0; +      int w = item->width(); + +      if (!noSnap) { +            //x = editor->rasterVal1(x); //round down +            x = MusEGlobal::tempomap.tick2frame(editor->rasterVal1(MusEGlobal::tempomap.frame2tick(x))); //round down +            //w = editor->rasterVal(x + w) - x; +            w = MusEGlobal::tempomap.tick2frame(editor->rasterVal(MusEGlobal::tempomap.frame2tick(x + w))) - x; +            if (w == 0) +                  //w = editor->raster(); +                  w = MusEGlobal::tempomap.tick2frame(editor->raster()); +            } +      MusECore::Part* part = wevent->part(); +      event.setFrame(x - part->frame()); +      event.setLenFrame(w); + +      MusECore::Undo operations; +      int diff = event.endFrame() - part->lenFrame(); +       +      if (! ((diff > 0) && part->hasHiddenEvents()) ) //operation is allowed +      { +        operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent,event, part, false, false)); +         +        if (diff > 0)// part must be extended? +        { +              //schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations); +              schedule_resize_all_same_len_clone_parts(part, event.endFrame(), operations); +              printf("newItem: extending\n"); +        } +         +        MusEGlobal::song->applyOperationGroup(operations); +      } +      else // forbid action by not applying it    +          songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary +                                          //to remove "forbidden" events from the list again +      } + +//--------------------------------------------------------- +//   resizeItem +//--------------------------------------------------------- + +void WaveCanvas::resizeItem(MusEGui::CItem* item, bool noSnap, bool)         // experimental changes to try dynamically extending parts +      { +      WEvent* wevent = (WEvent*) item; +      MusECore::Event event    = wevent->event(); +      MusECore::Event newEvent = event.clone(); +      int len; + +      MusECore::Part* part = wevent->part(); + +      if (noSnap) +            len = wevent->width(); +      else { +            unsigned frame = event.frame() + part->frame(); +            //len = editor->rasterVal(tick + wevent->width()) - tick; +            len = MusEGlobal::tempomap.tick2frame(editor->rasterVal(MusEGlobal::tempomap.frame2tick(frame + wevent->width()))) - frame; +            if (len <= 0) +                  //len = editor->raster(); +                  len = MusEGlobal::tempomap.tick2frame(editor->raster()); +      } + +      MusECore::Undo operations; +      //int diff = event.tick()+len-part->lenTick(); +      int diff = event.frame() + len - part->lenFrame(); +       +      if (! ((diff > 0) && part->hasHiddenEvents()) ) //operation is allowed +      { +        //newEvent.setLenTick(len); +        newEvent.setLenFrame(len); +        operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent,newEvent, event, wevent->part(), false, false)); +         +        if (diff > 0)// part must be extended? +        { +              //schedule_resize_all_same_len_clone_parts(part, event.tick()+len, operations); +              schedule_resize_all_same_len_clone_parts(part, event.frame() + len, operations); +              printf("resizeItem: extending\n"); +        } +      } +      //else forbid action by not performing it +      MusEGlobal::song->applyOperationGroup(operations); +      songChanged(SC_EVENT_MODIFIED); //this forces an update of the itemlist, which is neccessary +                                      //to remove "forbidden" events from the list again +      } + +//--------------------------------------------------------- +//   deleteItem +//--------------------------------------------------------- + +bool WaveCanvas::deleteItem(MusEGui::CItem* item) +      { +      WEvent* wevent = (WEvent*) item; +      if (wevent->part() == curPart) { +            MusECore::Event ev = wevent->event(); +            // Indicate do undo, and do not do port controller values and clone parts.  +            MusEGlobal::audio->msgDeleteEvent(ev, curPart, true, false, false); +            return true; +            } +      return false; +      } + +//--------------------------------------------------------- +//   draw +//--------------------------------------------------------- + +void WaveCanvas::drawCanvas(QPainter& p, const QRect& rect) +      { +      int x = rect.x(); +      int y = rect.y(); +      int w = rect.width(); +      int h = rect.height(); + +      //--------------------------------------------------- +      // vertical lines +      //--------------------------------------------------- + +      drawTickRaster(p, x, y, w, h, editor->raster()); +      } + +//--------------------------------------------------------- +//   waveCmd +//--------------------------------------------------------- + +void WaveCanvas::waveCmd(int cmd) +      { +      // TODO: New WaveCanvas: Convert this routine to frames.   +      switch(cmd) { +            case CMD_LEFT: +                  { +                  int spos = pos[0]; +                  if(spos > 0)  +                  { +                    spos -= 1;     // Nudge by -1, then snap down with raster1. +                    spos = AL::sigmap.raster1(spos, editor->rasterStep(pos[0])); +                  }   +                  if(spos < 0) +                    spos = 0; +                  MusECore::Pos p(spos,true); +                  MusEGlobal::song->setPos(0, p, true, true, true); +                  } +                  break; +            case CMD_RIGHT: +                  { +                  int spos = AL::sigmap.raster2(pos[0] + 1, editor->rasterStep(pos[0]));    // Nudge by +1, then snap up with raster2. +                  MusECore::Pos p(spos,true); +                  MusEGlobal::song->setPos(0, p, true, true, true);  +                  } +                  break; +            case CMD_LEFT_NOSNAP: +                  { +                  int spos = pos[0] - editor->rasterStep(pos[0]); +                  if (spos < 0) +                        spos = 0; +                  MusECore::Pos p(spos,true); +                  MusEGlobal::song->setPos(0, p, true, true, true); //CDW +                  } +                  break; +            case CMD_RIGHT_NOSNAP: +                  { +                  MusECore::Pos p(pos[0] + editor->rasterStep(pos[0]), true); +                  MusEGlobal::song->setPos(0, p, true, true, true); //CDW +                  } +                  break; +            case CMD_INSERT: +                  { +                  if (pos[0] < start() || pos[0] >= end()) +                        break; +                  MusECore::MidiPart* part = (MusECore::MidiPart*)curPart; + +                  if (part == 0) +                        break; + +                  MusECore::EventList* el = part->events(); +                  MusECore::Undo operations; + +                  std::list <MusECore::Event> elist; +                  for (MusECore::iEvent e = el->lower_bound(pos[0] - part->tick()); e != el->end(); ++e) +                        elist.push_back((MusECore::Event)e->second); +                  for (std::list<MusECore::Event>::iterator i = elist.begin(); i != elist.end(); ++i) { +                        MusECore::Event event = *i; +                        MusECore::Event newEvent = event.clone(); +                        newEvent.setTick(event.tick() + editor->raster());// - part->tick()); DELETETHIS +                        // Do not do port controller values and clone parts.  +                        operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false)); +                        } +                  MusEGlobal::song->applyOperationGroup(operations); +                   +                  MusECore::Pos p(editor->rasterVal(pos[0] + editor->rasterStep(pos[0])), true); +                  MusEGlobal::song->setPos(0, p, true, false, true); +                  } +                  return; +            case CMD_BACKSPACE: +                  if (pos[0] < start() || pos[0] >= end()) +                        break; +                  { +                  MusECore::MidiPart* part = (MusECore::MidiPart*)curPart; +                  if (part == 0) +                        break; +                   +                  MusECore::Undo operations; +                  MusECore::EventList* el = part->events(); + +                  std::list<MusECore::Event> elist; +                  for (MusECore::iEvent e = el->lower_bound(pos[0]); e != el->end(); ++e) +                        elist.push_back((MusECore::Event)e->second); +                  for (std::list<MusECore::Event>::iterator i = elist.begin(); i != elist.end(); ++i) { +                        MusECore::Event event = *i; +                        MusECore::Event newEvent = event.clone(); +                        newEvent.setTick(event.tick() - editor->raster() - part->tick()); +                        // Do not do port controller values and clone parts.  +                        operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false)); +                        } +                  MusEGlobal::song->applyOperationGroup(operations); +                  MusECore::Pos p(editor->rasterVal(pos[0] - editor->rasterStep(pos[0])), true); +                  MusEGlobal::song->setPos(0, p, true, false, true); +                  } +                  break; +            } +      } + +//--------------------------------------------------------- +//   cmd +//    pulldown menu commands +//--------------------------------------------------------- + +void WaveCanvas::cmd(int cmd) +      { +      int modifyoperation = -1; +      double paramA = 0.0; +      switch (cmd) { +            case CMD_SELECT_ALL:     // select all +                  if (tool() == MusEGui::CursorTool)  +                  { +                    if (!editor->parts()->empty()) { +                          MusECore::iPart iBeg = editor->parts()->begin(); +                          MusECore::iPart iEnd = editor->parts()->end(); +                          iEnd--; +                          MusECore::WavePart* beg = (MusECore::WavePart*) iBeg->second; +                          MusECore::WavePart* end = (MusECore::WavePart*) iEnd->second; +                          selectionStart = beg->frame(); +                          selectionStop  = end->frame() + end->lenFrame(); +                          redraw(); +                          } +                  } +                  for (MusEGui::iCItem k = items.begin(); k != items.end(); ++k) { +                        if (!k->second->isSelected()) +                              selectItem(k->second, true); +                        } +                  break; +            case CMD_SELECT_NONE:     // select none +                  selectionStart = selectionStop = 0; +                  deselectAll(); +                  break; +            case CMD_SELECT_INVERT:     // invert selection +                  for (MusEGui::iCItem k = items.begin(); k != items.end(); ++k) { +                        selectItem(k->second, !k->second->isSelected()); +                        } +                  break; +            case CMD_SELECT_ILOOP:     // select inside loop +                  for (MusEGui::iCItem k = items.begin(); k != items.end(); ++k) { +                        WEvent* wevent = (WEvent*)(k->second); +                        MusECore::Part* part     = wevent->part(); +                        MusECore::Event event    = wevent->event(); +                        unsigned tick  = event.tick() + part->tick(); +                        if (tick < MusEGlobal::song->lpos() || tick >= MusEGlobal::song->rpos()) +                              selectItem(k->second, false); +                        else +                              selectItem(k->second, true); +                        } +                  break; +            case CMD_SELECT_OLOOP:     // select outside loop +                  for (MusEGui::iCItem k = items.begin(); k != items.end(); ++k) { +                        WEvent* wevent = (WEvent*)(k->second); +                        MusECore::Part* part     = wevent->part(); +                        MusECore::Event event    = wevent->event(); +                        unsigned tick  = event.tick() + part->tick(); +                        if (tick < MusEGlobal::song->lpos() || tick >= MusEGlobal::song->rpos()) +                              selectItem(k->second, true); +                        else +                              selectItem(k->second, false); +                        } +                  break; +            case CMD_SELECT_PREV_PART:     // select previous part +                  { +                    MusECore::Part* pt = editor->curCanvasPart(); +                    MusECore::Part* newpt = pt; +                    MusECore::PartList* pl = editor->parts(); +                    for(MusECore::iPart ip = pl->begin(); ip != pl->end(); ++ip) +                      if(ip->second == pt)  +                      { +                        if(ip == pl->begin()) +                          ip = pl->end(); +                        --ip; +                        newpt = ip->second; +                        break;     +                      } +                    if(newpt != pt) +                      editor->setCurCanvasPart(newpt); +                  } +                  break; +            case CMD_SELECT_NEXT_PART:     // select next part +                  { +                    MusECore::Part* pt = editor->curCanvasPart(); +                    MusECore::Part* newpt = pt; +                    MusECore::PartList* pl = editor->parts(); +                    for(MusECore::iPart ip = pl->begin(); ip != pl->end(); ++ip) +                      if(ip->second == pt)  +                      { +                        ++ip; +                        if(ip == pl->end()) +                          ip = pl->begin(); +                        newpt = ip->second; +                        break;     +                      } +                    if(newpt != pt) +                      editor->setCurCanvasPart(newpt); +                  } +                  break; +                  +                   +            case CMD_EDIT_EXTERNAL: +                  modifyoperation = EDIT_EXTERNAL; +                  break; + +            case CMD_EDIT_COPY: +                  modifyoperation = COPY; +                  break; +            case CMD_EDIT_CUT: +                  modifyoperation = CUT; +                  break; +            case CMD_EDIT_PASTE: +                  modifyoperation = PASTE; +                  break; + +            case CMD_MUTE: +                  modifyoperation = MUTE; +                  break; + +            case CMD_NORMALIZE: +                  modifyoperation = NORMALIZE; +                  break; + +            case CMD_FADE_IN: +                  modifyoperation = FADE_IN; +                  break; + +            case CMD_FADE_OUT: +                  modifyoperation = FADE_OUT; +                  break; + +            case CMD_REVERSE: +                  modifyoperation = REVERSE; +                  break; + +            case CMD_GAIN_FREE: { +                  EditGain* editGain = new EditGain(this, lastGainvalue); +                  if (editGain->exec() == QDialog::Accepted) { +                        lastGainvalue = editGain->getGain(); +                        modifyoperation = GAIN; +                        paramA = (double)lastGainvalue / 100.0; +                        } +                  delete editGain; +                  } +                  break; + +            case CMD_GAIN_200: +                  modifyoperation = GAIN; +                  paramA = 2.0; +                  break; + +            case CMD_GAIN_150: +                  modifyoperation = GAIN; +                  paramA = 1.5; +                  break; + +            case CMD_GAIN_75: +                  modifyoperation = GAIN; +                  paramA = 0.75; +                  break; + +            case CMD_GAIN_50: +                  modifyoperation = GAIN; +                  paramA = 0.5; +                  break; + +            case CMD_GAIN_25: +                  modifyoperation = GAIN; +                  paramA = 0.25; +                  break; + +                   + +            case CMD_ERASE_MEASURE: +            case CMD_DELETE_MEASURE: +            case CMD_CREATE_MEASURE: +                  break; +            default: +//                  printf("unknown ecanvas cmd %d\n", cmd); +                  break; +            } +             +      if (modifyoperation != -1) { +            if (selectionStart == selectionStop && modifyoperation!=PASTE) { +                  printf("No selection. Ignoring\n"); //@!TODO: Disable menu options when no selection +                  QMessageBox::information(this,  +                     QString("MusE"), +                     QWidget::tr("No selection. Ignoring")); + +                  return; +                  } +             +            //if(!modifyWarnedYet) +            //{ +            //  modifyWarnedYet = true; +            //  if(QMessageBox::warning(this, QString("Muse"), +            //     tr("Warning! Muse currently operates directly on the sound file.\n" +            //        "Undo is supported, but NOT after exit, WITH OR WITHOUT A SAVE!\n" +            //        "If you are stuck, try deleting the associated .wca file and reloading."), tr("&Ok"), tr("&Cancel"), +            //     QString::null, 0, 1 ) != 0) +            //   return; +            //} +            modifySelection(modifyoperation, selectionStart, selectionStop, paramA); +            } +             +      updateSelection(); +      redraw(); +      } + +//--------------------------------------------------------- +//   getSelection +//--------------------------------------------------------- +MusECore::WaveSelectionList WaveCanvas::getSelection(unsigned startpos, unsigned stoppos) +      { +      MusECore::WaveSelectionList selection; + +      for (MusECore::iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) { +            MusECore::WavePart* wp = (MusECore::WavePart*)(ip->second); +            unsigned part_offset = wp->frame(); +             +            MusECore::EventList* el = wp->events(); +            //printf("eventlist length=%d\n",el->size()); + +            for (MusECore::iEvent e = el->begin(); e != el->end(); ++e) { +                  MusECore::Event event  = e->second; +                  if (event.empty()) +                        continue; +                  MusECore::SndFileR file = event.sndFile(); +                  if (file.isNull()) +                        continue; + +                  // Respect part end: Don't modify stuff outside of part boundary. +                  unsigned elen = event.lenFrame(); +                  if(event.frame() + event.lenFrame() >= wp->lenFrame()) +                  { +                    // Adjust apparent operation length: +                    if(event.frame() > wp->lenFrame()) +                      elen = 0; +                    else +                      elen = wp->lenFrame() - event.frame(); +                  } +                   +                  unsigned event_offset = event.frame() + part_offset; +                  unsigned event_startpos  = event.spos(); +                  unsigned event_length = elen + event.spos(); +                  unsigned event_end    = event_offset + event_length; +                  //printf("startpos=%d stoppos=%d part_offset=%d event_offset=%d event_startpos=%d event_length=%d event_end=%d\n", startpos, stoppos, part_offset, event_offset, event_startpos, event_length, event_end); + +                  if (!(event_end <= startpos || event_offset > stoppos)) { +                        int tmp_sx = startpos - event_offset + event_startpos; +                        int tmp_ex = stoppos  - event_offset + event_startpos; +                        unsigned sx; +                        unsigned ex; + +                        tmp_sx < (int)event_startpos ? sx = event_startpos : sx = tmp_sx; +                        tmp_ex > (int)event_length   ? ex = event_length   : ex = tmp_ex; + +                        //printf("Event data affected: %d->%d filename:%s\n", sx, ex, file.name().toLatin1().constData()); +                        MusECore::WaveEventSelection s; +                        s.file = file; +                        s.startframe = sx; +                        s.endframe   = ex+1; +                        //printf("sx=%d ex=%d\n",sx,ex); +                        selection.push_back(s); +                        } +                  } +            } + +            return selection; +      } + +//--------------------------------------------------------- +//   modifySelection +//--------------------------------------------------------- +void WaveCanvas::modifySelection(int operation, unsigned startpos, unsigned stoppos, double paramA) +      { +         MusEGlobal::song->startUndo(); + +         if (operation == PASTE) { +           // we need to redefine startpos and stoppos +           if (copiedPart =="") +             return; +           MusECore::SndFile pasteFile(copiedPart); +           pasteFile.openRead(); +           startpos = pos[0]; +           stoppos = startpos+ pasteFile.samples(); // possibly this is wrong if there are tempo changes +           pasteFile.close(); +           pos[0]=stoppos; +         } + +         MusECore::WaveSelectionList selection = getSelection(startpos, stoppos); +         for (MusECore::iWaveSelection i = selection.begin(); i != selection.end(); i++) { +               MusECore::WaveEventSelection w = *i; +               MusECore::SndFileR& file         = w.file; +               unsigned sx            = w.startframe; +               unsigned ex            = w.endframe; +               unsigned file_channels = file.channels(); + +               QString tmpWavFile = QString::null; +               if (!MusEGlobal::getUniqueTmpfileName("tmp_musewav",".wav", tmpWavFile)) { +                     break; +                     } + +               MusEGlobal::audio->msgIdle(true); // Not good with playback during operations +               MusECore::SndFile tmpFile(tmpWavFile); +               tmpFile.setFormat(file.format(), file_channels, file.samplerate()); +               if (tmpFile.openWrite()) { +                     MusEGlobal::audio->msgIdle(false); +                     printf("Could not open temporary file...\n"); +                     break; +                     } + +               // +               // Write out data that will be changed to temp file +               // +               unsigned tmpdatalen = ex - sx; +               off_t    tmpdataoffset = sx; +               float*   tmpdata[file_channels]; + +               for (unsigned i=0; i<file_channels; i++) { +                     tmpdata[i] = new float[tmpdatalen]; +                     } +               file.seek(tmpdataoffset, 0); +               file.readWithHeap(file_channels, tmpdata, tmpdatalen); +               file.close(); +               tmpFile.write(file_channels, tmpdata, tmpdatalen); +               tmpFile.close(); + +               switch(operation) +               { +                     case MUTE: +                           muteSelection(file_channels, tmpdata, tmpdatalen); +                           break; + +                     case NORMALIZE: +                           normalizeSelection(file_channels, tmpdata, tmpdatalen); +                           break; + +                     case FADE_IN: +                           fadeInSelection(file_channels, tmpdata, tmpdatalen); +                           break; + +                     case FADE_OUT: +                           fadeOutSelection(file_channels, tmpdata, tmpdatalen); +                           break; + +                     case REVERSE: +                           reverseSelection(file_channels, tmpdata, tmpdatalen); +                           break; + +                     case GAIN: +                           applyGain(file_channels, tmpdata, tmpdatalen, paramA); +                           break; +                     case CUT: +                           copySelection(file_channels, tmpdata, tmpdatalen, true, file.format(), file.samplerate()); +                           break; +                     case COPY: +                           copySelection(file_channels, tmpdata, tmpdatalen, false, file.format(), file.samplerate()); +                           break; +                     case PASTE: +                           { +                           MusECore::SndFile pasteFile(copiedPart); +                           pasteFile.openRead(); +                           pasteFile.seek(tmpdataoffset, 0); +                           pasteFile.readWithHeap(file_channels, tmpdata, tmpdatalen); +                           } +                           break; + +                     case EDIT_EXTERNAL: +                           editExternal(file.format(), file.samplerate(), file_channels, tmpdata, tmpdatalen); +                           break; + +                     default: +                           printf("Error: Default state reached in modifySelection\n"); +                           break; + +               } + +               file.openWrite(); +               file.seek(tmpdataoffset, 0); +               file.write(file_channels, tmpdata, tmpdatalen); +               file.update(); +               file.close(); +               file.openRead(); + +               for (unsigned i=0; i<file_channels; i++) { +                     delete[] tmpdata[i]; +                     } + +               // Undo handling +               MusEGlobal::song->cmdChangeWave(file.dirPath() + "/" + file.name(), tmpWavFile, sx, ex); +               MusEGlobal::audio->msgIdle(false); // Not good with playback during operations +               } +         MusEGlobal::song->endUndo(SC_CLIP_MODIFIED); +         redraw(); +      } + +//--------------------------------------------------------- +//   copySelection +//--------------------------------------------------------- +void WaveCanvas::copySelection(unsigned file_channels, float** tmpdata, unsigned length, bool blankData, unsigned format, unsigned sampleRate) +{ +      if (copiedPart!="") { +        QFile::remove(copiedPart); +      } +      if (!MusEGlobal::getUniqueTmpfileName("tmp_musewav",".wav", copiedPart)) { +            return; +            } + +      MusECore::SndFile tmpFile(copiedPart); +      tmpFile.setFormat(format, file_channels, sampleRate); +      tmpFile.openWrite(); +      tmpFile.write(file_channels, tmpdata, length); +      tmpFile.close(); + +      if (blankData) { +        // Set everything to 0! +        for (unsigned i=0; i<file_channels; i++) { +              for (unsigned j=0; j<length; j++) { +                    tmpdata[i][j] = 0; +                    } +              } +        } +} + +//--------------------------------------------------------- +//   muteSelection +//--------------------------------------------------------- +void WaveCanvas::muteSelection(unsigned channels, float** data, unsigned length) +      { +      // Set everything to 0! +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length; j++) { +                  data[i][j] = 0; +                  } +            } +      } + +//--------------------------------------------------------- +//   normalizeSelection +//--------------------------------------------------------- +void WaveCanvas::normalizeSelection(unsigned channels, float** data, unsigned length) +      { +      float loudest = 0.0; + +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length; j++) { +                  if (data[i][j]  > loudest) +                        loudest = data[i][j]; +                  } +            } + +      double scale = 0.99 / (double)loudest; + +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length; j++) { +                  data[i][j] = (float) ((double)data[i][j] * scale); +                  } +            } +      } + +//--------------------------------------------------------- +//   fadeInSelection +//--------------------------------------------------------- +void WaveCanvas::fadeInSelection(unsigned channels, float** data, unsigned length) +      { +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length; j++) { +                  double scale = (double) j / (double)length ; +                  data[i][j] = (float) ((double)data[i][j] * scale); +                  } +            } +      } + +//--------------------------------------------------------- +//   fadeOutSelection +//--------------------------------------------------------- +void WaveCanvas::fadeOutSelection(unsigned channels, float** data, unsigned length) +      { +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length; j++) { +                  double scale = (double) (length - j) / (double)length ; +                  data[i][j] = (float) ((double)data[i][j] * scale); +                  } +            } +      } + +//--------------------------------------------------------- +//   reverseSelection +//--------------------------------------------------------- +void WaveCanvas::reverseSelection(unsigned channels, float** data, unsigned length) +      { +      if(length <= 1)     +        return; +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length/2; j++) { +                  float tmpl = data[i][j]; +                  float tmpr = data[i][length - j - 1]; +                  data[i][j] = tmpr; +                  data[i][length - j - 1] = tmpl; +                  } +            } +      } +//--------------------------------------------------------- +//   applyGain +//--------------------------------------------------------- +void WaveCanvas::applyGain(unsigned channels, float** data, unsigned length, double gain) +      { +      for (unsigned i=0; i<channels; i++) { +            for (unsigned j=0; j<length; j++) { +                  data[i][j] = (float) ((double)data[i][j] * gain); +                  } +            } +      } + +//--------------------------------------------------------- +//   editExternal +//--------------------------------------------------------- +void WaveCanvas::editExternal(unsigned file_format, unsigned file_samplerate, unsigned file_channels, float** tmpdata, unsigned tmpdatalen) +      { +      // Create yet another tmp-file +      QString exttmpFileName; +      if (!MusEGlobal::getUniqueTmpfileName("tmp_musewav",".wav", exttmpFileName)) { +            printf("Could not create temp file - aborting...\n"); +            return; +            } + +      MusECore::SndFile exttmpFile(exttmpFileName); +      exttmpFile.setFormat(file_format, file_channels, file_samplerate); +      if (exttmpFile.openWrite()) { +            printf("Could not open temporary file...\n"); +            return; +            } +      // Write out change-data to this file: +      exttmpFile.write(file_channels, tmpdata, tmpdatalen); +      exttmpFile.close(); + +      // Forkaborkabork +      int pid = fork(); +      if (pid == 0) { +            if (execlp(MusEGlobal::config.externalWavEditor.toLatin1().constData(), MusEGlobal::config.externalWavEditor.toLatin1().constData(), exttmpFileName.toLatin1().constData(), NULL) == -1) { +                  perror("Failed to launch external editor"); +                  // Get out of here +                   +                    +                  // cannot report error through gui, we are in another fork! +                  //@!TODO: Handle unsuccessful attempts +                  exit(99); +                  } +            exit(0); +            } +      else if (pid == -1) { +            perror("fork failed"); +            } +      else { +            int status; +            waitpid(pid, &status, 0); +            //printf ("status=%d\n",status); +            if( WEXITSTATUS(status) != 0 ){ +                   QMessageBox::warning(this, tr("MusE - external editor failed"), +                         tr("MusE was unable to launch the external editor\ncheck if the editor setting in:\n" +                         "Global Settings->Audio:External Waveditor\nis set to a valid editor.")); +            } +             +            if (exttmpFile.openRead()) { +                printf("Could not reopen temporary file!\n"); +                } +            else { +                // Re-read file again +                exttmpFile.seek(0, 0); +                size_t sz = exttmpFile.readWithHeap(file_channels, tmpdata, tmpdatalen); +                if (sz != tmpdatalen) { +                        // File must have been shrunken - not good. Alert user. +                        QMessageBox::critical(this, tr("MusE - file size changed"), +                            tr("When editing in external editor - you should not change the filesize\nsince it must fit the selected region.\n\nMissing data is muted")); +                        for (unsigned i=0; i<file_channels; i++) { +                            for (unsigned j=sz; j<tmpdatalen; j++) { +                                    tmpdata[i][j] = 0; +                                    } +                            } +                        } +                } +            QDir dir = exttmpFile.dirPath(); +            dir.remove(exttmpFileName); +            dir.remove(exttmpFile.basename() + ".wca"); +            } +      } + +       +       +//--------------------------------------------------------- +//   startDrag +//--------------------------------------------------------- + +void WaveCanvas::startDrag(MusEGui::CItem* /* item*/, bool copymode) +      { +      QMimeData* md = MusECore::selected_events_to_mime(MusECore::partlist_to_set(editor->parts()), 1); +       +      if (md) { +            // "Note that setMimeData() assigns ownership of the QMimeData object to the QDrag object.  +            //  The QDrag must be constructed on the heap with a parent QWidget to ensure that Qt can  +            //  clean up after the drag and drop operation has been completed. " +            QDrag* drag = new QDrag(this); +            drag->setMimeData(md); +             +            if (copymode) +                  drag->exec(Qt::CopyAction); +            else +                  drag->exec(Qt::MoveAction); +            } +      } + +//--------------------------------------------------------- +//   dragEnterEvent +//--------------------------------------------------------- + +void WaveCanvas::dragEnterEvent(QDragEnterEvent* event) +      { +      //event->accept(Q3TextDrag::canDecode(event)); +      event->acceptProposedAction();  // TODO CHECK Tim. +      } + +//--------------------------------------------------------- +//   dragMoveEvent +//--------------------------------------------------------- + +void WaveCanvas::dragMoveEvent(QDragMoveEvent*) +      { +      //printf("drag move %x\n", this); DELETETHIS (whole function?) +      //event->acceptProposedAction();   +      } + +//--------------------------------------------------------- +//   dragLeaveEvent +//--------------------------------------------------------- + +void WaveCanvas::dragLeaveEvent(QDragLeaveEvent*) +      { +      //printf("drag leave\n");         DELETETHIS (whole function?) +      //event->acceptProposedAction();   +      } + +//--------------------------------------------------------- +//   itemPressed +//--------------------------------------------------------- + +void WaveCanvas::itemPressed(const MusEGui::CItem*) +      { +      } + +//--------------------------------------------------------- +//   itemReleased +//--------------------------------------------------------- + +void WaveCanvas::itemReleased(const MusEGui::CItem*, const QPoint&) +      { +      } + +//--------------------------------------------------------- +//   itemMoved +//--------------------------------------------------------- + +void WaveCanvas::itemMoved(const MusEGui::CItem*, const QPoint&) +      { +      } + +//--------------------------------------------------------- +//   curPartChanged +//--------------------------------------------------------- + +void WaveCanvas::curPartChanged() +      { +      EventCanvas::curPartChanged(); +      editor->setWindowTitle(getCaption()); +      } + +//--------------------------------------------------------- +//   modifySelected +//--------------------------------------------------------- + +void WaveCanvas::modifySelected(MusEGui::NoteInfo::ValType type, int val, bool delta_mode) +      { +      // TODO: New WaveCanvas: Convert this routine to frames and remove unneeded operations.  +      QList< QPair<MusECore::EventList*,MusECore::Event> > already_done; +      MusEGlobal::audio->msgIdle(true); +      MusEGlobal::song->startUndo(); +      for (MusEGui::iCItem i = items.begin(); i != items.end(); ++i) { +            if (!(i->second->isSelected())) +                  continue; +            WEvent* e   = (WEvent*)(i->second); +            MusECore::Event event = e->event(); +            if (event.type() != MusECore::Note) +                  continue; + +            MusECore::WavePart* part = (MusECore::WavePart*)(e->part()); +             +            if (already_done.contains(QPair<MusECore::EventList*,MusECore::Event>(part->events(), event))) +              continue; +             +            MusECore::Event newEvent = event.clone(); + +            switch (type) { +                  case MusEGui::NoteInfo::VAL_TIME: +                        { +                        int newTime = val; +                        if(delta_mode) +                          newTime += event.tick(); +                        else +                          newTime -= part->tick(); +                        if (newTime < 0) +                           newTime = 0; +                        newEvent.setTick(newTime); +                        } +                        break; +                  case MusEGui::NoteInfo::VAL_LEN: +                        { +                        int len = val; +                        if(delta_mode) +                          len += event.lenTick(); +                        if (len < 1) +                              len = 1; +                        newEvent.setLenTick(len); +                        } +                        break; +                  case MusEGui::NoteInfo::VAL_VELON: +                        { +                        int velo = val; +                        if(delta_mode) +                          velo += event.velo(); +                        if (velo > 127) +                              velo = 127; +                        else if (velo < 0) +                              velo = 0; +                        newEvent.setVelo(velo); +                        } +                        break; +                  case MusEGui::NoteInfo::VAL_VELOFF: +                        { +                        int velo = val; +                        if(delta_mode) +                          velo += event.veloOff(); +                        if (velo > 127) +                              velo = 127; +                        else if (velo < 0) +                              velo = 0; +                        newEvent.setVeloOff(velo); +                        } +                        break; +                  case MusEGui::NoteInfo::VAL_PITCH: +                        { +                        int pitch = val; +                        if(delta_mode) +                          pitch += event.pitch(); +                        if (pitch > 127) +                              pitch = 127; +                        else if (pitch < 0) +                              pitch = 0; +                        newEvent.setPitch(pitch); +                        } +                        break; +                  } +             +            MusEGlobal::song->changeEvent(event, newEvent, part); +            // Indicate do not do port controller values and clone parts.  +            MusEGlobal::song->addUndo(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false)); + +            already_done.append(QPair<MusECore::EventList*,MusECore::Event>(part->events(), event)); +            } +      MusEGlobal::song->endUndo(SC_EVENT_MODIFIED); +      MusEGlobal::audio->msgIdle(false); +      } + +//--------------------------------------------------------- +//   resizeEvent +//--------------------------------------------------------- + +void WaveCanvas::resizeEvent(QResizeEvent* ev) +      { +      // Readjust all wave canvas item heights   +      bool do_redraw = false; +      for (iCItem k = items.begin(); k != items.end(); ++k)  +      { +        if(k->second->height() != ev->size().height()) +        { +          k->second->setHeight(ev->size().height()); +          do_redraw = true; +        } +      } +   +      if (ev->size().width() != ev->oldSize().width()) +            emit newWidth(ev->size().width()); +      EventCanvas::resizeEvent(ev); +   +      if(do_redraw) +        redraw(); +      } + +} // namespace MusEGui diff --git a/muse2/muse/waveedit/wavecanvas.h b/muse2/muse/waveedit/wavecanvas.h new file mode 100644 index 00000000..df285abc --- /dev/null +++ b/muse2/muse/waveedit/wavecanvas.h @@ -0,0 +1,185 @@ +//========================================================= +//  MusE +//  Linux Music Editor +//    wavecanvas.h +//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +//  Based on WaveView.cpp and PianoCanvas.cpp +//  (C) Copyright 2000 Werner Schweer (ws@seh.de) +//   and others. +// +//  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; version 2 of +//  the License, or (at your option) any later version. +// +//  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. +// +//========================================================= + +#ifndef __WAVECANVAS_H__ +#define __WAVECANVAS_H__ + +#include "type_defs.h" +#include "ecanvas.h" +#include <QDragEnterEvent> +#include <QDropEvent> +#include <QMouseEvent> +#include <QDragMoveEvent> +#include <QDragLeaveEvent> +#include <QWheelEvent> +#include <QResizeEvent> +#include <QTimer> + +class QRect; + +namespace MusECore { +class SndFileR; +class WavePart; +class WaveTrack; + +struct WaveEventSelection { +      SndFileR file; +      unsigned startframe; +      unsigned endframe; +      }; + +typedef std::list<WaveEventSelection> WaveSelectionList; +typedef std::list<WaveEventSelection>::iterator iWaveSelection; +} + +namespace MusEGui { + +//--------------------------------------------------------- +//   WEvent +//    ''visual'' Wave Event +//--------------------------------------------------------- + +class WEvent : public CItem { +   public: +      WEvent(MusECore::Event& e, MusECore::Part* p, int height); +      }; + +//--------------------------------------------------------- +//   WaveCanvas +//--------------------------------------------------------- + +class WaveCanvas : public EventCanvas { +      Q_OBJECT +     +      enum { NORMAL, DRAG } mode; +      enum { MUTE = 0, NORMALIZE, FADE_IN, FADE_OUT, REVERSE, GAIN, EDIT_EXTERNAL, CUT, COPY, PASTE }; //!< Modify operations +       +      int yScale; +      int button; +      unsigned startSample; +      unsigned endSample; +      int colorMode; +      int selectionStart, selectionStop, dragstartx; +      int lastGainvalue; //!< Stores the last used gainvalue when specifiying gain value in the editgain dialog +      QString copiedPart; +       +      //bool getUniqueTmpfileName(QString& newFilename); //!< Generates unique filename for temporary SndFile +      MusECore::WaveSelectionList getSelection(unsigned startpos, unsigned stoppos); +      void modifySelection(int operation, unsigned startpos, unsigned stoppos, double paramA); //!< Modifies selection +      void muteSelection(unsigned channels, float** data, unsigned length); //!< Mutes selection +      void normalizeSelection(unsigned channels, float** data, unsigned length); //!< Normalizes selection +      void fadeInSelection(unsigned channels, float** data, unsigned length); //!< Linear fade in of selection +      void fadeOutSelection(unsigned channels, float** data, unsigned length); //!< Linear fade out of selection +      void reverseSelection(unsigned channels, float** data, unsigned length); //!< Reverse selection +      void applyGain(unsigned channels, float** data, unsigned length, double gain); //!< Apply gain to selection +      void copySelection(unsigned file_channels, float** tmpdata, unsigned tmpdatalen, bool blankData, unsigned format, unsigned sampleRate); +      void editExternal(unsigned file_format, unsigned file_samplerate, unsigned channels, float** data, unsigned length); +      //void applyLadspa(unsigned channels, float** data, unsigned length); //!< Apply LADSPA plugin on selection + +       +   protected: +      virtual QPoint raster(const QPoint&) const; +      void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster); +      void drawParts(QPainter&, const QRect&, bool do_cur_part); +   +      // REMOVE Tim. +      //virtual void pdraw(QPainter&, const QRect&); +      virtual void draw(QPainter&, const QRect&); +      virtual void viewMouseDoubleClickEvent(QMouseEvent*); +      virtual void wheelEvent(QWheelEvent*); +      virtual bool mousePress(QMouseEvent*); +      virtual void mouseMove(QMouseEvent* event); +      virtual void mouseRelease(const QPoint&); +      virtual void drawItem(QPainter&, const CItem*, const QRect&); +      void drawTopItem(QPainter &p, const QRect &rect); +      virtual void drawMoving(QPainter&, const CItem*, const QRect&); +      virtual MusECore::Undo moveCanvasItems(CItemList&, int, int, DragType); +      virtual bool moveItem(MusECore::Undo&, CItem*, const QPoint&, DragType); +      virtual CItem* newItem(const QPoint&, int); +      virtual void resizeItem(CItem*, bool noSnap, bool); +      virtual void newItem(CItem*, bool noSnap); +      virtual bool deleteItem(CItem*); +      virtual void startDrag(CItem* item, bool copymode); +      virtual void dragEnterEvent(QDragEnterEvent* event); +      virtual void dragMoveEvent(QDragMoveEvent*); +      virtual void dragLeaveEvent(QDragLeaveEvent*); +      virtual CItem* addItem(MusECore::Part*, MusECore::Event&); + +      int y2pitch(int) const; +      int pitch2y(int) const; +      virtual void drawCanvas(QPainter&, const QRect&); +      virtual void itemPressed(const CItem*); +      virtual void itemReleased(const CItem*, const QPoint&); +      virtual void itemMoved(const CItem*, const QPoint&); +      virtual void curPartChanged(); +      virtual void resizeEvent(QResizeEvent*); + +   private slots: +      void setPos(int idx, unsigned val, bool adjustScrollbar); + +   signals: +      void quantChanged(int); +      void rasterChanged(int); +      void newWidth(int); +      void mouseWheelMoved(int); + +   public slots: +      void setYScale(int); +      void waveCmd(int); + +   public: +      +      enum { CMD_MUTE=0, CMD_NORMALIZE, CMD_FADE_IN, CMD_FADE_OUT, CMD_REVERSE, +             CMD_GAIN_FREE, CMD_GAIN_200, CMD_GAIN_150, CMD_GAIN_75, CMD_GAIN_50, CMD_GAIN_25, +             CMD_EDIT_COPY, CMD_EDIT_CUT, CMD_EDIT_PASTE, CMD_PASTE_DIALOG, CMD_DEL, +             CMD_EDIT_EXTERNAL, +             CMD_QUANTIZE, +             CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT,  +             CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PREV_PART, CMD_SELECT_NEXT_PART,  +             CMD_ERASE_MEASURE, CMD_DELETE_MEASURE, CMD_CREATE_MEASURE +           }; +              +      WaveCanvas(MidiEditor*, QWidget*, int, int); +      virtual ~WaveCanvas(); +      MusECore::WaveTrack* track() const; +      void cmd(int cmd); +      void setColorMode(int mode) { +            colorMode = mode; +            redraw(); +            } +      QString getCaption() const; +      void songChanged(MusECore::SongChangedFlags_t); +      void range(int* s, int* e) const { *s = startSample; *e = endSample; } +      void selectAtTick(unsigned int tick); +      void selectAtFrame(unsigned int frame); +      void modifySelected(NoteInfo::ValType type, int val, bool delta_mode = true); +      void keyPress(QKeyEvent*); +      }; + +} // namespace MusEGui + +#endif + diff --git a/muse2/muse/waveedit/waveedit.cpp b/muse2/muse/waveedit/waveedit.cpp index e1f18722..8290128f 100644 --- a/muse2/muse/waveedit/waveedit.cpp +++ b/muse2/muse/waveedit/waveedit.cpp @@ -3,6 +3,7 @@  //  Linux Music Editor  //    $Id: waveedit.cpp,v 1.5.2.12 2009/04/06 01:24:54 terminator356 Exp $  //  (C) Copyright 2000 Werner Schweer (ws@seh.de) +//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)  //  //  This program is free software; you can redistribute it and/or  //  modify it under the terms of the GNU General Public License @@ -20,6 +21,8 @@  //  //========================================================= +#include <limits.h> +  #include <QMenu>  #include <QSignalMapper>  #include <QToolBar> @@ -41,7 +44,8 @@  #include "waveedit.h"  #include "mtscale.h"  #include "scrollscale.h" -#include "waveview.h" +//#include "waveview.h" +#include "wavecanvas.h"  #include "ttoolbar.h"  #include "globals.h"  #include "audio.h" @@ -51,6 +55,7 @@  #include "gconfig.h"  #include "icons.h"  #include "shortcuts.h" +#include "cmd.h"  namespace MusECore {  extern QColor readColor(MusECore::Xml& xml); @@ -58,6 +63,12 @@ extern QColor readColor(MusECore::Xml& xml);  namespace MusEGui { +static int waveEditTools = MusEGui::PointerTool | MusEGui::PencilTool | MusEGui::RubberTool |  +                           MusEGui::CutTool | MusEGui::CursorTool; + +int WaveEdit::_rasterInit = 96; +int WaveEdit::colorModeInit = 0; +    //---------------------------------------------------------  //   closeEvent  //--------------------------------------------------------- @@ -81,8 +92,10 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)     : MidiEditor(TopWin::WAVE, 1, pl)        {        setFocusPolicy(Qt::NoFocus); +      colorMode      = colorModeInit;        QSignalMapper* mapper = new QSignalMapper(this); +      QSignalMapper* colorMapper = new QSignalMapper(this);        QAction* act;        //---------Pulldown Menu---------------------------- @@ -95,27 +108,27 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)        menuGain = menuFunctions->addMenu(tr("&Gain"));        act = menuGain->addAction("200%"); -      mapper->setMapping(act, CMD_GAIN_200); +      mapper->setMapping(act, WaveCanvas::CMD_GAIN_200);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuGain->addAction("150%"); -      mapper->setMapping(act, CMD_GAIN_150); +      mapper->setMapping(act, WaveCanvas::CMD_GAIN_150);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuGain->addAction("75%"); -      mapper->setMapping(act, CMD_GAIN_75); +      mapper->setMapping(act, WaveCanvas::CMD_GAIN_75);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuGain->addAction("50%"); -      mapper->setMapping(act, CMD_GAIN_50); +      mapper->setMapping(act, WaveCanvas::CMD_GAIN_50);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuGain->addAction("25%"); -      mapper->setMapping(act, CMD_GAIN_25); +      mapper->setMapping(act, WaveCanvas::CMD_GAIN_25);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuGain->addAction(tr("Other")); -      mapper->setMapping(act, CMD_GAIN_FREE); +      mapper->setMapping(act, WaveCanvas::CMD_GAIN_FREE);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        connect(mapper, SIGNAL(mapped(int)), this, SLOT(cmd(int))); @@ -123,65 +136,99 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)        menuFunctions->addSeparator();        copyAction = menuEdit->addAction(tr("&Copy")); -      mapper->setMapping(copyAction, CMD_EDIT_COPY); +      mapper->setMapping(copyAction, WaveCanvas::CMD_EDIT_COPY);        connect(copyAction, SIGNAL(triggered()), mapper, SLOT(map()));        cutAction = menuEdit->addAction(tr("C&ut")); -      mapper->setMapping(cutAction, CMD_EDIT_CUT); +      mapper->setMapping(cutAction, WaveCanvas::CMD_EDIT_CUT);        connect(cutAction, SIGNAL(triggered()), mapper, SLOT(map()));        pasteAction = menuEdit->addAction(tr("&Paste")); -      mapper->setMapping(pasteAction, CMD_EDIT_PASTE); +      mapper->setMapping(pasteAction, WaveCanvas::CMD_EDIT_PASTE);        connect(pasteAction, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuEdit->addAction(tr("Edit in E&xternal Editor")); -      mapper->setMapping(act, CMD_EDIT_EXTERNAL); +      mapper->setMapping(act, WaveCanvas::CMD_EDIT_EXTERNAL);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuFunctions->addAction(tr("Mute Selection")); -      mapper->setMapping(act, CMD_MUTE); +      mapper->setMapping(act, WaveCanvas::CMD_MUTE);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuFunctions->addAction(tr("Normalize Selection")); -      mapper->setMapping(act, CMD_NORMALIZE); +      mapper->setMapping(act, WaveCanvas::CMD_NORMALIZE);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuFunctions->addAction(tr("Fade In Selection")); -      mapper->setMapping(act, CMD_FADE_IN); +      mapper->setMapping(act, WaveCanvas::CMD_FADE_IN);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuFunctions->addAction(tr("Fade Out Selection")); -      mapper->setMapping(act, CMD_FADE_OUT); +      mapper->setMapping(act, WaveCanvas::CMD_FADE_OUT);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        act = menuFunctions->addAction(tr("Reverse Selection")); -      mapper->setMapping(act, CMD_REVERSE); +      mapper->setMapping(act, WaveCanvas::CMD_REVERSE);        connect(act, SIGNAL(triggered()), mapper, SLOT(map()));        select = menuEdit->addMenu(QIcon(*selectIcon), tr("Select"));        selectAllAction = select->addAction(QIcon(*select_allIcon), tr("Select &All")); -      mapper->setMapping(selectAllAction, CMD_SELECT_ALL); +      mapper->setMapping(selectAllAction, WaveCanvas::CMD_SELECT_ALL);        connect(selectAllAction, SIGNAL(triggered()), mapper, SLOT(map()));        selectNoneAction = select->addAction(QIcon(*select_allIcon), tr("&Deselect All")); -      mapper->setMapping(selectNoneAction, CMD_SELECT_NONE); +      mapper->setMapping(selectNoneAction, WaveCanvas::CMD_SELECT_NONE);        connect(selectNoneAction, SIGNAL(triggered()), mapper, SLOT(map())); +      select->addSeparator(); +       +      selectPrevPartAction = select->addAction(QIcon(*select_all_parts_on_trackIcon), tr("&Previous Part")); +      mapper->setMapping(selectPrevPartAction, WaveCanvas::CMD_SELECT_PREV_PART); +      connect(selectPrevPartAction, SIGNAL(triggered()), mapper, SLOT(map())); +       +      selectNextPartAction = select->addAction(QIcon(*select_all_parts_on_trackIcon), tr("&Next Part")); +      mapper->setMapping(selectNextPartAction, WaveCanvas::CMD_SELECT_NEXT_PART); +      connect(selectNextPartAction, SIGNAL(triggered()), mapper, SLOT(map())); +        QMenu* settingsMenu = menuBar()->addMenu(tr("Window &Config")); + +      eventColor = settingsMenu->addMenu(tr("&Event Color"));       +       +      QActionGroup* actgrp = new QActionGroup(this); +      actgrp->setExclusive(true); +       +      evColorNormalAction = actgrp->addAction(tr("&Part colors")); +      evColorNormalAction->setCheckable(true); +      colorMapper->setMapping(evColorNormalAction, 0); +       +      evColorPartsAction = actgrp->addAction(tr("&Gray")); +      evColorPartsAction->setCheckable(true); +      colorMapper->setMapping(evColorPartsAction, 1); +       +      connect(evColorNormalAction, SIGNAL(triggered()), colorMapper, SLOT(map())); +      connect(evColorPartsAction, SIGNAL(triggered()), colorMapper, SLOT(map())); +       +      eventColor->addActions(actgrp->actions()); +       +      connect(colorMapper, SIGNAL(mapped(int)), this, SLOT(eventColorModeChanged(int))); +       +      settingsMenu->addSeparator();        settingsMenu->addAction(subwinAction);        settingsMenu->addAction(shareAction);        settingsMenu->addAction(fullscreenAction); -        connect(MusEGlobal::muse, SIGNAL(configChanged()), SLOT(configChanged()));        //--------------------------------------------------        //    ToolBar:   Solo  Cursor1 Cursor2 +      tools2 = new MusEGui::EditToolBar(this, waveEditTools); +      addToolBar(tools2); +              addToolBarBreak();        tb1 = addToolBar(tr("WaveEdit tools"));        tb1->setObjectName("WaveEdit tools"); @@ -222,8 +269,9 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)              }        hscroll = new ScrollScale(-32768, 1, xscale, 10000, Qt::Horizontal, mainw, 0, false, 10000.0); -      view    = new WaveView(this, mainw, xscale, yscale); -      wview   = view;   // HACK! +      //view    = new WaveView(this, mainw, xscale, yscale); +      canvas    = new WaveCanvas(this, mainw, xscale, yscale); +      //wview   = canvas;   // HACK!        QSizeGrip* corner    = new QSizeGrip(mainw);        ymag                 = new QSlider(Qt::Vertical, mainw); @@ -235,10 +283,10 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)        time                 = new MTScale(&_raster, mainw, xscale, true);        ymag->setFixedWidth(16); -      connect(view, SIGNAL(mouseWheelMoved(int)), this, SLOT(moveVerticalSlider(int))); -      connect(ymag, SIGNAL(valueChanged(int)), view, SLOT(setYScale(int))); -      connect(view, SIGNAL(horizontalZoomIn()), SLOT(horizontalZoomIn())); -      connect(view, SIGNAL(horizontalZoomOut()), SLOT(horizontalZoomOut())); +      connect(canvas, SIGNAL(mouseWheelMoved(int)), this, SLOT(moveVerticalSlider(int))); +      connect(ymag, SIGNAL(valueChanged(int)), canvas, SLOT(setYScale(int))); +      connect(canvas, SIGNAL(horizontalZoomIn()), SLOT(horizontalZoomIn())); +      connect(canvas, SIGNAL(horizontalZoomOut()), SLOT(horizontalZoomOut()));        time->setOrigin(0, 0); @@ -247,28 +295,38 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)        mainGrid->addWidget(time,   0, 0, 1, 2);        mainGrid->addWidget(MusECore::hLine(mainw),    1, 0, 1, 2); -      mainGrid->addWidget(view,    2, 0); +      mainGrid->addWidget(canvas,    2, 0);        mainGrid->addWidget(ymag,    2, 1);        mainGrid->addWidget(hscroll, 3, 0);        mainGrid->addWidget(corner,  3, 1, Qt::AlignBottom | Qt::AlignRight); -      view->setFocus();   +      canvas->setFocus();   -      connect(hscroll, SIGNAL(scrollChanged(int)), view, SLOT(setXPos(int))); -      connect(hscroll, SIGNAL(scaleChanged(int)),  view, SLOT(setXMag(int))); -      setWindowTitle(view->getCaption()); -      connect(view, SIGNAL(followEvent(int)), hscroll, SLOT(setOffset(int))); +      connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int))); +      connect(tools2, SIGNAL(toolChanged(int)), canvas,   SLOT(setTool(int))); +       +      connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int))); +      connect(hscroll, SIGNAL(scaleChanged(int)),  canvas, SLOT(setXMag(int))); +      setWindowTitle(canvas->getCaption()); +      connect(canvas, 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(unsigned)),  SLOT(setTime(unsigned))); -      connect(view,    SIGNAL(timeChanged(unsigned)),  SLOT(setTime(unsigned))); +      connect(time,    SIGNAL(timeChanged(unsigned)),  SLOT(timeChanged(unsigned))); +      connect(canvas,    SIGNAL(timeChanged(unsigned)),  SLOT(setTime(unsigned))); -      connect(view,  SIGNAL(horizontalScroll(unsigned)),hscroll, SLOT(setPos(unsigned))); +      connect(canvas,  SIGNAL(horizontalScroll(unsigned)),hscroll, SLOT(setPos(unsigned))); +      connect(canvas,  SIGNAL(horizontalScrollNoLimit(unsigned)),hscroll, SLOT(setPosNoLimit(unsigned)));         connect(hscroll, SIGNAL(scaleChanged(int)),  SLOT(updateHScrollRange()));        connect(MusEGlobal::song, SIGNAL(songChanged(MusECore::SongChangedFlags_t)), SLOT(songChanged1(MusECore::SongChangedFlags_t))); +      // For the wave editor, let's start with the operation range selection tool. +      canvas->setTool(MusEGui::CursorTool); +      tools2->set(MusEGui::CursorTool); +       +      setEventColorMode(colorMode); +              initShortcuts();        updateHScrollRange(); @@ -291,6 +349,17 @@ void WaveEdit::initShortcuts()        pasteAction->setShortcut(shortcuts[SHRT_PASTE].key);        selectAllAction->setShortcut(shortcuts[SHRT_SELECT_ALL].key);        selectNoneAction->setShortcut(shortcuts[SHRT_SELECT_NONE].key); +       +      //selectInvertAction->setShortcut(shortcuts[SHRT_SELECT_INVERT].key); +      //selectInsideLoopAction->setShortcut(shortcuts[SHRT_SELECT_ILOOP].key); +      //selectOutsideLoopAction->setShortcut(shortcuts[SHRT_SELECT_OLOOP].key); +      selectPrevPartAction->setShortcut(shortcuts[SHRT_SELECT_PREV_PART].key); +      selectNextPartAction->setShortcut(shortcuts[SHRT_SELECT_NEXT_PART].key); +       +      eventColor->menuAction()->setShortcut(shortcuts[SHRT_EVENT_COLOR].key); +      //evColorNormalAction->setShortcut(shortcuts[  ].key); +      //evColorPartsAction->setShortcut(shortcuts[  ].key); +              }  //--------------------------------------------------------- @@ -299,9 +368,15 @@ void WaveEdit::initShortcuts()  void WaveEdit::configChanged()        { -      view->setBg(MusEGlobal::config.waveEditBackgroundColor); -      selectAllAction->setShortcut(shortcuts[SHRT_SELECT_ALL].key); -      selectNoneAction->setShortcut(shortcuts[SHRT_SELECT_NONE].key); +      if (MusEGlobal::config.canvasBgPixmap.isEmpty()) { +            canvas->setBg(MusEGlobal::config.waveEditBackgroundColor); +            canvas->setBg(QPixmap()); +      } +      else { +            canvas->setBg(QPixmap(MusEGlobal::config.canvasBgPixmap)); +      } +       +      initShortcuts();        }  //--------------------------------------------------------- @@ -310,17 +385,39 @@ void WaveEdit::configChanged()  void WaveEdit::updateHScrollRange()  {        int s, e; -      wview->range(&s, &e); -      // Show one more measure. -      e += AL::sigmap.ticksMeasure(e);   -      // Show another quarter measure due to imprecise drawing at canvas end point. -      e += AL::sigmap.ticksMeasure(e) / 4; +      canvas->range(&s, &e);   // Range in frames +      unsigned tm = AL::sigmap.ticksMeasure(MusEGlobal::tempomap.frame2tick(e)); +       +      // Show one more measure, and show another quarter measure due to imprecise drawing at canvas end point. +      //e += MusEGlobal::tempomap.tick2frame(tm + tm / 4);  // TODO: Try changing scrollbar to use units of frames? +      e += (tm + tm / 4); +              // Compensate for the vscroll width.         //e += wview->rmapxDev(-vscroll->width());         int s1, e1; -      hscroll->range(&s1, &e1); +      hscroll->range(&s1, &e1);                             //   ...        if(s != s1 || e != e1)  -        hscroll->setRange(s, e); +        hscroll->setRange(s, e);                            //   ... +} + +//--------------------------------------------------------- +//   timeChanged +//--------------------------------------------------------- + +void WaveEdit::timeChanged(unsigned t) +{ +      if(t == INT_MAX) +      { +        // Let the PosLabels disable themselves with INT_MAX. +        pos1->setValue(t); +        pos2->setValue(t); +        return; +      } +      +      unsigned frame = MusEGlobal::tempomap.tick2frame(t); +      pos1->setValue(t); +      pos2->setValue(frame); +      time->setPos(3, t, false);  }  //--------------------------------------------------------- @@ -329,10 +426,16 @@ void WaveEdit::updateHScrollRange()  void WaveEdit::setTime(unsigned samplepos)        { -//    printf("setTime %d %x\n", samplepos, samplepos); +      if(samplepos == INT_MAX) +      { +        // Let the PosLabels disable themselves with INT_MAX. +        pos1->setValue(samplepos); +        pos2->setValue(samplepos); +        return; +      } +             unsigned tick = MusEGlobal::tempomap.frame2tick(samplepos);        pos1->setValue(tick); -      //pos2->setValue(tick);        pos2->setValue(samplepos);        time->setPos(3, tick, false);        } @@ -343,7 +446,6 @@ void WaveEdit::setTime(unsigned samplepos)  WaveEdit::~WaveEdit()        { -      // MusEGlobal::undoRedo->removeFrom(tools); // p4.0.6 Removed        }  //--------------------------------------------------------- @@ -352,7 +454,7 @@ WaveEdit::~WaveEdit()  void WaveEdit::cmd(int n)        { -      view->cmd(n); +      ((WaveCanvas*)canvas)->cmd(n);        }  //--------------------------------------------------------- @@ -368,6 +470,10 @@ void WaveEdit::readConfiguration(MusECore::Xml& xml)                    case MusECore::Xml::TagStart:                          if (tag == "bgcolor")                                MusEGlobal::config.waveEditBackgroundColor = readColor(xml); +                        else if (tag == "raster") +                              _rasterInit = xml.parseInt(); +                        else if (tag == "colormode") +                              colorModeInit = xml.parseInt();                          else if (tag == "topwin")                                TopWin::readConfiguration(WAVE, xml);                          else @@ -393,6 +499,8 @@ void WaveEdit::writeConfiguration(int level, MusECore::Xml& xml)        {        xml.tag(level++, "waveedit");        xml.colorTag(level, "bgcolor", MusEGlobal::config.waveEditBackgroundColor); +      xml.intTag(level, "raster", _rasterInit); +      xml.intTag(level, "colormode", colorModeInit);        TopWin::writeConfiguration(WAVE, level,xml);        xml.tag(level, "/waveedit");        } @@ -406,6 +514,7 @@ void WaveEdit::writeStatus(int level, MusECore::Xml& xml) const        writePartList(level, xml);        xml.tag(level++, "waveedit");        MidiEditor::writeStatus(level, xml); +      xml.intTag(level, "tool", int(canvas->tool()));        xml.intTag(level, "xpos", hscroll->pos());        xml.intTag(level, "xmag", hscroll->mag());        xml.intTag(level, "ymag", ymag->value()); @@ -427,6 +536,11 @@ void WaveEdit::readStatus(MusECore::Xml& xml)                    case MusECore::Xml::TagStart:                          if (tag == "midieditor")                                MidiEditor::readStatus(xml); +                        else if (tag == "tool") { +                              int tool = xml.parseInt(); +                              canvas->setTool(tool); +                              tools2->set(tool); +                              }                          else if (tag == "xmag")                                hscroll->setMag(xml.parseInt());                          else if (tag == "ymag") @@ -486,14 +600,170 @@ void WaveEdit::soloChanged(bool flag)  void WaveEdit::keyPressEvent(QKeyEvent* event)        { +// TODO: Raster: +//       int index; +//       int n = sizeof(rasterTable)/sizeof(*rasterTable); +//       for (index = 0; index < n; ++index) +//             if (rasterTable[index] == raster()) +//                   break; +//       if (index == n) { +//             index = 0; +//             // raster 1 is not in table +//             } +//       int off = (index / 9) * 9; +//       index   = index % 9; + +//       int val = 0; + +      WaveCanvas* wc = (WaveCanvas*)canvas;        int key = event->key(); + +      if (((QInputEvent*)event)->modifiers() & Qt::ShiftModifier) +            key += Qt::SHIFT; +      if (((QInputEvent*)event)->modifiers() & Qt::AltModifier) +            key += Qt::ALT; +      if (((QInputEvent*)event)->modifiers() & Qt::ControlModifier) +            key+= Qt::CTRL; +        if (key == Qt::Key_Escape) {              close();              return;              } -      else { +             +      else if (key == shortcuts[SHRT_POS_INC].key) { +            wc->waveCmd(CMD_RIGHT); +            return; +            } +      else if (key == shortcuts[SHRT_POS_DEC].key) { +            wc->waveCmd(CMD_LEFT); +            return; +            } +      else if (key == shortcuts[SHRT_POS_INC_NOSNAP].key) { +            wc->waveCmd(CMD_RIGHT_NOSNAP); +            return; +            } +      else if (key == shortcuts[SHRT_POS_DEC_NOSNAP].key) { +            wc->waveCmd(CMD_LEFT_NOSNAP); +            return; +            } +      else if (key == shortcuts[SHRT_INSERT_AT_LOCATION].key) { +            wc->waveCmd(CMD_INSERT); +            return; +            } +      else if (key == Qt::Key_Backspace) { +            wc->waveCmd(CMD_BACKSPACE); +            return; +            } +             +      else if (key == shortcuts[SHRT_TOOL_POINTER].key) { +            tools2->set(MusEGui::PointerTool); +            return; +            } +      else if (key == shortcuts[SHRT_TOOL_PENCIL].key) { +            tools2->set(MusEGui::PencilTool); +            return; +            } +      else if (key == shortcuts[SHRT_TOOL_RUBBER].key) { +            tools2->set(MusEGui::RubberTool); +            return; +            } +      else if (key == shortcuts[SHRT_TOOL_SCISSORS].key) { +            tools2->set(MusEGui::CutTool); +            return; +            } +      else if (key == shortcuts[SHRT_TOOL_CURSOR].key) { +            tools2->set(MusEGui::CursorTool); +            return; +            } +      else if (key == shortcuts[SHRT_EVENT_COLOR].key) { +            if (colorMode == 0) +                  colorMode = 1; +            else if (colorMode == 1) +                  colorMode = 0; +            setEventColorMode(colorMode); +            return; +            } +             +      // TODO: New WaveCanvas: Convert some of these to use frames. +      else if (key == shortcuts[SHRT_ZOOM_IN].key) { +            int mag = hscroll->mag(); +            int zoomlvl = MusEGui::ScrollScale::getQuickZoomLevel(mag); +            if (zoomlvl < MusEGui::ScrollScale::zoomLevels-1) +                  zoomlvl++; + +            int newmag = MusEGui::ScrollScale::convertQuickZoomLevelToMag(zoomlvl); +            hscroll->setMag(newmag); +            //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag); +            return; +            } +      else if (key == shortcuts[SHRT_ZOOM_OUT].key) { +            int mag = hscroll->mag(); +            int zoomlvl = MusEGui::ScrollScale::getQuickZoomLevel(mag); +            if (zoomlvl > 1) +                  zoomlvl--; + +            int newmag = MusEGui::ScrollScale::convertQuickZoomLevelToMag(zoomlvl); +            hscroll->setMag(newmag); +            //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag); +            return; +            } +      else if (key == shortcuts[SHRT_GOTO_CPOS].key) { +            MusECore::PartList* p = this->parts(); +            MusECore::Part* first = p->begin()->second; +            hscroll->setPos(MusEGlobal::song->cpos() - first->tick() ); +            return; +            } +      else if (key == shortcuts[SHRT_SCROLL_LEFT].key) { +            int pos = hscroll->pos() - MusEGlobal::config.division; +            if (pos < 0) +                  pos = 0; +            hscroll->setPos(pos); +            return; +            } +      else if (key == shortcuts[SHRT_SCROLL_RIGHT].key) { +            int pos = hscroll->pos() + MusEGlobal::config.division; +            hscroll->setPos(pos); +            return; +            } +             +// TODO: Raster:             +//       else if (key == shortcuts[SHRT_SET_QUANT_1].key) +//             val = rasterTable[8 + off]; +//       else if (key == shortcuts[SHRT_SET_QUANT_2].key) +//             val = rasterTable[7 + off]; +//       else if (key == shortcuts[SHRT_SET_QUANT_3].key) +//             val = rasterTable[6 + off]; +//       else if (key == shortcuts[SHRT_SET_QUANT_4].key) +//             val = rasterTable[5 + off]; +//       else if (key == shortcuts[SHRT_SET_QUANT_5].key) +//             val = rasterTable[4 + off]; +//       else if (key == shortcuts[SHRT_SET_QUANT_6].key) +//             val = rasterTable[3 + off]; +//       else if (key == shortcuts[SHRT_SET_QUANT_7].key) +//             val = rasterTable[2 + off]; +//       else if (key == shortcuts[SHRT_TOGGLE_TRIOL].key) +//             val = rasterTable[index + ((off == 0) ? 9 : 0)]; +//       else if (key == shortcuts[SHRT_TOGGLE_PUNCT].key) +//             val = rasterTable[index + ((off == 18) ? 9 : 18)]; +//       else if (key == shortcuts[SHRT_TOGGLE_PUNCT2].key) {//CDW +//             if ((off == 18) && (index > 2)) { +//                   val = rasterTable[index + 9 - 1]; +//                   } +//             else if ((off == 9) && (index < 8)) { +//                   val = rasterTable[index + 18 + 1]; +//                   } +//             else +//                   return; +//             } +             +      else { //Default:              event->ignore(); +            return;              } +         +      // TODO: Raster:   +      //setRaster(val); +      //toolbar->setRaster(_raster);        }  //--------------------------------------------------------- @@ -540,9 +810,38 @@ void WaveEdit::focusCanvas()  {    if(MusEGlobal::config.smartFocus)    { -    view->setFocus(); -    view->activateWindow(); +    canvas->setFocus(); +    canvas->activateWindow();    }  } +//--------------------------------------------------------- +//   eventColorModeChanged +//--------------------------------------------------------- + +void WaveEdit::eventColorModeChanged(int mode) +      { +      colorMode = mode; +      colorModeInit = colorMode; +       +      ((WaveCanvas*)(canvas))->setColorMode(colorMode); +      } + +//--------------------------------------------------------- +//   setEventColorMode +//--------------------------------------------------------- + +void WaveEdit::setEventColorMode(int mode) +      { +      colorMode = mode; +      colorModeInit = colorMode; +       +      evColorNormalAction->setChecked(mode == 0); +      evColorPartsAction->setChecked(mode == 1); +       +      ((WaveCanvas*)(canvas))->setColorMode(colorMode); +      } + + +  } // namespace MusEGui diff --git a/muse2/muse/waveedit/waveedit.h b/muse2/muse/waveedit/waveedit.h index d52eb986..2d74391a 100644 --- a/muse2/muse/waveedit/waveedit.h +++ b/muse2/muse/waveedit/waveedit.h @@ -3,6 +3,7 @@  //  Linux Music Editor  //    $Id: waveedit.h,v 1.3.2.8 2008/01/26 07:23:21 terminator356 Exp $  //  (C) Copyright 2000 Werner Schweer (ws@seh.de) +//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)  //  //  This program is free software; you can redistribute it and/or  //  modify it under the terms of the GNU General Public License @@ -33,6 +34,7 @@  #include "type_defs.h"  #include "midieditor.h" +#include "tools.h"  class QAction;  class QResizeEvent; @@ -48,7 +50,7 @@ namespace MusEGui {  class PosLabel;  class ScrollScale;  class SNode; -class WaveView; +class WaveCanvas;  //---------------------------------------------------------  //   WaveEdit @@ -57,7 +59,6 @@ class WaveView;  class WaveEdit : public MidiEditor {        Q_OBJECT -      WaveView* view;        QSlider* ymag;        QToolBar* tb1;        QToolButton* solo; @@ -68,22 +69,32 @@ class WaveEdit : public MidiEditor {        QAction* cutAction;        QAction* copyAction;        QAction* pasteAction; -       +      QAction* selectPrevPartAction; +      QAction* selectNextPartAction; +      QAction* evColorNormalAction; +      QAction* evColorPartsAction; +      MusEGui::EditToolBar* tools2; +      QMenu* menuFunctions, *select, *menuGain, *eventColor; +      int colorMode; +      static int _rasterInit; +      static int colorModeInit; +        virtual void closeEvent(QCloseEvent*);        virtual void keyPressEvent(QKeyEvent*); -      QMenu* menuFunctions, *select, *menuGain; -        void initShortcuts(); +      void setEventColorMode(int);     private slots:        void cmd(int); +      void timeChanged(unsigned t);        void setTime(unsigned t);        void songChanged1(MusECore::SongChangedFlags_t);        void soloChanged(bool flag);        void moveVerticalSlider(int val); +      void eventColorModeChanged(int);     public slots:        void configChanged(); @@ -102,12 +113,6 @@ class WaveEdit : public MidiEditor {        virtual void writeStatus(int, MusECore::Xml&) const;        static void readConfiguration(MusECore::Xml&);        static void writeConfiguration(int, MusECore::Xml&); - -      enum { CMD_MUTE=0, CMD_NORMALIZE, CMD_FADE_IN, CMD_FADE_OUT, CMD_REVERSE, -             CMD_GAIN_FREE, CMD_GAIN_200, CMD_GAIN_150, CMD_GAIN_75, CMD_GAIN_50, CMD_GAIN_25, -             CMD_EDIT_COPY, CMD_EDIT_CUT, CMD_EDIT_PASTE, -             CMD_EDIT_EXTERNAL, -             CMD_SELECT_ALL, CMD_SELECT_NONE };        };  } // namespace MusEGui diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index a4617d53..f9280ab5 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -374,7 +374,7 @@ void Canvas::draw(QPainter& p, const QRect& rect)                    // Draw unselected parts.                    list2.push_back(ci);                }   -            }   +            }              int i;              int sz = list1.size();              for(i = 0; i != sz; ++i)  diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h index fe26c25a..74de63c5 100644 --- a/muse2/muse/widgets/canvas.h +++ b/muse2/muse/widgets/canvas.h @@ -176,7 +176,7 @@ class Canvas : public View {     public slots:        void setTool(int t); -      void setPos(int, unsigned, bool adjustScrollbar); +      virtual void setPos(int, unsigned, bool adjustScrollbar);        void scrollTimerDone(void);        void redirectedWheelEvent(QWheelEvent*); diff --git a/muse2/muse/widgets/poslabel.cpp b/muse2/muse/widgets/poslabel.cpp index b893c58d..5687089c 100644 --- a/muse2/muse/widgets/poslabel.cpp +++ b/muse2/muse/widgets/poslabel.cpp @@ -123,6 +123,14 @@ void PosLabel::updateValue()  void PosLabel::setSampleValue(unsigned val)        { +      if (val == INT_MAX) +      { +        setEnabled(false); +        return; +      } +      if(!isEnabled()) +        setEnabled(true); +                    if (val == _sampleValue)              return;        _sampleValue = val; @@ -135,6 +143,14 @@ void PosLabel::setSampleValue(unsigned val)  void PosLabel::setTickValue(unsigned val)        { +      if (val == INT_MAX) +      { +        setEnabled(false); +        return; +      } +      if(!isEnabled()) +        setEnabled(true); +                    if (val == _tickValue)              return;        if (val >= MAX_TICK) @@ -153,6 +169,14 @@ void PosLabel::setTickValue(unsigned val)  void PosLabel::setValue(unsigned val)        { +      if (val == INT_MAX) +      { +        setEnabled(false); +        return; +      } +      if(!isEnabled()) +        setEnabled(true); +                    unsigned oval = _smpte ? _sampleValue : _tickValue;        if (val == oval)              return; | 
