diff options
author | Florian Jung <flo@windfisch.org> | 2012-01-03 19:13:48 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2012-01-03 19:13:48 +0000 |
commit | 7993a73cece885bac45021dd021ac43f6f332040 (patch) | |
tree | 2f8296b31efa6d93cb53b8b735519163ec163a84 /muse2/muse | |
parent | 845d28b2fba8f2c1d4211aee7beb5ab041315531 (diff) | |
parent | 1bc4ba9dfc00b6e7511fbf4765296a2002f83315 (diff) |
merged with trunk
added "copy drummap" to duplicate track dialog
Diffstat (limited to 'muse2/muse')
35 files changed, 1491 insertions, 374 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 6a4e7c06..21426979 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -3146,7 +3146,7 @@ void MusE::focusInEvent(QFocusEvent* ev) // mixer1->raise(); //if (mixer2) // mixer2->raise(); - raise(); + //raise(); QMainWindow::focusInEvent(ev); } diff --git a/muse2/muse/arranger/arrangerview.cpp b/muse2/muse/arranger/arrangerview.cpp index d6266531..2eab50a5 100644 --- a/muse2/muse/arranger/arrangerview.cpp +++ b/muse2/muse/arranger/arrangerview.cpp @@ -146,6 +146,7 @@ ArrangerView::ArrangerView(QWidget* parent) editPasteCloneDialogAction = new QAction(QIcon(*editpasteCloneIconSet), tr("Paste clone (show dialog)"), this); editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this); editDeleteSelectedAction = new QAction(QIcon(*edit_track_delIcon), tr("Delete Selected Tracks"), this); + editDuplicateSelTrackAction = new QAction(QIcon(*edit_track_addIcon), tr("Duplicate Selected Tracks"), this); editShrinkPartsAction = new QAction(tr("Shrink selected parts"), this); editExpandPartsAction = new QAction(tr("Expand selected parts"), this); @@ -224,6 +225,7 @@ ArrangerView::ArrangerView(QWidget* parent) menuEdit->addAction(editDeleteSelectedAction); menuEdit->addMenu(addTrack); + menuEdit->addAction(editDuplicateSelTrackAction); menuEdit->addMenu(select); select->addAction(editSelectAllAction); select->addAction(editDeselectAllAction); @@ -298,6 +300,7 @@ ArrangerView::ArrangerView(QWidget* parent) connect(editPasteCloneDialogAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editDeleteSelectedAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); + connect(editDuplicateSelTrackAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editShrinkPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editExpandPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); @@ -319,6 +322,7 @@ ArrangerView::ArrangerView(QWidget* parent) editSignalMapper->setMapping(editPasteCloneDialogAction, CMD_PASTE_CLONE_DIALOG); editSignalMapper->setMapping(editInsertEMAction, CMD_INSERTMEAS); editSignalMapper->setMapping(editDeleteSelectedAction, CMD_DELETE_TRACK); + editSignalMapper->setMapping(editDuplicateSelTrackAction, CMD_DUPLICATE_TRACK); editSignalMapper->setMapping(editShrinkPartsAction, CMD_SHRINK_PART); editSignalMapper->setMapping(editExpandPartsAction, CMD_EXPAND_PART); editSignalMapper->setMapping(editCleanPartsAction, CMD_CLEAN_PART); @@ -515,6 +519,10 @@ void ArrangerView::cmd(int cmd) MusEGlobal::audio->msgUpdateSoloStates(); break; + case CMD_DUPLICATE_TRACK: + MusEGlobal::song->duplicateTracks(); + break; + case CMD_SELECT_ALL: case CMD_SELECT_NONE: case CMD_SELECT_INVERT: diff --git a/muse2/muse/arranger/arrangerview.h b/muse2/muse/arranger/arrangerview.h index 0dac67e4..5407c2ab 100644 --- a/muse2/muse/arranger/arrangerview.h +++ b/muse2/muse/arranger/arrangerview.h @@ -69,7 +69,7 @@ class ArrangerView : public TopWin CMD_PASTE_DIALOG, CMD_PASTE_CLONE_DIALOG, CMD_DELETE, CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT, CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PARTS, - CMD_DELETE_TRACK, CMD_EXPAND_PART, CMD_SHRINK_PART, CMD_CLEAN_PART, + CMD_DELETE_TRACK, CMD_DUPLICATE_TRACK, CMD_EXPAND_PART, CMD_SHRINK_PART, CMD_CLEAN_PART, CMD_QUANTIZE, CMD_VELOCITY, CMD_CRESCENDO, CMD_NOTELEN, CMD_TRANSPOSE, CMD_ERASE, CMD_MOVE, CMD_FIXED_LEN, CMD_DELETE_OVERLAPS, CMD_LEGATO }; @@ -95,6 +95,7 @@ class ArrangerView : public TopWin QAction *editCutAction, *editCopyAction, *editCopyRangeAction; QAction *editPasteAction, *editPasteCloneAction, *editPasteDialogAction, *editPasteCloneDialogAction; QAction *editInsertEMAction, *editPasteC2TAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction; + QAction *editDuplicateSelTrackAction; QAction *editInvertSelectionAction, *editInsideLoopAction, *editOutsideLoopAction, *editAllPartsAction; QAction *masterGraphicAction, *masterListAction; QAction *midiTransformerAction; diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index fc0014e2..897ae1c8 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -380,7 +380,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& if(t == MOVE_MOVE) item->setPart(dpart); if (t == MOVE_COPY && !clone) { - dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it + //dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it // so we must decrement it first :/ // @@ -397,11 +397,19 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& if (t == MOVE_COPY || t == MOVE_CLONE) { + dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it + // so we must decrement it first :/ // These will not increment ref count, and will not chain clones... // TODO: is this comment still correct (by flo93)? i doubt it! operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddPart,dpart)); } else if (t == MOVE_MOVE) { + // In all cases found ev lists were same. So this is redundant - Redo incs then decs the same list. + // But just in case we ever have two different lists... + dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it + // so we must decrement it first :/ + spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it + // so we must increment it first :/ dpart->setSelected(spart->selected()); // These will increment ref count if not a clone, and will chain clones... // TODO: is this comment still correct (by flo93)? i doubt it! diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index 8cc2a05a..3b33fc66 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -364,8 +364,6 @@ void TList::paint(const QRect& r) int outport = ((MusECore::MidiTrack*)track)->outPort(); s.sprintf("%d:%s", outport+1, MusEGlobal::midiPorts[outport].portname().toLatin1().constData()); } - // Added by Tim. p3.3.9 - else if(track->type() == MusECore::Track::AUDIO_SOFTSYNTH) { @@ -453,44 +451,140 @@ void TList::paint(const QRect& r) //--------------------------------------------------------- void TList::returnPressed() - { - editor->hide(); - if (editor->text() != editTrack->name()) { - MusECore::TrackList* tl = MusEGlobal::song->tracks(); - for (MusECore::iTrack i = tl->begin(); i != tl->end(); ++i) { - if ((*i)->name() == editor->text()) { - QMessageBox::critical(this, - tr("MusE: bad trackname"), - tr("please choose a unique track name"), - QMessageBox::Ok, - Qt::NoButton, - Qt::NoButton); - editTrack = 0; - setFocus(); - return; - } - } - //MusECore::Track* track = editTrack->clone(); - MusECore::Track* track = editTrack->clone(false); - editTrack->setName(editor->text()); - MusEGlobal::audio->msgChangeTrack(track, editTrack); - } - editTrack = 0; +{ + if(editTrack) + { + if(editor && editor->isVisible()) + { + //editor->hide(); + if (editor->text() != editTrack->name()) { + MusECore::TrackList* tl = MusEGlobal::song->tracks(); + for (MusECore::iTrack i = tl->begin(); i != tl->end(); ++i) { + if ((*i)->name() == editor->text()) { + QMessageBox::critical(this, + tr("MusE: bad trackname"), + tr("please choose a unique track name"), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + editTrack = 0; + editor->blockSignals(true); + editor->hide(); + editor->blockSignals(false); + setFocus(); + return; + } + } + + //MusECore::Track* track = editTrack->clone(false); + //editTrack->setName(editor->text()); + //MusEGlobal::audio->msgChangeTrack(track, editTrack); + // p4.0.46 Tim... + MusEGlobal::song->startUndo(); + MusEGlobal::song->addUndo(MusECore::UndoOp(MusECore::UndoOp::ModifyTrackName, + editTrack, + editTrack->name().toLatin1().constData(), + editor->text().toLatin1().constData())); + editTrack->setName(editor->text()); + //MusEGlobal::song->update(SC_TRACK_MODIFIED); + MusEGlobal::song->endUndo(-1); + } + } + + editTrack = 0; + } + editMode = false; + if(editor->isVisible()) + { + editor->blockSignals(true); + editor->hide(); + editor->blockSignals(false); + } setFocus(); - } +} -void TList::chanValueChanged(int val) +void TList::chanValueChanged(int /*val*/) { - MusECore::Track* track = editTrack->clone(false); - ((MusECore::MidiTrack*)editTrack)->setOutChannel(val-1); - MusEGlobal::audio->msgChangeTrack(track, editTrack); + //MusECore::Track* track = editTrack->clone(false); + //((MusECore::MidiTrack*)editTrack)->setOutChannel(val-1); + //MusEGlobal::audio->msgChangeTrack(track, editTrack); } void TList::chanValueFinished() { - editTrack = 0; - chan_edit->hide(); + if(editTrack) + { + if(editTrack->isMidiTrack()) + { + MusECore::MidiTrack* mt = dynamic_cast<MusECore::MidiTrack*>(editTrack); + if (mt && mt->type() != MusECore::Track::DRUM) + //if (mt && !mt->isDrumTrack()) // For Flo later with new drum tracks. + { + int channel = chan_edit->value() - 1; + if(channel >= MIDI_CHANNELS) + channel = MIDI_CHANNELS - 1; + if(channel < 0) + channel = 0; + if(channel != mt->outChannel()) + { + MusEGlobal::song->startUndo(); + MusEGlobal::song->addUndo(MusECore::UndoOp(MusECore::UndoOp::ModifyTrackChannel, + editTrack, + mt->outChannel(), + channel)); + //mt->setOutChannel(channel); + MusEGlobal::audio->msgIdle(true); + //MusEGlobal::audio->msgSetTrackOutChannel(mt, channel); + mt->setOutChanAndUpdate(channel); + MusEGlobal::audio->msgIdle(false); + //if (mt->type() == MusECore::MidiTrack::DRUM) {//Change channel on all drum instruments + // for (int i=0; i<DRUM_MAPSIZE; i++) + // MusEGlobal::drumMap[i].channel = channel; + // } + MusEGlobal::audio->msgUpdateSoloStates(); + //MusEGlobal::song->endUndo(SC_CHANNELS); + //MusEGlobal::song->endUndo(SC_MIDI_TRACK_PROP | SC_ROUTE); + MusEGlobal::song->endUndo(SC_MIDI_TRACK_PROP); + } + } + } + else + { + if(editTrack->type() != MusECore::Track::AUDIO_SOFTSYNTH) + { + MusECore::AudioTrack* at = dynamic_cast<MusECore::AudioTrack*>(editTrack); + if(at) + { + int n = chan_edit->value(); + if(n > MAX_CHANNELS) + n = MAX_CHANNELS; + else if (n < 1) + n = 1; + if(n != at->channels()) + { + MusEGlobal::song->startUndo(); + MusEGlobal::song->addUndo(MusECore::UndoOp(MusECore::UndoOp::ModifyTrackChannel, + editTrack, + at->channels(), + n)); + MusEGlobal::audio->msgSetChannels(at, n); + MusEGlobal::song->endUndo(SC_CHANNELS); + } + } + } + } + + editTrack = 0; + } + + editMode = false; + if(chan_edit->isVisible()) + { + chan_edit->blockSignals(true); + chan_edit->hide(); + chan_edit->blockSignals(false); + } setFocus(); } @@ -531,11 +625,21 @@ MusECore::Track* TList::y2Track(int y) const void TList::mouseDoubleClickEvent(QMouseEvent* ev) { + int button = ev->button(); + //bool ctrl = ((QInputEvent*)ev)->modifiers() & Qt::ControlModifier; + if(button != Qt::LeftButton) { + mousePressEvent(ev); + return; + } + int x = ev->x(); int section = header->logicalIndexAt(x); if (section == -1) - return; - + { + mousePressEvent(ev); + return; + } + MusECore::Track* t = y2Track(ev->y() + ypos); if (t) { @@ -551,30 +655,53 @@ void TList::mouseDoubleClickEvent(QMouseEvent* ev) /*connect(editor, SIGNAL(returnPressed()), SLOT(returnPressed()));*/ editor->setFrame(true); + connect(editor, SIGNAL(editingFinished()), SLOT(returnPressed())); } + //editor->blockSignals(true); editor->setText(editTrack->name()); + //editor->blockSignals(false); editor->end(false); editor->setGeometry(colx, coly, colw, colh); editMode = true; editor->show(); } else if (section == COL_OCHANNEL) { - if (t->isMidiTrack() && t->type() != MusECore::Track::DRUM) + //if (t->isMidiTrack() && t->type() != MusECore::Track::DRUM) + // Enabled for audio tracks. And synth channels cannot be changed ATM. + if(t->type() == MusECore::Track::DRUM || t->type() == MusECore::Track::AUDIO_SOFTSYNTH) + { + mousePressEvent(ev); + return; + } + + //if(t->type() != MusECore::Track::DRUM && t->type() != MusECore::Track::AUDIO_SOFTSYNTH) { editTrack=t; if (chan_edit==0) { chan_edit=new QSpinBox(this); chan_edit->setMinimum(1); - chan_edit->setMaximum(16); - connect(chan_edit, SIGNAL(valueChanged(int)), SLOT(chanValueChanged(int))); + //connect(chan_edit, SIGNAL(valueChanged(int)), SLOT(chanValueChanged(int))); connect(chan_edit, SIGNAL(editingFinished()), SLOT(chanValueFinished())); } - chan_edit->setValue(((MusECore::MidiTrack*)editTrack)->outChannel()+1); + //chan_edit->blockSignals(true); + if (t->isMidiTrack()) + { + chan_edit->setMaximum(MIDI_CHANNELS); + chan_edit->setValue(((MusECore::MidiTrack*)editTrack)->outChannel()+1); + } + else // if(t->type() != MusECore::Track::AUDIO_SOFTSYNTH) + { + chan_edit->setMaximum(MAX_CHANNELS); + chan_edit->setValue(((MusECore::AudioTrack*)editTrack)->channels()); + } + //chan_edit->blockSignals(false); int w=colw; if (w < chan_edit->sizeHint().width()) w=chan_edit->sizeHint().width(); chan_edit->setGeometry(colx, coly, w, colh); + editMode = true; chan_edit->show(); chan_edit->setFocus(); + ev->accept(); } } else @@ -842,7 +969,6 @@ void TList::portsPopupMenu(MusECore::Track* t, int x, int y) void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y) { - // Added by Tim. p3.3.9 if(t->type() == MusECore::Track::AUDIO_SOFTSYNTH) { MusECore::SynthI* synth = (MusECore::SynthI*)t; @@ -870,7 +996,7 @@ void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y) // If it has a gui but we don't have OSC, disable the action. #ifndef OSC_SUPPORT #ifdef DSSI_SUPPORT - if(dynamic_cast<DssiMusECore::SynthIF*>(synth->sif())) + if(dynamic_cast<MusECore::DssiSynthIF*>(synth->sif())) { //act->setChecked(false); //act->setEnabled(false); @@ -923,7 +1049,7 @@ void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y) #ifndef OSC_SUPPORT #ifdef DSSI_SUPPORT MusECore::MidiDevice* dev = port->device(); - if(dev && dev->isSynti() && (dynamic_cast<DssiMusECore::SynthIF*>(((MusECore::SynthI*)dev)->sif()))) + if(dev && dev->isSynti() && (dynamic_cast<MusECore::DssiSynthIF*>(((MusECore::SynthI*)dev)->sif()))) { //act->setChecked(false); //act->setEnabled(false); @@ -968,14 +1094,26 @@ void TList::keyPressEvent(QKeyEvent* e) { // First time we get a keypress event when lineedit is open is on the return key: // -- Not true for Qt4. Modifier keys also send key events - Orcan - if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) - { - returnPressed(); - return; - } - else if ( e->key() == Qt::Key_Escape ) + //if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) // Removed p4.0.46 Tim. + // { + // returnPressed(); + // return; + // } + //else + if ( e->key() == Qt::Key_Escape ) { - editor->hide(); + if(editor && editor->isVisible()) + { + editor->blockSignals(true); + editor->hide(); + editor->blockSignals(false); + } + if(chan_edit && chan_edit->isVisible()) + { + chan_edit->blockSignals(true); + chan_edit->hide(); + chan_edit->blockSignals(false); + } editTrack = 0; editMode = false; setFocus(); @@ -1058,8 +1196,9 @@ void TList::moveSelection(int n) MusEGlobal::song->setRecordFlag((*t),true); } - if (editTrack && editTrack != *t) + if (editTrack && editTrack != *t) returnPressed(); + redraw(); break; } @@ -1854,6 +1993,9 @@ void TList::mouseReleaseEvent(QMouseEvent* ev) } if (editTrack && editor && editor->isVisible()) editor->setFocus(); + //else + //if (editTrack && chan_edit && chan_edit->isVisible()) // p4.0.46 + // chan_edit->setFocus(); adjustScrollbar(); } diff --git a/muse2/muse/audio.cpp b/muse2/muse/audio.cpp index 0b1574cc..3f1d4dc8 100644 --- a/muse2/muse/audio.cpp +++ b/muse2/muse/audio.cpp @@ -67,7 +67,8 @@ extern double curTime(); //static const unsigned char mmcStopMsg[] = { 0x7f, 0x7f, 0x06, 0x01 }; const char* seqMsgList[] = { - "SEQM_ADD_TRACK", "SEQM_REMOVE_TRACK", "SEQM_CHANGE_TRACK", "SEQM_MOVE_TRACK", + "SEQM_ADD_TRACK", "SEQM_REMOVE_TRACK", //"SEQM_CHANGE_TRACK", + "SEQM_MOVE_TRACK", "SEQM_ADD_PART", "SEQM_REMOVE_PART", "SEQM_CHANGE_PART", "SEQM_ADD_EVENT", "SEQM_REMOVE_EVENT", "SEQM_CHANGE_EVENT", "SEQM_ADD_TEMPO", "SEQM_SET_TEMPO", "SEQM_REMOVE_TEMPO", "SEQM_ADD_SIG", "SEQM_REMOVE_SIG", diff --git a/muse2/muse/audio.h b/muse2/muse/audio.h index 3c4eb17d..a81498a6 100644 --- a/muse2/muse/audio.h +++ b/muse2/muse/audio.h @@ -55,7 +55,8 @@ class Track; //--------------------------------------------------------- enum { - SEQM_ADD_TRACK, SEQM_REMOVE_TRACK, SEQM_CHANGE_TRACK, SEQM_MOVE_TRACK, + SEQM_ADD_TRACK, SEQM_REMOVE_TRACK, //SEQM_CHANGE_TRACK, + SEQM_MOVE_TRACK, SEQM_ADD_PART, SEQM_REMOVE_PART, SEQM_CHANGE_PART, SEQM_ADD_EVENT, SEQM_REMOVE_EVENT, SEQM_CHANGE_EVENT, SEQM_ADD_TEMPO, SEQM_SET_TEMPO, SEQM_REMOVE_TEMPO, SEQM_ADD_SIG, SEQM_REMOVE_SIG, @@ -221,7 +222,7 @@ class Audio { void msgRemoveTrack(Track*, bool u = true); void msgRemoveTracks(); - void msgChangeTrack(Track* oldTrack, Track* newTrack, bool u = true); + //void msgChangeTrack(Track* oldTrack, Track* newTrack, bool u = true); void msgMoveTrack(int idx1, int dx2, bool u = true); void msgAddPart(Part*, bool u = true); void msgRemovePart(Part*, bool u = true); diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp index aceacc75..e542deec 100644 --- a/muse2/muse/audiotrack.cpp +++ b/muse2/muse/audiotrack.cpp @@ -93,7 +93,6 @@ void cacheJackRouteNames() //--------------------------------------------------------- AudioTrack::AudioTrack(TrackType t) -//AudioTrack::AudioTrack(TrackType t, int num_out_bufs) : Track(t) { //_totalOutChannels = num_out_bufs; // Is either parameter-default MAX_CHANNELS, or custom value passed (used by syntis). @@ -111,7 +110,6 @@ AudioTrack::AudioTrack(TrackType t) addController(new CtrlList(AC_PAN, "Pan", -1.0, 1.0, VAL_LINEAR)); addController(new CtrlList(AC_MUTE,"Mute",0.0,1.0, VAL_LINEAR, true /*dont show in arranger */)); - // Changed by Tim. p3.3.15 //outBuffers = new float*[MAX_CHANNELS]; //for (int i = 0; i < MAX_CHANNELS; ++i) // outBuffers[i] = new float[MusEGlobal::segmentSize]; @@ -125,7 +123,6 @@ AudioTrack::AudioTrack(TrackType t) //for (int i = 0; i < MAX_CHANNELS; ++i) // *(outBuffers + i) = sizeof(float) * MusEGlobal::segmentSize * i; - // p3.3.38 // Easy way, less desirable... Start out with enough for MAX_CHANNELS. Then multi-channel syntis can re-allocate, // via a call to (a modified!) setChannels(). // Hard way, more desirable... Creating a synti instance passes the total channels to this constructor, overriding MAX_CHANNELS. @@ -142,71 +139,181 @@ AudioTrack::AudioTrack(TrackType t) setVolume(1.0); } -//AudioTrack::AudioTrack(const AudioTrack& t) -// : Track(t) -AudioTrack::AudioTrack(const AudioTrack& t, bool cloneParts) - : Track(t, cloneParts) +AudioTrack::AudioTrack(const AudioTrack& t, int flags) + : Track(t, flags) { - _totalOutChannels = t._totalOutChannels; // Is either MAX_CHANNELS, or custom value (used by syntis). _processed = false; _haveData = false; - _sendMetronome = t._sendMetronome; - _controller = t._controller; - _prefader = t._prefader; - _auxSend = t._auxSend; - _efxPipe = new Pipeline(*(t._efxPipe)); - _automationType = t._automationType; - _inRoutes = t._inRoutes; - _outRoutes = t._outRoutes; - // Changed by Tim. p3.3.15 - //outBuffers = new float*[MAX_CHANNELS]; - //for (int i = 0; i < MAX_CHANNELS; ++i) - // outBuffers[i] = new float[MusEGlobal::segmentSize]; - //for (int i = 0; i < MAX_CHANNELS; ++i) - // posix_memalign((void**)(outBuffers + i), 16, sizeof(float) * MusEGlobal::segmentSize); + _efxPipe = new Pipeline(); // Start off with a new pipeline. - // p3.3.38 - int chans = _totalOutChannels; - // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. - if(chans < MAX_CHANNELS) - chans = MAX_CHANNELS; - outBuffers = new float*[chans]; - for (int i = 0; i < chans; ++i) - posix_memalign((void**)&outBuffers[i], 16, sizeof(float) * MusEGlobal::segmentSize); + // Don't allocate outBuffers here. Let internal_assign() call setTotalOutChannels to set them up. + outBuffers = 0; + _totalOutChannels = 0; + // This is only set by multi-channel syntis... + _totalInChannels = 0; bufferPos = MAXINT; - _recFile = t._recFile; + + //_recFile = t._recFile; + _recFile = NULL; + + internal_assign(t, flags | ASSIGN_PROPERTIES); } +void AudioTrack::internal_assign(const Track& t, int flags) +{ + if(t.isMidiTrack()) + return; + + const AudioTrack& at = (const AudioTrack&)t; + + if(flags & ASSIGN_PROPERTIES) + { + _sendMetronome = at._sendMetronome; + _prefader = at._prefader; + _auxSend = at._auxSend; + _automationType = at._automationType; + + if(!(flags & ASSIGN_STD_CTRLS)) + { + _controller.clearDelete(); + for(ciCtrlList icl = at._controller.begin(); icl != at._controller.end(); ++icl) + { + CtrlList* cl = icl->second; + // Copy all built-in controllers (id below AC_PLUGIN_CTL_BASE), but not plugin controllers. + if(cl->id() >= AC_PLUGIN_CTL_BASE) + continue; + CtrlList* new_cl = new CtrlList(); + new_cl->assign(*cl, CtrlList::ASSIGN_PROPERTIES); // Don't copy values. + addController(new_cl); + } + } + + // This will set up or reallocate the outBuffers. + setTotalOutChannels(at._totalOutChannels); + + // This is only set by multi-channel syntis... + //_totalInChannels = 0; + //_totalInChannels = t._totalInChannels; + setTotalInChannels(at._totalInChannels); + + setChannels(at.channels()); // Set track channels (max 2). + + //bufferPos = MAXINT; + + //_recFile = at._recFile; + //_recFile = NULL; + } + + if(flags & ASSIGN_PLUGINS) + { + delete _efxPipe; + _efxPipe = new Pipeline(*(at._efxPipe)); // Make copies of the plugins. + } + + if(flags & (ASSIGN_STD_CTRLS | ASSIGN_PLUGIN_CTRLS)) + { + _controller.clearDelete(); + for(ciCtrlList icl = at._controller.begin(); icl != at._controller.end(); ++icl) + { + CtrlList* cl = icl->second; + // Discern between built-in controllers (id below AC_PLUGIN_CTL_BASE), and plugin controllers. + if(cl->id() >= AC_PLUGIN_CTL_BASE) + { + if(!(flags & ASSIGN_PLUGIN_CTRLS)) + continue; + } + else if(!(flags & ASSIGN_STD_CTRLS)) + continue; + + CtrlList* new_cl = new CtrlList(*cl); // Let copy constructor handle the rest. Copy values. + addController(new_cl); + } + } + + // FIXME: May get "addRoute: src track route already exists" when say, + // an audio output and wave track are selected just because + // of the redundancy (wave track wants to connect to output by default). + if(flags & ASSIGN_ROUTES) + { + for(ciRoute ir = at._inRoutes.begin(); ir != at._inRoutes.end(); ++ir) + { + // Defer all Jack routes to Audio Input and Output copy constructors or assign ! + if(ir->type == Route::JACK_ROUTE) + continue; + // Amazingly, this single line seems to work. + MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel, ir->channels)); + } + + for(ciRoute ir = at._outRoutes.begin(); ir != at._outRoutes.end(); ++ir) + { + // Defer all Jack routes to Audio Input and Output copy constructors or assign ! + if(ir->type == Route::JACK_ROUTE) + continue; + // Amazingly, this single line seems to work. + MusEGlobal::audio->msgAddRoute(Route(this, ir->channel, ir->channels), *ir); + } + } + else if(flags & ASSIGN_DEFAULT_ROUTES) + { + // + // add default route to master + // + OutputList* ol = MusEGlobal::song->outputs(); + if (!ol->empty()) { + AudioOutput* ao = ol->front(); + switch(type()) { + //case Track::MIDI: + //case Track::DRUM: + //case Track::AUDIO_OUTPUT: + // break; + + case Track::WAVE: + //case Track::AUDIO_GROUP: + case Track::AUDIO_AUX: + //case Track::AUDIO_INPUT: + //case Track::AUDIO_SOFTSYNTH: + MusEGlobal::audio->msgAddRoute(Route(this, -1), Route(ao, -1)); + //updateFlags |= SC_ROUTE; + break; + // It should actually never get here now, but just in case. + case Track::AUDIO_SOFTSYNTH: + MusEGlobal::audio->msgAddRoute(Route(this, 0, channels()), Route(ao, 0, channels())); + //updateFlags |= SC_ROUTE; + break; + default: + break; + } + } + } + +} + +void AudioTrack::assign(const Track& t, int flags) +{ + Track::assign(t, flags); + internal_assign(t, flags); +} + AudioTrack::~AudioTrack() { delete _efxPipe; - //for (int i = 0; i < MAX_CHANNELS; ++i) - // delete[] outBuffers[i]; - //delete[] outBuffers; - - // p3.3.15 - //for(int i = 0; i < MAX_CHANNELS; ++i) - //{ - // if(outBuffers[i]) - // free(outBuffers[i]); - //} - // p3.3.38 int chans = _totalOutChannels; // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. if(chans < MAX_CHANNELS) chans = MAX_CHANNELS; - for(int i = 0; i < chans; ++i) + if(outBuffers) { - if(outBuffers[i]) - free(outBuffers[i]); + for(int i = 0; i < chans; ++i) + { + if(outBuffers[i]) + free(outBuffers[i]); + } + delete[] outBuffers; } - delete[] outBuffers; - - for(iCtrlList i = _controller.begin(); i != _controller.end(); ++i) - delete i->second; + _controller.clearDelete(); } //--------------------------------------------------------- @@ -1028,8 +1135,7 @@ bool AudioTrack::readProperties(Xml& xml, const QString& tag) //PluginI* p = 0; PluginIBase* p = 0; bool ctlfound = false; - //int m = l->id() & AC_PLUGIN_CTL_ID_MASK; - unsigned m = l->id() & AC_PLUGIN_CTL_ID_MASK; // p4.0.21 + unsigned m = l->id() & AC_PLUGIN_CTL_ID_MASK; int n = (l->id() >> AC_PLUGIN_CTL_BASE_POW) - 1; if(n >= 0 && n < PipelineDepth) { @@ -1195,8 +1301,7 @@ void AudioTrack::mapRackPluginsToControllers() // Ignore volume, pan, mute etc. if(id < AC_PLUGIN_CTL_BASE) continue; - //int param = id & AC_PLUGIN_CTL_ID_MASK; - unsigned param = id & AC_PLUGIN_CTL_ID_MASK; // p4.0.21 + unsigned param = id & AC_PLUGIN_CTL_ID_MASK; int idx = (id >> AC_PLUGIN_CTL_BASE_POW) - 1; //PluginI* p = (*_efxPipe)[idx]; @@ -1346,14 +1451,50 @@ AudioInput::AudioInput() //setChannels(2); } -//AudioInput::AudioInput(const AudioInput& t) -// : AudioTrack(t) -AudioInput::AudioInput(const AudioInput& t, bool cloneParts) - : AudioTrack(t, cloneParts) - { - for (int i = 0; i < MAX_CHANNELS; ++i) - jackPorts[i] = t.jackPorts[i]; - } +AudioInput::AudioInput(const AudioInput& t, int flags) + : AudioTrack(t, flags) +{ + for (int i = 0; i < MAX_CHANNELS; ++i) + //jackPorts[i] = t.jackPorts[i]; + jackPorts[i] = 0; + + // Register ports. + if(MusEGlobal::checkAudioDevice()) + { + for (int i = 0; i < channels(); ++i) + { + char buffer[128]; + snprintf(buffer, 128, "%s-%d", _name.toLatin1().constData(), i); + jackPorts[i] = MusEGlobal::audioDevice->registerInPort(buffer, false); + } + } + internal_assign(t, flags); +} + +void AudioInput::assign(const Track& t, int flags) +{ + AudioTrack::assign(t, flags); + internal_assign(t, flags); +} + +void AudioInput::internal_assign(const Track& t, int flags) +{ + if(t.type() != AUDIO_INPUT) + return; + + const AudioInput& at = (const AudioInput&)t; + + if(flags & ASSIGN_ROUTES) + { + for(ciRoute ir = at._inRoutes.begin(); ir != at._inRoutes.end(); ++ir) + { + // Defer all Jack routes to these copy constructors or assign ! + if(ir->type != Route::JACK_ROUTE) + continue; + MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel, ir->channels)); + } + } +} //--------------------------------------------------------- // ~AudioInput @@ -1422,16 +1563,53 @@ AudioOutput::AudioOutput() //setChannels(2); } -//AudioOutput::AudioOutput(const AudioOutput& t) -// : AudioTrack(t) -AudioOutput::AudioOutput(const AudioOutput& t, bool cloneParts) - : AudioTrack(t, cloneParts) - { - for (int i = 0; i < MAX_CHANNELS; ++i) - jackPorts[i] = t.jackPorts[i]; - _nframes = t._nframes; - } +AudioOutput::AudioOutput(const AudioOutput& t, int flags) + : AudioTrack(t, flags) +{ + for (int i = 0; i < MAX_CHANNELS; ++i) + //jackPorts[i] = t.jackPorts[i]; + jackPorts[i] = 0; + //_nframes = t._nframes; + _nframes = 0; + + // Register ports. + if(MusEGlobal::checkAudioDevice()) + { + for (int i = 0; i < channels(); ++i) + { + char buffer[128]; + snprintf(buffer, 128, "%s-%d", _name.toLatin1().constData(), i); + jackPorts[i] = MusEGlobal::audioDevice->registerOutPort(buffer, false); + } + } + internal_assign(t, flags); +} + +void AudioOutput::assign(const Track& t, int flags) +{ + AudioTrack::assign(t, flags); + internal_assign(t, flags); +} +void AudioOutput::internal_assign(const Track& t, int flags) +{ + if(t.type() != AUDIO_OUTPUT) + return; + + const AudioOutput& at = (const AudioOutput&)t; + + if(flags & ASSIGN_ROUTES) + { + for(ciRoute ir = at._outRoutes.begin(); ir != at._outRoutes.end(); ++ir) + { + // Defer all Jack routes to these copy constructors or assign ! + if(ir->type != Route::JACK_ROUTE) + continue; + MusEGlobal::audio->msgAddRoute(Route(this, ir->channel, ir->channels), *ir); + } + } +} + //--------------------------------------------------------- // ~AudioOutput //--------------------------------------------------------- @@ -1548,7 +1726,6 @@ AudioAux::AudioAux() { //_channels = 0; //setChannels(2); - // Changed by Tim. p3.3.15 //for (int i = 0; i < MAX_CHANNELS; ++i) // buffer[i] = (i < channels()) ? new float[MusEGlobal::segmentSize] : 0; for(int i = 0; i < MAX_CHANNELS; ++i) @@ -1560,13 +1737,27 @@ AudioAux::AudioAux() } } +AudioAux::AudioAux(const AudioAux& t, int flags) + : AudioTrack(t, flags) +{ + //_channels = 0; + //setChannels(2); + //for (int i = 0; i < MAX_CHANNELS; ++i) + // buffer[i] = (i < channels()) ? new float[MusEGlobal::segmentSize] : 0; + for(int i = 0; i < MAX_CHANNELS; ++i) + { + if(i < channels()) + posix_memalign((void**)(buffer + i), 16, sizeof(float) * MusEGlobal::segmentSize); + else + buffer[i] = 0; + } +} //--------------------------------------------------------- // AudioAux //--------------------------------------------------------- AudioAux::~AudioAux() { - // Changed by Tim. p3.3.15 //for (int i = 0; i < channels(); ++i) // delete[] buffer[i]; for (int i = 0; i < MAX_CHANNELS; ++i) { @@ -1657,7 +1848,6 @@ void AudioAux::setChannels(int n) { if(n > channels()) { - // Changed by Tim. p3.3.15 //for (int i = channels(); i < n; ++i) // buffer[i] = new float[MusEGlobal::segmentSize]; for(int i = channels(); i < n; ++i) @@ -1665,7 +1855,6 @@ void AudioAux::setChannels(int n) } else if(n < channels()) { - // Changed by Tim. p3.3.15 //for (int i = n; i < channels(); ++i) // delete[] buffer[i]; for(int i = n; i < channels(); ++i) @@ -1704,7 +1893,6 @@ bool AudioTrack::setRecordFlag1(bool f) // recording, the _recFile pointer is made into an event, // then _recFile is made zero before this function is called. QString s = _recFile->path(); - // Added by Tim. p3.3.8 delete _recFile; setRecFile(0); diff --git a/muse2/muse/confmport.cpp b/muse2/muse/confmport.cpp index d45dd370..0acb8f64 100644 --- a/muse2/muse/confmport.cpp +++ b/muse2/muse/confmport.cpp @@ -1162,7 +1162,8 @@ MPConfig::MPConfig(QWidget* parent) instrPopup = 0; defpup = 0; //_showAliases = -1; // 0: Show first aliases, if available. Nah, stick with -1: none at first. - _showAliases = 0; // 0: Show first aliases, if available. + //_showAliases = 0; // 0: Show first aliases, if available. + _showAliases = 1; // 0: Show second aliases, if available. QStringList columnnames; columnnames << tr("Port") diff --git a/muse2/muse/ctrl.cpp b/muse2/muse/ctrl.cpp index bc4ce246..f9353860 100644 --- a/muse2/muse/ctrl.cpp +++ b/muse2/muse/ctrl.cpp @@ -56,6 +56,17 @@ void CtrlList::initColor(int i) // CtrlList //--------------------------------------------------------- +CtrlList::CtrlList() + { + _id = 0; + _default = 0.0; + _curVal = 0.0; + _mode = INTERPOLATE; + _dontShow = false; + _visible = false; + initColor(0); + } + CtrlList::CtrlList(int id) { _id = id; @@ -63,11 +74,10 @@ CtrlList::CtrlList(int id) _curVal = 0.0; _mode = INTERPOLATE; _dontShow = false; + _visible = false; initColor(id); } -//--------------------------------------------------------- -// CtrlList -//--------------------------------------------------------- + CtrlList::CtrlList(int id, QString name, double min, double max, CtrlValueType v, bool dontShow) { _id = id; @@ -79,21 +89,36 @@ CtrlList::CtrlList(int id, QString name, double min, double max, CtrlValueType v _max = max; _valueType = v; _dontShow = dontShow; + _visible = false; initColor(id); } + //--------------------------------------------------------- -// CtrlList +// assign //--------------------------------------------------------- -CtrlList::CtrlList() - { - _id = 0; - _default = 0.0; - _curVal = 0.0; - _mode = INTERPOLATE; - _dontShow = false; - initColor(0); - } +void CtrlList::assign(const CtrlList& l, int flags) +{ + if(flags & ASSIGN_PROPERTIES) + { + _id = l._id; + _default = l._default; + _curVal = l._curVal; + _mode = l._mode; + _name = l._name; + _min = l._min; + _max = l._max; + _valueType = l._valueType; + _dontShow = l._dontShow; + _displayColor = l._displayColor; + _visible = l._visible; + } + + if(flags & ASSIGN_VALUES) + { + *this = l; // Let the vector assign values. + } +} //--------------------------------------------------------- // value @@ -396,5 +421,5 @@ void CtrlListList::add(CtrlList* vl) // printf("CtrlListList(%p)::add(id=%d) size %d\n", this, vl->id(), size()); insert(std::pair<const int, CtrlList*>(vl->id(), vl)); } - + } // namespace MusECore diff --git a/muse2/muse/ctrl.h b/muse2/muse/ctrl.h index 5e4ee531..83db1063 100644 --- a/muse2/muse/ctrl.h +++ b/muse2/muse/ctrl.h @@ -97,7 +97,7 @@ typedef std::map<int, CtrlVal, std::less<int> >::const_iterator ciCtrl; class CtrlList : public std::map<int, CtrlVal, std::less<int> > { public: enum Mode { INTERPOLATE, DISCRETE}; - + enum AssignFlags { ASSIGN_PROPERTIES=1, ASSIGN_VALUES=2 }; // Can be or'd together. private: Mode _mode; int _id; @@ -116,6 +116,7 @@ class CtrlList : public std::map<int, CtrlVal, std::less<int> > { CtrlList(); CtrlList(int id); CtrlList(int id, QString name, double min, double max, CtrlValueType v, bool dontShow=false); + void assign(const CtrlList& l, int flags); Mode mode() const { return _mode; } void setMode(Mode m) { _mode = m; } @@ -162,6 +163,12 @@ typedef std::map<int, CtrlList*, std::less<int> >::const_iterator ciCtrlList; class CtrlListList : public std::map<int, CtrlList*, std::less<int> > { public: void add(CtrlList* vl); + void clearDelete() { + for(iCtrlList i = begin(); i != end(); ++i) + delete i->second; + clear(); + } + iCtrlList find(int id) { return std::map<int, CtrlList*, std::less<int> >::find(id); } diff --git a/muse2/muse/driver/alsamidi.cpp b/muse2/muse/driver/alsamidi.cpp index 2c6f9468..740de1fb 100644 --- a/muse2/muse/driver/alsamidi.cpp +++ b/muse2/muse/driver/alsamidi.cpp @@ -792,8 +792,9 @@ bool initMidiAlsa() const char* cname = snd_seq_client_info_get_name(cinfo); //printf( "ALSA client name: %s\n", cname); - // Put Midi Through and user clients after others. Insert other unwanted clients here: // p4.0.41 - if( !(snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT || strcmp("Midi Through", cname) == 0) ) + bool is_thru = (strcmp("Midi Through", cname) == 0); + // Put Midi Through and user clients after others. Insert other unwanted clients here: // p4.0.41 + if( !(snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT || is_thru) ) continue; snd_seq_port_info_t *pinfo; @@ -820,6 +821,8 @@ bool initMidiAlsa() if (capability & inCap) flags |= 2; dev->setrwFlags(flags); + if(is_thru) // Don't auto-open Midi Through. + dev->setOpenFlags(0); if (MusEGlobal::debugMsg) printf("ALSA port add: <%s>, %d:%d flags %d 0x%0x\n", snd_seq_port_info_get_name(pinfo), diff --git a/muse2/muse/evdata.h b/muse2/muse/evdata.h index 4700e20a..333a5e2d 100644 --- a/muse2/muse/evdata.h +++ b/muse2/muse/evdata.h @@ -58,8 +58,9 @@ class EvData { return *this; if (--(*refCount) == 0) { delete refCount; - delete[] data; - } + if(data) + delete[] data; + } data = ed.data; dataLen = ed.dataLen; refCount = ed.refCount; @@ -69,9 +70,17 @@ class EvData { ~EvData() { if (--(*refCount) == 0) { - delete[] data; - delete refCount; - } + if(data) + { + delete[] data; + data = 0; + } + if(refCount) + { + delete refCount; + refCount = 0; + } + } } void setData(const unsigned char* p, int l) { if(data) diff --git a/muse2/muse/mididev.cpp b/muse2/muse/mididev.cpp index 3bec7716..f7686e18 100644 --- a/muse2/muse/mididev.cpp +++ b/muse2/muse/mididev.cpp @@ -92,8 +92,8 @@ void initMidiDevices() void MidiDevice::init() { - _readEnable = false; - _writeEnable = false; + _readEnable = false; + _writeEnable = false; _rwFlags = 3; _openFlags = 3; _port = -1; diff --git a/muse2/muse/mididev.h b/muse2/muse/mididev.h index e2eab0b1..57c96090 100644 --- a/muse2/muse/mididev.h +++ b/muse2/muse/mididev.h @@ -56,6 +56,7 @@ class MidiDevice { int _openFlags; // configured open flags bool _readEnable; // set when opened/closed. bool _writeEnable; // + //int _sysexWriteChunk; //int _sysexReadChunk; //bool _sysexWritingChunks; diff --git a/muse2/muse/mixer/amixer.cpp b/muse2/muse/mixer/amixer.cpp index 08999777..1f8aa27f 100644 --- a/muse2/muse/mixer/amixer.cpp +++ b/muse2/muse/mixer/amixer.cpp @@ -149,7 +149,8 @@ bool ScrollArea::viewportEvent(QEvent* event) if(event->type() == QEvent::LayoutRequest) emit layoutRequest(); - return false; + //return false; + return true; } //--------------------------------------------------------- @@ -222,7 +223,7 @@ AudioMixerApp::AudioMixerApp(QWidget* parent, MusEGlobal::MixerConfig* c) ///view = new QScrollArea(); view = new ScrollArea(); - view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +// view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setCentralWidget(view); central = new QWidget(view); diff --git a/muse2/muse/mixer/strip.cpp b/muse2/muse/mixer/strip.cpp index d574adb6..54cd2e8c 100644 --- a/muse2/muse/mixer/strip.cpp +++ b/muse2/muse/mixer/strip.cpp @@ -320,11 +320,15 @@ void Strip::mousePressEvent(QMouseEvent* ev) if (!act) { delete menu; + QFrame::mousePressEvent(ev); return; } MusEGlobal::song->removeTrack0(track); MusEGlobal::audio->msgUpdateSoloStates(); + ev->accept(); + return; } + QFrame::mousePressEvent(ev); } diff --git a/muse2/muse/node.cpp b/muse2/muse/node.cpp index b6b40738..20440b45 100644 --- a/muse2/muse/node.cpp +++ b/muse2/muse/node.cpp @@ -1851,12 +1851,15 @@ void AudioTrack::setTotalOutChannels(int num) // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. if(chans < MAX_CHANNELS) chans = MAX_CHANNELS; - for(int i = 0; i < chans; ++i) - { - if(outBuffers[i]) - free(outBuffers[i]); - } - delete[] outBuffers; + if(outBuffers) + { + for(int i = 0; i < chans; ++i) + { + if(outBuffers[i]) + free(outBuffers[i]); + } + delete[] outBuffers; + } _totalOutChannels = num; chans = num; diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp index 7daeb9ff..7bdc0b00 100644 --- a/muse2/muse/osc.cpp +++ b/muse2/muse/osc.cpp @@ -61,8 +61,12 @@ #include "globals.h" #include "globaldefs.h" +#endif // OSC_SUPPORT + namespace MusECore { +#ifdef OSC_SUPPORT + static lo_server_thread serverThread = 0; static char* url = 0; static bool oscServerRunning = false; diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp index e7e5c1f8..ed3a8655 100644 --- a/muse2/muse/plugin.cpp +++ b/muse2/muse/plugin.cpp @@ -1300,7 +1300,6 @@ Plugin* PluginList::find(const QString& file, const QString& name) Pipeline::Pipeline() : std::vector<PluginI*>() { - // Added by Tim. p3.3.15 for (int i = 0; i < MAX_CHANNELS; ++i) posix_memalign((void**)(buffer + i), 16, sizeof(float) * MusEGlobal::segmentSize); @@ -1309,6 +1308,21 @@ Pipeline::Pipeline() } //--------------------------------------------------------- +// Pipeline copy constructor +//--------------------------------------------------------- + +Pipeline::Pipeline(const Pipeline& /*p*/) + : std::vector<PluginI*>() + { + for (int i = 0; i < MAX_CHANNELS; ++i) + posix_memalign((void**)(buffer + i), 16, sizeof(float) * MusEGlobal::segmentSize); + + // TODO: Copy plug-ins ! + for (int i = 0; i < PipelineDepth; ++i) + push_back(0); + } + +//--------------------------------------------------------- // ~Pipeline //--------------------------------------------------------- @@ -1316,6 +1330,7 @@ Pipeline::~Pipeline() { removeAll(); for (int i = 0; i < MAX_CHANNELS; ++i) + if(buffer[i]) ::free(buffer[i]); } diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h index 717dc281..719db108 100644 --- a/muse2/muse/plugin.h +++ b/muse2/muse/plugin.h @@ -439,11 +439,11 @@ class PluginI : public PluginIBase { class Pipeline : public std::vector<PluginI*> { float* buffer[MAX_CHANNELS]; - + public: Pipeline(); + Pipeline(const Pipeline&); ~Pipeline(); - void insert(PluginI* p, int index); void remove(int index); void removeAll(); diff --git a/muse2/muse/seqmsg.cpp b/muse2/muse/seqmsg.cpp index 39dcc53c..abdebda7 100644 --- a/muse2/muse/seqmsg.cpp +++ b/muse2/muse/seqmsg.cpp @@ -879,13 +879,14 @@ void Audio::msgRemoveTracks() } +/* //--------------------------------------------------------- // msgChangeTrack // oldTrack - copy of the original track befor modification // newTrack - modified original track //--------------------------------------------------------- -void Audio::msgChangeTrack(Track* oldTrack, Track* newTrack, bool doUndoFlag) +void Audio::msgChangeTrack(Track* oldTrack, Track* newTrack, bool doUndoFlag) { AudioMsg msg; msg.id = SEQM_CHANGE_TRACK; @@ -893,7 +894,8 @@ void Audio::msgChangeTrack(Track* oldTrack, Track* newTrack, bool doUndoFlag) msg.p2 = newTrack; sendMessage(&msg, doUndoFlag); } - +*/ + //--------------------------------------------------------- // msgMoveTrack // move track idx1 to slot idx2 diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index 69900bbc..6d7e419e 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -31,6 +31,7 @@ #include <QMessageBox> #include <QPoint> #include <QSignalMapper> +#include <QString> #include <QTextStream> #include <QProcess> #include <QByteArray> @@ -56,6 +57,7 @@ #include "sync.h" #include "midictrl.h" #include "menutitleitem.h" +#include "tracks_duplicate.h" #include "midi.h" ///#include "sig.h" #include "al/sig.h" @@ -381,6 +383,168 @@ Track* Song::addTrack(Undo& operations, Track::TrackType type, Track* insertAt) } //--------------------------------------------------------- +// duplicateTracks +// Called from GUI context +//--------------------------------------------------------- + +void Song::duplicateTracks() +{ + // Make a temporary copy. + TrackList tl = _tracks; + + int audio_found = 0; + int midi_found = 0; + int drum_found = 0; + int new_drum_found = 0; + for(iTrack it = tl.begin(); it != tl.end(); ++it) + if((*it)->selected()) + { + Track::TrackType type = (*it)->type(); + // TODO: Handle synths. p4.0.47 + if(type == Track::AUDIO_SOFTSYNTH) + continue; + + if(type == Track::DRUM) + ++drum_found; + else if(type == Track::NEW_DRUM) + ++new_drum_found; + else if(type == Track::MIDI) + ++midi_found; + else + ++audio_found; + } + + if(audio_found == 0 && midi_found == 0 && drum_found == 0 && new_drum_found==0) + return; + + + MusEGui::DuplicateTracksDialog* dlg = new MusEGui::DuplicateTracksDialog(audio_found, midi_found, drum_found, new_drum_found); + + int rv = dlg->exec(); + if(rv == QDialog::Rejected) + { + delete dlg; + return; + } + + int copies = dlg->copies(); + + int flags = Track::ASSIGN_PROPERTIES; + if(dlg->copyStdCtrls()) + flags |= Track::ASSIGN_STD_CTRLS; + if(dlg->copyPlugins()) + flags |= Track::ASSIGN_PLUGINS; + if(dlg->copyPluginCtrls()) + flags |= Track::ASSIGN_PLUGIN_CTRLS; + if(dlg->allRoutes()) + flags |= Track::ASSIGN_ROUTES; + if(dlg->defaultRoutes()) + flags |= Track::ASSIGN_DEFAULT_ROUTES; + if(dlg->copyParts()) + flags |= Track::ASSIGN_PARTS; + if(dlg->copyDrumlist()) + flags |= Track::ASSIGN_DRUMLIST; + + delete dlg; + + QString track_name; + int idx; + int trackno = tl.size(); + MusEGlobal::song->startUndo(); + for(TrackList::reverse_iterator it = tl.rbegin(); it != tl.rend(); ++it) + { + Track* track = *it; + if(track->selected()) + { + track_name = track->name(); + + for(int cp = 0; cp < copies; ++cp) + { + // There are two ways to copy a track now. Using the copy constructor or using new + assign(). + // Tested: Both ways seem OK. Prefer copy constructors for simplicity. But new + assign() may be + // required for fine-grained control over initializing various track types. + // + + // Set to 0 to use the copy constructor. Set to 1 to use new + assign(). + #if 0 + + Track* new_track = 0; + int lastAuxIdx = _auxs.size(); + switch(track->type()) + { + case Track::AUDIO_SOFTSYNTH: // TODO: Handle synths. p4.0.47 + // ((AudioTrack*)new_track)->addAuxSend(lastAuxIdx); + break; + + case Track::MIDI: + new_track = new MidiTrack(); + new_track->setType(Track::MIDI); + break; + case Track::DRUM: + new_track = new MidiTrack(); + new_track->setType(Track::DRUM); + //((MidiTrack*)new_track)->setOutChannel(9); + break; + case Track::WAVE: + new_track = new MusECore::WaveTrack(); + //((AudioTrack*)new_track)->addAuxSend(lastAuxIdx); + break; + case Track::AUDIO_OUTPUT: + new_track = new AudioOutput(); + break; + case Track::AUDIO_GROUP: + new_track = new AudioGroup(); + //((AudioTrack*)new_track)->addAuxSend(lastAuxIdx); + break; + case Track::AUDIO_AUX: + new_track = new AudioAux(); + break; + case Track::AUDIO_INPUT: + new_track = new AudioInput(); + //((AudioTrack*)new_track)->addAuxSend(lastAuxIdx); + break; + default: + printf("Song::duplicateTracks: Illegal type %d\n", track->type()); + break; + } + + if(new_track) + { + new_track->assign(*track, flags); + #else + if(track->type() != Track::AUDIO_SOFTSYNTH) // TODO: Handle synths. p4.0.47 + { + Track* new_track = track->clone(flags); + #endif + + //new_track->setDefaultName(track_name); // Handled in class now. + + idx = trackno + cp; + insertTrack1(new_track, idx); + addUndo(MusECore::UndoOp(MusECore::UndoOp::AddTrack, idx, new_track)); + msgInsertTrack(new_track, idx, false); // No undo. + insertTrack3(new_track, idx); + } + } + } + --trackno; + } + + int update_flags = SC_TRACK_INSERTED; + if(flags & (Track::ASSIGN_ROUTES | Track::ASSIGN_DEFAULT_ROUTES)) + update_flags |= SC_ROUTE; + MusEGlobal::song->endUndo(update_flags); + MusEGlobal::audio->msgUpdateSoloStates(); + + //if (t->isVisible()) + //{ + ////deselectTracks(); + //t->setSelected(true); + ////update(SC_SELECTION); + //} +} + +//--------------------------------------------------------- // cmdRemoveTrack //--------------------------------------------------------- @@ -421,6 +585,7 @@ void Song::deselectTracks() (*t)->setSelected(false); } +/* //--------------------------------------------------------- // changeTrack // oldTrack - copy of the original track befor modification @@ -436,7 +601,8 @@ void Song::changeTrack(Track* oldTrack, Track* newTrack) addUndo(UndoOp(UndoOp::ModifyTrack, idx, oldTrack, newTrack)); updateFlags |= SC_TRACK_MODIFIED; } - +*/ + //--------------------------------------------------------- // addEvent // return true if event was added @@ -1702,7 +1868,8 @@ void Song::rescanAlsaPorts() void Song::endMsgCmd() { if (updateFlags) { - redoList->clear(); // TODO: delete elements in list + //redoList->clear(); // TODO: delete elements in list + redoList->clearDelete(); // p4.0.46 Tim. NOTE Hm, shouldn't this be above? MusEGlobal::undoAction->setEnabled(true); MusEGlobal::redoAction->setEnabled(false); emit songChanged(updateFlags); @@ -1823,9 +1990,9 @@ void Song::processMsg(AudioMsg* msg) //removeTrack2(msg->track); cmdRemoveTrack(msg->track); break; - case SEQM_CHANGE_TRACK: - changeTrack((Track*)(msg->p1), (Track*)(msg->p2)); - break; + //case SEQM_CHANGE_TRACK: + // changeTrack((Track*)(msg->p1), (Track*)(msg->p2)); + // break; case SEQM_ADD_PART: cmdAddPart((Part*)msg->p1); break; @@ -2039,8 +2206,15 @@ void Song::clear(bool signal, bool clear_all) MusEGlobal::tempomap.clear(); AL::sigmap.clear(); MusEGlobal::keymap.clear(); + undoList->clearDelete(); - redoList->clear(); + //redoList->clear(); // Check this - Should we do a clearDelete? IIRC it was OK this way - no clearDelete in case of same items in both lists. + redoList->clearDelete(); // p4.0.46 Tim + if(MusEGlobal::undoAction) + MusEGlobal::undoAction->setEnabled(false); // + if(MusEGlobal::redoAction) + MusEGlobal::redoAction->setEnabled(false); // + _markerList->clear(); pos[0].setTick(0); pos[1].setTick(0); @@ -2131,7 +2305,8 @@ void Song::cleanupForQuit() if(MusEGlobal::debugMsg) printf("deleting undoList, clearing redoList\n"); undoList->clearDelete(); - redoList->clear(); // Check this - Should we do a clearDelete? IIRC it was OK this way - no clearDelete in case of same items in both lists. + //redoList->clear(); // Check this - Should we do a clearDelete? IIRC it was OK this way - no clearDelete in case of same items in both lists. + redoList->clearDelete(); // p4.0.46 Tim _markerList->clear(); diff --git a/muse2/muse/song.h b/muse2/muse/song.h index 047dbac3..22a3a86c 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -319,7 +319,7 @@ class Song : public QObject { void removeTrack2(Track* track); void removeTrack3(Track* track); void removeMarkedTracks(); - void changeTrack(Track* oldTrack, Track* newTrack); + //void changeTrack(Track* oldTrack, Track* newTrack); MidiTrack* findTrack(const Part* part) const; Track* findTrack(const QString& name) const; void swapTracks(int i1, int i2); @@ -415,6 +415,7 @@ class Song : public QObject { void seqSignal(int fd); Track* addTrack(Undo& operations, Track::TrackType type, Track* insertAt = 0); Track* addNewTrack(QAction* action, Track* insertAt = 0); + void duplicateTracks(); QString getScriptPath(int id, bool delivered); void populateScriptMenu(QMenu* menuPlugins, QObject* receiver); diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp index 70b19540..d1d8d3a1 100644 --- a/muse2/muse/structure.cpp +++ b/muse2/muse/structure.cpp @@ -116,15 +116,12 @@ void adjustGlobalLists(Undo& operations, int startPos, int diff) if (tick > startPos) { if (tick + diff < startPos ) { // these ticks should be removed - Marker *oldMarker = new Marker(); - *oldMarker = *m; - markerlist->remove(m); - operations.push_back(UndoOp(UndoOp::ModifyMarker,oldMarker, 0)); + operations.push_back(UndoOp(UndoOp::ModifyMarker, 0, m)); } else { - Marker *oldMarker = new Marker(); - *oldMarker = *m; - m->setTick(tick + diff); - operations.push_back(UndoOp(UndoOp::ModifyMarker,oldMarker, m)); + Marker *newMarker = new Marker(); + *newMarker = *m; + newMarker->setTick(tick + diff); + operations.push_back(UndoOp(UndoOp::ModifyMarker, newMarker, m)); } } } diff --git a/muse2/muse/synth.h b/muse2/muse/synth.h index 497395c0..b9f1dcd2 100644 --- a/muse2/muse/synth.h +++ b/muse2/muse/synth.h @@ -246,8 +246,7 @@ class SynthI : public AudioTrack, public MidiDevice, SynthI(); virtual ~SynthI(); - //SynthI* clone() const { return new SynthI(*this); } - SynthI* clone(bool /*cloneParts*/) const { return new SynthI(*this); } + SynthI* clone(int /*flags*/) const { return new SynthI(*this/*, flags*/); } virtual inline int deviceType() const { return SYNTH_MIDI; } diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp index 595a25e7..cdb81a8f 100644 --- a/muse2/muse/track.cpp +++ b/muse2/muse/track.cpp @@ -233,67 +233,21 @@ void Track::init() } Track::Track(Track::TrackType t) - { +{ init(); _type = t; - } +} -//Track::Track(const Track& t) -Track::Track(const Track& t, bool cloneParts) - { - _auxRouteCount = t._auxRouteCount; - _nodeTraversed = t._nodeTraversed; - _activity = t._activity; - _lastActivity = t._lastActivity; - _recordFlag = t._recordFlag; - _mute = t._mute; - _solo = t._solo; - _internalSolo = t._internalSolo; - _off = t._off; - _channels = t._channels; - - _volumeEnCtrl = t._volumeEnCtrl; - _volumeEn2Ctrl = t._volumeEn2Ctrl; - _panEnCtrl = t._panEnCtrl; - _panEn2Ctrl = t._panEn2Ctrl; - - _selected = t.selected(); - _y = t._y; - _height = t._height; - _comment = t.comment(); - _name = t.name(); - _type = t.type(); - _locked = t.locked(); - - if(cloneParts) - { - const PartList* pl = t.cparts(); - for (ciPart ip = pl->begin(); ip != pl->end(); ++ip) { - Part* newPart = ip->second->clone(); - newPart->setTrack(this); - _parts.add(newPart); - } - } - else - { - _parts = *(t.cparts()); - // NOTE: We can't do this because of the way clipboard, cloneList, and undoOp::ModifyTrack, work. - // A couple of schemes were conceived to deal with cloneList being invalid, but the best way is - // to not alter the part list here. It's a big headache because: Either the parts in the cloneList - // need to be reliably looked up replaced with the new ones, or the clipboard and cloneList must be cleared. - // Fortunately the ONLY part of muse using this function is track rename (in TrackList and TrackInfo). - // So we can get away with leaving this out: - //for (iPart ip = _parts.begin(); ip != _parts.end(); ++ip) - // ip->second->setTrack(this); - } - +Track::Track(const Track& t, int flags) +{ + internal_assign(t, flags | ASSIGN_PROPERTIES); for (int i = 0; i < MAX_CHANNELS; ++i) { //_meter[i] = 0; //_peak[i] = 0; _meter[i] = 0.0; _peak[i] = 0.0; } - } +} Track::~Track() { @@ -301,47 +255,70 @@ Track::~Track() } //--------------------------------------------------------- -// operator = -// Added by Tim. Parts' track members MUST point to this track, -// not some other track, so simple assignment operator won't do! +// assign //--------------------------------------------------------- -Track& Track::operator=(const Track& t) +void Track::assign(const Track& t, int flags) { - _auxRouteCount = t._auxRouteCount; - _nodeTraversed = t._nodeTraversed; - _activity = t._activity; - _lastActivity = t._lastActivity; - _recordFlag = t._recordFlag; - _mute = t._mute; - _solo = t._solo; - _internalSolo = t._internalSolo; - _off = t._off; - _channels = t._channels; - - _volumeEnCtrl = t._volumeEnCtrl; - _volumeEn2Ctrl = t._volumeEn2Ctrl; - _panEnCtrl = t._panEnCtrl; - _panEn2Ctrl = t._panEn2Ctrl; - - _selected = t.selected(); - _y = t._y; - _height = t._height; - _comment = t.comment(); - _name = t.name(); - _type = t.type(); - _locked = t.locked(); - - _parts = *(t.cparts()); - // NOTE: Can't do this. See comments in copy constructor. - //for (iPart ip = _parts.begin(); ip != _parts.end(); ++ip) - // ip->second->setTrack(this); - - for (int i = 0; i < MAX_CHANNELS; ++i) { - _meter[i] = t._meter[i]; - _peak[i] = t._peak[i]; - } - return *this; + internal_assign(t, flags); +} + +void Track::internal_assign(const Track& t, int flags) +{ + if(flags & ASSIGN_PROPERTIES) + { + _auxRouteCount = t._auxRouteCount; + _nodeTraversed = t._nodeTraversed; + _activity = t._activity; + _lastActivity = t._lastActivity; + _recordFlag = t._recordFlag; + _mute = t._mute; + _solo = t._solo; + _internalSolo = t._internalSolo; + _off = t._off; + _channels = t._channels; + + _volumeEnCtrl = t._volumeEnCtrl; + _volumeEn2Ctrl = t._volumeEn2Ctrl; + _panEnCtrl = t._panEnCtrl; + _panEn2Ctrl = t._panEn2Ctrl; + + _selected = t.selected(); + _y = t._y; + _height = t._height; + _comment = t.comment(); + _type = t.type(); + _locked = t.locked(); + + //_name = t.name(); + _name = t.name() + " #"; + for(int i = 2; true; ++i) + { + QString n; + n.setNum(i); + QString s = _name + n; + Track* track = MusEGlobal::song->findTrack(s); + if(track == 0) + { + // Do not call setName here. Audio Input and Output override it and try to set + // Jack ports, which have not been initialized yet here. Must wait until + // .Audio Input and Output copy constructors or assign are called. + //setName(s); + _name = s; + break; + } + } + } + + if(flags & ASSIGN_PARTS) + { + const PartList* pl = t.cparts(); + for (ciPart ip = pl->begin(); ip != pl->end(); ++ip) { + Part* newPart = ip->second->clone(); + newPart->setTrack(this); + _parts.add(newPart); + } + } } //--------------------------------------------------------- @@ -349,34 +326,43 @@ Track& Track::operator=(const Track& t) // generate unique name for track //--------------------------------------------------------- -void Track::setDefaultName() +void Track::setDefaultName(QString base) { - QString base; - switch(_type) { - case MIDI: - case DRUM: - case NEW_DRUM: - case WAVE: - base = QString("Track"); - break; - case AUDIO_OUTPUT: - base = QString("Out"); - break; - case AUDIO_GROUP: - base = QString("Group"); - break; - case AUDIO_AUX: - base = QString("Aux"); - break; - case AUDIO_INPUT: - base = QString("Input"); - break; - case AUDIO_SOFTSYNTH: - base = QString("Synth"); - break; - }; - base += " "; - for (int i = 1; true; ++i) { + int num_base = 1; + if(base.isEmpty()) + { + switch(_type) { + case MIDI: + case DRUM: + case NEW_DRUM: + case WAVE: + base = QString("Track"); + break; + case AUDIO_OUTPUT: + base = QString("Out"); + break; + case AUDIO_GROUP: + base = QString("Group"); + break; + case AUDIO_AUX: + base = QString("Aux"); + break; + case AUDIO_INPUT: + base = QString("Input"); + break; + case AUDIO_SOFTSYNTH: + base = QString("Synth"); + break; + }; + base += " "; + } + else + { + num_base = 2; + base += " #"; + } + + for (int i = num_base; true; ++i) { QString n; n.setNum(i); QString s = base + n; @@ -547,31 +533,53 @@ MidiTrack::MidiTrack() init_drummap(true /* write drummap ordering information as well */); } -//MidiTrack::MidiTrack(const MidiTrack& mt) -// : Track(mt) -MidiTrack::MidiTrack(const MidiTrack& mt, bool cloneParts) - : Track(mt, cloneParts) - { - _outPort = mt.outPort(); - _outChannel = mt.outChannel(); - ///_inPortMask = mt.inPortMask(); - ///_inChannelMask = mt.inChannelMask(); - _events = new EventList; - _mpevents = new MPEventList; - transposition = mt.transposition; - velocity = mt.velocity; - delay = mt.delay; - len = mt.len; - compression = mt.compression; - _recEcho = mt.recEcho(); - clefType=trebleClef; +MidiTrack::MidiTrack(const MidiTrack& mt, int flags) + : Track(mt, flags) +{ + _events = new EventList; + _mpevents = new MPEventList; _drummap=new DrumMap[128]; _drummap_hidden=new bool[128]; - memcpy(_drummap, mt._drummap, 128*sizeof(*_drummap)); - memcpy(_drummap_hidden, mt._drummap_hidden, 128*sizeof(*_drummap_hidden)); - update_drum_in_map(); + init_drummap(true /* write drummap ordering information as well */); + + internal_assign(mt, flags | Track::ASSIGN_PROPERTIES); +} + +void MidiTrack::internal_assign(const Track& t, int flags) +{ + if(!t.isMidiTrack()) + return; + + const MidiTrack& mt = (const MidiTrack&)t; + + if(flags & ASSIGN_PROPERTIES) + { + _outPort = mt.outPort(); + _outChannel = mt.outChannel(); + transposition = mt.transposition; + velocity = mt.velocity; + delay = mt.delay; + len = mt.len; + compression = mt.compression; + _recEcho = mt.recEcho(); + clefType = mt.clefType; + } + + // FIXME: May get "addRoute: src track route already exists" when say, + // an audio output and wave track are selected just because + // of the redundancy (wave track wants to connect to output by default). + if(flags & ASSIGN_ROUTES) + { + for(ciRoute ir = mt._inRoutes.begin(); ir != mt._inRoutes.end(); ++ir) + // Amazingly, this single line seems to work. + MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel)); + + for(ciRoute ir = mt._outRoutes.begin(); ir != mt._outRoutes.end(); ++ir) + // Amazingly, this single line seems to work. + MusEGlobal::audio->msgAddRoute(Route(this, ir->channel), *ir); + for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end(); it++) if (it->first == &mt) { @@ -580,6 +588,72 @@ MidiTrack::MidiTrack(const MidiTrack& mt, bool cloneParts) it->first=this; } } + else if(flags & ASSIGN_DEFAULT_ROUTES) + { + // Add default track <-> midiport routes. + int c, cbi, ch; + bool defOutFound = false; /// TODO: Remove this if and when multiple output routes supported. + for(int i = 0; i < MIDI_PORTS; ++i) + { + MidiPort* mp = &MusEGlobal::midiPorts[i]; + + if(mp->device()) // Only if device is valid. + { + c = mp->defaultInChannels(); + if(c) + { + MusEGlobal::audio->msgAddRoute(Route(i, c), Route(this, c)); + //updateFlags |= SC_ROUTE; + } + } + + if(!defOutFound) /// + { + c = mp->defaultOutChannels(); + if(c) + { + + /// TODO: Switch if and when multiple output routes supported. + #if 0 + MusEGlobal::audio->msgAddRoute(Route(this, c), Route(i, c)); + //updateFlags |= SC_ROUTE; + #else + for(ch = 0; ch < MIDI_CHANNELS; ++ch) + { + cbi = 1 << ch; + if(c & cbi) + { + defOutFound = true; + _outPort = i; + if(type() != Track::DRUM) // Leave drum tracks at channel 10. + _outChannel = ch; + //updateFlags |= SC_ROUTE; + break; + } + } + #endif + } + } + } + } + + if (flags & ASSIGN_DRUMLIST) + { + for (int i=0;i<128;i++) // no memcpy allowed here. dunno exactly why, + _drummap[i]=mt._drummap[i]; // seems QString-related. + memcpy(_drummap_hidden, mt._drummap_hidden, 128*sizeof(bool)); + update_drum_in_map(); + _drummap_tied_to_patch=mt._drummap_tied_to_patch; + _drummap_ordering_tied_to_patch=mt._drummap_ordering_tied_to_patch; + // TODO FINDMICH "assign" ordering as well + } +} + +void MidiTrack::assign(const Track& t, int flags) +{ + Track::assign(t, flags); + internal_assign(t, flags); +} MidiTrack::~MidiTrack() { diff --git a/muse2/muse/track.h b/muse2/muse/track.h index 1df8cad0..5cc217b6 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -58,6 +58,8 @@ class Track { MIDI=0, DRUM, NEW_DRUM, WAVE, AUDIO_OUTPUT, AUDIO_INPUT, AUDIO_GROUP, AUDIO_AUX, AUDIO_SOFTSYNTH }; + enum AssignFlags { + ASSIGN_PROPERTIES=1, ASSIGN_PARTS=2, ASSIGN_PLUGINS=4, ASSIGN_STD_CTRLS=8, ASSIGN_PLUGIN_CTRLS=16, ASSIGN_ROUTES=32, ASSIGN_DEFAULT_ROUTES=64, ASSIGN_DRUMLIST=128 }; private: TrackType _type; QString _comment; @@ -65,6 +67,7 @@ class Track { PartList _parts; void init(); + void internal_assign(const Track&, int flags); protected: static unsigned int _soloRefCnt; @@ -105,10 +108,10 @@ class Track { public: Track(TrackType); - //Track(const Track&); - Track(const Track&, bool cloneParts); + Track(const Track&, int flags); virtual ~Track(); - virtual Track& operator=(const Track& t); + //virtual Track& operator=(const Track& t); + virtual void assign(const Track&, int flags); static const char* _cname[]; @@ -160,8 +163,7 @@ class Track { virtual void write(int, Xml&) const = 0; virtual Track* newTrack() const = 0; - //virtual Track* clone() const = 0; - virtual Track* clone(bool CloneParts) const = 0; + virtual Track* clone(int flags) const = 0; virtual bool setRecordFlag1(bool f) = 0; virtual void setRecordFlag2(bool f) = 0; @@ -200,7 +202,7 @@ class Track { void resetMeter(); bool readProperty(Xml& xml, const QString& tag); - void setDefaultName(); + void setDefaultName(QString base = QString()); int channels() const { return _channels; } virtual void setChannels(int n); bool isMidiTrack() const { return type() == MIDI || type() == DRUM || type() == NEW_DRUM; } @@ -232,6 +234,7 @@ class MidiTrack : public Track { MPEventList* _mpevents; // tmp Events druring recording static bool _isVisible; clefTypes clefType; + DrumMap* _drummap; // _drummap[foo].anote is always equal to foo bool* _drummap_hidden; // _drummap und _drummap_hidden will be an array[128] @@ -240,6 +243,7 @@ class MidiTrack : public Track { int drum_in_map[128]; void init(); + void internal_assign(const Track&, int flags); void init_drummap(bool write_ordering); // function without argument in public void remove_ourselves_from_drum_ordering(); void init_drum_ordering(); @@ -251,10 +255,11 @@ class MidiTrack : public Track { public: MidiTrack(); - //MidiTrack(const MidiTrack&); - MidiTrack(const MidiTrack&, bool cloneParts); + MidiTrack(const MidiTrack&, int flags); virtual ~MidiTrack(); + virtual void assign(const Track&, int flags); + virtual AutomationType automationType() const; virtual void setAutomationType(AutomationType); @@ -275,9 +280,9 @@ class MidiTrack : public Track { virtual void write(int, Xml&) const; virtual int height() const; + virtual MidiTrack* newTrack() const { return new MidiTrack(); } - //virtual MidiTrack* clone() const { return new MidiTrack(*this); } - virtual MidiTrack* clone(bool cloneParts) const { return new MidiTrack(*this, cloneParts); } + virtual MidiTrack* clone(int flags) const { return new MidiTrack(*this, flags); } virtual Part* newPart(Part*p=0, bool clone=false); void setOutChannel(int i) { _outChannel = i; } @@ -361,6 +366,7 @@ class AudioTrack : public Track { bool _sendMetronome; AutomationType _automationType; Pipeline* _efxPipe; + void internal_assign(const Track&, int flags); protected: float** outBuffers; @@ -378,10 +384,14 @@ class AudioTrack : public Track { AudioTrack(TrackType t); //AudioTrack(TrackType t, int num_out_bufs = MAX_CHANNELS); - //AudioTrack(const AudioTrack&); - AudioTrack(const AudioTrack&, bool cloneParts); + AudioTrack(const AudioTrack&, int flags); virtual ~AudioTrack(); + virtual void assign(const Track&, int flags); + + virtual AudioTrack* clone(int flags) const = 0; + virtual Part* newPart(Part*p=0, bool clone=false); + virtual bool setRecordFlag1(bool f); virtual void setRecordFlag2(bool f); bool prepareRecording(); @@ -399,10 +409,6 @@ class AudioTrack : public Track { void mapRackPluginsToControllers(); void showPendingPluginNativeGuis(); - //virtual AudioTrack* clone() const = 0; - virtual AudioTrack* clone(bool cloneParts) const = 0; - virtual Part* newPart(Part*p=0, bool clone=false); - SndFile* recFile() const { return _recFile; } void setRecFile(SndFile* sf) { _recFile = sf; } @@ -484,14 +490,15 @@ class AudioInput : public AudioTrack { void* jackPorts[MAX_CHANNELS]; virtual bool getData(unsigned, int, unsigned, float**); static bool _isVisible; - + void internal_assign(const Track& t, int flags); + public: AudioInput(); - //AudioInput(const AudioInput&); - AudioInput(const AudioInput&, bool cloneParts); + AudioInput(const AudioInput&, int flags); virtual ~AudioInput(); - //AudioInput* clone() const { return new AudioInput(*this); } - AudioInput* clone(bool cloneParts) const { return new AudioInput(*this, cloneParts); } + + virtual void assign(const Track&, int flags); + AudioInput* clone(int flags) const { return new AudioInput(*this, flags); } virtual AudioInput* newTrack() const { return new AudioInput(); } virtual void read(Xml&); virtual void write(int, Xml&) const; @@ -515,16 +522,16 @@ class AudioOutput : public AudioTrack { float* buffer1[MAX_CHANNELS]; unsigned long _nframes; static bool _isVisible; - float* _monitorBuffer[MAX_CHANNELS]; + void internal_assign(const Track& t, int flags); public: AudioOutput(); - //AudioOutput(const AudioOutput&); - AudioOutput(const AudioOutput&, bool cloneParts); + AudioOutput(const AudioOutput&, int flags); virtual ~AudioOutput(); - //AudioOutput* clone() const { return new AudioOutput(*this); } - AudioOutput* clone(bool cloneParts) const { return new AudioOutput(*this, cloneParts); } + + virtual void assign(const Track&, int flags); + AudioOutput* clone(int flags) const { return new AudioOutput(*this, flags); } virtual AudioOutput* newTrack() const { return new AudioOutput(); } virtual void read(Xml&); virtual void write(int, Xml&) const; @@ -553,8 +560,9 @@ class AudioGroup : public AudioTrack { static bool _isVisible; public: AudioGroup() : AudioTrack(AUDIO_GROUP) { } - //AudioGroup* clone() const { return new AudioGroup(*this); } - AudioGroup* clone(bool /*cloneParts*/) const { return new AudioGroup(*this); } + AudioGroup(const AudioGroup& t, int flags) : AudioTrack(t, flags) { } + + AudioGroup* clone(int flags) const { return new AudioGroup(*this, flags); } virtual AudioGroup* newTrack() const { return new AudioGroup(); } virtual void read(Xml&); virtual void write(int, Xml&) const; @@ -573,8 +581,9 @@ class AudioAux : public AudioTrack { static bool _isVisible; public: AudioAux(); - //AudioAux* clone() const { return new AudioAux(*this); } - AudioAux* clone(bool /*cloneParts*/) const { return new AudioAux(*this); } + AudioAux(const AudioAux& t, int flags); + + AudioAux* clone(int flags) const { return new AudioAux(*this, flags); } ~AudioAux(); virtual AudioAux* newTrack() const { return new AudioAux(); } virtual void read(Xml&); @@ -599,11 +608,9 @@ class WaveTrack : public AudioTrack { public: WaveTrack() : AudioTrack(Track::WAVE) { } - //WaveTrack(const WaveTrack& wt) : AudioTrack(wt) {} - WaveTrack(const WaveTrack& wt, bool cloneParts) : AudioTrack(wt, cloneParts) {} + WaveTrack(const WaveTrack& wt, int flags) : AudioTrack(wt, flags) {} - //virtual WaveTrack* clone() const { return new WaveTrack(*this); } - virtual WaveTrack* clone(bool cloneParts) const { return new WaveTrack(*this, cloneParts); } + virtual WaveTrack* clone(int flags) const { return new WaveTrack(*this, flags); } virtual WaveTrack* newTrack() const { return new WaveTrack(); } virtual Part* newPart(Part*p=0, bool clone=false); diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp index 06c190a2..9cece41c 100644 --- a/muse2/muse/undo.cpp +++ b/muse2/muse/undo.cpp @@ -21,14 +21,16 @@ // //========================================================= -///#include "sig.h" -#include "al/sig.h" // Tim. +//#include "sig.h" +#include "al/sig.h" #include "keyevent.h" #include "undo.h" #include "song.h" #include "globals.h" +#include "audio.h" +#include <string.h> #include <QAction> #include <set> @@ -53,7 +55,9 @@ const char* UndoOp::typeName() "AddTempo", "DeleteTempo", "AddSig", "DeleteSig", "AddKey", "DeleteKey", - "SwapTrack", "ModifyClip", "ModifyMarker", + "ModifyTrackName", "ModifyTrackChannel", + "SwapTrack", + "ModifyClip", "ModifyMarker", "ModifySongLen", "DoNothing" }; return name[type]; @@ -88,6 +92,12 @@ void UndoOp::dump() if (part) part->dump(5); break; + case ModifyTrackName: + printf("<%s>-<%s>\n", _oldName, _newName); + break; + case ModifyTrackChannel: + printf("<%d>-<%d>\n", _oldPropValue, _newPropValue); + break; case ModifyEvent: case AddTempo: case DeleteTempo: @@ -101,6 +111,8 @@ void UndoOp::dump() case ModifySongLen: case DoNothing: break; + default: + break; } } @@ -139,7 +151,7 @@ void UndoList::clearDelete() } } break; - case UndoOp::ModifyTrack: + /* case UndoOp::ModifyTrack: if(i->oTrack) { // Prevent delete i->oTrack from crashing. @@ -181,7 +193,8 @@ void UndoList::clearDelete() } } } - break; + break; */ + //case UndoOp::DeletePart: //delete i->oPart; // break; @@ -192,6 +205,14 @@ void UndoList::clearDelete() case UndoOp::ModifyMarker: if (i->copyMarker) delete i->copyMarker; + break; + case UndoOp::ModifyTrackName: + //printf("UndoList::clearDelete ModifyTrackName old:%s new:%s\n", i->_oldName, i->_newName); + if (i->_oldName) + delete i->_oldName; + if (i->_newName) + delete i->_newName; + break; default: break; } @@ -209,8 +230,9 @@ void UndoList::clearDelete() void Song::startUndo() { - redoList->clear(); // added by flo93: redo must be invalidated when - MusEGlobal::redoAction->setEnabled(false); // a new undo is started + //redoList->clear(); // added by flo93: redo must be invalidated when a new undo is started + redoList->clearDelete(); // p4.0.46 Tim + MusEGlobal::redoAction->setEnabled(false); // undoList->push_back(Undo()); updateFlags = 0; @@ -277,8 +299,9 @@ bool Song::applyOperationGroup(Undo& group, bool doUndo) } else { - redoList->clear(); // added by flo93: redo must be invalidated when - MusEGlobal::redoAction->setEnabled(false); // a new undo is started + //redoList->clear(); // added by flo93: redo must be invalidated when a new undo is started + redoList->clearDelete(); // p4.0.46 Tim. + MusEGlobal::redoAction->setEnabled(false); // } return doUndo; @@ -310,9 +333,9 @@ void Song::doUndo2() updateFlags |= SC_TRACK_INSERTED; break; +/* case UndoOp::ModifyTrack: { - // Added by Tim. p3.3.6 //printf("Song::doUndo2 ModifyTrack #1 oTrack %p %s nTrack %p %s\n", i->oTrack, i->oTrack->name().toLatin1().constData(), i->nTrack, i->nTrack->name().toLatin1().constData()); // Unchain the track parts, but don't touch the ref counts. @@ -324,7 +347,6 @@ void Song::doUndo2() // A Track custom assignment operator was added by Tim. *(i->nTrack) = *(i->oTrack); - // Added by Tim. p3.3.6 //printf("Song::doUndo2 ModifyTrack #2 oTrack %p %s nTrack %p %s\n", i->oTrack, i->oTrack->name().toLatin1().constData(), i->nTrack, i->nTrack->name().toLatin1().constData()); // Prevent delete i->oTrack from crashing. @@ -356,7 +378,6 @@ void Song::doUndo2() // Chain the track parts, but don't touch the ref counts. chainTrackParts(i->nTrack, false); - // Added by Tim. p3.3.6 //printf("Song::doUndo2 ModifyTrack #3 oTrack %p %s nTrack %p %s\n", i->oTrack, i->oTrack->name().toLatin1().constData(), i->nTrack, i->nTrack->name().toLatin1().constData()); // Connect and register ports. @@ -384,6 +405,7 @@ void Song::doUndo2() updateFlags |= SC_TRACK_MODIFIED; } break; +*/ /* switch(i->nTrack->type()) @@ -542,6 +564,8 @@ void Song::doUndo2() case UndoOp::ModifyMarker: case UndoOp::DoNothing: break; + default: + break; } } } @@ -566,6 +590,8 @@ void Song::doRedo2() removeTrack2(i->oTrack); updateFlags |= SC_TRACK_REMOVED; break; + +/* case UndoOp::ModifyTrack: { // Unchain the track parts, but don't touch the ref counts. @@ -630,7 +656,8 @@ void Song::doRedo2() updateFlags |= SC_TRACK_MODIFIED; } break; - +*/ + /* // Prevent delete i->oTrack from crashing. switch(i->oTrack->type()) @@ -783,6 +810,8 @@ void Song::doRedo2() case UndoOp::ModifyMarker: case UndoOp::DoNothing: break; + default: + break; } } } @@ -885,6 +914,24 @@ UndoOp::UndoOp(UndoType type_, const char* changedFile, const char* changeData, endframe = endframe_; } +UndoOp::UndoOp(UndoOp::UndoType type_, Track* track, const char* old_name, const char* new_name) +{ + type = type_; + _renamedTrack = track; + _oldName = new char[strlen(old_name) + 1]; + _newName = new char[strlen(new_name) + 1]; + strcpy(_oldName, old_name); + strcpy(_newName, new_name); +} + +UndoOp::UndoOp(UndoOp::UndoType type_, Track* track, int old_chan, int new_chan) +{ + type = type_; + _propertyTrack = track; + _oldPropValue = old_chan; + _newPropValue = new_chan; +} + void Song::undoOp(UndoOp::UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe) { addUndo(UndoOp(type,changedFile,changeData,startframe,endframe)); @@ -944,9 +991,51 @@ bool Song::doUndo1() } break; + case UndoOp::ModifyTrackName: + i->_renamedTrack->setName(i->_oldName); + updateFlags |= SC_TRACK_MODIFIED; + break; case UndoOp::ModifyClip: MusECore::SndFile::applyUndoFile(i->filename, i->tmpwavfile, i->startframe, i->endframe); break; + case UndoOp::ModifyTrackChannel: + if (i->_propertyTrack->isMidiTrack()) + { + MusECore::MidiTrack* mt = dynamic_cast<MusECore::MidiTrack*>(i->_propertyTrack); + if (mt == 0 || mt->type() == MusECore::Track::DRUM) + //if (mt == 0 || mt->isDrumTrack()) // For Flo later with new drum tracks. p4.0.46 Tim + break; + if (i->_oldPropValue != mt->outChannel()) + { + //mt->setOutChannel(i->_oldPropValue); + MusEGlobal::audio->msgIdle(true); + //MusEGlobal::audio->msgSetTrackOutChannel(mt, i->_oldPropValue); + mt->setOutChanAndUpdate(i->_oldPropValue); + MusEGlobal::audio->msgIdle(false); + //if (mt->type() == MusECore::MidiTrack::DRUM) {//Change channel on all drum instruments + // for (int i=0; i<DRUM_MAPSIZE; i++) + // MusEGlobal::drumMap[i].channel = i->_oldPropValue; + // } + //updateFlags |= SC_CHANNELS; + MusEGlobal::audio->msgUpdateSoloStates(); + //updateFlags |= SC_MIDI_TRACK_PROP | SC_ROUTE; + updateFlags |= SC_MIDI_TRACK_PROP; + } + } + else + { + if(i->_propertyTrack->type() != MusECore::Track::AUDIO_SOFTSYNTH) + { + MusECore::AudioTrack* at = dynamic_cast<MusECore::AudioTrack*>(i->_propertyTrack); + if (at == 0) + break; + if (i->_oldPropValue != at->channels()) { + MusEGlobal::audio->msgSetChannels(at, i->_oldPropValue); + updateFlags |= SC_CHANNELS; + } + } + } + break; default: break; @@ -1035,9 +1124,52 @@ bool Song::doRedo1() case UndoOp::DeleteTrack: removeTrack1(i->oTrack); break; + case UndoOp::ModifyTrackName: + i->_renamedTrack->setName(i->_newName); + updateFlags |= SC_TRACK_MODIFIED; + break; case UndoOp::ModifyClip: MusECore::SndFile::applyUndoFile(i->filename, i->tmpwavfile, i->startframe, i->endframe); break; + case UndoOp::ModifyTrackChannel: + if (i->_propertyTrack->isMidiTrack()) + { + MusECore::MidiTrack* mt = dynamic_cast<MusECore::MidiTrack*>(i->_propertyTrack); + if (mt == 0 || mt->type() == MusECore::Track::DRUM) + //if (mt == 0 || mt->isDrumTrack()) // For Flo later with new drum tracks. p4.0.46 Tim + break; + if (i->_newPropValue != mt->outChannel()) + { + //mt->setOutChannel(i->_newPropValue); + MusEGlobal::audio->msgIdle(true); + //MusEGlobal::audio->msgSetTrackOutChannel(mt, i->_newPropValue); + mt->setOutChanAndUpdate(i->_newPropValue); + MusEGlobal::audio->msgIdle(false); + //if (mt->type() == MusECore::MidiTrack::DRUM) {//Change channel on all drum instruments + // for (int i=0; i<DRUM_MAPSIZE; i++) + // MusEGlobal::drumMap[i].channel = i->_newPropValue; + // } + //updateFlags |= SC_CHANNELS; + MusEGlobal::audio->msgUpdateSoloStates(); + //updateFlags |= SC_MIDI_TRACK_PROP | SC_ROUTE; + updateFlags |= SC_MIDI_TRACK_PROP; + } + } + else + { + if(i->_propertyTrack->type() != MusECore::Track::AUDIO_SOFTSYNTH) + { + MusECore::AudioTrack* at = dynamic_cast<MusECore::AudioTrack*>(i->_propertyTrack); + if (at == 0) + break; + if (i->_newPropValue != at->channels()) { + MusEGlobal::audio->msgSetChannels(at, i->_newPropValue); + updateFlags |= SC_CHANNELS; + } + } + } + break; + default: break; } diff --git a/muse2/muse/undo.h b/muse2/muse/undo.h index dffa1f55..3487da47 100644 --- a/muse2/muse/undo.h +++ b/muse2/muse/undo.h @@ -51,6 +51,7 @@ struct UndoOp { AddTempo, DeleteTempo, AddSig, DeleteSig, AddKey, DeleteKey, + ModifyTrackName, ModifyTrackChannel, SwapTrack, ModifyClip, ModifyMarker, @@ -97,6 +98,16 @@ struct UndoOp { Marker* realMarker; Marker* copyMarker; }; + struct { + Track* _renamedTrack; + char* _oldName; + char* _newName; + }; + struct { + Track* _propertyTrack; + int _oldPropValue; + int _newPropValue; + }; }; Event oEvent; Event nEvent; @@ -118,6 +129,8 @@ struct UndoOp { UndoOp(UndoType type, SigEvent* oevent, SigEvent* nevent); UndoOp(UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe); UndoOp(UndoType type, Marker* copyMarker, Marker* realMarker); + UndoOp(UndoType type, Track* track, const char* old_name, const char* new_name); + UndoOp(UndoType type, Track* track, int old_chan, int new_chan); UndoOp(UndoType type); }; diff --git a/muse2/muse/widgets/CMakeLists.txt b/muse2/muse/widgets/CMakeLists.txt index bf71f51e..0328b89d 100644 --- a/muse2/muse/widgets/CMakeLists.txt +++ b/muse2/muse/widgets/CMakeLists.txt @@ -89,6 +89,7 @@ QT4_WRAP_CPP (widget_mocs tb1.h tempolabel.h tools.h + tracks_duplicate.h # ttoolbar.h ttoolbutton.h unusedwavefiles.h @@ -126,6 +127,7 @@ file (GLOB widgets_ui_files shortcutconfigbase.ui songinfo.ui synthconfigbase.ui + tracks_duplicate_base.ui transformbase.ui unusedwavefiles.ui ) @@ -197,6 +199,7 @@ file (GLOB widgets_source_files tb1.cpp tempolabel.cpp tools.cpp + tracks_duplicate.cpp # ttoolbar.cpp ttoolbutton.cpp unusedwavefiles.cpp diff --git a/muse2/muse/widgets/fdialogbuttons.ui b/muse2/muse/widgets/fdialogbuttons.ui index 24f58e1f..09f9e52d 100644 --- a/muse2/muse/widgets/fdialogbuttons.ui +++ b/muse2/muse/widgets/fdialogbuttons.ui @@ -135,6 +135,9 @@ <string>Songdata + Configuration</string> </property> + <property name="checked"> + <bool>true</bool> + </property> </widget> </item> <item> @@ -143,9 +146,6 @@ Configuration</string> <string>only Songdata</string> </property> - <property name="checked"> - <bool>true</bool> - </property> </widget> </item> </layout> diff --git a/muse2/muse/widgets/tracks_duplicate.cpp b/muse2/muse/widgets/tracks_duplicate.cpp new file mode 100644 index 00000000..07cefe38 --- /dev/null +++ b/muse2/muse/widgets/tracks_duplicate.cpp @@ -0,0 +1,42 @@ +//========================================================= +// MusE +// Linux Music Editor +// tracks_duplicate.cpp +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge.net) +// +// 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 "tracks_duplicate.h" + +namespace MusEGui { + +DuplicateTracksDialog::DuplicateTracksDialog(bool audio, bool /*midi*/, bool /*drum*/, bool newdrum, QWidget* parent) + : QDialog(parent) +{ + setupUi(this); + + standardCtrlsCheckBox->setVisible(audio); + pluginsCheckBox->setVisible(audio); + pluginCtrlsCheckBox->setVisible(audio); + copyDrumlistCheckBox->setVisible(newdrum); + + + connect(okPushButton, SIGNAL(clicked()), this, SLOT(accept())); + connect(cancelPushButton, SIGNAL(clicked()), this, SLOT(reject())); +} + +} // namespace MusEGui diff --git a/muse2/muse/widgets/tracks_duplicate.h b/muse2/muse/widgets/tracks_duplicate.h new file mode 100644 index 00000000..cdcfc479 --- /dev/null +++ b/muse2/muse/widgets/tracks_duplicate.h @@ -0,0 +1,59 @@ +//========================================================= +// MusE +// Linux Music Editor +// tracks_duplicate.h +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge.net) +// +// 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 __TRACKS_DUPLICATE_H__ +#define __TRACKS_DUPLICATE_H__ + +#include "ui_tracks_duplicate_base.h" + +namespace MusEGui { + +class DuplicateTracksDialog : public QDialog, public Ui::DuplicateTracksBase +{ + Q_OBJECT + protected: + + protected slots: + //void accept(); + + public slots: + //int exec(); + + public: + DuplicateTracksDialog(bool audio, bool midi, bool drum, bool newdrum, QWidget* parent = 0); + + int copies() const { return copiesSpinBox->value(); } + bool copyStdCtrls() const { return standardCtrlsCheckBox->isChecked(); } + bool copyPlugins() const { return pluginsCheckBox->isChecked(); } + bool copyPluginCtrls() const { return pluginCtrlsCheckBox->isChecked(); } + + bool allRoutes() const { return allRoutesRadioButton->isChecked(); } + bool defaultRoutes() const { return defaultRoutesRadioButton->isChecked(); } + + bool copyParts() const { return copyPartsCheckBox->isChecked(); } + bool copyDrumlist() const { return copyDrumlistCheckBox->isChecked(); } +}; + +} // namespace MusEGui + +#endif + diff --git a/muse2/muse/widgets/tracks_duplicate_base.ui b/muse2/muse/widgets/tracks_duplicate_base.ui new file mode 100644 index 00000000..a8ec5766 --- /dev/null +++ b/muse2/muse/widgets/tracks_duplicate_base.ui @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DuplicateTracksBase</class> + <widget class="QDialog" name="DuplicateTracksBase"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>269</width> + <height>319</height> + </rect> + </property> + <property name="windowTitle"> + <string>Duplicate tracks</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QSpinBox" name="copiesSpinBox"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Number of copies</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="allRoutesRadioButton"> + <property name="text"> + <string>Copy all routes</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="defaultRoutesRadioButton"> + <property name="text"> + <string>Default routing</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="noRoutesRadioButton"> + <property name="text"> + <string>No routes</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="copyPartsCheckBox"> + <property name="text"> + <string>Copy parts</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="copyDrumlistCheckBox"> + <property name="text"> + <string>Copy drumlist</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="standardCtrlsCheckBox"> + <property name="text"> + <string>Copy standard controllers (vol, pan)</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="pluginsCheckBox"> + <property name="text"> + <string>Copy effects rack plugins</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="pluginCtrlsCheckBox"> + <property name="text"> + <string>Copy plugin controllers</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>27</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="okPushButton"> + <property name="text"> + <string>Ok</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelPushButton"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> |