summaryrefslogtreecommitdiff
path: root/attic/muse2-oom/muse2/muse/song.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse2-oom/muse2/muse/song.cpp')
-rw-r--r--attic/muse2-oom/muse2/muse/song.cpp3911
1 files changed, 0 insertions, 3911 deletions
diff --git a/attic/muse2-oom/muse2/muse/song.cpp b/attic/muse2-oom/muse2/muse/song.cpp
deleted file mode 100644
index 9174bbe4..00000000
--- a/attic/muse2-oom/muse2/muse/song.cpp
+++ /dev/null
@@ -1,3911 +0,0 @@
-//=========================================================
-// MusE
-// Linux Music Editor
-// $Id: song.cpp,v 1.59.2.52 2009/12/15 03:39:58 terminator356 Exp $
-//
-// (C) Copyright 2000-2004 Werner Schweer (ws@seh.de)
-//=========================================================
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <QAction>
-#include <QDir>
-#include <QMenu>
-#include <QMessageBox>
-#include <QPoint>
-#include <QSignalMapper>
-#include <QTextStream>
-
-#include "app.h"
-#include "driver/jackmidi.h"
-#include "driver/alsamidi.h"
-#include "song.h"
-#include "track.h"
-#include "undo.h"
-#include "key.h"
-#include "globals.h"
-#include "event.h"
-#include "drummap.h"
-#include "marker/marker.h"
-#include "synth.h"
-#include "audio.h"
-#include "mididev.h"
-#include "amixer.h"
-#include "midiseq.h"
-#include "audiodev.h"
-#include "gconfig.h"
-#include "sync.h"
-#include "midictrl.h"
-#include "menutitleitem.h"
-#include "midi.h"
-///#include "sig.h"
-#include "al/sig.h"
-#include <sys/wait.h>
-#include "trackview.h"
-
-extern void clearMidiTransforms();
-extern void clearMidiInputTransforms();
-Song* song;
-
-/*
-//---------------------------------------------------------
-// RoutingMenuItem
-//---------------------------------------------------------
-
-class RoutingMenuItem : public QCustomMenuItem
-{
- Route route;
- //virtual QSize sizeHint() { return QSize(80, h); }
- virtual void paint(QPainter* p, const QColorGroup&, bool, bool, int x, int y, int w, int h)
- {
- p->fillRect(x, y, w, h, QBrush(lightGray));
- p->drawText(x, y, w, h, AlignCenter, route.name());
- }
-
- public:
- RoutingMenuItem(const Route& r) : route(r) { }
-};
-*/
-
-//---------------------------------------------------------
-// Song
-//---------------------------------------------------------
-
-Song::Song(const char* name)
- :QObject(0)
- {
- setObjectName(name);
- _arrangerRaster = 0; // Set to measure, the same as Arranger intial value. Arranger snap combo will set this.
- noteFifoSize = 0;
- noteFifoWindex = 0;
- noteFifoRindex = 0;
- undoList = new UndoList;
- redoList = new UndoList;
- _markerList = new MarkerList;
- _globalPitchShift = 0;
- clear(false);
- }
-
-//---------------------------------------------------------
-// Song
-//---------------------------------------------------------
-
-Song::~Song()
- {
- delete undoList;
- delete redoList;
- delete _markerList;
- }
-
-//---------------------------------------------------------
-// putEvent
-//---------------------------------------------------------
-
-void Song::putEvent(int pv)
- {
- if (noteFifoSize < REC_NOTE_FIFO_SIZE) {
- recNoteFifo[noteFifoWindex] = pv;
- noteFifoWindex = (noteFifoWindex + 1) % REC_NOTE_FIFO_SIZE;
- ++noteFifoSize;
- }
- }
-
-//---------------------------------------------------------
-// setTempo
-// public slot
-//---------------------------------------------------------
-
-void Song::setTempo(int newTempo)
- {
- audio->msgSetTempo(pos[0].tick(), newTempo, true);
- }
-
-//---------------------------------------------------------
-// setSig
-// called from transport window
-//---------------------------------------------------------
-
-void Song::setSig(int z, int n)
- {
- if (_masterFlag) {
- audio->msgAddSig(pos[0].tick(), z, n);
- }
- }
-
-void Song::setSig(const AL::TimeSignature& sig)
- {
- if (_masterFlag) {
- audio->msgAddSig(pos[0].tick(), sig.z, sig.n);
- }
- }
-
-//---------------------------------------------------------
-// addNewTrack
-// Called from GUI context
-// Besides normal track types, n includes synth menu ids from populateAddTrack()
-//---------------------------------------------------------
-
-Track* Song::addNewTrack(QAction* action)
-{
- int n = action->data().toInt();
- // Ignore negative numbers since this slot could be called by a menu or list etc. passing -1.
- if(n < 0)
- return 0;
-
- // Synth sub-menu id?
- if(n >= MENU_ADD_SYNTH_ID_BASE)
- {
- n -= MENU_ADD_SYNTH_ID_BASE;
- if(n < (int)synthis.size())
- {
- //SynthI* si = createSynthI(synthis[n]->baseName());
- //SynthI* si = createSynthI(synthis[n]->name());
- SynthI* si = createSynthI(synthis[n]->baseName(), synthis[n]->name());
- if(!si)
- return 0;
-
- // Add instance last in midi device list.
- for (int i = 0; i < MIDI_PORTS; ++i)
- {
- MidiPort* port = &midiPorts[i];
- MidiDevice* dev = port->device();
- if (dev==0)
- {
- midiSeq->msgSetMidiDevice(port, si);
- muse->changeConfig(true); // save configuration file
- deselectTracks();
- si->setSelected(true);
- update();
- return si;
- }
- }
- deselectTracks();
- si->setSelected(true);
- update(SC_SELECTION);
- return si;
- }
- else
- return 0;
- }
- // Normal track.
- else
- {
- // Ignore AUDIO_SOFTSYNTH, now that we have it as the synth menu id, since addTrack doesn't like it.
- if((Track::TrackType)n == Track::AUDIO_SOFTSYNTH)
- return 0;
-
- Track* t = addTrack((Track::TrackType)n);
- deselectTracks();
- t->setSelected(true);
- update(SC_SELECTION);
- return t;
- }
-}
-
-
-//---------------------------------------------------------/*{{{*/
-// addTrack
-// called from GUI context
-//---------------------------------------------------------
-
-Track* Song::addTrack(int t)
- {
- Track::TrackType type = (Track::TrackType) t;
- Track* track = 0;
- int lastAuxIdx = _auxs.size();
- switch(type) {
- case Track::MIDI:
- track = new MidiTrack();
- track->setType(Track::MIDI);
- break;
- case Track::DRUM:
- track = new MidiTrack();
- track->setType(Track::DRUM);
- ((MidiTrack*)track)->setOutChannel(9);
- break;
- case Track::WAVE:
- track = new WaveTrack();
- ((AudioTrack*)track)->addAuxSend(lastAuxIdx);
- break;
- case Track::AUDIO_OUTPUT:
- track = new AudioOutput();
- break;
- case Track::AUDIO_GROUP:
- track = new AudioGroup();
- ((AudioTrack*)track)->addAuxSend(lastAuxIdx);
- break;
- case Track::AUDIO_AUX:
- track = new AudioAux();
- break;
- case Track::AUDIO_INPUT:
- track = new AudioInput();
- ((AudioTrack*)track)->addAuxSend(lastAuxIdx);
- break;
- case Track::AUDIO_SOFTSYNTH:
- printf("not implemented: Song::addTrack(SOFTSYNTH)\n");
- // ((AudioTrack*)track)->addAuxSend(lastAuxIdx);
- break;
- default:
- printf("Song::addTrack() illegal type %d\n", type);
- abort();
- }
- track->setDefaultName();
- insertTrack1(track, -1);
- msgInsertTrack(track, -1, true);
- insertTrack3(track, -1);
-
- // Add default track <-> midiport routes.
- if(track->isMidiTrack())
- {
- MidiTrack* mt = (MidiTrack*)track;
- int c, cbi, ch;
- bool defOutFound = false; /// TODO: Remove this when multiple out routes supported.
- for(int i = 0; i < MIDI_PORTS; ++i)
- {
- MidiPort* mp = &midiPorts[i];
-
- c = mp->defaultInChannels();
- if(c)
- {
- audio->msgAddRoute(Route(i, c), Route(track, c));
- updateFlags |= SC_ROUTE;
- }
-
- if(!defOutFound) ///
- {
- c = mp->defaultOutChannels();
- if(c)
- {
-
- /// TODO: Switch when multiple out routes supported.
- #if 0
- audio->msgAddRoute(Route(track, c), Route(i, c));
- updateFlags |= SC_ROUTE;
- #else
- for(ch = 0; ch < MIDI_CHANNELS; ++ch)
- {
- cbi = 1 << ch;
- if(c & cbi)
- {
- defOutFound = true;
- mt->setOutPort(i);
- mt->setOutChannel(ch);
- updateFlags |= SC_ROUTE;
- break;
- }
- }
- #endif
- }
- }
- }
- }
-
- //
- // add default route to master
- //
- OutputList* ol = 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: // Removed by Tim.
- case Track::AUDIO_AUX:
- //case Track::AUDIO_INPUT: // Removed by Tim.
- // p3.3.38
- //case Track::AUDIO_SOFTSYNTH:
- audio->msgAddRoute(Route((AudioTrack*)track, -1), Route(ao, -1));
- updateFlags |= SC_ROUTE;
- break;
- // p3.3.38 It should actually never get here now, but just in case.
- case Track::AUDIO_SOFTSYNTH:
- audio->msgAddRoute(Route((AudioTrack*)track, 0, ((AudioTrack*)track)->channels()), Route(ao, 0, ((AudioTrack*)track)->channels()));
- updateFlags |= SC_ROUTE;
- break;
- default:
- break;
- }
- }
- audio->msgUpdateSoloStates();
- return track;
- }/*}}}*/
-
-//---------------------------------------------------------
-// cmdRemoveTrack
-//---------------------------------------------------------
-
-void Song::cmdRemoveTrack(Track* track)
- {
- int idx = _tracks.index(track);
- undoOp(UndoOp::DeleteTrack, idx, track);
- removeTrack2(track);
- updateFlags |= SC_TRACK_REMOVED;
- }
-
-//---------------------------------------------------------
-// removeMarkedTracks
-//---------------------------------------------------------
-
-void Song::removeMarkedTracks()
- {
- bool loop;
- do {
- loop = false;
- for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
- if ((*t)->selected()) {
- removeTrack2(*t);
- loop = true;
- break;
- }
- }
- } while (loop);
- }
-
-//---------------------------------------------------------
-// deselectTracks
-//---------------------------------------------------------
-
-void Song::deselectTracks()
- {
- for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t)
- (*t)->setSelected(false);
- }
-
-//---------------------------------------------------------
-// changeTrack
-// oldTrack - copy of the original track befor modification
-// newTrack - modified original track
-//---------------------------------------------------------
-
-void Song::changeTrack(Track* oldTrack, Track* newTrack)
- {
- oldTrack->setSelected(false); //??
- int idx = _tracks.index(newTrack);
-
- //undoOp(UndoOp::ModifyTrack, oldTrack, newTrack);
- undoOp(UndoOp::ModifyTrack, idx, oldTrack, newTrack);
- updateFlags |= SC_TRACK_MODIFIED;
- }
-
-//---------------------------------------------------------
-// addEvent
-// return true if event was added
-//---------------------------------------------------------
-
-bool Song::addEvent(Event& event, Part* part)
- {
- /*
- if (event.type() == Controller) {
- MidiTrack* track = (MidiTrack*)part->track();
- int ch = track->outChannel();
- int tick = event.tick() + part->tick();
- int cntrl = event.dataA();
- int val = event.dataB();
- MidiPort* mp = &midiPorts[track->outPort()];
-
- // Is it a drum controller event, according to the track port's instrument?
- if(track->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- // Changed by T356.
- //if (!mp->setCtrl(ch, tick, cntrl, val)) {
- // mp->addManagedController(ch, cntrl);
- // if (!mp->setCtrl(ch, tick, cntrl, val))
- // return false;
- // }
- // Changed again. Don't depend on return value of this - search for the event, below.
- //if(!mp->setControllerVal(ch, tick, cntrl, val, part))
- // return false;
- if(mp->setControllerVal(ch, tick, cntrl, val, part))
- updateFlags |= SC_MIDI_CONTROLLER;
- }
- */
-
- //addPortCtrlEvents(event, part);
-
- // Return false if the event is already found.
- // (But allow a port controller value, above, in case it is not already stored.)
- if(part->events()->find(event) != part->events()->end())
- {
- // This can be normal for some (redundant) operations.
- if(debugMsg)
- printf("Song::addEvent event already found in part:%s size:%zd\n", part->name().toLatin1().constData(), part->events()->size());
- return false;
- }
-
- part->events()->add(event);
- return true;
- }
-
-//---------------------------------------------------------
-// changeEvent
-//---------------------------------------------------------
-
-void Song::changeEvent(Event& oldEvent, Event& newEvent, Part* part)
-{
- iEvent i = part->events()->find(oldEvent);
-
- if (i == part->events()->end()) {
- // This can be normal for some (redundant) operations.
- if(debugMsg)
- printf("Song::changeEvent event not found in part:%s size:%zd\n", part->name().toLatin1().constData(), part->events()->size());
- // abort();
- // Removed by T356. Allow it to add the new event.
- // (And remove the old one from the midi port controller!)
- //return;
- }
- else
- part->events()->erase(i);
-
- part->events()->add(newEvent);
-
- /*
- if (oldEvent.type() == Controller) {
- MidiTrack* track = (MidiTrack*)part->track();
- int ch = track->outChannel();
- int tick = oldEvent.tick() + part->tick();
- int cntrl = oldEvent.dataA();
- MidiPort* mp = &midiPorts[track->outPort()];
- // Is it a drum controller event, according to the track port's instrument?
- if(track->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->deleteController(ch, tick, cntrl, part);
- }
- */
- //removePortCtrlEvents(oldEvent, part);
-
- /*
- if (newEvent.type() == Controller) {
- MidiTrack* track = (MidiTrack*)part->track();
- int ch = track->outChannel();
- int tick = newEvent.tick() + part->tick();
- int cntrl = newEvent.dataA();
- int val = newEvent.dataB();
- MidiPort* mp = &midiPorts[track->outPort()];
- // Is it a drum controller event, according to the track port's instrument?
- if(track->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->setControllerVal(ch, tick, cntrl, val, part);
- }
- */
- //addPortCtrlEvents(newEvent, part);
-}
-
-//---------------------------------------------------------
-// deleteEvent
-//---------------------------------------------------------
-
-void Song::deleteEvent(Event& event, Part* part)
- {
- /*
- if (event.type() == Controller) {
- MidiTrack* track = (MidiTrack*)part->track();
- int ch = track->outChannel();
- int tick = event.tick() + part->tick();
- int cntrl = event.dataA();
-
- MidiPort* mp = &midiPorts[track->outPort()];
- // Is it a drum controller event, according to the track port's instrument?
- if(track->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->deleteController(ch, tick, cntrl, part);
- }
- */
- //removePortCtrlEvents(event, part);
-
- iEvent ev = part->events()->find(event);
- if (ev == part->events()->end()) {
- // This can be normal for some (redundant) operations.
- if(debugMsg)
- printf("Song::deleteEvent event not found in part:%s size:%zd\n", part->name().toLatin1().constData(), part->events()->size());
- return;
- }
- part->events()->erase(ev);
- }
-
-//---------------------------------------------------------
-// remapPortDrumCtrlEvents
-// Called when drum map anote, channel, or port is changed.
-//---------------------------------------------------------
-
-void Song::remapPortDrumCtrlEvents(int mapidx, int newnote, int newchan, int newport)
-{
- if(mapidx == -1)
- return;
-
- for(ciMidiTrack it = _midis.begin(); it != _midis.end(); ++it)
- {
- MidiTrack* mt = *it;
- if(mt->type() != Track::DRUM)
- continue;
-
- MidiPort* trackmp = &midiPorts[mt->outPort()];
- const PartList* pl = mt->cparts();
- for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
- {
- MidiPart* part = (MidiPart*)(ip->second);
- const EventList* el = part->cevents();
- unsigned len = part->lenTick();
- for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- {
- const Event& ev = ie->second;
- // Added by T356. Do not handle events which are past the end of the part.
- if(ev.tick() >= len)
- break;
-
- if(ev.type() != Controller)
- continue;
-
- int cntrl = ev.dataA();
-
- // Is it a drum controller event, according to the track port's instrument?
- MidiController* mc = trackmp->drumController(cntrl);
- if(!mc)
- continue;
-
- int note = cntrl & 0x7f;
- // Does the index match?
- if(note == mapidx)
- {
- int tick = ev.tick() + part->tick();
- int ch = drumMap[note].channel;
- int port = drumMap[note].port;
- MidiPort* mp = &midiPorts[port];
- cntrl = (cntrl & ~0xff) | drumMap[note].anote;
-
- // Remove the port controller value.
- mp->deleteController(ch, tick, cntrl, part);
-
- if(newnote != -1 && newnote != drumMap[note].anote)
- cntrl = (cntrl & ~0xff) | newnote;
- if(newchan != -1 && newchan != ch)
- ch = newchan;
- if(newport != -1 && newport != port)
- port = newport;
-
- mp = &midiPorts[port];
-
- // Add the port controller value.
- mp->setControllerVal(ch, tick, cntrl, ev.dataB(), part);
- }
- }
- }
- }
-}
-
-//---------------------------------------------------------
-// changeAllPortDrumCtlEvents
-// add true: add events. false: remove events
-// drumonly true: Do drum controller events ONLY. false (default): Do ALL controller events.
-//---------------------------------------------------------
-
-void Song::changeAllPortDrumCtrlEvents(bool add, bool drumonly)
-{
- int ch, trackch, cntrl, tick;
- MidiPort* mp, *trackmp;
- for(ciMidiTrack it = _midis.begin(); it != _midis.end(); ++it)
- {
- MidiTrack* mt = *it;
- if(mt->type() != Track::DRUM)
- continue;
-
- trackmp = &midiPorts[mt->outPort()];
- trackch = mt->outChannel();
- const PartList* pl = mt->cparts();
- for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
- {
- MidiPart* part = (MidiPart*)(ip->second);
- const EventList* el = part->cevents();
- unsigned len = part->lenTick();
- for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- {
- const Event& ev = ie->second;
- // Added by T356. Do not handle events which are past the end of the part.
- if(ev.tick() >= len)
- break;
-
- if(ev.type() != Controller)
- continue;
-
- cntrl = ev.dataA();
- mp = trackmp;
- ch = trackch;
-
- // Is it a drum controller event, according to the track port's instrument?
- if(trackmp->drumController(cntrl))
- {
- int note = cntrl & 0x7f;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl = (cntrl & ~0xff) | drumMap[note].anote;
- }
- else
- {
- if(drumonly)
- continue;
- }
-
- tick = ev.tick() + part->tick();
-
- if(add)
- // Add the port controller value.
- mp->setControllerVal(ch, tick, cntrl, ev.dataB(), part);
- else
- // Remove the port controller value.
- mp->deleteController(ch, tick, cntrl, part);
- }
- }
- }
-}
-
-//---------------------------------------------------------
-// cmdAddRecordedEvents
-// add recorded Events into part
-//---------------------------------------------------------
-
-void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned startTick)
- {
- if (events->empty()) {
- if (debugMsg)
- printf("no events recorded\n");
- return;
- }
- iEvent s;
- iEvent e;
- unsigned endTick;
-
- // Changed by Tim. p3.3.8
-
- //if (punchin())
- if((audio->loopCount() > 0 && startTick > lPos().tick()) || (punchin() && startTick < lPos().tick()))
- {
- startTick = lpos();
- s = events->lower_bound(startTick);
- }
- else
- {
- s = events->begin();
-// startTick = s->first;
- }
-
- // Changed by Tim. p3.3.8
-
- //if (punchout())
- //{
- // endTick = rpos();
- // e = events->lower_bound(endTick);
- //}
- //else
- //{
- // search for last noteOff:
- endTick = 0;
- for (iEvent i = events->begin(); i != events->end(); ++i) {
- Event ev = i->second;
- unsigned l = ev.endTick();
- if (l > endTick)
- endTick = l;
- }
- // e = events->end();
- //}
- if((audio->loopCount() > 0) || (punchout() && endTick > rPos().tick()) )
- {
- endTick = rpos();
- e = events->lower_bound(endTick);
- }
- else
- e = events->end();
-
- if (startTick > endTick) {
- if (debugMsg)
- printf("no events in record area\n");
- return;
- }
-
- //---------------------------------------------------
- // if startTick points into a part,
- // record to that part
- // else
- // create new part
- //---------------------------------------------------
-
- PartList* pl = mt->parts();
- MidiPart* part = 0;
- iPart ip;
- for (ip = pl->begin(); ip != pl->end(); ++ip) {
- part = (MidiPart*)(ip->second);
- unsigned partStart = part->tick();
- unsigned partEnd = part->endTick();
- if (startTick >= partStart && startTick < partEnd)
- break;
- }
- if (ip == pl->end()) {
- if (debugMsg)
- printf("create new part for recorded events\n");
- // create new part
- part = new MidiPart(mt);
-
- // Changed by Tim. p3.3.8
-
- // Honour the Arranger snap settings. (Set to bar by default).
- //startTick = roundDownBar(startTick);
- //endTick = roundUpBar(endTick);
- // Round the start down using the Arranger part snap raster value.
- startTick = AL::sigmap.raster1(startTick, arrangerRaster());
- // Round the end up using the Arranger part snap raster value.
- endTick = AL::sigmap.raster2(endTick, arrangerRaster());
-
- part->setTick(startTick);
- part->setLenTick(endTick - startTick);
- part->setName(mt->name());
- // copy events
- for (iEvent i = s; i != e; ++i) {
- Event old = i->second;
- Event event = old.clone();
- event.setTick(old.tick() - startTick);
- // addEvent also adds port controller values. So does msgAddPart, below. Let msgAddPart handle them.
- //addEvent(event, part);
- if(part->events()->find(event) == part->events()->end())
- part->events()->add(event);
- }
- audio->msgAddPart(part);
- updateFlags |= SC_PART_INSERTED;
- return;
- }
-
- updateFlags |= SC_EVENT_INSERTED;
-
- unsigned partTick = part->tick();
- if (endTick > part->endTick()) {
- // Determine new part length...
- endTick = 0;
- for (iEvent i = s; i != e; ++i) {
- Event event = i->second;
- unsigned tick = event.tick() - partTick + event.lenTick();
- if (endTick < tick)
- endTick = tick;
- }
- // Added by Tim. p3.3.8
-
- // Round the end up (again) using the Arranger part snap raster value.
- endTick = AL::sigmap.raster2(endTick, arrangerRaster());
-
- // Remove all of the part's port controller values. Indicate do not do clone parts.
- removePortCtrlEvents(part, false);
- // Clone the part. This doesn't increment aref count, and doesn't chain clones.
- // It also gives the new part a new serial number, but it is
- // overwritten with the old one by Song::changePart(), below.
- Part* newPart = part->clone();
- // Set the new part's length.
- newPart->setLenTick(endTick);
- // Change the part.
- changePart(part, newPart);
- // Manually adjust reference counts.
- part->events()->incARef(-1);
- newPart->events()->incARef(1);
- // Replace the part in the clone chain with the new part.
- replaceClone(part, newPart);
- // Now add all of the new part's port controller values. Indicate do not do clone parts.
- addPortCtrlEvents(newPart, false);
- // Create an undo op. Indicate do port controller values but not clone parts.
- undoOp(UndoOp::ModifyPart, part, newPart, true, false);
- updateFlags |= SC_PART_MODIFIED;
-
- if (_recMode == REC_REPLACE)
- {
- iEvent si = newPart->events()->lower_bound(startTick - newPart->tick());
- iEvent ei = newPart->events()->lower_bound(newPart->endTick() - newPart->tick());
- for (iEvent i = si; i != ei; ++i)
- {
- Event event = i->second;
- // Create an undo op. Indicate do port controller values and clone parts.
- undoOp(UndoOp::DeleteEvent, event, newPart, true, true);
- // Remove the event from the new part's port controller values, and do all clone parts.
- removePortCtrlEvents(event, newPart, true);
- }
- newPart->events()->erase(si, ei);
- }
-
- for (iEvent i = s; i != e; ++i) {
- Event event = i->second;
- event.setTick(event.tick() - partTick);
- Event e;
- // Create an undo op. Indicate do port controller values and clone parts.
- undoOp(UndoOp::AddEvent, e, event, newPart, true, true);
-
- if(newPart->events()->find(event) == newPart->events()->end())
- newPart->events()->add(event);
-
- // Add the event to the new part's port controller values, and do all clone parts.
- addPortCtrlEvents(event, newPart, true);
- }
-
-
- /*
- if (_recMode == REC_REPLACE)
- {
- iEvent si = part->events()->lower_bound(startTick - part->tick());
- iEvent ei = part->events()->lower_bound(part->endTick() - part->tick());
-
- for (iEvent i = si; i != ei; ++i)
- {
- Event event = i->second;
- // Create an undo op. Indicate do port controller values and clone parts.
- //undoOp(UndoOp::DeleteEvent, event, part);
- undoOp(UndoOp::DeleteEvent, event, part, true, true);
-
- //if (event.type() == Controller) {
- // MidiTrack* track = (MidiTrack*)part->track();
- // int ch = track->outChannel();
- // int tick = event.tick() + part->tick();
- // int cntrl = event.dataA();
- // midiPorts[track->outPort()].deleteController(ch, tick, cntrl, part);
- // }
-
- // Remove the event from the part's port controller values, and do all clone parts.
- //removePortCtrlEvents(event, part, true);
- }
- part->events()->erase(si, ei);
- }
-
- // Remove all of the part's port controller values, and do all clone parts.
- removePortCtrlEvents(part, true);
-
- // Clone the part. This doesn't increment aref count, and doesn't chain clones.
- // It also gives the new part a new serial number, but it is
- // overwritten with the old one by Song::changePart(), below.
- Part* newPart = part->clone();
-
- endTick = 0;
- for (iEvent i = s; i != e; ++i) {
- Event event = i->second;
- unsigned tick = event.tick() - partTick;
- event.setTick(tick);
- Event e;
- // Create an undo op. Indicate do port controller values and clone parts.
- //undoOp(UndoOp::AddEvent, e, event, newPart);
- undoOp(UndoOp::AddEvent, e, event, newPart, true, true);
-
- // addEvent also adds port controller values. So does msgChangePart, below. Let msgChangePart handle them.
- //addEvent(event, (MidiPart*)newPart);
- if(newPart->events()->find(event) == newPart->events()->end())
- newPart->events()->add(event);
-
- if (endTick < event.tick() + event.lenTick())
- endTick = event.tick() + event.lenTick();
- }
- newPart->setLenTick(endTick); // endTick - part->tick()
-
- //printf("Song::cmdAddRecordedEvents before changePart part:%p events:%p refs:%d Arefs:%d newPart:%p events:%p refs:%d Arefs:%d\n", part, part->events(), part->events()->refCount(), part->events()->arefCount(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount());
-
- // Change the part.
- changePart(part, newPart);
- // Manually adjust reference counts.
- part->events()->incARef(-1);
- newPart->events()->incARef(1);
- // Replace the part in the clone chain with the new part.
- replaceClone(part, newPart);
- // Now add all of the new part's port controller values, and do all clone parts.
- addPortCtrlEvents(newPart, true);
-
- //printf("Song::cmdAddRecordedEvents after changePart part:%p events:%p refs:%d Arefs:%d newPart:%p events:%p refs:%d Arefs:%d\n", part, part->events(), part->events()->refCount(), part->events()->arefCount(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount());
-
- //undoOp(UndoOp::ModifyPart, part, newPart);
- // Create an undo op. Indicate do not do port controller values and clone parts.
- undoOp(UndoOp::ModifyPart, part, newPart, false, false);
-
- // Removed by T356.
- //part->events()->incARef(-1);
-
- updateFlags |= SC_PART_MODIFIED;
- //printf("Song::cmdAddRecordedEvents final part:%p events:%p refs:%d Arefs:%d newPart:%p events:%p refs:%d Arefs:%d\n", part, part->events(), part->events()->refCount(), part->events()->arefCount(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount());
- */
-
- }
- else {
- if (_recMode == REC_REPLACE) {
- iEvent si = part->events()->lower_bound(startTick - part->tick());
- iEvent ei = part->events()->lower_bound(endTick - part->tick());
-
- for (iEvent i = si; i != ei; ++i) {
- Event event = i->second;
- // Create an undo op. Indicate that controller values and clone parts were handled.
- //undoOp(UndoOp::DeleteEvent, event, part);
- undoOp(UndoOp::DeleteEvent, event, part, true, true);
- /*
- if (event.type() == Controller) {
- MidiTrack* track = (MidiTrack*)part->track();
- int ch = track->outChannel();
- int tick = event.tick() + part->tick();
- int cntrl = event.dataA();
- midiPorts[track->outPort()].deleteController(ch, tick, cntrl, part);
- }
- */
- // Remove the event from the part's port controller values, and do all clone parts.
- removePortCtrlEvents(event, part, true);
- }
- part->events()->erase(si, ei);
- }
- for (iEvent i = s; i != e; ++i) {
- Event event = i->second;
- int tick = event.tick() - partTick;
- event.setTick(tick);
-
- // Create an undo op. Indicate that controller values and clone parts were handled.
- //undoOp(UndoOp::AddEvent, event, part);
- undoOp(UndoOp::AddEvent, event, part, true, true);
-
- //addEvent(event, part);
- if(part->events()->find(event) == part->events()->end())
- part->events()->add(event);
-
- // Add the event to the part's port controller values, and do all clone parts.
- addPortCtrlEvents(event, part, true);
- }
- }
- }
-
-//---------------------------------------------------------
-// findTrack
-//---------------------------------------------------------
-
-MidiTrack* Song::findTrack(const Part* part) const
- {
- for (ciTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*t);
- if (track == 0)
- continue;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- if (part == p->second)
- return track;
- }
- }
- return 0;
- }
-
-//---------------------------------------------------------
-// findTrack
-// find track by name
-//---------------------------------------------------------
-
-Track* Song::findTrack(const QString& name) const
- {
- for (ciTrack i = _tracks.begin(); i != _tracks.end(); ++i) {
- if ((*i)->name() == name)
- return *i;
- }
- return 0;
- }
-
-//---------------------------------------------------------
-// setLoop
-// set transport loop flag
-//---------------------------------------------------------
-
-void Song::setLoop(bool f)
- {
- if (loopFlag != f) {
- loopFlag = f;
- loopAction->setChecked(loopFlag);
- emit loopChanged(loopFlag);
- }
- }
-
-//---------------------------------------------------------
-// clearTrackRec
-//---------------------------------------------------------
-void Song::clearTrackRec()
-{
- for (iTrack it = tracks()->begin(); it != tracks()->end(); ++it)
- setRecordFlag(*it,false);
-}
-
-//---------------------------------------------------------
-// setRecord
-//---------------------------------------------------------
-void Song::setRecord(bool f, bool autoRecEnable)
- {
- if (f && museProject == museProjectInitPath ) { // check that there is a project stored before commencing
- // no project, we need to create one.
- if (!muse->saveAs())
- return; // could not store project, won't enable record
- }
- if (recordFlag != f) {
- if (f && autoRecEnable) {
- bool alreadyRecEnabled = false;
- Track *selectedTrack = 0;
- // loop through list and check if any track is rec enabled
- // if not then rec enable the selected track
- WaveTrackList* wtl = waves();
- for (iWaveTrack i = wtl->begin(); i != wtl->end(); ++i) {
- if((*i)->recordFlag())
- {
- alreadyRecEnabled = true;
- break;
- }
- if((*i)->selected())
- selectedTrack = (*i);
- }
- if (!alreadyRecEnabled) {
- MidiTrackList* mtl = midis();
- for (iMidiTrack it = mtl->begin(); it != mtl->end(); ++it) {
- if((*it)->recordFlag())
- {
- alreadyRecEnabled = true;
- break;
- }
- if((*it)->selected())
- selectedTrack = (*it);
- }
- }
- if (!alreadyRecEnabled && selectedTrack) {
- setRecordFlag(selectedTrack, true);
- }
- else if (alreadyRecEnabled) {
- // do nothing
- }
- else {
- // if there are no tracks, do not enable record
- if (!waves()->size() && !midis()->size()) {
- printf("No track to select, won't enable record\n");
- f = false;
- }
- }
- // prepare recording of wave files for all record enabled wave tracks
- for (iWaveTrack i = wtl->begin(); i != wtl->end(); ++i) {
- if((*i)->recordFlag())
- {
- (*i)->prepareRecording();
- }
- }
-
-#if 0
- // check for midi devices suitable for recording
- bool portFound = false;
- for (int i = 0; i < MIDI_PORTS; ++i) {
- MidiDevice* dev = midiPorts[i].device();
- if (dev && (dev->rwFlags() & 0x2))
- portFound = true;
- }
- if (!portFound) {
- QMessageBox::critical(qApp->mainWidget(), "MusE: Record",
- "There are no midi devices configured for recording");
- f = false;
- }
-#endif
- }
- else {
- bounceTrack = 0;
- }
- if (audio->isPlaying() && f)
- f = false;
- recordFlag = f;
- recordAction->setChecked(recordFlag);
- emit recordChanged(recordFlag);
- }
- }
-
-//---------------------------------------------------------
-// setPunchin
-// set punchin flag
-//---------------------------------------------------------
-
-void Song::setPunchin(bool f)
- {
- if (punchinFlag != f) {
- punchinFlag = f;
- punchinAction->setChecked(punchinFlag);
- emit punchinChanged(punchinFlag);
- }
- }
-
-//---------------------------------------------------------
-// setPunchout
-// set punchout flag
-//---------------------------------------------------------
-
-void Song::setPunchout(bool f)
- {
- if (punchoutFlag != f) {
- punchoutFlag = f;
- punchoutAction->setChecked(punchoutFlag);
- emit punchoutChanged(punchoutFlag);
- }
- }
-
-//---------------------------------------------------------
-// setClick
-//---------------------------------------------------------
-
-void Song::setClick(bool val)
- {
- if (_click != val) {
- _click = val;
- emit clickChanged(_click);
- }
- }
-
-//---------------------------------------------------------
-// setQuantize
-//---------------------------------------------------------
-
-void Song::setQuantize(bool val)
- {
- if (_quantize != val) {
- _quantize = val;
- emit quantizeChanged(_quantize);
- }
- }
-
-//---------------------------------------------------------
-// setMasterFlag
-//---------------------------------------------------------
-
-void Song::setMasterFlag(bool val)
- {
- _masterFlag = val;
- if (tempomap.setMasterFlag(cpos(), val))
- {
- //audioDevice->setMaster(val);
- emit songChanged(SC_MASTER);
- }
- // Removed. p3.3.26
- //audioDevice->setMaster(val);
- }
-
-//---------------------------------------------------------
-// setPlay
-// set transport play flag
-//---------------------------------------------------------
-
-void Song::setPlay(bool f)
- {
- if (extSyncFlag.value()) {
- if (debugMsg)
- printf("not allowed while using external sync");
- return;
- }
- // only allow the user to set the button "on"
- if (!f)
- playAction->setChecked(true);
- else
- audio->msgPlay(true);
- }
-
-void Song::setStop(bool f)
- {
- if (extSyncFlag.value()) {
- if (debugMsg)
- printf("not allowed while using external sync");
- return;
- }
- // only allow the user to set the button "on"
- if (!f)
- stopAction->setChecked(true);
- else
- audio->msgPlay(false);
- }
-
-void Song::setStopPlay(bool f)
- {
- playAction->blockSignals(true);
- stopAction->blockSignals(true);
-
- emit playChanged(f); // signal transport window
-
- playAction->setChecked(f);
- stopAction->setChecked(!f);
-
- stopAction->blockSignals(false);
- playAction->blockSignals(false);
- }
-
-//---------------------------------------------------------
-// swapTracks
-//---------------------------------------------------------
-
-void Song::swapTracks(int i1, int i2)
- {
- undoOp(UndoOp::SwapTrack, i1, i2);
- Track* track = _tracks[i1];
- _tracks[i1] = _tracks[i2];
- _tracks[i2] = track;
- }
-
-//---------------------------------------------------------
-// setPos
-// song->setPos(Song::CPOS, pos, true, true, true);
-//---------------------------------------------------------
-
-void Song::setPos(int idx, const Pos& val, bool sig,
- bool isSeek, bool adjustScrollbar)
- {
-// printf("setPos %d sig=%d,seek=%d,scroll=%d ",
-// idx, sig, isSeek, adjustScrollbar);
-// val.dump(0);
-// printf("\n");
-
- // p3.3.23
- //printf("Song::setPos before audio->msgSeek idx:%d isSeek:%d frame:%d\n", idx, isSeek, val.frame());
- if (pos[idx] == val)
- return;
- if (idx == CPOS) {
- _vcpos = val;
- if (isSeek && !extSyncFlag.value()) {
- audio->msgSeek(val);
- // p3.3.23
- //printf("Song::setPos after audio->msgSeek idx:%d isSeek:%d frame:%d\n", idx, isSeek, val.frame());
- return;
- }
- }
- pos[idx] = val;
- bool swap = pos[LPOS] > pos[RPOS];
- if (swap) { // swap lpos/rpos if lpos > rpos
- Pos tmp = pos[LPOS];
- pos[LPOS] = pos[RPOS];
- pos[RPOS] = tmp;
- }
- if (sig) {
- if (swap) {
- emit posChanged(LPOS, pos[LPOS].tick(), adjustScrollbar);
- emit posChanged(RPOS, pos[RPOS].tick(), adjustScrollbar);
- if (idx != LPOS && idx != RPOS)
- emit posChanged(idx, pos[idx].tick(), adjustScrollbar);
- }
- else
- emit posChanged(idx, pos[idx].tick(), adjustScrollbar);
- }
-
- if (idx == CPOS) {
- iMarker i1 = _markerList->begin();
- iMarker i2 = i1;
- bool currentChanged = false;
- for (; i1 != _markerList->end(); ++i1) {
- ++i2;
- if (val.tick() >= i1->first && (i2==_markerList->end() || val.tick() < i2->first)) {
- if (i1->second.current())
- return;
- i1->second.setCurrent(true);
- if (currentChanged) {
- emit markerChanged(MARKER_CUR);
- return;
- }
- ++i1;
- for (; i1 != _markerList->end(); ++i1) {
- if (i1->second.current())
- i1->second.setCurrent(false);
- }
- emit markerChanged(MARKER_CUR);
- return;
- }
- else {
- if (i1->second.current()) {
- currentChanged = true;
- i1->second.setCurrent(false);
- }
- }
- }
- if (currentChanged)
- emit markerChanged(MARKER_CUR);
- }
- }
-
-//---------------------------------------------------------
-// forward
-//---------------------------------------------------------
-
-void Song::forward()
- {
- unsigned newPos = pos[0].tick() + config.division;
- audio->msgSeek(Pos(newPos, true));
- }
-
-//---------------------------------------------------------
-// rewind
-//---------------------------------------------------------
-
-void Song::rewind()
- {
- unsigned newPos;
- if (unsigned(config.division) > pos[0].tick())
- newPos = 0;
- else
- newPos = pos[0].tick() - config.division;
- audio->msgSeek(Pos(newPos, true));
- }
-
-//---------------------------------------------------------
-// rewindStart
-//---------------------------------------------------------
-
-void Song::rewindStart()
- {
- // Added by T356
- //audio->msgIdle(true);
-
- audio->msgSeek(Pos(0, true));
-
- // Added by T356
- //audio->msgIdle(false);
- }
-
-//---------------------------------------------------------
-// update
-//---------------------------------------------------------
-
-void Song::update(int flags)
- {
- static int level = 0; // DEBUG
- if (level) {
- printf("Song::update %08x, level %d\n", flags, level);
- return;
- }
- ++level;
- emit songChanged(flags);
- --level;
- }
-
-//---------------------------------------------------------
-// updatePos
-//---------------------------------------------------------
-
-void Song::updatePos()
- {
- emit posChanged(0, pos[0].tick(), false);
- emit posChanged(1, pos[1].tick(), false);
- emit posChanged(2, pos[2].tick(), false);
- }
-
-//---------------------------------------------------------
-// setChannelMute
-// mute all midi tracks associated with channel
-//---------------------------------------------------------
-
-void Song::setChannelMute(int channel, bool val)
- {
- for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*i);
- if (track == 0)
- continue;
- if (track->outChannel() == channel)
- track->setMute(val);
- }
- emit songChanged(SC_MUTE);
- }
-
-//---------------------------------------------------------
-// len
-//---------------------------------------------------------
-
-void Song::initLen()
- {
- _len = AL::sigmap.bar2tick(40, 0, 0); // default song len
- for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*t);
- if (track == 0)
- continue;
- PartList* parts = track->parts();
- for (iPart p = parts->begin(); p != parts->end(); ++p) {
- unsigned last = p->second->tick() + p->second->lenTick();
- if (last > _len)
- _len = last;
- }
- }
- _len = roundUpBar(_len);
- }
-
-//---------------------------------------------------------
-// tempoChanged
-//---------------------------------------------------------
-
-void Song::tempoChanged()
-{
- emit songChanged(SC_TEMPO);
-}
-
-//---------------------------------------------------------
-// roundUpBar
-//---------------------------------------------------------
-
-int Song::roundUpBar(int t) const
- {
- int bar, beat;
- unsigned tick;
- AL::sigmap.tickValues(t, &bar, &beat, &tick);
- if (beat || tick)
- return AL::sigmap.bar2tick(bar+1, 0, 0);
- return t;
- }
-
-//---------------------------------------------------------
-// roundUpBeat
-//---------------------------------------------------------
-
-int Song::roundUpBeat(int t) const
- {
- int bar, beat;
- unsigned tick;
- AL::sigmap.tickValues(t, &bar, &beat, &tick);
- if (tick)
- return AL::sigmap.bar2tick(bar, beat+1, 0);
- return t;
- }
-
-//---------------------------------------------------------
-// roundDownBar
-//---------------------------------------------------------
-
-int Song::roundDownBar(int t) const
- {
- int bar, beat;
- unsigned tick;
- AL::sigmap.tickValues(t, &bar, &beat, &tick);
- return AL::sigmap.bar2tick(bar, 0, 0);
- }
-
-//---------------------------------------------------------
-// dumpMaster
-//---------------------------------------------------------
-
-void Song::dumpMaster()
- {
- tempomap.dump();
- AL::sigmap.dump();
- }
-
-//---------------------------------------------------------
-// getSelectedParts
-//---------------------------------------------------------
-
-PartList* Song::getSelectedMidiParts() const
- {
- PartList* parts = new PartList();
-
- //------------------------------------------------------
- // wenn ein Part selektiert ist, diesen editieren
- // wenn ein Track selektiert ist, den Ersten
- // Part des Tracks editieren, die restlichen sind
- // 'ghostparts'
- // wenn mehrere Parts selektiert sind, dann Ersten
- // editieren, die restlichen sind 'ghostparts'
- //
- // Rough translation:
- /*
- If a part is selected, edit that.
- If a track is selected, edit the first
- part of the track, the rest are
- 'ghost parts'
- When multiple parts are selected, then edit the first,
- the rest are 'ghost parts'
- */
-
-
- // collect marked parts
- for (ciMidiTrack t = _midis.begin(); t != _midis.end(); ++t) {
- MidiTrack* track = *t;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- if (p->second->selected()) {
- parts->add(p->second);
- }
- }
- }
- // if no part is selected, then search for selected track
- // and collect all parts of this track
-
- if (parts->empty()) {
- for (ciTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
- if ((*t)->selected()) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*t);
- if (track == 0)
- continue;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p)
- parts->add(p->second);
- break;
- }
- }
- }
- return parts;
- }
-
-PartList* Song::getSelectedWaveParts() const
- {
- PartList* parts = new PartList();
-
- //------------------------------------------------------
- // wenn ein Part selektiert ist, diesen editieren
- // wenn ein Track selektiert ist, den Ersten
- // Part des Tracks editieren, die restlichen sind
- // 'ghostparts'
- // wenn mehrere Parts selektiert sind, dann Ersten
- // editieren, die restlichen sind 'ghostparts'
- //
-
- // markierte Parts sammeln
- for (ciTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
- WaveTrack* track = dynamic_cast<WaveTrack*>(*t);
- if (track == 0)
- continue;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- if (p->second->selected()) {
- parts->add(p->second);
- }
- }
- }
- // wenn keine Parts selektiert, dann markierten Track suchen
- // und alle Parts dieses Tracks zusammensuchen
-
- if (parts->empty()) {
- for (ciTrack t = _tracks.begin(); t != _tracks.end(); ++t) {
- if ((*t)->selected()) {
- WaveTrack* track = dynamic_cast<WaveTrack*>(*t);
- if (track == 0)
- continue;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p)
- parts->add(p->second);
- break;
- }
- }
- }
- return parts;
- }
-
-void Song::setMType(MType t)
- {
-// printf("set MType %d\n", t);
- _mtype = t;
- song->update(SC_SONG_TYPE); // p4.0.7 Tim.
- }
-
-//---------------------------------------------------------
-// beat
-//---------------------------------------------------------
-
-void Song::beat()
- {
- // Keep the sync detectors running...
- for(int port = 0; port < MIDI_PORTS; ++port)
- {
- // Must keep them running even if there's no device...
- //if(midiPorts[port].device())
- midiPorts[port].syncInfo().setTime();
- }
-
-
- int tick = audio->tickPos();
- if (audio->isPlaying())
- setPos(0, tick, true, false, true);
-
- // p3.3.40 Update synth native guis at the heartbeat rate.
- for(ciSynthI is = _synthIs.begin(); is != _synthIs.end(); ++is)
- (*is)->guiHeartBeat();
-
- while (noteFifoSize) {
- int pv = recNoteFifo[noteFifoRindex];
- noteFifoRindex = (noteFifoRindex + 1) % REC_NOTE_FIFO_SIZE;
- int pitch = (pv >> 8) & 0xff;
- int velo = pv & 0xff;
-
- //---------------------------------------------------
- // filter midi remote control events
- //---------------------------------------------------
-
- if (rcEnable && velo != 0) {
- if (pitch == rcStopNote)
- setStop(true);
- else if (pitch == rcRecordNote)
- setRecord(true);
- else if (pitch == rcGotoLeftMarkNote)
- setPos(0, pos[LPOS].tick(), true, true, true);
- else if (pitch == rcPlayNote)
- setPlay(true);
- }
- emit song->midiNote(pitch, velo);
- --noteFifoSize;
- }
- }
-
-//---------------------------------------------------------
-// setLen
-//---------------------------------------------------------
-
-void Song::setLen(unsigned l)
- {
- _len = l;
- update();
- }
-
-//---------------------------------------------------------
-// addMarker
-//---------------------------------------------------------
-
-Marker* Song::addMarker(const QString& s, int t, bool lck)
- {
- Marker* marker = _markerList->add(s, t, lck);
- emit markerChanged(MARKER_ADD);
- return marker;
- }
-
-//---------------------------------------------------------
-// addMarker
-//---------------------------------------------------------
-
-Marker* Song::getMarkerAt(int t)
- {
- iMarker markerI;
- for (markerI=_markerList->begin(); markerI != _markerList->end(); ++markerI) {
-// if (i1->second.current())
- if (unsigned(t) == markerI->second.tick())//prevent of copmiler warning: comparison signed/unsigned
- return &markerI->second;
- }
- //Marker* marker = _markerList->add(s, t, lck);
- return NULL;
- }
-
-//---------------------------------------------------------
-// removeMarker
-//---------------------------------------------------------
-
-void Song::removeMarker(Marker* marker)
- {
- _markerList->remove(marker);
- emit markerChanged(MARKER_REMOVE);
- }
-
-Marker* Song::setMarkerName(Marker* m, const QString& s)
- {
- m->setName(s);
- emit markerChanged(MARKER_NAME);
- return m;
- }
-
-Marker* Song::setMarkerTick(Marker* m, int t)
- {
- Marker mm(*m);
- _markerList->remove(m);
- mm.setTick(t);
- m = _markerList->add(mm);
- emit markerChanged(MARKER_TICK);
- return m;
- }
-
-Marker* Song::setMarkerLock(Marker* m, bool f)
- {
- m->setType(f ? Pos::FRAMES : Pos::TICKS);
- emit markerChanged(MARKER_LOCK);
- return m;
- }
-
-//---------------------------------------------------------
-// setRecordFlag
-//---------------------------------------------------------
-
-void Song::setRecordFlag(Track* track, bool val)
- {
- if (track->type() == Track::WAVE) {
- WaveTrack* audioTrack = (WaveTrack*)track;
- if(!audioTrack->setRecordFlag1(val))
- return;
- audio->msgSetRecord(audioTrack, val);
- }
- else {
- track->setRecordFlag1(val);
- track->setRecordFlag2(val);
- }
-// updateFlags |= SC_RECFLAG;
- update(SC_RECFLAG);
-
- }
-
-//---------------------------------------------------------
-// rescanAlsaPorts
-//---------------------------------------------------------
-
-void Song::rescanAlsaPorts()
- {
- emit midiPortsChanged();
- }
-
-//---------------------------------------------------------
-// endMsgCmd
-//---------------------------------------------------------
-
-void Song::endMsgCmd()
- {
- if (updateFlags) {
- redoList->clear(); // TODO: delete elements in list
- undoAction->setEnabled(true);
- redoAction->setEnabled(false);
- emit songChanged(updateFlags);
- }
- }
-
-//---------------------------------------------------------
-// undo
-//---------------------------------------------------------
-
-void Song::undo()
- {
- updateFlags = 0;
- if (doUndo1())
- return;
- audio->msgUndo();
- doUndo3();
- redoAction->setEnabled(true);
- undoAction->setEnabled(!undoList->empty());
-
- if(updateFlags && (SC_TRACK_REMOVED | SC_TRACK_INSERTED))
- audio->msgUpdateSoloStates();
-
- emit songChanged(updateFlags);
- }
-
-//---------------------------------------------------------
-// redo
-//---------------------------------------------------------
-
-void Song::redo()
- {
- updateFlags = 0;
- if (doRedo1())
- return;
- audio->msgRedo();
- doRedo3();
- undoAction->setEnabled(true);
- redoAction->setEnabled(!redoList->empty());
-
- if(updateFlags && (SC_TRACK_REMOVED | SC_TRACK_INSERTED))
- audio->msgUpdateSoloStates();
-
- emit songChanged(updateFlags);
- }
-
-//---------------------------------------------------------
-// processMsg
-// executed in realtime thread context
-//---------------------------------------------------------
-
-void Song::processMsg(AudioMsg* msg)
- {
- switch(msg->id) {
- case SEQM_UPDATE_SOLO_STATES:
- updateSoloStates();
- break;
- case SEQM_UNDO:
- doUndo2();
- break;
- case SEQM_REDO:
- doRedo2();
- break;
- case SEQM_MOVE_TRACK:
- if (msg->a > msg->b) {
- for (int i = msg->a; i > msg->b; --i) {
- swapTracks(i, i-1);
- }
- }
- else {
- for (int i = msg->a; i < msg->b; ++i) {
- swapTracks(i, i+1);
- }
- }
- updateFlags = SC_TRACK_MODIFIED;
- break;
- case SEQM_ADD_EVENT:
- updateFlags = SC_EVENT_INSERTED;
- if (addEvent(msg->ev1, (MidiPart*)msg->p2)) {
- Event ev;
- //undoOp(UndoOp::AddEvent, ev, msg->ev1, (Part*)msg->p2);
- undoOp(UndoOp::AddEvent, ev, msg->ev1, (Part*)msg->p2, msg->a, msg->b);
- }
- else
- updateFlags = 0;
- if(msg->a)
- addPortCtrlEvents(msg->ev1, (Part*)msg->p2, msg->b);
- break;
- case SEQM_REMOVE_EVENT:
- {
- Event event = msg->ev1;
- MidiPart* part = (MidiPart*)msg->p2;
- if(msg->a)
- removePortCtrlEvents(event, part, msg->b);
- Event e;
- //undoOp(UndoOp::DeleteEvent, e, event, (Part*)part);
- undoOp(UndoOp::DeleteEvent, e, event, (Part*)part, msg->a, msg->b);
- deleteEvent(event, part);
- updateFlags = SC_EVENT_REMOVED;
- }
- break;
- case SEQM_CHANGE_EVENT:
- if(msg->a)
- removePortCtrlEvents(msg->ev1, (MidiPart*)msg->p3, msg->b);
- changeEvent(msg->ev1, msg->ev2, (MidiPart*)msg->p3);
- if(msg->a)
- addPortCtrlEvents(msg->ev2, (Part*)msg->p3, msg->b);
- //undoOp(UndoOp::ModifyEvent, msg->ev2, msg->ev1, (Part*)msg->p3);
- undoOp(UndoOp::ModifyEvent, msg->ev2, msg->ev1, (Part*)msg->p3, msg->a, msg->b);
- updateFlags = SC_EVENT_MODIFIED;
- break;
-
- case SEQM_ADD_TEMPO:
- //printf("processMsg (SEQM_ADD_TEMPO) UndoOp::AddTempo. adding tempo at: %d with tempo=%d\n", msg->a, msg->b);
- undoOp(UndoOp::AddTempo, msg->a, msg->b);
- tempomap.addTempo(msg->a, msg->b);
- updateFlags = SC_TEMPO;
- break;
-
- case SEQM_SET_TEMPO:
- //printf("processMsg (SEQM_SET_TEMPO) UndoOp::AddTempo. adding tempo at: %d with tempo=%d\n", msg->a, msg->b);
- undoOp(UndoOp::AddTempo, msg->a, msg->b);
- tempomap.setTempo(msg->a, msg->b);
- updateFlags = SC_TEMPO;
- break;
-
- case SEQM_SET_GLOBAL_TEMPO:
- tempomap.setGlobalTempo(msg->a);
- break;
-
- case SEQM_REMOVE_TEMPO:
- //printf("processMsg (SEQM_REMOVE_TEMPO) UndoOp::DeleteTempo. adding tempo at: %d with tempo=%d\n", msg->a, msg->b);
- undoOp(UndoOp::DeleteTempo, msg->a, msg->b);
- tempomap.delTempo(msg->a);
- updateFlags = SC_TEMPO;
- break;
-
- case SEQM_ADD_SIG:
- undoOp(UndoOp::AddSig, msg->a, msg->b, msg->c);
- AL::sigmap.add(msg->a, AL::TimeSignature(msg->b, msg->c));
- updateFlags = SC_SIG;
- break;
-
- case SEQM_REMOVE_SIG:
- undoOp(UndoOp::DeleteSig, msg->a, msg->b, msg->c);
- AL::sigmap.del(msg->a);
- updateFlags = SC_SIG;
- break;
-
- default:
- printf("unknown seq message %d\n", msg->id);
- break;
- }
- }
-
-//---------------------------------------------------------
-// cmdAddPart
-//---------------------------------------------------------
-
-void Song::cmdAddPart(Part* part)
- {
- addPart(part);
- undoOp(UndoOp::AddPart, part);
- updateFlags = SC_PART_INSERTED;
- }
-
-//---------------------------------------------------------
-// cmdRemovePart
-//---------------------------------------------------------
-
-void Song::cmdRemovePart(Part* part)
- {
- removePart(part);
- undoOp(UndoOp::DeletePart, part);
- part->events()->incARef(-1);
- //part->unchainClone();
- unchainClone(part);
- updateFlags = SC_PART_REMOVED;
- }
-
-//---------------------------------------------------------
-// cmdChangePart
-//---------------------------------------------------------
-
-//void Song::cmdChangePart(Part* oldPart, Part* newPart)
-void Song::cmdChangePart(Part* oldPart, Part* newPart, bool doCtrls, bool doClones)
- {
- //printf("Song::cmdChangePart before changePart oldPart:%p events:%p refs:%d Arefs:%d sn:%d newPart:%p events:%p refs:%d Arefs:%d sn:%d\n", oldPart, oldPart->events(), oldPart->events()->refCount(), oldPart->events()->arefCount(), oldPart->sn(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount(), newPart->sn());
-
- if(doCtrls)
- removePortCtrlEvents(oldPart, doClones);
-
- changePart(oldPart, newPart);
-
- //undoOp(UndoOp::ModifyPart, oldPart, newPart);
- undoOp(UndoOp::ModifyPart, oldPart, newPart, doCtrls, doClones);
-
- // Changed by T356. Do not decrement ref count if the new part is a clone of the old part, since the event list
- // will still be active.
- if(oldPart->cevents() != newPart->cevents())
- oldPart->events()->incARef(-1);
-
- //oldPart->replaceClone(newPart);
-
- //printf("Song::cmdChangePart before repl/unchClone oldPart:%p events:%p refs:%d Arefs:%d sn:%d newPart:%p events:%p refs:%d Arefs:%d sn:%d\n", oldPart, oldPart->events(), oldPart->events()->refCount(), oldPart->events()->arefCount(), oldPart->sn(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount(), newPart->sn());
-
- replaceClone(oldPart, newPart);
-
- if(doCtrls)
- addPortCtrlEvents(newPart, doClones);
-
- //printf("Song::cmdChangePart after repl/unchClone oldPart:%p events:%p refs:%d Arefs:%d sn:%d newPart:%p events:%p refs:%d Arefs:%d sn:%d\n", oldPart, oldPart->events(), oldPart->events()->refCount(), oldPart->events()->arefCount(), oldPart->sn(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount(), newPart->sn());
-
- updateFlags = SC_PART_MODIFIED;
- }
-
-//---------------------------------------------------------
-// panic
-//---------------------------------------------------------
-
-void Song::panic()
- {
- audio->msgPanic();
- }
-
-//---------------------------------------------------------
-// clear
-// signal - emit signals for changes if true
-// called from constructor as clear(false) and
-// from MusE::clearSong() as clear(false)
-//---------------------------------------------------------
-
-void Song::clear(bool signal)
- {
- if(debugMsg)
- printf("Song::clear\n");
-
- bounceTrack = 0;
-
- _tracks.clear();
- _midis.clearDelete();
- _waves.clearDelete();
- _inputs.clearDelete(); // audio input ports
- _outputs.clearDelete(); // audio output ports
- _groups.clearDelete(); // mixer groups
- _auxs.clearDelete(); // aux sends
-
- // p3.3.45 Clear all midi port devices.
- for(int i = 0; i < MIDI_PORTS; ++i)
- {
- // p3.3.50 Since midi ports are not deleted, clear all midi port in/out routes. They point to non-existant tracks now.
- midiPorts[i].inRoutes()->clear();
- midiPorts[i].outRoutes()->clear();
-
- // p3.3.50 Reset this.
- midiPorts[i].setFoundInSongFile(false);
-
- // This will also close the device.
- midiPorts[i].setMidiDevice(0);
- }
-
- _synthIs.clearDelete();
-
- // p3.3.45 Make sure to delete Jack midi devices, and remove all ALSA midi device routes...
- // Otherwise really nasty things happen when loading another song when one is already loaded.
- // The loop is a safe way to delete while iterating.
- bool loop;
- do
- {
- loop = false;
- for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
- {
- //if((*imd)->deviceType() == MidiDevice::JACK_MIDI)
- if(dynamic_cast< MidiJackDevice* >(*imd))
- {
- // Remove the device from the list.
- midiDevices.erase(imd);
- // Since Jack midi devices are created dynamically, we must delete them.
- // The destructor unregisters the device from Jack, which also disconnects all device-to-jack routes.
- // This will also delete all midi-track-to-device routes, they point to non-existant midi tracks
- // which were all deleted above
- delete (*imd);
- loop = true;
- break;
- }
- else
- //if((*imd)->deviceType() == MidiDevice::ALSA_MIDI)
- if(dynamic_cast< MidiAlsaDevice* >(*imd))
- {
- // With alsa devices, we must not delete them (they're always in the list). But we must
- // clear all routes. They point to non-existant midi tracks, which were all deleted above.
- (*imd)->inRoutes()->clear();
- (*imd)->outRoutes()->clear();
- }
- }
- }
- while (loop);
-
- tempomap.clear();
- AL::sigmap.clear();
- undoList->clearDelete();
- redoList->clear();
- _markerList->clear();
- pos[0].setTick(0);
- pos[1].setTick(0);
- pos[2].setTick(0);
- _vcpos.setTick(0);
-
- Track::clearSoloRefCounts();
- clearMidiTransforms();
- clearMidiInputTransforms();
-
- // Clear all midi port controller values.
- for(int i = 0; i < MIDI_PORTS; ++i)
- // Don't remove the controllers, just the values.
- midiPorts[i].controller()->clearDelete(false);
-
- _masterFlag = true;
- loopFlag = false;
- loopFlag = false;
- punchinFlag = false;
- punchoutFlag = false;
- recordFlag = false;
- soloFlag = false;
- // seq
- _mtype = MT_UNKNOWN;
- _recMode = REC_OVERDUP;
- _cycleMode = CYCLE_NORMAL;
- _click = false;
- _quantize = false;
- _len = 0; // song len in ticks
- _follow = JUMP;
- // _tempo = 500000; // default tempo 120
- dirty = false;
- initDrumMap();
- if (signal) {
- emit loopChanged(false);
- recordChanged(false);
- }
- }
-
-//---------------------------------------------------------
-// cleanupForQuit
-// called from Muse::closeEvent
-//---------------------------------------------------------
-
-void Song::cleanupForQuit()
-{
- bounceTrack = 0;
-
- if(debugMsg)
- printf("MusE: Song::cleanupForQuit...\n");
-
- _tracks.clear();
-
- if(debugMsg)
- printf("deleting _midis\n");
- _midis.clearDelete();
-
- if(debugMsg)
- printf("deleting _waves\n");
- _waves.clearDelete();
-
- if(debugMsg)
- printf("deleting _inputs\n");
- _inputs.clearDelete(); // audio input ports
-
- if(debugMsg)
- printf("deleting _outputs\n");
- _outputs.clearDelete(); // audio output ports
-
- if(debugMsg)
- printf("deleting _groups\n");
- _groups.clearDelete(); // mixer groups
-
- if(debugMsg)
- printf("deleting _auxs\n");
- _auxs.clearDelete(); // aux sends
-
- if(debugMsg)
- printf("deleting _synthIs\n");
- _synthIs.clearDelete(); // each ~SynthI() -> deactivate3() -> ~SynthIF()
-
- tempomap.clear();
- AL::sigmap.clear();
-
- if(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.
-
- _markerList->clear();
-
- _tviews.clear();
-
- if(debugMsg)
- printf("deleting transforms\n");
- clearMidiTransforms(); // Deletes stuff.
- clearMidiInputTransforms(); // Deletes stuff.
-
- if(debugMsg)
- printf("deleting midiport controllers\n");
- // Clear all midi port controllers and values.
- for(int i = 0; i < MIDI_PORTS; ++i)
- // Remove the controllers and the values.
- midiPorts[i].controller()->clearDelete(true);
-
- // Can't do this here. Jack isn't running. Fixed. Test OK so far.
- #if 1
- if(debugMsg)
- printf("deleting midi devices except synths\n");
- for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
- {
- // Since Syntis are midi devices, there's no need to delete them below.
- if((*imd)->isSynti())
- continue;
- delete (*imd);
- }
- midiDevices.clear(); // midi devices
- #endif
-
- if(debugMsg)
- printf("deleting global available synths\n");
- // Delete all synths.
- std::vector<Synth*>::iterator is;
- for(is = synthis.begin(); is != synthis.end(); ++is)
- {
- Synth* s = *is;
-
- if(s)
- delete s;
- }
- synthis.clear();
-
- if(debugMsg)
- printf("deleting midi instruments\n");
- for(iMidiInstrument imi = midiInstruments.begin(); imi != midiInstruments.end(); ++imi)
- {
- // Since Syntis are midi instruments, there's no need to delete them below.
- // Tricky, must cast as SynthI*.
- SynthI* s = dynamic_cast <SynthI*> (*imi);
- if(s)
- continue;
- delete (*imi);
- }
- midiInstruments.clear(); // midi devices
-
- // Nothing required for ladspa plugin list, and rack instances of them
- // are handled by ~AudioTrack.
-
- if(debugMsg)
- printf("...finished cleaning up.\n");
-}
-
-//---------------------------------------------------------
-// seqSignal
-// sequencer message to GUI
-// execution environment: gui thread
-//---------------------------------------------------------
-
-void Song::seqSignal(int fd)
- {
- char buffer[16];
-
- int n = ::read(fd, buffer, 16);
- if (n < 0) {
- printf("Song: seqSignal(): READ PIPE failed: %s\n",
- strerror(errno));
- return;
- }
- for (int i = 0; i < n; ++i) {
-// printf("seqSignal to gui:<%c>\n", buffer[i]);
- switch(buffer[i]) {
- case '0': // STOP
- stopRolling();
- break;
- case '1': // PLAY
- setStopPlay(true);
- break;
- case '2': // record
- setRecord(true);
- break;
- case '3': // START_PLAY + jack STOP
- abortRolling();
- break;
- case 'P': // alsa ports changed
- rescanAlsaPorts();
- break;
- case 'G':
- clearRecAutomation(true);
- setPos(0, audio->tickPos(), true, false, true);
- break;
- case 'S': // shutdown audio
- muse->seqStop();
-
- {
- // give the user a sensible explanation
- int btn = QMessageBox::critical( muse, tr("Jack shutdown!"),
- tr("Jack has detected a performance problem which has lead to\n"
- "MusE being disconnected.\n"
- "This could happen due to a number of reasons:\n"
- "- a performance issue with your particular setup.\n"
- "- a bug in MusE (or possibly in another connected software).\n"
- "- a random hiccup which might never occur again.\n"
- "- jack was voluntary stopped by you or someone else\n"
- "- jack crashed\n"
- "If there is a persisting problem you are much welcome to discuss it\n"
- "on the MusE mailinglist.\n"
- "(there is information about joining the mailinglist on the MusE\n"
- " homepage which is available through the help menu)\n"
- "\n"
- "To proceed check the status of Jack and try to restart it and then .\n"
- "click on the Restart button."), "restart", "cancel");
- if (btn == 0) {
- printf("restarting!\n");
- muse->seqRestart();
- }
- }
-
- break;
- case 'f': // start freewheel
- if(debugMsg)
- printf("Song: seqSignal: case f: setFreewheel start\n");
-
- // Enabled by Tim. p3.3.6
- if(config.freewheelMode)
- audioDevice->setFreewheel(true);
-
- break;
-
- case 'F': // stop freewheel
- if(debugMsg)
- printf("Song: seqSignal: case F: setFreewheel stop\n");
-
- // Enabled by Tim. p3.3.6
- if(config.freewheelMode)
- audioDevice->setFreewheel(false);
-
- audio->msgPlay(false);
-#if 0
- if (record())
- audio->recordStop();
- setStopPlay(false);
-#endif
- break;
-
- case 'C': // Graph changed
- if (audioDevice)
- audioDevice->graphChanged();
- break;
-
- // p3.3.37
- case 'R': // Registration changed
- if (audioDevice)
- audioDevice->registrationChanged();
- break;
-
- default:
- printf("unknown Seq Signal <%c>\n", buffer[i]);
- break;
- }
- }
- }
-
-//---------------------------------------------------------
-// recordEvent
-//---------------------------------------------------------
-
-void Song::recordEvent(MidiTrack* mt, Event& event)
- {
- //---------------------------------------------------
- // if tick points into a part,
- // record to that part
- // else
- // create new part
- //---------------------------------------------------
-
- unsigned tick = event.tick();
- PartList* pl = mt->parts();
- MidiPart* part = 0;
- iPart ip;
- for (ip = pl->begin(); ip != pl->end(); ++ip) {
- part = (MidiPart*)(ip->second);
- unsigned partStart = part->tick();
- unsigned partEnd = partStart + part->lenTick();
- if (tick >= partStart && tick < partEnd)
- break;
- }
- updateFlags |= SC_EVENT_INSERTED;
- if (ip == pl->end()) {
- // create new part
- part = new MidiPart(mt);
- int startTick = roundDownBar(tick);
- //int endTick = roundUpBar(tick);
- int endTick = roundUpBar(tick + 1);
- part->setTick(startTick);
- part->setLenTick(endTick - startTick);
- part->setName(mt->name());
- event.move(-startTick);
- part->events()->add(event);
- audio->msgAddPart(part);
- return;
- }
- part = (MidiPart*)(ip->second);
- tick -= part->tick();
- event.setTick(tick);
-
- Event ev;
- if(event.type() == Controller)
- {
- EventRange range = part->events()->equal_range(tick);
- for(iEvent i = range.first; i != range.second; ++i)
- {
- ev = i->second;
- // At the moment, Song::recordEvent() is only called by the 'Rec' buttons in the
- // midi track info panel. So only controller types are fed to it. If other event types
- // are to be passed, we will have to expand on this to check if equal. Instead, maybe add an isEqual() to Event class.
- //if((ev.type() == Controller && event.type() == Controller || ev.type() == Controller && event.type() == Controller)
- // && ev.dataA() == event.dataA() && ev.dataB() == event.dataB())
- if(ev.type() == Controller && ev.dataA() == event.dataA())
- {
- // Don't bother if already set.
- if(ev.dataB() == event.dataB())
- return;
- // Indicate do undo, and do port controller values and clone parts.
- audio->msgChangeEvent(ev, event, part, true, true, true);
- return;
- }
- }
- }
-
- // Indicate do undo, and do port controller values and clone parts.
- //audio->msgAddEvent(event, part);
- audio->msgAddEvent(event, part, true, true, true);
- }
-
-//---------------------------------------------------------
-// execAutomationCtlPopup
-//---------------------------------------------------------
-
-int Song::execAutomationCtlPopup(AudioTrack* track, const QPoint& menupos, int acid)
-{
- //enum { HEADER, SEP1, PREV_EVENT, NEXT_EVENT, SEP2, ADD_EVENT, CLEAR_EVENT, CLEAR_RANGE, CLEAR_ALL_EVENTS };
- enum { HEADER, PREV_EVENT, NEXT_EVENT, SEP2, ADD_EVENT, CLEAR_EVENT, CLEAR_RANGE, CLEAR_ALL_EVENTS };
- QMenu* menu = new QMenu;
-
- int count = 0;
- bool isEvent = false, canSeekPrev = false, canSeekNext = false, canEraseRange = false;
- bool canAdd = false;
- double ctlval = 0.0;
- if(track)
- {
- ciCtrlList icl = track->controller()->find(acid);
- if(icl != track->controller()->end())
- {
- CtrlList *cl = icl->second;
- canAdd = true;
- ctlval = cl->curVal();
- count = cl->size();
- if(count)
- {
- int frame = pos[0].frame();
-
- iCtrl s = cl->lower_bound(frame);
- iCtrl e = cl->upper_bound(frame);
-
- isEvent = (s != cl->end() && s->second.frame == frame);
-
- canSeekPrev = s != cl->begin();
- canSeekNext = e != cl->end();
-
- s = cl->lower_bound(pos[1].frame());
-
- canEraseRange = s != cl->end()
- && (int)pos[2].frame() > s->second.frame;
- }
- }
- }
-
- //menu->insertItem(tr("Automation:"), HEADER, HEADER);
- //menu->setItemEnabled(HEADER, false);
- //MenuTitleItem* title = new MenuTitleItem(tr("Automation:")); ddskrjo
- //menu->insertItem(title, HEADER, HEADER); ddskrjo
- menu->addAction(new MenuTitleItem(tr("Automation:"), menu));
-
- //menu->insertSeparator(SEP1);
-
- QAction* prevEvent = menu->addAction(tr("previous event"));
- prevEvent->setData(PREV_EVENT);
- prevEvent->setEnabled(canSeekPrev);
-
- QAction* nextEvent = menu->addAction(tr("next event"));
- nextEvent->setData(NEXT_EVENT);
- nextEvent->setEnabled(canSeekNext);
-
- //menu->insertSeparator(SEP2);
- menu->addSeparator();
-
- QAction* addEvent = new QAction(menu);
- menu->addAction(addEvent);
- if(isEvent)
- addEvent->setText(tr("set event"));
- else
- addEvent->setText(tr("add event"));
- addEvent->setData(ADD_EVENT);
- addEvent->setEnabled(canAdd);
-
- QAction* eraseEventAction = menu->addAction(tr("erase event"));
- eraseEventAction->setData(CLEAR_EVENT);
- eraseEventAction->setEnabled(isEvent);
-
- QAction* eraseRangeAction = menu->addAction(tr("erase range"));
- eraseRangeAction->setData(CLEAR_RANGE);
- eraseRangeAction->setEnabled(canEraseRange);
-
- QAction* clearAction = menu->addAction(tr("clear automation"));
- clearAction->setData(CLEAR_ALL_EVENTS);
- clearAction->setEnabled((bool)count);
-
- QAction* act = menu->exec(menupos);
- //delete menu;
- if (!act || !track)
- {
- delete menu;
- return -1;
- }
-
- //if(!track)
- // return -1;
-
- int sel = act->data().toInt();
- delete menu;
-
- switch(sel)
- {
- case ADD_EVENT:
- audio->msgAddACEvent(track, acid, pos[0].frame(), ctlval);
- break;
- case CLEAR_EVENT:
- audio->msgEraseACEvent(track, acid, pos[0].frame());
- break;
-
- case CLEAR_RANGE:
- audio->msgEraseRangeACEvents(track, acid, pos[1].frame(), pos[2].frame());
- break;
-
- case CLEAR_ALL_EVENTS:
- if(QMessageBox::question(muse, QString("Muse"),
- tr("Clear all controller events?"), tr("&Ok"), tr("&Cancel"),
- QString::null, 0, 1 ) == 0)
- audio->msgClearControllerEvents(track, acid);
- break;
-
- case PREV_EVENT:
- audio->msgSeekPrevACEvent(track, acid);
- break;
-
- case NEXT_EVENT:
- audio->msgSeekNextACEvent(track, acid);
- break;
-
- default:
- return -1;
- break;
- }
-
- return sel;
-}
-
-//---------------------------------------------------------
-// execMidiAutomationCtlPopup
-//---------------------------------------------------------
-
-int Song::execMidiAutomationCtlPopup(MidiTrack* track, MidiPart* part, const QPoint& menupos, int ctlnum)
-{
- if(!track && !part)
- return -1;
-
- //enum { HEADER, SEP1, PREV_EVENT, NEXT_EVENT, SEP2, ADD_EVENT, CLEAR_EVENT, CLEAR_RANGE, CLEAR_ALL_EVENTS };
- enum { HEADER, ADD_EVENT, CLEAR_EVENT };
- QMenu* menu = new QMenu;
-
- //int count = 0;
- bool isEvent = false;
- //bool canSeekPrev = false, canSeekNext = false, canEraseRange = false;
- //bool canAdd = false;
- //double ctlval = 0.0;
-
- MidiTrack* mt;
- if(track)
- mt = track;
- else
- mt = (MidiTrack*)part->track();
- int portno = mt->outPort();
- int channel = mt->outChannel();
- MidiPort* mp = &midiPorts[portno];
-
- int dctl = ctlnum;
- // Is it a drum controller, according to the track port's instrument?
- MidiController *mc = mp->drumController(ctlnum);
- if(mc)
- {
- // Change the controller event's index into the drum map to an instrument note.
- int note = ctlnum & 0x7f;
- dctl &= ~0xff;
- channel = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- dctl |= drumMap[note].anote;
- }
-
- //printf("Song::execMidiAutomationCtlPopup ctlnum:%d dctl:%d anote:%d\n", ctlnum, dctl, drumMap[ctlnum & 0x7f].anote);
-
- unsigned tick = cpos();
-
- if(!part)
- {
- PartList* pl = mt->parts();
- iPart ip;
- for(ip = pl->begin(); ip != pl->end(); ++ip)
- {
- MidiPart* tpart = (MidiPart*)(ip->second);
- unsigned partStart = tpart->tick();
- unsigned partEnd = partStart + tpart->lenTick();
- if(tick >= partStart && tick < partEnd)
- {
- // Prefer a selected part, otherwise keep looking...
- if(tpart->selected())
- {
- part = tpart;
- break;
- }
- else
- // Remember the first part found...
- if(!part)
- part = tpart;
- }
- }
- }
-
- Event ev;
- if(part)
- {
- unsigned partStart = part->tick();
- unsigned partEnd = partStart + part->lenTick();
- if(tick >= partStart && tick < partEnd)
- {
- EventRange range = part->events()->equal_range(tick - partStart);
- for(iEvent i = range.first; i != range.second; ++i)
- {
- ev = i->second;
- if(ev.type() == Controller)
- {
- //printf("Song::execMidiAutomationCtlPopup ev.dataA:%d\n", ev.dataA());
-
- //if(ev.dataA() == dctl)
- if(ev.dataA() == ctlnum)
- {
- isEvent = true;
- break;
- }
- }
- }
- }
- }
-
-
- //menu->insertItem(tr("Automation:"), HEADER, HEADER);
- //menu->setItemEnabled(HEADER, false);
- //MenuTitleItem* title = new MenuTitleItem(tr("Automation:")); ddskrjo
- ///menu->insertItem(title, HEADER, HEADER); ddskrjo
-
- //menu->insertSeparator(SEP1);
-
-// menu->insertItem(tr("previous event"), PREV_EVENT, PREV_EVENT);
-// menu->setItemEnabled(PREV_EVENT, canSeekPrev);
-
-// menu->insertItem(tr("next event"), NEXT_EVENT, NEXT_EVENT);
-// menu->setItemEnabled(NEXT_EVENT, canSeekNext);
-
-// menu->insertSeparator(SEP2);
-
- QAction* addEvent = new QAction(menu);
- menu->addAction(addEvent);
- if(isEvent)
- addEvent->setText(tr("set event"));
- else
- addEvent->setText(tr("add event"));
- addEvent->setData(ADD_EVENT);
- //addEvent->setEnabled(canAdd);
- addEvent->setEnabled(true);
-
- QAction* eraseEventAction = menu->addAction(tr("erase event"));
- eraseEventAction->setData(CLEAR_EVENT);
- eraseEventAction->setEnabled(isEvent);
-
-// menu->insertItem(tr("erase range"), CLEAR_RANGE, CLEAR_RANGE);
-// menu->setItemEnabled(CLEAR_RANGE, canEraseRange);
-
-// menu->insertItem(tr("clear automation"), CLEAR_ALL_EVENTS, CLEAR_ALL_EVENTS);
-// menu->setItemEnabled(CLEAR_ALL_EVENTS, (bool)count);
-
-
- QAction* act = menu->exec(menupos);
- //delete menu;
- if (!act)
- {
- delete menu;
- return -1;
- }
-
- //if(!part)
- // return -1;
-
- int sel = act->data().toInt();
- delete menu;
-
- switch(sel)
- {
- case ADD_EVENT:
- {
- //int val = mp->hwCtrlState(channel, ctlnum);
- int val = mp->hwCtrlState(channel, dctl);
- if(val == CTRL_VAL_UNKNOWN)
- return -1;
- Event e(Controller);
- //e.setA(dctl);
- e.setA(ctlnum);
- e.setB(val);
- // Do we replace an old event?
- if(isEvent)
- {
- // Don't bother if already set.
- if(ev.dataB() == val)
- return -1;
-
- e.setTick(tick - part->tick());
- // Indicate do undo, and do port controller values and clone parts.
- audio->msgChangeEvent(ev, e, part, true, true, true);
- }
- else
- {
- // Store a new event...
- if(part)
- {
- e.setTick(tick - part->tick());
- // Indicate do undo, and do port controller values and clone parts.
- audio->msgAddEvent(e, part, true, true, true);
- }
- else
- {
- // Create a new part...
- part = new MidiPart(mt);
- int startTick = roundDownBar(tick);
- int endTick = roundUpBar(tick + 1);
- part->setTick(startTick);
- part->setLenTick(endTick - startTick);
- part->setName(mt->name());
- e.setTick(tick - startTick);
- part->events()->add(e);
- // Allow undo.
- audio->msgAddPart(part);
- }
- }
- }
- break;
- case CLEAR_EVENT:
- // Indicate do undo, and do port controller values and clone parts.
- audio->msgDeleteEvent(ev, part, true, true, true);
- break;
-
- //case CLEAR_RANGE:
- //audio->msgEraseRangeACEvents(track, acid, pos[1].frame(), pos[2].frame());
- //break;
-
- //case CLEAR_ALL_EVENTS:
- //if(QMessageBox::question(muse, QString("Muse"),
- // tr("Clear all controller events?"), tr("&Ok"), tr("&Cancel"),
- // QString::null, 0, 1 ) == 0)
- //audio->msgClearControllerEvents(track, acid);
- //break;
-
- //case PREV_EVENT:
- //audio->msgSeekPrevACEvent(track, acid);
- //break;
-
- //case NEXT_EVENT:
- //audio->msgSeekNextACEvent(track, acid);
- //break;
-
- default:
- return -1;
- break;
- }
-
- return sel;
-}
-
-//---------------------------------------------------------
-// updateSoloStates
-// This will properly set all soloing variables (including other tracks) based entirely
-// on the current values of all the tracks' _solo members.
-//---------------------------------------------------------
-
-void Song::updateSoloStates()
-{
- Track::clearSoloRefCounts();
- for(ciTrack i = _tracks.begin(); i != _tracks.end(); ++i)
- (*i)->setInternalSolo(0);
- for(ciTrack i = _tracks.begin(); i != _tracks.end(); ++i)
- (*i)->updateSoloStates(true);
-}
-
-//---------------------------------------------------------
-// clearRecAutomation
-//---------------------------------------------------------
-
-void Song::clearRecAutomation(bool clearList)
-{
- // Clear all pan/vol pressed and touched flags, and all rec event lists, if needed.
- for (iTrack it = tracks()->begin(); it != tracks()->end(); ++it)
- ((Track*)(*it))->clearRecAutomation(clearList);
-}
-
-//---------------------------------------------------------
-// processAutomationEvents
-//---------------------------------------------------------
-
-void Song::processAutomationEvents()
-{
- // Just clear all pressed and touched flags, not rec event lists.
- clearRecAutomation(false);
- if (!automation)
- return;
- for(iTrack i = _tracks.begin(); i != _tracks.end(); ++i)
- {
- if(!(*i)->isMidiTrack())
- // Process (and clear) rec events.
- ((AudioTrack*)(*i))->processAutomationEvents();
- }
-}
-
-//---------------------------------------------------------
-// abortRolling
-//---------------------------------------------------------
-
-void Song::abortRolling()
-{
- if (record())
- audio->recordStop();
- setStopPlay(false);
-}
-
-//---------------------------------------------------------
-// stopRolling
-//---------------------------------------------------------
-
-void Song::stopRolling()
- {
- abortRolling();
- processAutomationEvents();
- }
-
-//---------------------------------------------------------
-// connectJackRoutes
-//---------------------------------------------------------
-
-void Song::connectJackRoutes(AudioTrack* track, bool disconnect)
-{
- switch(track->type())
- {
- case Track::AUDIO_OUTPUT:
- {
- AudioOutput* ao = (AudioOutput*)track;
- // This will re-register the track's jack ports.
- if(!disconnect)
- ao->setName(ao->name());
- // Now reconnect the output routes.
- if(checkAudioDevice() && audio->isRunning())
- {
- for(int ch = 0; ch < ao->channels(); ++ch)
- {
- RouteList* ir = ao->outRoutes();
- for (iRoute ii = ir->begin(); ii != ir->end(); ++ii)
- {
- Route r = *ii;
- if ((r.type == Route::JACK_ROUTE) && (r.channel == ch))
- {
- if(disconnect)
- audioDevice->disconnect(ao->jackPort(ch), r.jackPort);
- else
- audioDevice->connect(ao->jackPort(ch), r.jackPort);
- break;
- }
- }
- if(disconnect)
- {
- audioDevice->unregisterPort(ao->jackPort(ch));
- ao->setJackPort(ch, 0);
- }
- }
- }
- }
- break;
- case Track::AUDIO_INPUT:
- {
- AudioInput* ai = (AudioInput*)track;
- // This will re-register the track's jack ports.
- if(!disconnect)
- ai->setName(ai->name());
- // Now reconnect the input routes.
- if(checkAudioDevice() && audio->isRunning())
- {
- for(int ch = 0; ch < ai->channels(); ++ch)
- {
- RouteList* ir = ai->inRoutes();
- for (iRoute ii = ir->begin(); ii != ir->end(); ++ii)
- {
- Route r = *ii;
- if ((r.type == Route::JACK_ROUTE) && (r.channel == ch))
- {
- if(disconnect)
- audioDevice->disconnect(r.jackPort, ai->jackPort(ch));
- else
- audioDevice->connect(r.jackPort, ai->jackPort(ch));
- break;
- }
- }
- if(disconnect)
- {
- audioDevice->unregisterPort(ai->jackPort(ch));
- ai->setJackPort(ch, 0);
- }
- }
- }
- }
- break;
- default:
- break;
- }
-}
-
-/*
-//---------------------------------------------------------
-// chooseMidiRoutes
-//---------------------------------------------------------
-
-void Song::chooseMidiRoutes(QButton* parent, MidiTrack* track, bool dst)
-{
- if(!track)
- return;
-
- //if(!track->isMidiTrack())
- // return;
-
- QPoint ppt = QCursor::pos();
- //QPoint ppt = parent->rect().bottomLeft();
-
- //if(dst)
- //{
- // TODO
-
- //}
- //else
- //{
- RouteList* rl = dst ? track->outRoutes() : track->inRoutes();
- //Route dst(track, -1);
-
- QPopupMenu* pup = new QPopupMenu(parent);
- pup->setCheckable(true);
-
- int gid = 0;
- int n;
-
- // FIXME:
- // Routes can't be re-read until the message sent from msgAddRoute1()
- // has had time to be sent and actually affected the routes.
- ///_redisplay:
-
- pup->clear();
- gid = 0;
-
- //MidiInPortList* tl = song->midiInPorts();
- //for(iMidiInPort i = tl->begin();i != tl->end(); ++i)
- for(int i = 0; i < MIDI_PORTS; ++i)
- {
- //MidiInPort* track = *i;
- // NOTE: Could possibly list all devices, bypassing ports, but no, let's stick wth ports.
- MidiPort* mp = &midiPorts[i];
- MidiDevice* md = mp->device();
- if(!md)
- continue;
-
- if(!(md->rwFlags() & (dst ? 1 : 2)))
- continue;
-
- //printf("MidiStrip::iRoutePressed adding submenu portnum:%d\n", i);
-
- //QMenu* m = menu->addMenu(track->name());
- QPopupMenu* subp = new QPopupMenu(parent);
-
- for(int ch = 0; ch < MIDI_CHANNELS; ++ch)
- {
- //QAction* a = m->addAction(QString("Channel %1").arg(ch+1));
- //subp->insertItem(QT_TRANSLATE_NOOP("@default", QString("Channel %1").arg(ch+1)), i * MIDI_CHANNELS + ch);
- gid = i * MIDI_CHANNELS + ch;
-
- //printf("MidiStrip::iRoutePressed inserting gid:%d\n", gid);
-
- subp->insertItem(QString("Channel %1").arg(ch+1), gid);
- //a->setCheckable(true);
- //Route src(track, ch, RouteNode::TRACK);
- //Route src(md, ch);
- //Route r = Route(src, dst);
- //a->setData(QVariant::fromValue(r));
- //a->setChecked(rl->indexOf(r) != -1);
- Route srcRoute(md, ch);
- for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)
- {
- //if(*ir == dst)
- if(*ir == srcRoute)
- {
- subp->setItemChecked(gid, true);
- break;
- }
- }
- }
- pup->insertItem(QT_TRANSLATE_NOOP("@default", md->name()), subp);
- }
-
-// QPopupMenu* pup = new QPopupMenu(iR);
-// pup->setCheckable(true);
- //MidiTrack* t = (MidiTrack*)track;
-// RouteList* irl = track->inRoutes();
-
-// MidiTrack* t = (MidiTrack*)track;
-// int gid = 0;
-// for (int i = 0; i < channel; ++i)
-// {
-// char buffer[128];
-// snprintf(buffer, 128, "%s %d", tr("Channel").toLatin1().constData(), i+1);
-// MenuTitleItem* titel = new MenuTitleItem(QString(buffer));
-// pup->insertItem(titel);
-
-// if (!checkAudioDevice()) return;
-// std::list<QString> ol = audioDevice->outputPorts();
-// for (std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip) {
-// int id = pup->insertItem(*ip, (gid * 16) + i);
-// Route dst(*ip, true, i);
-// ++gid;
-// for (iRoute ir = irl->begin(); ir != irl->end(); ++ir) {
-// if (*ir == dst) {
-// pup->setItemChecked(id, true);
-// break;
-// }
-// }
-// }
-// if (i+1 != channel)
-// pup->insertSeparator();
-// }
-
- if(pup->count() == 0)
- {
- delete pup;
- return;
- }
-
- //n = pup->exec(QCursor::pos());
- n = pup->exec(ppt);
- ///delete pup;
- if (n != -1)
- {
- int mdidx = n / MIDI_CHANNELS;
- int ch = n % MIDI_CHANNELS;
-
- //if(debugMsg)
- //printf("Song::chooseMidiRoutes mdidx:%d ch:%d\n", mdidx, ch);
-
- MidiPort* mp = &midiPorts[mdidx];
- MidiDevice* md = mp->device();
- if(!md)
- {
- delete pup;
- return;
- }
-
- //if(!(md->rwFlags() & 2))
- if(!(md->rwFlags() & (dst ? 1 : 2)))
- {
- delete pup;
- return;
- }
-
- //QString s(pup->text(n));
- //QT_TRANSLATE_NOOP("@default", md->name())
-
- //Route srcRoute(s, false, -1);
- Route aRoute(md, ch);
- //Route srcRoute(md, -1);
- //Route dstRoute(track, -1);
- Route bRoute(track, ch);
-
- //if (track->type() == Track::AUDIO_INPUT)
- // srcRoute.channel = dstRoute.channel = n & 0xf;
- iRoute iir = rl->begin();
- for (; iir != rl->end(); ++iir)
- {
- //if(*iir == (dst ? bRoute : aRoute))
- if(*iir == aRoute)
- break;
- }
- if (iir != rl->end())
- {
- // disconnect
- if(dst)
- {
- //printf("Song::chooseMidiRoutes removing route src track name: %s dst device name: %s\n", track->name().toLatin1().constData(), md->name().toLatin1().constData());
- audio->msgRemoveRoute(bRoute, aRoute);
- }
- else
- {
- //printf("Song::chooseMidiRoutes removing route src device name: %s dst track name: %s\n", md->name().toLatin1().constData(), track->name().toLatin1().constData());
- audio->msgRemoveRoute(aRoute, bRoute);
- }
- }
- else
- {
- // connect
- if(dst)
- {
- //printf("Song::chooseMidiRoutes adding route src track name: %s dst device name: %s\n", track->name().toLatin1().constData(), md->name().toLatin1().constData());
- audio->msgAddRoute(bRoute, aRoute);
- }
- else
- {
- //printf("Song::chooseMidiRoutes adding route src device name: %s dst track name: %s\n", md->name().toLatin1().constData(), track->name().toLatin1().constData());
- audio->msgAddRoute(aRoute, bRoute);
- }
- }
-
- //printf("Song::chooseMidiRoutes calling msgUpdateSoloStates\n");
- audio->msgUpdateSoloStates();
- //printf("Song::chooseMidiRoutes calling song->update\n");
- song->update(SC_ROUTE);
-
- // p3.3.46
- ///goto _redisplay;
- }
- delete pup;
- parent->setDown(false); // pup->exec() catches mouse release event
- //printf("Song::chooseMidiRoutes end\n");
-
- //}
-}
-*/
-
-//---------------------------------------------------------
-// insertTrackView
-// add a new trackview for the arranger
-//---------------------------------------------------------
-
-void Song::insertTrackView(TrackView* tv, int idx)
-{
- iTrackView i = _tviews.index2iterator(idx);
- _tviews.insert(i, tv);
-}
-
-//---------------------------------------------------------
-// cmdRemoveTrackView
-//---------------------------------------------------------
-
-void Song::cmdRemoveTrackView(TrackView* tv)
-{
- int idx = _tviews.index(tv);
- //undoOp(UndoOp::DeleteTrackView, idx, tv);
- removeTrackView(tv);
- updateFlags |= SC_TRACKVIEW_REMOVED;
-}
-
-//---------------------------------------------------------
-// removeTrackView
-// add a new trackview for the arranger
-//---------------------------------------------------------
-
-void Song::removeTrackView(TrackView* tv)
-{
- _tviews.erase(tv);
-}
-
-//---------------------------------------------------------
-// addNewTrackView
-// add a new trackview for the arranger
-//---------------------------------------------------------
-
-TrackView* Song::addNewTrackView(int idx)
-{
- TrackView* tv = addTrackView((Track::TrackType)idx);
- return tv;
-}
-
-//---------------------------------------------------------/*{{{*/
-// addTrackView
-// called from GUI context
-//---------------------------------------------------------
-
-TrackView* Song::addTrackView(int t)
-{
- Track::TrackType type = (Track::TrackType) t;
- TrackView* tv = new TrackView();
- switch(type) {
- case Track::MIDI:
- tv->setType(Track::MIDI);
- break;
- case Track::DRUM:
- tv->setType(Track::MIDI);
- break;
- case Track::WAVE:
- tv->setType(Track::WAVE);
- break;
- case Track::AUDIO_OUTPUT:
- tv->setType(Track::AUDIO_OUTPUT);
- break;
- case Track::AUDIO_GROUP:
- tv->setType(Track::AUDIO_GROUP);
- break;
- case Track::AUDIO_AUX:
- tv->setType(Track::AUDIO_AUX);
- break;
- case Track::AUDIO_INPUT:
- tv->setType(Track::AUDIO_INPUT);
- break;
- case Track::AUDIO_SOFTSYNTH:
- printf("not implemented: Song::addTrackView(SOFTSYNTH)\n");
- break;
- default:
- printf("Song::addTrackView() illegal type %d\n", type);
- abort();
- }
- tv->setDefaultName();
- //msgInsertTrackView(tv, -1, true);
-
- return tv;
-}/*}}}*/
-
-//---------------------------------------------------------
-// findTrackView
-// find track view by name
-//---------------------------------------------------------
-
-TrackView* Song::findTrackView(const QString& name) const
-{
- for (ciTrackView i = _tviews.begin(); i != _tviews.end(); ++i)
- {
- if ((*i)->viewName() == name)
- return *i;
- }
- return 0;
-}
-
-
-//---------------------------------------------------------
-// insertTrack0
-//---------------------------------------------------------
-
-void Song::insertTrack0(Track* track, int idx)
- {
- insertTrack1(track, idx);
- insertTrack2(track, idx); // audio->msgInsertTrack(track, idx, false);
- insertTrack3(track, idx);
- }
-
-//---------------------------------------------------------
-// insertTrack1
-// non realtime part of insertTrack
-//---------------------------------------------------------
-
-void Song::insertTrack1(Track* track, int /*idx*/)
- {
- //printf("Song::insertTrack1 track:%lx\n", track);
-
- switch(track->type()) {
- case Track::AUDIO_SOFTSYNTH:
- {
- SynthI* s = (SynthI*)track;
- Synth* sy = s->synth();
- if (!s->isActivated()) {
- s->initInstance(sy, s->name());
- }
- }
- break;
- default:
- break;
- }
-
- //printf("Song::insertTrack1 end of function\n");
-
- }
-
-//---------------------------------------------------------
-// insertTrack2
-// realtime part
-//---------------------------------------------------------
-
-void Song::insertTrack2(Track* track, int idx)
-{
- //printf("Song::insertTrack2 track:%lx\n", track);
-
- int n;
- switch(track->type()) {
- case Track::MIDI:
- case Track::DRUM:
- _midis.push_back((MidiTrack*)track);
- // Added by T356.
- //((MidiTrack*)track)->addPortCtrlEvents();
- addPortCtrlEvents(((MidiTrack*)track));
-
- break;
- case Track::WAVE:
- _waves.push_back((WaveTrack*)track);
- break;
- case Track::AUDIO_OUTPUT:
- _outputs.push_back((AudioOutput*)track);
- // set default master & monitor if not defined
- if (audio->audioMaster() == 0)
- audio->setMaster((AudioOutput*)track);
- if (audio->audioMonitor() == 0)
- audio->setMonitor((AudioOutput*)track);
- break;
- case Track::AUDIO_GROUP:
- _groups.push_back((AudioGroup*)track);
- break;
- case Track::AUDIO_AUX:
- _auxs.push_back((AudioAux*)track);
- break;
- case Track::AUDIO_INPUT:
- _inputs.push_back((AudioInput*)track);
- break;
- case Track::AUDIO_SOFTSYNTH:
- {
- SynthI* s = (SynthI*)track;
- midiDevices.add(s);
- midiInstruments.push_back(s);
- _synthIs.push_back(s);
- }
- break;
- default:
- fprintf(stderr, "unknown track type %d\n", track->type());
- // abort();
- return;
- }
-
- //
- // initialize missing aux send
- //
- iTrack i = _tracks.index2iterator(idx);
- //printf("Song::insertTrack2 inserting into _tracks...\n");
-
- _tracks.insert(i, track);
- //printf("Song::insertTrack2 inserted\n");
-
- n = _auxs.size();
- for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) {
- if ((*i)->isMidiTrack())
- continue;
- WaveTrack* wt = (WaveTrack*)*i;
- if (wt->hasAuxSend()) {
- wt->addAuxSend(n);
- }
- }
-
- /*
- //
- // add routes
- //
-
- if (track->isMidiTrack())
- return;
- AudioTrack* at = (AudioTrack*)track;
- Route src(at, -1);
- if (at->type() == Track::AUDIO_OUTPUT) {
- const RouteList* rl = at->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->outRoutes()->push_back(src);
- }
- else if (at->type() == Track::AUDIO_INPUT) {
- const RouteList* rl = at->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->inRoutes()->push_back(src);
- }
- else {
- const RouteList* rl = at->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->outRoutes()->push_back(src);
- rl = at->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->inRoutes()->push_back(src);
- }
- */
-
- // p3.3.38
-
- //
- // add routes
- //
-
- if (track->type() == Track::AUDIO_OUTPUT)
- {
- const RouteList* rl = track->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->outRoutes()->push_back(*r);
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->outRoutes()->push_back(src);
- }
- }
- else if (track->type() == Track::AUDIO_INPUT)
- {
- const RouteList* rl = track->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->inRoutes()->push_back(*r);
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->inRoutes()->push_back(src);
- }
- }
- else if (track->isMidiTrack()) // p3.3.50
- {
- const RouteList* rl = track->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //printf("Song::insertTrack2 %s in route port:%d\n", track->name().toLatin1().constData(), r->midiPort); // p3.3.50
- Route src(track, r->channel);
- midiPorts[r->midiPort].outRoutes()->push_back(src);
- }
- rl = track->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //printf("Song::insertTrack2 %s out route port:%d\n", track->name().toLatin1().constData(), r->midiPort); // p3.3.50
- Route src(track, r->channel);
- midiPorts[r->midiPort].inRoutes()->push_back(src);
- }
- }
- else
- {
- const RouteList* rl = track->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->outRoutes()->push_back(*r);
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->outRoutes()->push_back(src);
- }
- rl = track->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->inRoutes()->push_back(*r);
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->inRoutes()->push_back(src);
- }
- }
-
- //printf("Song::insertTrack2 end of function\n");
-
-}
-
-//---------------------------------------------------------
-// insertTrack3
-// non realtime part of insertTrack
-//---------------------------------------------------------
-
-void Song::insertTrack3(Track* /*track*/, int /*idx*/)//prevent compiler warning: unused parameter
-{
- //printf("Song::insertTrack3\n");
-
- /*
- switch(track->type()) {
- case Track::AUDIO_SOFTSYNTH:
- break;
- default:
- break;
- }
- */
-}
-
-//---------------------------------------------------------
-// removeTrack0
-//---------------------------------------------------------
-
-void Song::removeTrack0(Track* track)
- {
- removeTrack1(track);
- audio->msgRemoveTrack(track);
- removeTrack3(track);
- //delete track;
- update(SC_TRACK_REMOVED);
- }
-
-//---------------------------------------------------------
-// removeTrack1
-// non realtime part of removeTrack
-//---------------------------------------------------------
-
-void Song::removeTrack1(Track* track)
- {
- switch(track->type())
- {
- case Track::WAVE:
- case Track::AUDIO_OUTPUT:
- case Track::AUDIO_INPUT:
- case Track::AUDIO_GROUP:
- case Track::AUDIO_AUX:
- case Track::AUDIO_SOFTSYNTH:
- ((AudioTrack*)track)->deleteAllEfxGuis();
- break;
- default:
- break;
- }
-
- switch(track->type())
- {
- case Track::AUDIO_OUTPUT:
- case Track::AUDIO_INPUT:
- connectJackRoutes((AudioTrack*)track, true);
- break;
- case Track::AUDIO_SOFTSYNTH:
- {
- SynthI* si = (SynthI*)track;
- if(si->hasGui())
- si->showGui(false);
- }
- break;
- default:
- break;
- }
- }
-
-//---------------------------------------------------------
-// removeTrack
-// called from RT context
-//---------------------------------------------------------
-
-void Song::removeTrack2(Track* track)
-{
- //printf("Song::removeTrack2 track:%s\n", track->name().toLatin1().constData()); // p3.3.50
-
- switch(track->type()) {
- case Track::MIDI:
- case Track::DRUM:
- // Added by T356.
- //((MidiTrack*)track)->removePortCtrlEvents();
- removePortCtrlEvents(((MidiTrack*)track));
- unchainTrackParts(track, true);
-
- _midis.erase(track);
- break;
- case Track::WAVE:
- // Added by T356.
- unchainTrackParts(track, true);
-
- _waves.erase(track);
- break;
- case Track::AUDIO_OUTPUT:
- _outputs.erase(track);
- break;
- case Track::AUDIO_INPUT:
- _inputs.erase(track);
- break;
- case Track::AUDIO_GROUP:
- _groups.erase(track);
- break;
- case Track::AUDIO_AUX:
- _auxs.erase(track);
- break;
- case Track::AUDIO_SOFTSYNTH:
- {
- SynthI* s = (SynthI*) track;
- s->deactivate2();
- _synthIs.erase(track);
- }
- break;
- }
- _tracks.erase(track);
-
-
- /*
- if (track->isMidiTrack())
- return;
- //
- // remove routes
- //
-
- AudioTrack* at = (AudioTrack*)track;
- Route src(at, -1);
- if (at->type() == Track::AUDIO_OUTPUT) {
- const RouteList* rl = at->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->outRoutes()->removeRoute(src);
- }
- else if (at->type() == Track::AUDIO_INPUT) {
- const RouteList* rl = at->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->inRoutes()->removeRoute(src);
- }
- else {
- const RouteList* rl = at->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->outRoutes()->removeRoute(src);
- rl = at->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- r->track->inRoutes()->removeRoute(src);
- }
- */
-
- // p3.3.38
-
- //
- // remove routes
- //
-
- if (track->type() == Track::AUDIO_OUTPUT)
- {
- const RouteList* rl = track->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->outRoutes()->removeRoute(*r);
- //printf("Song::removeTrack2 %s audio out track:%s\n", track->name().toLatin1().constData(), r->track->name().toLatin1().constData()); // p3.3.50
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->outRoutes()->removeRoute(src);
- }
- }
- else if (track->type() == Track::AUDIO_INPUT)
- {
- const RouteList* rl = track->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->inRoutes()->removeRoute(*r);
- //printf("Song::removeTrack2 %s audio in track:%s\n", track->name().toLatin1().constData(), r->track->name().toLatin1().constData()); // p3.3.50
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->inRoutes()->removeRoute(src);
- }
- }
- else if (track->isMidiTrack()) // p3.3.50
- {
- const RouteList* rl = track->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //printf("Song::removeTrack2 %s in route port:%d\n", track->name().toLatin1().constData(), r->midiPort); // p3.3.50
- Route src(track, r->channel);
- midiPorts[r->midiPort].outRoutes()->removeRoute(src);
- }
- rl = track->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //printf("Song::removeTrack2 %s out route port:%d\n", track->name().toLatin1().constData(), r->midiPort); // p3.3.50
- Route src(track, r->channel);
- midiPorts[r->midiPort].inRoutes()->removeRoute(src);
- }
- }
- else
- {
- const RouteList* rl = track->inRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->outRoutes()->removeRoute(*r);
- //printf("Song::removeTrack2 %s in route track:%s\n", track->name().toLatin1().constData(), r->track->name().toLatin1().constData()); // p3.3.50
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->outRoutes()->removeRoute(src);
- }
- rl = track->outRoutes();
- for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- {
- //if(r->track == track)
- // r->track->inRoutes()->removeRoute(*r);
- //printf("Song::removeTrack2 %s out route track:%s\n", track->name().toLatin1().constData(), r->track->name().toLatin1().constData()); // p3.3.50
- // p3.3.50
- Route src(track, r->channel, r->channels);
- src.remoteChannel = r->remoteChannel;
- r->track->inRoutes()->removeRoute(src);
- }
- }
-
-}
-
-//---------------------------------------------------------
-// removeTrack3
-// non realtime part of removeTrack
-//---------------------------------------------------------
-
-void Song::removeTrack3(Track* /*track*/)//prevent of compiler warning: unused parameter
- {
- /*
- switch(track->type()) {
- case Track::AUDIO_SOFTSYNTH:
- {
- SynthI* s = (SynthI*) track;
- s->deactivate3();
- }
- break;
- default:
- break;
- }
- */
- }
-
-//---------------------------------------------------------
-// executeScript
-//---------------------------------------------------------
-void Song::executeScript(const char* scriptfile, PartList* parts, int quant, bool onlyIfSelected)
-{
- // a simple format for external processing
- // will be extended if there is a need
- //
- // Semantics:
- // PARTLEN <len in ticks>
- // BEATLEN <len in ticks>
- // QUANTLEN <len in ticks>
- // NOTE <tick> <nr> <len in ticks> <velocity>
- // CONTROLLER <tick> <a> <b> <c>
- //
- song->startUndo(); // undo this entire block
- for (iPart i = parts->begin(); i != parts->end(); i++) {
- //const char* tmp = tmpnam(NULL);
- char tmp[16] = "muse-tmp-XXXXXX";
- int fd = mkstemp(tmp);
- printf("script input filename=%s\n",tmp);
- //FILE *fp = fopen(tmp, "w");
- FILE *fp = fdopen(fd , "w");
- MidiPart *part = (MidiPart*)(i->second);
- int partStart = part->endTick()-part->lenTick();
- int z, n;
- AL::sigmap.timesig(0, z, n);
- fprintf(fp, "TIMESIG %d %d\n", z, n);
- fprintf(fp, "PART %d %d\n", partStart, part->lenTick());
- fprintf(fp, "BEATLEN %d\n", AL::sigmap.ticksBeat(0));
- fprintf(fp, "QUANTLEN %d\n", quant);
-
- //for (iCItem i = items.begin(); i != items.end(); ++i) {
- for (iEvent e = part->events()->begin(); e != part->events()->end(); e++) {
- Event ev = e->second;
-
- if (ev.isNote())
- {
- if (onlyIfSelected && ev.selected() == false)
- continue;
-
- fprintf(fp,"NOTE %d %d %d %d\n", ev.tick(), ev.dataA(), ev.lenTick(), ev.dataB());
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgDeleteEvent(ev, part, false, false, false);
- } else if (ev.type()==Controller) {
- fprintf(fp,"CONTROLLER %d %d %d %d\n", ev.tick(), ev.dataA(), ev.dataB(), ev.dataC());
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgDeleteEvent(ev, part, false, false, false);
- }
- }
- fclose(fp);
-
- // Call external program, let it manipulate the file
- int pid = fork();
- if (pid == 0) {
- if (execlp(scriptfile, scriptfile, tmp, NULL) == -1) {
- perror("Failed to launch script!");
- // Get out of here
-
- // cannot report error through gui, we are in another fork!
- //@!TODO: Handle unsuccessful attempts
- exit(99);
- }
- exit(0);
- }
- else if (pid == -1) {
- perror("fork failed");
- }
- else {
- int status;
- waitpid(pid, &status, 0);
- if (WEXITSTATUS(status) != 0 ) {
- QMessageBox::warning(muse, tr("MusE - external script failed"),
- tr("MusE was unable to launch the script\n")
- );
- endUndo(SC_EVENT_REMOVED);
- return;
- }
- else { // d0 the fun55or5!
- // TODO: Create a new part, update the entire editor from it, hehh....
-
- QFile file(tmp);
- if ( file.open( QIODevice::ReadOnly ) ) {
- QTextStream stream( &file );
- QString line;
- while ( !stream.atEnd() ) {
- line = stream.readLine(); // line of text excluding '\n'
- if (line.startsWith("NOTE"))
- {
- QStringList sl = line.split(" ");
-
- Event e(Note);
- int tick = sl[1].toInt();
- int pitch = sl[2].toInt();
- int len = sl[3].toInt();
- int velo = sl[4].toInt();
- printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len);
- e.setTick(tick);
- e.setPitch(pitch);
- e.setVelo(velo);
- e.setLenTick(len);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgAddEvent(e, part, false, false, false);
- }
- if (line.startsWith("CONTROLLER"))
- {
- QStringList sl = line.split(" ");
-
- Event e(Controller);
- int tick = sl[1].toInt();
- int a = sl[2].toInt();
- int b = sl[3].toInt();
- int c = sl[4].toInt();
- printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c);
- e.setA(a);
- e.setB(b);
- e.setB(c);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgAddEvent(e, part, false, false, false);
- }
- }
- file.close();
- }
- }
- }
- remove(tmp);
- }
-
- endUndo(SC_EVENT_REMOVED);
-}
-
-
-void Song::populateScriptMenu(QMenu* menuPlugins, QObject* receiver)
-{
- //
- // List scripts
- //
- QString distScripts = museGlobalShare + "/scripts";
-
- QString userScripts = configPath + "/scripts";
-
- QFileInfo distScriptsFi(distScripts);
- if (distScriptsFi.isDir()) {
- QDir dir = QDir(distScripts);
- dir.setFilter(QDir::Executable | QDir::Files);
- deliveredScriptNames = dir.entryList();
- }
- QFileInfo userScriptsFi(userScripts);
- if (userScriptsFi.isDir()) {
- QDir dir(userScripts);
- dir.setFilter(QDir::Executable | QDir::Files);
- userScriptNames = dir.entryList();
- }
-
- QSignalMapper* distSignalMapper = new QSignalMapper(this);
- QSignalMapper* userSignalMapper = new QSignalMapper(this);
-
- if (deliveredScriptNames.size() > 0 || userScriptNames.size() > 0) {
- //menuPlugins = new QPopupMenu(this);
- //menuBar()->insertItem(tr("&Plugins"), menuPlugins);
- int id = 0;
- if (deliveredScriptNames.size() > 0) {
- for (QStringList::Iterator it = deliveredScriptNames.begin(); it != deliveredScriptNames.end(); it++, id++) {
- //menuPlugins->insertItem(*it, this, SLOT(execDeliveredScript(int)), 0, id);
- //menuPlugins->insertItem(*it, this, slot_deliveredscripts, 0, id);
- QAction* act = menuPlugins->addAction(*it);
- connect(act, SIGNAL(triggered()), distSignalMapper, SLOT(map()));
- distSignalMapper->setMapping(act, id);
- }
- menuPlugins->addSeparator();
- }
- if (userScriptNames.size() > 0) {
- for (QStringList::Iterator it = userScriptNames.begin(); it != userScriptNames.end(); it++, id++) {
- //menuPlugins->insertItem(*it, this, slot_userscripts, 0, id);
- QAction* act = menuPlugins->addAction(*it);
- connect(act, SIGNAL(triggered()), userSignalMapper, SLOT(map()));
- userSignalMapper->setMapping(act, id);
- }
- menuPlugins->addSeparator();
- }
- connect(distSignalMapper, SIGNAL(mapped(int)), receiver, SLOT(execDeliveredScript(int)));
- connect(userSignalMapper, SIGNAL(mapped(int)), receiver, SLOT(execUserScript(int)));
- }
- return;
-}
-
-//---------------------------------------------------------
-// getScriptPath
-//---------------------------------------------------------
-QString Song::getScriptPath(int id, bool isdelivered)
-{
- if (isdelivered) {
- QString path = museGlobalShare + "/scripts/" + deliveredScriptNames[id];
- return path;
- }
-
- QString path = configPath + "/scripts/" + userScriptNames[id - deliveredScriptNames.size()];
- return path;
-}
-