summaryrefslogtreecommitdiff
path: root/attic/muse_qt4_evolution/muse/songtrack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse_qt4_evolution/muse/songtrack.cpp')
-rw-r--r--attic/muse_qt4_evolution/muse/songtrack.cpp715
1 files changed, 715 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/muse/songtrack.cpp b/attic/muse_qt4_evolution/muse/songtrack.cpp
new file mode 100644
index 00000000..8a865620
--- /dev/null
+++ b/attic/muse_qt4_evolution/muse/songtrack.cpp
@@ -0,0 +1,715 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "song.h"
+#include "audio.h"
+#include "midiplugin.h"
+#include "audiodev.h"
+#include "muse.h"
+
+//---------------------------------------------------------
+// deselectTracks
+//---------------------------------------------------------
+
+void Song::deselectTracks()
+ {
+ for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t)
+ (*t)->setSelected(false);
+ }
+
+//---------------------------------------------------------
+// selectTrack
+//---------------------------------------------------------
+
+void Song::selectTrack(Track* track)
+ {
+ bool changed = false;
+ for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
+ bool select = *t == track;
+ if ((*t)->selected() != select) {
+ (*t)->setSelected(select);
+ changed = true;
+ }
+ }
+ if (changed) {
+ updateSelectedTrack();
+ trackSelectionChanged(_selectedTrack);
+ }
+ }
+
+//---------------------------------------------------------
+// updateSelectedTrack
+// set _selectedTrack to first selected track
+//---------------------------------------------------------
+
+void Song::updateSelectedTrack()
+ {
+ _selectedTrack = 0;
+ for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
+ bool select = (*t)->selected();
+ if (select) {
+ _selectedTrack = *t;
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// addTrack
+// called from GUI context
+//---------------------------------------------------------
+
+Track* Song::addTrack(QAction* action)
+ {
+ int t = action->data().toInt();
+
+ deselectTracks();
+ Track* track = 0;
+
+ Track::TrackType type = (Track::TrackType) t;
+ if (t >= 5000) {
+ int idx = t - 5000;
+ type = Track::MIDI_SYNTI;
+ int k = 0;
+ iMidiPlugin i;
+ for (i = midiPlugins.begin(); i != midiPlugins.end(); ++i) {
+ if ((*i)->type() != MEMPI_GENERATOR)
+ continue;
+ if (k == idx)
+ break;
+ ++k;
+ }
+ if (i == midiPlugins.end()) {
+ fprintf(stderr, "Song::addTrack: midi synti not found\n");
+ return 0;
+ }
+ MidiPlugin* s = *i;
+ MidiSynti* si = new MidiSynti();
+ QString sName(s->name());
+ for (k = s->instances(); k < 1000; ++k) {
+ QString instanceName = (k == 0) ?
+ sName : instanceName.arg(sName).arg(k);
+
+ MidiSyntiList* sl = midiSyntis();
+ iMidiSynti sii;
+ for (sii = sl->begin(); sii != sl->end(); ++sii) {
+ if ((*sii)->name() == instanceName)
+ break;
+ }
+ if (sii == sl->end()) {
+ si->setName(instanceName);
+ break;
+ }
+ }
+ if (si->initInstance(s)) {
+ delete si;
+ return 0;
+ }
+ track = si;
+ }
+ else if (t >= 1000) {
+ type = Track::AUDIO_SOFTSYNTH;
+ QString sclass = synthis[t-1000]->name();
+
+ Synth* s = findSynth(sclass);
+ if (s == 0) {
+ fprintf(stderr, "synthi class <%s> not found\n", sclass.toLatin1().data());
+ return 0;
+ }
+
+ SynthI* si = new SynthI();
+ int i;
+ for (i = s->instances(); i < 1000; ++i) {
+ QString instanceName = (i == 0) ?
+ s->name() : QString("%1-%2").arg(s->name()).arg(i);
+
+ SynthIList* sl = syntis();
+ iSynthI sii;
+ for (sii = sl->begin(); sii != sl->end(); ++sii) {
+ if ((*sii)->name() == instanceName)
+ break;
+ }
+ if (sii == sl->end()) {
+ si->setName(instanceName);
+ break;
+ }
+ }
+ if (si->initInstance(s)) {
+ delete si;
+ return 0;
+ }
+ track = si;
+ }
+ else {
+ switch (type) {
+ case Track::MIDI:
+ track = new MidiTrack();
+ break;
+ case Track::MIDI_OUT:
+ track = new MidiOutPort();
+ break;
+ case Track::MIDI_IN:
+ track = new MidiInPort();
+ break;
+ case Track::WAVE:
+ track = new WaveTrack();
+ break;
+ case Track::AUDIO_OUTPUT:
+ track = new AudioOutput();
+ break;
+ case Track::AUDIO_GROUP:
+ track = new AudioGroup();
+ break;
+ case Track::AUDIO_INPUT:
+ track = new AudioInput();
+ break;
+ case Track::AUDIO_SOFTSYNTH:
+ case Track::TRACK_TYPES:
+ default:
+ printf("Song::addTrack() illegal type %d\n", type);
+ abort();
+ }
+ if (track == 0)
+ return 0;
+ }
+ track->setDefaultName();
+ cmdInsertTrack(track, -1);
+ return track;
+ }
+
+//---------------------------------------------------------
+// cmdInsertTrack
+//---------------------------------------------------------
+
+void Song::cmdInsertTrack(Track* track, int idx)
+ {
+ startUndo();
+ insertTrack(track, idx);
+ endUndo(SC_TRACK_INSERTED | SC_ROUTE);
+ selectTrack(track);
+ }
+
+//---------------------------------------------------------
+// insertTrack
+//---------------------------------------------------------
+
+void Song::insertTrack(Track* track, int idx)
+ {
+ //
+ // add default routes
+ //
+ OutputList* ol = outputs();
+ AudioOutput* ao = 0;
+ if (!ol->empty())
+ ao = ol->front();
+
+ switch (track->type()) {
+ case Track::TRACK_TYPES:
+ case Track::MIDI_OUT:
+ {
+#if 0
+ QList<PortName> op = midiDriver->outputPorts(false);
+ if (!op.isEmpty()) {
+ RouteNode src(track);
+ RouteNode dst(op.back().port, -1, RouteNode::MIDIPORT);
+ Route r = Route(src, dst);
+ track->addOutRoute(r);
+ }
+#endif
+ //TODO: autoconnect to JACK midi ports
+ }
+ break;
+
+ case Track::MIDI_IN:
+ {
+#if 0
+ QList<PortName> op = midiDriver->inputPorts(true);
+ if (!op.isEmpty()) {
+ RouteNode src(op.back().port, -1, RouteNode::MIDIPORT);
+ RouteNode dst(track);
+ Route r = Route(src, dst);
+ track->addInRoute(r);
+ }
+#endif
+ //TODO: autoconnect to JACK midi ports
+ }
+ break;
+
+ case Track::MIDI_SYNTI:
+ break;
+ case Track::MIDI:
+ //
+ // connect to first channel of all all midi input ports,
+ // if there is not already a route
+ //
+ if (track->noInRoute()) {
+ MidiInPortList* mi = midiInPorts();
+ RouteNode dst(track);
+ for (iMidiInPort i = mi->begin(); i != mi->end(); ++i) {
+ RouteNode src(*i, 0, RouteNode::TRACK);
+ track->addInRoute(Route(src, dst));
+ }
+ }
+ //
+ // connect to first free input channel in midi output ports
+ //
+ if (track->noOutRoute()) {
+ MidiOutPortList* mo = midiOutPorts();
+ for (iMidiOutPort i = mo->begin(); i != mo->end(); ++i) {
+ RouteList* rl = (*i)->inRoutes();
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
+ RouteNode src(track);
+ RouteNode dst(*i, ch, RouteNode::TRACK);
+ Route r(src, dst);
+ bool channelUsed = false;
+ for (iRoute ir = rl->begin(); ir != rl->end(); ++ir) {
+ if (ir->dst.channel == ch) {
+ channelUsed = true;
+ break;
+ }
+ }
+ if (!channelUsed) {
+ track->addOutRoute(r);
+ break;
+ }
+ }
+ if (!track->noOutRoute())
+ break;
+ }
+ }
+ break;
+ case Track::AUDIO_SOFTSYNTH:
+ case Track::WAVE:
+ case Track::AUDIO_GROUP:
+ if (ao)
+ track->addOutRoute(Route(RouteNode(track), RouteNode(ao)));
+ break;
+
+ case Track::AUDIO_INPUT:
+ {
+ // connect first input channel to first available jack output
+ // etc.
+ QList<PortName> op = audioDriver->outputPorts(false);
+ QList<PortName>::iterator is = op.begin();
+ for (int ch = 0; ch < track->channels(); ++ch) {
+ if (is != op.end()) {
+ RouteNode src(is->port, -1, RouteNode::AUDIOPORT);
+ RouteNode dst(track, ch, RouteNode::TRACK);
+ Route r = Route(src, dst);
+ track->addInRoute(r);
+ ++is;
+ }
+ }
+ }
+ break;
+ case Track::AUDIO_OUTPUT:
+ {
+ QList<PortName> op = audioDriver->inputPorts(false);
+ QList<PortName>::iterator is = op.begin();
+ for (int ch = 0; ch < track->channels(); ++ch) {
+ if (is != op.end()) {
+ RouteNode src(track, ch, RouteNode::TRACK);
+ RouteNode dst(is->port, -1, RouteNode::AUDIOPORT);
+ Route r = Route(src, dst);
+ track->addOutRoute(r);
+ ++is;
+ }
+ }
+ }
+ break;
+ }
+ insertTrack1(track, idx);
+
+ undoOp(UndoOp::AddTrack, idx, track);
+ AudioMsg msg;
+ msg.id = SEQM_ADD_TRACK;
+ msg.track = track;
+ msg.ival = idx;
+ audio->sendMsg(&msg);
+ emit trackAdded(track, idx);
+ }
+
+//---------------------------------------------------------
+// insertTrack0
+// can only be called if sequencer is idle
+// (during song load)
+//---------------------------------------------------------
+
+void Song::insertTrack0(Track* track, int idx)
+ {
+ insertTrack1(track, idx);
+ insertTrack2(track);
+ }
+
+//---------------------------------------------------------
+// insertTrack1
+// non realtime part of insertTrack
+//---------------------------------------------------------
+
+void Song::insertTrack1(Track* track, int idx)
+ {
+ if (idx == -1)
+ idx = _tracks.size();
+ _tracks.insert(idx, track);
+ if (track->type() == Track::AUDIO_SOFTSYNTH) {
+ SynthI* s = (SynthI*)track;
+ Synth* sy = s->synth();
+ if (!s->isActivated())
+ s->initInstance(sy);
+ }
+ if (audioState == AUDIO_RUNNING) {
+ track->activate1();
+ track->activate2();
+ }
+ }
+
+//---------------------------------------------------------
+// insertTrack2
+// realtime part
+//---------------------------------------------------------
+
+void Song::insertTrack2(Track* track)
+ {
+ switch(track->type()) {
+ case Track::MIDI_SYNTI:
+ _midiSyntis.push_back((MidiSynti*)track);
+ break;
+ case Track::MIDI:
+ _midis.push_back((MidiTrack*)track);
+ break;
+ case Track::MIDI_OUT:
+ _midiOutPorts.push_back((MidiOutPort*)track);
+ break;
+ case Track::MIDI_IN:
+ _midiInPorts.push_back((MidiInPort*)track);
+ break;
+ case Track::WAVE:
+ _waves.push_back((WaveTrack*)track);
+ break;
+ case Track::AUDIO_OUTPUT:
+ _outputs.push_back((AudioOutput*)track);
+ break;
+ case Track::AUDIO_GROUP:
+ _groups.push_back((AudioGroup*)track);
+ break;
+ case Track::AUDIO_INPUT:
+ _inputs.push_back((AudioInput*)track);
+ break;
+ case Track::AUDIO_SOFTSYNTH:
+ {
+ SynthI* s = (SynthI*)track;
+ midiInstruments.push_back(s->instrument());
+ _synthIs.push_back(s);
+ }
+ break;
+ default:
+ fprintf(stderr, "insertTrack2: unknown track type %d\n", track->type());
+ // abort();
+ return;
+ }
+
+ //
+ // connect routes
+ //
+ if (track->type() == Track::AUDIO_OUTPUT || track->type() == Track::MIDI_OUT) {
+ foreach(Route r, *(track->inRoutes())) {
+ if (r.src.type != RouteNode::AUXPLUGIN) {
+ r.src.track->addOutRoute(r);
+ }
+ }
+ }
+ else if (track->type() == Track::AUDIO_INPUT || track->type() == Track::MIDI_IN) {
+ foreach(Route r, *(track->outRoutes())) {
+ if (r.dst.type != RouteNode::AUXPLUGIN) {
+ r.dst.track->addInRoute(r);
+ }
+ }
+ }
+ else {
+ foreach(Route r, *(track->inRoutes())) {
+ if (r.src.type != RouteNode::AUXPLUGIN) {
+ r.src.track->addOutRoute(r);
+ }
+ }
+ foreach(Route r, *(track->outRoutes())) {
+ if (r.dst.type != RouteNode::AUXPLUGIN) {
+ r.dst.track->addInRoute(r);
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// removeTrack
+// called from gui context
+//---------------------------------------------------------
+
+void Song::removeTrack(Track* track)
+ {
+ startUndo();
+ int idx = _tracks.indexOf(track);
+ undoOp(UndoOp::DeleteTrack, idx, track);
+ removeTrack1(track);
+ audio->msgRemoveTrack(track);
+ removeTrack3(track);
+ endUndo(SC_TRACK_REMOVED | SC_ROUTE);
+ }
+
+//---------------------------------------------------------
+// removeTrack1
+// non realtime part of removeTrack
+//---------------------------------------------------------
+
+void Song::removeTrack1(Track* track)
+ {
+ track->deactivate();
+ _tracks.removeAt(_tracks.indexOf(track));
+ }
+
+//---------------------------------------------------------
+// removeTrack2
+// called from RT context
+//---------------------------------------------------------
+
+void Song::removeTrack2(Track* track)
+ {
+ switch (track->type()) {
+ case Track::MIDI_SYNTI:
+ _midiSyntis.removeAt(_midiSyntis.indexOf((MidiSynti*)track));
+ break;
+ case Track::MIDI:
+ _midis.removeAt(_midis.indexOf((MidiTrack*)track));
+ break;
+ case Track::MIDI_OUT:
+ _midiOutPorts.removeAt(_midiOutPorts.indexOf((MidiOutPort*)track));
+ break;
+ case Track::MIDI_IN:
+ _midiInPorts.removeAt(_midiInPorts.indexOf((MidiInPort*)track));
+ break;
+ case Track::WAVE:
+ _waves.removeAt(_waves.indexOf((WaveTrack*)track));
+ break;
+ case Track::AUDIO_OUTPUT:
+ _outputs.removeAt(_outputs.indexOf((AudioOutput*)track));
+ break;
+ case Track::AUDIO_INPUT:
+ _inputs.removeAt(_inputs.indexOf((AudioInput*)track));
+ break;
+ case Track::AUDIO_GROUP:
+ _groups.removeAt(_groups.indexOf((AudioGroup*)track));
+ break;
+ case Track::AUDIO_SOFTSYNTH:
+ {
+ SynthI* s = (SynthI*) track;
+ s->deactivate2();
+ _synthIs.removeAt(_synthIs.indexOf(s));
+ }
+ break;
+ case Track::TRACK_TYPES:
+ return;
+ }
+ //
+ // remove routes
+ //
+ foreach (const Route r, *(track->inRoutes())) {
+ if (r.src.type != RouteNode::TRACK)
+ continue;
+ int idx = r.src.track->outRoutes()->indexOf(r);
+ if (idx != -1)
+ r.src.track->outRoutes()->removeAt(idx);
+ else
+ printf("Song::removeTrack2(): input route not found\n");
+ }
+ foreach (const Route r, *(track->outRoutes())) {
+ if (r.dst.type != RouteNode::TRACK)
+ continue;
+ int idx = r.dst.track->inRoutes()->indexOf(r);
+ if (idx != -1)
+ r.dst.track->inRoutes()->removeAt(idx);
+ else {
+ printf("Song::removeTrack2(): output route not found\n");
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// removeTrack3
+// non realtime part of removeTrack
+//---------------------------------------------------------
+
+void Song::removeTrack3(Track* track)
+ {
+ if (track->type() == Track::AUDIO_SOFTSYNTH) {
+ SynthI* s = (SynthI*) track;
+ s->deactivate3();
+ }
+ emit trackRemoved(track);
+ }
+
+//---------------------------------------------------------
+// synthesizer
+//---------------------------------------------------------
+
+std::vector<QString>* Song::synthesizer() const
+ {
+ std::vector<QString>* l = new std::vector<QString>;
+
+ for (std::vector<Synth*>::const_iterator i = synthis.begin();
+ i != synthis.end(); ++i) {
+ l->push_back((*i)->name());
+ }
+ return l;
+ }
+
+//---------------------------------------------------------
+// setRecordFlag
+//---------------------------------------------------------
+
+void Song::setRecordFlag(Track* track, bool val)
+ {
+ if (track->type() == Track::AUDIO_OUTPUT) {
+ if (!val && track->recordFlag() == false) {
+ muse->bounceToFile();
+ }
+ }
+ track->setRecordFlag(val);
+ }
+
+//---------------------------------------------------------
+// setMute
+//---------------------------------------------------------
+
+void Song::setMute(Track* track, bool val)
+ {
+ track->setMute(val);
+ emit muteChanged(track, track->mute());
+ }
+
+//---------------------------------------------------------
+// setMonitor
+//---------------------------------------------------------
+
+void Song::setMonitor(Track* track, bool val)
+ {
+ track->setMonitor(val);
+// emit monitorChanged(track, track->mute());
+ }
+
+//---------------------------------------------------------
+// setOff
+//---------------------------------------------------------
+
+void Song::setOff(Track* track, bool val)
+ {
+ track->setOff(val);
+ emit offChanged(track, track->off());
+ }
+
+//---------------------------------------------------------
+// setAutoRead
+//---------------------------------------------------------
+
+void Song::setAutoRead(Track* track, bool val)
+ {
+ track->setAutoRead(val);
+ emit autoReadChanged(track, track->autoRead());
+ }
+
+//---------------------------------------------------------
+// setAutoWrite
+//---------------------------------------------------------
+
+void Song::setAutoWrite(Track* track, bool val)
+ {
+ track->setAutoWrite(val);
+ emit autoWriteChanged(track, track->autoRead());
+ }
+
+//---------------------------------------------------------
+// setSolo
+//---------------------------------------------------------
+
+void Song::setSolo(Track* track, bool val)
+ {
+ if (!track->setSolo(val))
+ return;
+ emit soloChanged(track, track->solo());
+ soloFlag = false;
+ for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) {
+ if ((*i)->solo()) {
+ soloFlag = true;
+ break;
+ }
+ }
+ for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) {
+ (*i)->updateMute();
+ }
+ }
+
+//---------------------------------------------------------
+// moveTrack
+//---------------------------------------------------------
+
+void Song::moveTrack(Track* src, Track* dst)
+ {
+ iTrack si = qFind(_tracks.begin(), _tracks.end(), src);
+ iTrack di = qFind(_tracks.begin(), _tracks.end(), dst);
+ if (si == _tracks.end() || di == _tracks.end()) {
+ printf("Song::moveTrack() track not found\n");
+ return;
+ }
+ _tracks.erase(si);
+ _tracks.insert(di, src);
+ }
+
+//---------------------------------------------------------
+// changeTrackName
+//---------------------------------------------------------
+
+void Song::changeTrackName(Track* t, const QString& s)
+ {
+ startUndo();
+ undoOp(UndoOp::RenameTrack, t, t->name(), s);
+ t->setName(s);
+ endUndo(SC_TRACK_MODIFIED);
+ }
+
+//---------------------------------------------------------
+// trackExists
+//---------------------------------------------------------
+
+bool Song::trackExists(Track* t) const
+ {
+ return findTrack(t->name()) != 0;
+ }
+
+//---------------------------------------------------------
+// findTrack
+//---------------------------------------------------------
+
+Track* Song::findTrack(const QString& name) const
+ {
+ for (int i = 0; i < _tracks.size(); ++i) {
+ if (_tracks[i]->name() == name)
+ return _tracks[i];
+ }
+ return 0;
+ }
+