summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2012-01-03 19:13:48 +0000
committerFlorian Jung <flo@windfisch.org>2012-01-03 19:13:48 +0000
commit7993a73cece885bac45021dd021ac43f6f332040 (patch)
tree2f8296b31efa6d93cb53b8b735519163ec163a84 /muse2/muse
parent845d28b2fba8f2c1d4211aee7beb5ab041315531 (diff)
parent1bc4ba9dfc00b6e7511fbf4765296a2002f83315 (diff)
merged with trunk
added "copy drummap" to duplicate track dialog
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/app.cpp2
-rw-r--r--muse2/muse/arranger/arrangerview.cpp8
-rw-r--r--muse2/muse/arranger/arrangerview.h3
-rw-r--r--muse2/muse/arranger/pcanvas.cpp10
-rw-r--r--muse2/muse/arranger/tlist.cpp240
-rw-r--r--muse2/muse/audio.cpp3
-rw-r--r--muse2/muse/audio.h5
-rw-r--r--muse2/muse/audiotrack.cpp338
-rw-r--r--muse2/muse/confmport.cpp3
-rw-r--r--muse2/muse/ctrl.cpp53
-rw-r--r--muse2/muse/ctrl.h9
-rw-r--r--muse2/muse/driver/alsamidi.cpp7
-rw-r--r--muse2/muse/evdata.h19
-rw-r--r--muse2/muse/mididev.cpp4
-rw-r--r--muse2/muse/mididev.h1
-rw-r--r--muse2/muse/mixer/amixer.cpp5
-rw-r--r--muse2/muse/mixer/strip.cpp4
-rw-r--r--muse2/muse/node.cpp15
-rw-r--r--muse2/muse/osc.cpp4
-rw-r--r--muse2/muse/plugin.cpp17
-rw-r--r--muse2/muse/plugin.h4
-rw-r--r--muse2/muse/seqmsg.cpp6
-rw-r--r--muse2/muse/song.cpp189
-rw-r--r--muse2/muse/song.h3
-rw-r--r--muse2/muse/structure.cpp13
-rw-r--r--muse2/muse/synth.h3
-rw-r--r--muse2/muse/track.cpp350
-rw-r--r--muse2/muse/track.h75
-rw-r--r--muse2/muse/undo.cpp158
-rw-r--r--muse2/muse/undo.h13
-rw-r--r--muse2/muse/widgets/CMakeLists.txt3
-rw-r--r--muse2/muse/widgets/fdialogbuttons.ui6
-rw-r--r--muse2/muse/widgets/tracks_duplicate.cpp42
-rw-r--r--muse2/muse/widgets/tracks_duplicate.h59
-rw-r--r--muse2/muse/widgets/tracks_duplicate_base.ui191
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>