diff options
Diffstat (limited to 'attic/muse_qt4_evolution/muse/waveedit/waveview.cpp')
-rw-r--r-- | attic/muse_qt4_evolution/muse/waveedit/waveview.cpp | 1124 |
1 files changed, 1124 insertions, 0 deletions
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(); + } + } + + |