diff options
Diffstat (limited to 'attic/muse_qt4_evolution/muse/waveedit')
-rw-r--r-- | attic/muse_qt4_evolution/muse/waveedit/CMakeLists.txt | 34 | ||||
-rw-r--r-- | attic/muse_qt4_evolution/muse/waveedit/waveedit.cpp | 289 | ||||
-rw-r--r-- | attic/muse_qt4_evolution/muse/waveedit/waveedit.h | 88 | ||||
-rw-r--r-- | attic/muse_qt4_evolution/muse/waveedit/waveview.cpp | 1124 | ||||
-rw-r--r-- | attic/muse_qt4_evolution/muse/waveedit/waveview.h | 127 |
5 files changed, 1662 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/muse/waveedit/CMakeLists.txt b/attic/muse_qt4_evolution/muse/waveedit/CMakeLists.txt new file mode 100644 index 00000000..69ff19e3 --- /dev/null +++ b/attic/muse_qt4_evolution/muse/waveedit/CMakeLists.txt @@ -0,0 +1,34 @@ +#============================================================================= +# MusE +# Linux Music Editor +# $Id:$ +# +# Copyright (C) 2002-2006 by Werner Schweer and others +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#============================================================================= + +QT4_WRAP_CPP ( waveedit_mocs + waveedit.h + waveview.h + ) + +add_library ( waveedit STATIC + ${waveedit_mocs} + waveedit.cpp + waveview.cpp + ) + +set_target_properties( waveedit + PROPERTIES COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all.h" + ) diff --git a/attic/muse_qt4_evolution/muse/waveedit/waveedit.cpp b/attic/muse_qt4_evolution/muse/waveedit/waveedit.cpp new file mode 100644 index 00000000..3bfbbe40 --- /dev/null +++ b/attic/muse_qt4_evolution/muse/waveedit/waveedit.cpp @@ -0,0 +1,289 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2000-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include "waveedit.h" +#include "waveview.h" +#include "song.h" +#include "awl/poslabel.h" +#include "esettings.h" +#include "al/tempo.h" +#include "icons.h" +#include "shortcuts.h" +#include "wave.h" +#include "part.h" +#include "muse.h" + +int WaveEdit::initWidth = WaveEdit::INIT_WIDTH; +int WaveEdit::initHeight = WaveEdit::INIT_HEIGHT; + +//--------------------------------------------------------- +// WaveEdit +//--------------------------------------------------------- + +WaveEdit::WaveEdit(PartList* pl, bool init) + : Editor() + { + _parts = pl; + selPart = 0; + + //---------Pulldown Menu---------------------------- + QMenuBar* mb = menuBar(); + QAction* a; + + QMenu* menuFile = mb->addMenu(tr("&File")); + QMenu* menuEdit = mb->addMenu(tr("&Edit")); + menuFunctions = mb->addMenu(tr("Func&tions")); + + menuGain = menuFunctions->addMenu(tr("&Gain")); + a = menuGain->addAction(tr("200%")); + a->setData("gain200"); + a = menuGain->addAction(tr("150%")); + a->setData("gain150"); + a = menuGain->addAction(tr("75%")); + a->setData("gain75"); + a = menuGain->addAction(tr("50%")); + a->setData("gain50"); + a = menuGain->addAction(tr("25%")); + a->setData("gain25"); + a = menuGain->addAction(tr("Other")); + a->setData("gain_free"); + a = menuFunctions->addSeparator(); + + a = menuEdit->addAction(tr("Edit in E&xternal Editor")); + a->setData("exit_external"); + a = menuFunctions->addAction(tr("Mute Selection")); + a->setData("mute"); + a = menuFunctions->addAction(tr("Normalize Selection")); + a->setData("normalize"); + a = menuFunctions->addAction(tr("Fade In Selection")); + a->setData("fade_in"); + a = menuFunctions->addAction(tr("Fade Out Selection")); + a->setData("fade_out"); + a = menuFunctions->addAction(tr("Reverse Selection")); + a->setData("reverse"); + + select = menuEdit->addMenu(QIcon(*selectIcon), tr("Select")); + select->addAction(getAction("sel_all", this)); + select->addAction(getAction("sel_none", this)); + + connect(menuFunctions, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*))); + connect(menuFile, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*))); + connect(select, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*))); + connect(menuGain, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*))); + connect(menuEdit, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*))); + + //---------ToolBar---------------------------------- + tools = addToolBar(tr("waveedit-tools")); + tools->addAction(undoAction); + tools->addAction(redoAction); + + const int waveeditTools = PointerTool | PencilTool + | RubberTool | DrawTool; + EditToolBar* tools2 = new EditToolBar(this, waveeditTools); + addToolBar(tools2); + + //-------------------------------------------------- + // Transport Bar + QToolBar* transport = addToolBar(tr("Transport")); + muse->setupTransportToolbar(transport); + + //-------------------------------------------------- + // ToolBar: Solo Cursor1 Cursor2 + + addToolBarBreak(); + tb1 = addToolBar(tr("pianoroll-tools")); + solo = tb1->addAction(tr("Solo")); + solo->setCheckable(true); + connect(solo, SIGNAL(toggled(bool)), SLOT(soloChanged(bool))); + + tb1->addWidget(new QLabel(tr("Cursor"))); + pos1 = new PosLabel; + pos2 = new PosLabel; + pos2->setSmpte(true); + tb1->addWidget(pos1); + tb1->addWidget(pos2); + + //--------------------------------------------------- + // Rest + //--------------------------------------------------- + +// if (!parts()->empty()) { // Roughly match total size of part +// Part* firstPart = parts()->begin()->second; +// xscale = 0 - firstPart->lenFrame()/_widthInit; +// } + + view = new WaveView(this); + view->setRaster(0); + view->setFollow(INIT_FOLLOW); + + connect(muse, SIGNAL(configChanged()), SLOT(configChanged())); + connect(song, SIGNAL(posChanged(int,const AL::Pos&,bool)), view, SLOT(setLocatorPos(int,const AL::Pos&,bool))); + view->setLocatorPos(0, song->cpos(), true); + view->setLocatorPos(1, song->lpos(), false); + view->setLocatorPos(2, song->rpos(), false); +// connect(view, SIGNAL(cursorPos(unsigned)), SIGNAL(setTime(unsigned))); + connect(view, SIGNAL(posChanged(int,const AL::Pos&)), song, SLOT(setPos(int,const AL::Pos&))); + + setCentralWidget(view); + view->setCornerWidget(new QSizeGrip(view)); + setWindowTitle(view->getCaption()); + + Pos p1(0, AL::FRAMES), p2(0, AL::FRAMES); + view->range(p1, p2); + p2 += AL::sigmap.ticksMeasure(p2.tick()); // show one more measure + view->setTimeRange(p1, p2); + + connect(view, SIGNAL(toolChanged(int)), tools2, SLOT(set(int))); + connect(tools2, SIGNAL(toolChanged(int)), view, SLOT(setTool(int))); + +// view->selectFirst(); + configChanged(); + if (init) + ; // initFromPart(); + else { + resize(initWidth, initHeight); + } + } + +//--------------------------------------------------------- +// configChanged +//--------------------------------------------------------- + +void WaveEdit::configChanged() + { +// view->setBg(config.waveEditBackgroundColor); + } + +//--------------------------------------------------------- +// setTime +//--------------------------------------------------------- + +void WaveEdit::setTime(unsigned samplepos) + { +// printf("setTime %d %x\n", samplepos, samplepos); + unsigned tick = AL::tempomap.frame2tick(samplepos); + pos1->setValue(tick, true); + pos2->setValue(tick, true); +// time->setPos(3, tick, false); + } + +//--------------------------------------------------------- +// ~WaveEdit +//--------------------------------------------------------- + +WaveEdit::~WaveEdit() + { +// undoRedo->removeFrom(tools); + } + +//--------------------------------------------------------- +// cmd +//--------------------------------------------------------- + +void WaveEdit::cmd(QAction* a) + { + view->cmd(a->data().toString()); + } + +//--------------------------------------------------------- +// soloChanged +// signal from "song" +//--------------------------------------------------------- + +void WaveEdit::soloChanged(SNode*/* s*/) + { + Part* part = parts()->begin()->second; + solo->setChecked(part->track()->solo()); + } + +//--------------------------------------------------------- +// soloChanged +// signal from solo button +//--------------------------------------------------------- + +void WaveEdit::soloChanged(bool flag) + { + Part* part = parts()->begin()->second; + song->setSolo(part->track(), flag); + } + +//--------------------------------------------------------- +// viewKeyPressEvent +//--------------------------------------------------------- + +void WaveEdit::keyPressEvent(QKeyEvent* event) + { + int key = event->key(); + if (key == Qt::Key_Escape) { + close(); + return; + } + else { + event->ignore(); + } + } + +//--------------------------------------------------------- +// read +//--------------------------------------------------------- + +void WaveEdit::read(QDomNode node) + { + for (node = node.firstChild(); !node.isNull(); node = node.nextSibling()) { + QDomElement e = node.toElement(); + QString tag(e.tagName()); + if (tag == "CtrlEdit") { + int id = e.attribute("id","0").toInt(); + int h = e.attribute("h","50").toInt(); + view->addController(id, h); + } + else + AL::readProperties(this, node); + } + view->layout1(); + } + + +//--------------------------------------------------------- +// write +//--------------------------------------------------------- + +void WaveEdit::write(Xml& xml) const + { + for (ciPart p = _parts->begin(); p != _parts->end(); ++p) { + Part* part = p->second; + Track* track = part->track(); + int trkIdx = song->tracks()->indexOf(track); + int partIdx = track->parts()->index(part); + xml.stag("part"); + xml.put(QString("%1:%2").arg(trkIdx).arg(partIdx)); + xml.etag("part"); + } + xml.stag(metaObject()->className()); + xml.writeProperties(this); + const CtrlEditList* el = view->getCtrlEditors(); + for (ciCtrlEdit i = el->begin(); i != el->end(); ++i) { + xml.tagE(QString("CtrlEdit h=\"%1\" id=\"%2\"") + .arg((*i)->height()).arg((*i)->ctrl()->id())); + } + xml.etag(metaObject()->className()); + } + + diff --git a/attic/muse_qt4_evolution/muse/waveedit/waveedit.h b/attic/muse_qt4_evolution/muse/waveedit/waveedit.h new file mode 100644 index 00000000..f861587d --- /dev/null +++ b/attic/muse_qt4_evolution/muse/waveedit/waveedit.h @@ -0,0 +1,88 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#ifndef __WAVE_EDIT_H__ +#define __WAVE_EDIT_H__ + +#include "midiedit/midieditor.h" + +class PartList; +class WaveView; +class ScrollScale; +class SNode; + +namespace Awl { + class PosLabel; + }; +using Awl::PosLabel; + + +//--------------------------------------------------------- +// WaveEdit +//--------------------------------------------------------- + +class WaveEdit : public Editor { + Q_OBJECT + + PartList* _parts; + Part* selPart; + + WaveView* view; + QToolBar* tools; + QToolBar* tb1; + QAction* solo; + PosLabel* pos1; + PosLabel* pos2; + + static int _widthInit, _heightInit; + + virtual void keyPressEvent(QKeyEvent*); + + QMenu* menuFunctions, *select, *menuGain; + + private slots: + void cmd(QAction*); + void setTime(unsigned t); + void soloChanged(SNode* s); + void soloChanged(bool flag); + + public slots: + void configChanged(); + + public: + WaveEdit(PartList*, bool); + ~WaveEdit(); + PartList* parts() const { return _parts; } + void read(QDomNode node); + void write(Xml& xml) const; + + 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_EXTERNAL, + CMD_SELECT_ALL, CMD_SELECT_NONE }; + static int initWidth, initHeight; + static const int INIT_WIDTH = 650; + static const int INIT_HEIGHT = 450; + }; + +static const bool INIT_FOLLOW = false; + +#endif + diff --git a/attic/muse_qt4_evolution/muse/waveedit/waveview.cpp b/attic/muse_qt4_evolution/muse/waveedit/waveview.cpp new file mode 100644 index 00000000..eb5a744d --- /dev/null +++ b/attic/muse_qt4_evolution/muse/waveedit/waveview.cpp @@ -0,0 +1,1124 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include <sys/wait.h> + +#include "waveview.h" +#include "song.h" +#include "midiedit/midieditor.h" +#include "al/tempo.h" +#include "event.h" +#include "globals.h" +#include "waveedit.h" +#include "audio.h" +#include "gconfig.h" +#include "part.h" +#include "widgets/simplebutton.h" +#include "utils.h" + +static const int partLabelHeight = 13; + +//--------------------------------------------------------- +// WaveView +//--------------------------------------------------------- + +WaveView::WaveView(WaveEdit* pr) + : TimeCanvas(TIME_CANVAS_WAVEEDIT) + { + setMarkerList(song->marker()); + curSplitter = -1; + dragSplitter = false; + selectionStart = 0; + selectionStop = 0; + lastGainvalue = 100; + editor = pr; + + curPart = editor->parts()->begin()->second; + setMouseTracking(true); + + songChanged(SC_TRACK_INSERTED); + } + +//--------------------------------------------------------- +// drawWavePart +// y0 - start of track +// th - track height +// from - x pixel coordinate start drawing +// to - x end drawing +// +// redraw area is QRect(from, y0, to-from, th) +//--------------------------------------------------------- + +void WaveView::drawWavePart(QPainter& p, Part* wp, int y0, int th, int from, int to) + { + int h = th/2; + int y = y0 + 1 + h; + int cc = th % 2 ? 0 : 1; + + const Pos pos(pix2pos(from)); + EventList* el = wp->events(); + for (iEvent e = el->begin(); e != el->end(); ++e) { + Event event = e->second; + SndFileR f = event.sndFile(); + if (f.isNull()) + continue; + unsigned channels = f.channels(); + if (channels == 0) { + printf("drawWavePart: channels==0! %s\n", f.finfo()->fileName().toLatin1().data()); + continue; + } + + int x1 = pos2pix(event.pos() + *wp); + int x2 = pos2pix(event.end() + *wp); + int w = x2 - x1; + if (w == 0) + continue; + + int samples = event.lenFrame(); + int xScale = (samples + w/2)/w; + int frame = pos.frame() - wp->frame() + - event.pos().frame() + event.spos(); + + if (h < 20) { + // + // combine multi channels into one waveform + // + for (int i = from; i < to; i++) { + SampleV sa[channels]; + f.read(sa, xScale, frame); + frame += xScale; + int peak = 0; + int rms = 0; + for (unsigned k = 0; k < channels; ++k) { + if (sa[k].peak > peak) + peak = sa[k].peak; + rms += sa[k].rms; + } + rms /= channels; + peak = (peak * (th-2)) >> 9; + rms = (rms * (th-2)) >> 9; + p.setPen(QColor(Qt::darkGray)); + p.drawLine(i, y - peak - cc, i, y + peak); + p.setPen(QColor(Qt::black)); + p.drawLine(i, y - rms - cc, i, y + rms); + } + } + else { + // + // multi channel display + // + h = th / (channels * 2); + int cc = th % (channels * 2) ? 0 : 1; + for (int i = from; i < to; i++) { + y = y0 + 1 + h; + SampleV sa[channels]; + f.read(sa, xScale, frame); + frame += xScale; + for (unsigned k = 0; k < channels; ++k) { + int peak = (sa[k].peak * (h - 1)) >> 8; + int rms = (sa[k].rms * (h - 1)) >> 8; + p.setPen(QColor(Qt::darkGray)); + p.drawLine(i, y - peak - cc, i, y + peak); + p.setPen(QColor(Qt::black)); + p.drawLine(i, y - rms - cc, i, y + rms); + y += 2 * h; + } + } + } + } + } + +//--------------------------------------------------------- +// draw +//--------------------------------------------------------- + +void WaveView::paint(QPainter& p, QRect r) + { + QFont f = font(); + f.setPointSize(8); + p.setFont(f); + + int from = r.x(); + int to = from + r.width(); + + PartList* pl = editor->parts(); + for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { + Part* part = ip->second; + int x1 = pos2pix(*part); + int x2 = pos2pix(part->end()); + int len = x2 - x1; + + if (x2 <= from) + continue; + if (x1 > to) + break; + + int h = rCanvasA.height(); + int xx1 = x1; + if (xx1 < from) + xx1 = from; + int xx2 = x2; + if (xx2 > to) + xx2 = to; + drawWavePart(p, part, 0, h, xx1, xx2); + int yy = h - partLabelHeight; + p.drawText(x1 + 3, yy, len - 6, + partLabelHeight-1, Qt::AlignVCenter | Qt::AlignLeft, + part->name()); + } + } + +//--------------------------------------------------------- +// getCaption +//--------------------------------------------------------- + +QString WaveView::getCaption() const + { + QString caption("MusE: WaveEditor"); + if (curPart) + return caption + QString(": ") + curPart->name(); + return caption; + } + +//--------------------------------------------------------- +// songChanged +//--------------------------------------------------------- + +void WaveView::songChanged(int flags) + { + if (flags & ~SC_SELECTION) { + startFrame = MAXINT; + endFrame = 0; + for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) { + Part* part = p->second; + int sframe = part->frame(); + int eframe = sframe + part->lenFrame(); + if (sframe < startFrame) + startFrame = sframe; + if (eframe > endFrame) + endFrame = eframe; + } + } +// if (flags & SC_CLIP_MODIFIED) { +// update(); // Boring, but the only thing possible to do +// } + setPart(*curPart, curPart->end()); + widget()->update(); + } + +//--------------------------------------------------------- +// mousePress +//--------------------------------------------------------- + +void WaveView::mousePress(QMouseEvent* me) + { + QPoint pos(me->pos()); + + if (rCanvasA.contains(pos)) { +// mousePressCanvasA(me); + return; + } + if (curSplitter != -1) { + dragSplitter = true; + splitterY = pos.y(); + return; + } + + if (rCanvasB.contains(pos)) { + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + QRect r(rCanvasB.x(), rCanvasB.y() + c->y + splitWidth, + rCanvasB.width(), c->cheight()); + if (r.contains(pos)) { + c->mousePress(pos - r.topLeft(), me); + break; + } + } + } + } + +//--------------------------------------------------------- +// mouseRelease +//--------------------------------------------------------- + +void WaveView::mouseRelease(QMouseEvent* me) + { + if (dragSplitter) { + dragSplitter = false; + return; + } + QPoint pos(me->pos()); + if (rCanvasA.contains(pos)) { + // mouseReleaseCanvasA(me); + return; + } + if (rCanvasB.contains(pos)) { + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + QRect r(rCanvasB.x(), rCanvasB.y() + c->y + splitWidth, + rCanvasB.width(), c->cheight()); + if (r.contains(pos)) { + c->mouseRelease(); + break; + } + } + } + } + +//--------------------------------------------------------- +// mouseMove +//--------------------------------------------------------- + +void WaveView::mouseMove(QPoint pos) + { + if (dragSplitter) { + int deltaY = pos.y() - splitterY; + + iCtrlEdit i = ctrlEditList.begin(); + int y = 0; + if (curSplitter > 0) { + int k = 0; + CtrlEdit* c = 0; + for (; i != ctrlEditList.end(); ++i, ++k) { + c = *i; + y += c->height(); + if ((k+1) == curSplitter) + break; + } + if (i == ctrlEditList.end()) { + printf("unexpected edit list end, curSplitter %d\n", curSplitter); + return; + } + if (c->height() + deltaY < splitWidth) + deltaY = splitWidth - c->height(); + ++i; + int rest = 0; + for (iCtrlEdit ii = i; ii != ctrlEditList.end(); ++ii) + rest += (*ii)->cheight(); + if (rest < deltaY) + deltaY = rest; + c->setHeight(c->height() + deltaY); + layoutPanelB(c); + y += deltaY; + } + // + // layout rest, add deltaY vertical + // + int rest = 0; + for (iCtrlEdit ii = i; ii != ctrlEditList.end(); ++ii) { + CtrlEdit* c = *ii; + rest += c->cheight(); + } + if (rest < deltaY) + deltaY = rest; + rest = deltaY; + for (; i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + int d = c->cheight(); + if (d > deltaY) + d = deltaY; + c->setHeight(c->height() - d); + c->y = y; + layoutPanelB(c); + y += c->height(); + deltaY -= d; + if (deltaY == 0) + break; + } + if (i != ctrlEditList.end()) + ++i; + for (; i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + c->y = y; + y += c->height(); + } + if (curSplitter == 0) + resizeController(ctrlHeight - rest); + else + widget()->update(rPanelB | rCanvasB); + splitterY = pos.y(); + updatePartControllerList(); + return; + } + if (rCanvasA.contains(pos)) { + // mouseMoveCanvasA(pos - rCanvasA.topLeft()); + return; + } + if (button == 0) { + if (rPanelB.contains(pos) || rCanvasB.contains(pos)) { + int y = pos.y() - rPanelB.y(); + int k = 0; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i, ++k) { + CtrlEdit* c = *i; + if (y >= c->y && y < (c->y + splitWidth)) { + curSplitter = k; + setCursor(); + return; + } + int ypos = y - c->y - splitWidth; + if (ypos >= 0) + emit yChanged(c->pixel2val(ypos)); + } + } + if (curSplitter != -1) { + curSplitter = -1; + setCursor(); + } + return; + } + if (rCanvasB.contains(pos)) { + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + QRect r(rCanvasB.x(), rCanvasB.y() + c->y + splitWidth, + rCanvasB.width(), c->cheight()); + if (r.contains(pos)) { + c->mouseMove(pos - r.topLeft()); + break; + } + } + } + + } + +//--------------------------------------------------------- +// cmd +//--------------------------------------------------------- + +void WaveView::cmd(const QString&) + { +#if 0 + int modifyoperation = -1; + double paramA = 0.0; + + switch(n) { + case WaveEdit::CMD_SELECT_ALL: + if (!editor->parts()->empty()) { + iPart iBeg = editor->parts()->begin(); + iPart iEnd = editor->parts()->end(); + iEnd--; + Part* beg = iBeg->second; + Part* end = iEnd->second; + selectionStart = beg->frame(); + selectionStop = end->frame() + end->lenFrame(); + update(); + } + break; + + case WaveEdit::CMD_EDIT_EXTERNAL: + modifyoperation = EDIT_EXTERNAL; + break; + + case WaveEdit::CMD_SELECT_NONE: + selectionStart = selectionStop = 0; + update(); + break; + + case WaveEdit::CMD_MUTE: + modifyoperation = MUTE; + break; + + case WaveEdit::CMD_NORMALIZE: + modifyoperation = NORMALIZE; + break; + + case WaveEdit::CMD_FADE_IN: + modifyoperation = FADE_IN; + break; + + case WaveEdit::CMD_FADE_OUT: + modifyoperation = FADE_OUT; + break; + + case WaveEdit::CMD_REVERSE: + modifyoperation = REVERSE; + break; + + case WaveEdit::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; + */ + printf("Free gain - todo!\n"); + } + break; + + case WaveEdit::CMD_GAIN_200: + modifyoperation = GAIN; + paramA = 2.0; + break; + + case WaveEdit::CMD_GAIN_150: + modifyoperation = GAIN; + paramA = 1.5; + break; + + case WaveEdit::CMD_GAIN_75: + modifyoperation = GAIN; + paramA = 0.75; + break; + + case WaveEdit::CMD_GAIN_50: + modifyoperation = GAIN; + paramA = 0.5; + break; + + case WaveEdit::CMD_GAIN_25: + modifyoperation = GAIN; + paramA = 0.25; + break; + + default: + break; + } + + if (modifyoperation != -1) { + if (selectionStart == selectionStop) { + printf("No selection. Ignoring\n"); //@!TODO: Disable menu options when no selection + return; + } + modifySelection(modifyoperation, selectionStart, selectionStop, paramA); + } +#endif + } + +//--------------------------------------------------------- +// getSelection +//--------------------------------------------------------- + +WaveSelectionList WaveView::getSelection(unsigned /*startpos*/, unsigned /*stoppos*/) + { + WaveSelectionList selection; +#if 0 + for (iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) { + Part* wp = ip->second; + unsigned part_offset = wp->frame(); + EventList* el = wp->events(); + + for (iEvent e = el->begin(); e != el->end(); ++e) { + Event event = e->second; + if (event.empty()) + continue; + SndFileR file = event.sndFile(); + if (file.isNull()) + continue; + + unsigned event_offset = event.frame() + part_offset; + unsigned event_startpos = event.spos(); + unsigned event_length = event.lenFrame() + 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().data()); + WaveEventSelection s; + s.file = file; + s.startframe = sx; + s.endframe = ex; + selection.push_back(s); + } + } + } +#endif + return selection; + } + +//--------------------------------------------------------- +// modifySelection +//--------------------------------------------------------- + +void WaveView::modifySelection(int /*operation*/, unsigned /*startpos*/, unsigned /*stoppos*/, double /*paramA*/) + { +#if 0 + song->startUndo(); + + WaveSelectionList selection = getSelection(startpos, stoppos); + for (iWaveSelection i = selection.begin(); i != selection.end(); i++) { + WaveEventSelection w = *i; + SndFileR& file = w.file; + unsigned sx = w.startframe; + unsigned ex = w.endframe; + unsigned file_channels = file.channels(); + + QString tmpWavFile = QString::null; + if (!getUniqueTmpfileName(tmpWavFile)) { + break; + } + + audio->msgIdle(true); // Not good with playback during operations + SndFile tmpFile(tmpWavFile); + tmpFile.setFormat(file.format(), file_channels, file.samplerate()); + if (tmpFile.openWrite()) { + 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.read(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 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 + song->cmdChangeWave(file.dirPath() + "/" + file.name(), tmpWavFile, sx, ex); + audio->msgIdle(false); // Not good with playback during operations + } + song->endUndo(SC_CLIP_MODIFIED); + update(); +#endif + } + +//--------------------------------------------------------- +// muteSelection +//--------------------------------------------------------- + +void WaveView::muteSelection(unsigned /*channels*/, float** /*data*/, unsigned /*length*/) + { +#if 0 + // Set everything to 0! + for (unsigned i=0; i<channels; i++) { + for (unsigned j=0; j<length; j++) { + data[i][j] = 0; + } + } +#endif + } + +//--------------------------------------------------------- +// normalizeSelection +//--------------------------------------------------------- + +void WaveView::normalizeSelection(unsigned /*channels*/, float** /*data*/, unsigned /*length*/) + { +#if 0 + 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); + } + } +#endif + } + +//--------------------------------------------------------- +// fadeInSelection +//--------------------------------------------------------- + +void WaveView::fadeInSelection(unsigned /*channels*/, float** /*data*/, unsigned /*length*/) + { +#if 0 + 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); + } + } +#endif + } + +//--------------------------------------------------------- +// fadeOutSelection +//--------------------------------------------------------- + +void WaveView::fadeOutSelection(unsigned /*channels*/, float** /*data*/, unsigned /*length*/) + { +#if 0 + 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); + } + } +#endif + } + +//--------------------------------------------------------- +// reverseSelection +//--------------------------------------------------------- + +void WaveView::reverseSelection(unsigned channels, float** data, unsigned length) + { + 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]; + data[i][j] = tmpr; + data[i][length - j] = tmpl; + } + } + } + +//--------------------------------------------------------- +// applyGain +//--------------------------------------------------------- + +void WaveView::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 WaveView::editExternal(unsigned file_format, unsigned file_samplerate, unsigned file_channels, float** tmpdata, unsigned tmpdatalen) + { + // Create yet another tmp-file + QString exttmpFileName; + if (!getUniqueTmpfileName(exttmpFileName)) { + printf("Could not create temp file - aborting...\n"); + return; + } + + 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 = vfork(); + if (pid == 0) { + if (execlp(config.externalWavEditor.toLatin1().data(), "", exttmpFileName.toLatin1().data(), NULL) == -1) { + perror("Failed to launch external editor"); + // Get out of here + exit(-1); + } + //@!TODO: Handle unsuccessful attempts + } + else if (pid == -1) { + perror("fork failed"); + } + else { + waitpid(pid, 0, 0); + if (exttmpFile.openRead()) { + printf("Could not reopen temporary file again!\n"); + } + else { + // Re-read file again + exttmpFile.seek(0); + size_t sz = exttmpFile.read(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.finfo()->absolutePath(); + dir.remove(exttmpFileName); + dir.remove(exttmpFile.finfo()->baseName() + ".wca"); + } + } + +//--------------------------------------------------------- +// getUniqueTmpfileName +//--------------------------------------------------------- + +bool WaveView::getUniqueTmpfileName(QString& newFilename) + { + // Check if tmp-directory exists under project path + QString tmpWavDir = song->absoluteProjectPath() + "/tmp_musewav"; //!@TODO: Don't hardcode like this + QFileInfo tmpdirfi(tmpWavDir); + if (!tmpdirfi.isDir()) { + // Try to create a tmpdir + QDir projdir(song->absoluteProjectPath()); + if (!projdir.mkdir("tmp_musewav")) { + printf("Could not create undo dir!\n"); + return false; + } + } + + + tmpdirfi.setFile(tmpWavDir); + + if (!tmpdirfi.isWritable()) { + printf("Temp directory is not writable - aborting\n"); + return false; + } + + QDir tmpdir = tmpdirfi.dir(); + + // Find a new filename + for (int i=0; i<10000; i++) { + QString filename = "muse_tmp"; + filename.append(QString::number(i)); + filename.append(".wav"); + + if (!tmpdir.exists(tmpWavDir +"/" + filename)) { + newFilename = tmpWavDir + "/" + filename; + return true; + } + } + + printf("Could not find a suitable tmpfilename (more than 10000 tmpfiles in tmpdir - clean up!\n"); + return false; + } + +//--------------------------------------------------------- +// range +//--------------------------------------------------------- + +void WaveView::range(AL::Pos& s, AL::Pos& e) const + { + s.setFrame(startFrame); + e.setFrame(endFrame); + } + +//--------------------------------------------------------- +// layout +//--------------------------------------------------------- + +void WaveView::layout() + { + int n = ctrlEditList.size(); + if (n == 0) + return; + if (ctrlHeight == 0) { + int wh = widget()->height(); + resizeController(wh < 120 ? wh / 2 : 100); + } + // check, if layout is ok already; this happens after + // song load + int h = 0; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + h += c->height(); + } + if (h == ctrlHeight) { + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) + layoutPanelB(*i); + return; + } + int y = 0; + int sch = ctrlHeight / n; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + c->y = y; + c->setHeight(sch); + layoutPanelB(c); + y += sch; + } + } + +//--------------------------------------------------------- +// layout1 +//--------------------------------------------------------- + +void WaveView::layout1() + { + int n = ctrlEditList.size(); + if (n == 0) + return; + int y = 0; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + c->y = y; + y += c->height(); + } + resizeController(y); + } + +//--------------------------------------------------------- +// layoutPanelB +//--------------------------------------------------------- + +void WaveView::layoutPanelB(CtrlEdit* c) + { + int y = c->y; + int h = c->height(); + int bx = rPanelB.x() + rPanelB.width() - 23; + int by = rPanelB.y() + y + h - 19; + c->minus->setGeometry(bx, by, 18, 18); + bx = rPanelB.x() + 1; + by = rPanelB.y() + y + 5; + c->sel->setGeometry(bx, by, rPanelB.width() - 5, 18); + } + +//--------------------------------------------------------- +// addController +//--------------------------------------------------------- + +void WaveView::addController() + { + int n = ctrlEditList.size(); + CtrlEdit* ce = new CtrlEdit(widget(), this, curPart->track()); + ce->setHeight(50); + ctrlEditList.push_back(ce); + + ce->minus->defaultAction()->setData(n); + connect(ce->minus, SIGNAL(triggered(QAction*)), SLOT(removeController(QAction*))); + ce->minus->show(); + ce->sel->show(); + + layout(); + widget()->update(); + updatePartControllerList(); + } + +void WaveView::addController(int id, int h) + { + ctrlHeight += h; + int n = ctrlEditList.size(); + + CtrlEdit* ce = new CtrlEdit(widget(), this, curPart->track()); + ce->setHeight(h); + ce->setCtrl(id); + ctrlEditList.push_back(ce); + + ce->minus->defaultAction()->setData(n); + connect(ce->minus, SIGNAL(triggered(QAction*)), SLOT(removeController(QAction*))); + } + +//--------------------------------------------------------- +// removeController +//--------------------------------------------------------- + +void WaveView::removeController(QAction* a) + { + int id = a->data().toInt(); + + int k = 0; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i, ++k) { + if (k == id) { + CtrlEdit* c = *i; + delete c; + ctrlEditList.erase(i); + break; + } + } + k = 0; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i, ++k) { + CtrlEdit* c = *i; + c->minus->defaultAction()->setData(k); + } + + if (ctrlEditList.empty()) + resizeController(0); + else + layout(); + widget()->update(); + updatePartControllerList(); + } + +//--------------------------------------------------------- +// updatePartControllerList +//--------------------------------------------------------- + +void WaveView::updatePartControllerList() + { + if (curPart == 0) + return; + CtrlCanvasList* cl = curPart->getCtrlCanvasList(); + cl->clear(); + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlCanvas cc; + cc.ctrlId = (*i)->ctrlId; + cc.height = (*i)->height(); + cl->push_back(cc); + } + } + +//--------------------------------------------------------- +// paintControllerCanvas +// r(0, 0) is PanelB topLeft() +//--------------------------------------------------------- + +void WaveView::paintControllerCanvas(QPainter& p, QRect r) + { + int x1 = r.x(); + int x2 = x1 + r.width(); + + int xx2 = rCanvasB.width(); + if (xx2 >= x2) + x2 = xx2 - 2; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + int y = c->y; + paintHLine(p, x1, x2, y); + p.setPen(lineColor[0]); + p.drawLine(xx2-1, 1, xx2-1, splitWidth-2); + + QRect rc(0, y + splitWidth, rCanvasB.width(), c->cheight()); + QPoint pt(rc.topLeft()); + rc &= r; + if (!rc.isEmpty()) { + p.translate(pt); + c->paint(p, rc.translated(-pt)); + p.translate(-pt); + } + } + } + +//--------------------------------------------------------- +// paintControllerPanel +// panelB +//--------------------------------------------------------- + +void WaveView::paintControllerPanel(QPainter& p, QRect r) + { + p.fillRect(r, QColor(0xe0, 0xe0, 0xe0)); + int x1 = r.x(); + int x2 = x1 + r.width(); + + paintVLine(p, r.y() + splitWidth, r.y() + r.height(), + rPanelB.x() + rPanelB.width()); + + if (x1 == 0) + x1 = 1; + for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) { + CtrlEdit* c = *i; + paintHLine(p, x1, x2, c->y); + p.setPen(lineColor[0]); + p.drawLine(0, 1, 0, splitWidth-2); + } + } + +//--------------------------------------------------------- +// setCursor +//--------------------------------------------------------- + +void WaveView::setCursor() + { + if (curSplitter != -1) { + widget()->setCursor(Qt::SplitVCursor); + return; + } + TimeCanvas::setCursor(); + } + +//--------------------------------------------------------- +// enterB +//--------------------------------------------------------- + +void WaveView::enterB() + { + if ((button == 0) && curSplitter != -1) { + curSplitter = -1; + setCursor(); + } + } + +//--------------------------------------------------------- +// leaveB +//--------------------------------------------------------- + +void WaveView::leaveB() + { + if ((button == 0) && (curSplitter != -1)) { + curSplitter = -1; + setCursor(); + } + } + + diff --git a/attic/muse_qt4_evolution/muse/waveedit/waveview.h b/attic/muse_qt4_evolution/muse/waveedit/waveview.h new file mode 100644 index 00000000..462ce26d --- /dev/null +++ b/attic/muse_qt4_evolution/muse/waveedit/waveview.h @@ -0,0 +1,127 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#ifndef WAVE_VIEW_H +#define WAVE_VIEW_H + +#include "al/pos.h" +#include "wave.h" +#include "awl/tcanvas.h" +#include "ctrl/ctrledit.h" + +class PartList; +class QPainter; +class QRect; +class Part; +class WaveEdit; +class GraphMidiEditor; + +//--------------------------------------------------------- +// WaveEventSelection +//--------------------------------------------------------- + +struct WaveEventSelection { + SndFileR file; + unsigned startframe; + unsigned endframe; + }; + +typedef std::list<WaveEventSelection> WaveSelectionList; +typedef std::list<WaveEventSelection>::iterator iWaveSelection; + +//--------------------------------------------------------- +// WaveView +//--------------------------------------------------------- + +class WaveView : public TimeCanvas { + Q_OBJECT + + WaveEdit* editor; + CtrlEditList ctrlEditList; + + int startFrame; + int endFrame; + + Part* curPart; + + enum { NORMAL, DRAG } mode; + enum { MUTE = 0, NORMALIZE, FADE_IN, FADE_OUT, REVERSE, GAIN, EDIT_EXTERNAL }; //!< Modify operations + + unsigned selectionStart, selectionStop, dragstartx; + int curSplitter; // -1 mouse not in splitter + bool dragSplitter; + int splitterY; + + virtual void paint(QPainter&, QRect); + virtual void mousePress(QMouseEvent*); + virtual void mouseMove(QPoint); + virtual void enterB(); + virtual void leaveB(); + virtual void mouseRelease(QMouseEvent*); + + bool getUniqueTmpfileName(QString& newFilename); //!< Generates unique filename for temporary SndFile + WaveSelectionList getSelection(unsigned startpos, unsigned stoppos); + + int lastGainvalue; //!< Stores the last used gainvalue when specifiying gain value in the editgain dialog + 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 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 + + void drawWavePart(QPainter& p, Part* wp, int y0, int th, int from, int to); + virtual void addController(); + virtual void layout(); + void layoutPanelB(CtrlEdit*); + void updatePartControllerList(); + + virtual void paintControllerCanvas(QPainter&, QRect); + virtual void paintControllerPanel(QPainter&, QRect); + + void setCursor(); + + private slots: + void removeController(QAction*); + + public slots: + void songChanged(int type); + + signals: + void yChanged(int); // emitted from mouseMove in controller canvas + + public: + WaveView(WaveEdit*); + QString getCaption() const; + void cmd(const QString&); + void range(AL::Pos&, AL::Pos&) const; + void addController(int id, int h); + void layout1(); + const CtrlEditList* getCtrlEditors() const { return &ctrlEditList; } + }; + +#endif + |