summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Schweer <ws.seh.de>2006-10-25 21:19:08 +0000
committerWerner Schweer <ws.seh.de>2006-10-25 21:19:08 +0000
commit0ea27d42f28aae554bb0b7ec35a4bab961d7fd98 (patch)
tree767ce09c6aed898ea9794ae2a3076c814a3f3671
parent1fa1e5ede877626f6e29cfd42f4d9679723aa1ea (diff)
updates
-rw-r--r--muse/ChangeLog2
-rw-r--r--muse/TODO4
-rw-r--r--muse/muse/audio.cpp22
-rw-r--r--muse/muse/conf.cpp10
-rw-r--r--muse/muse/driver/jack.cpp6
-rw-r--r--muse/muse/driver/port.h8
-rw-r--r--muse/muse/gconfig.cpp2
-rw-r--r--muse/muse/gconfig.h2
-rw-r--r--muse/muse/importmidi.cpp84
-rw-r--r--muse/muse/midi.cpp4
-rw-r--r--muse/muse/midioutport.cpp228
-rw-r--r--muse/muse/midioutport.h12
-rw-r--r--muse/muse/midiseq.cpp226
-rw-r--r--muse/muse/midiseq.h24
-rw-r--r--muse/muse/muse.cpp7
-rw-r--r--muse/muse/muse.h2
-rw-r--r--muse/muse/preferences.cpp12
-rw-r--r--muse/muse/preferences.ui40
-rw-r--r--muse/muse/route.cpp5
-rw-r--r--muse/muse/sync.cpp13
20 files changed, 359 insertions, 354 deletions
diff --git a/muse/ChangeLog b/muse/ChangeLog
index 3056feb6..133527ea 100644
--- a/muse/ChangeLog
+++ b/muse/ChangeLog
@@ -1,3 +1,5 @@
+25.10 (ws)
+ - make default path for midi- and wave import configurable
23.10 (ws)
- simple jack midi output now works
20.10 (ws)
diff --git a/muse/TODO b/muse/TODO
index ef350f87..0fe4b9cb 100644
--- a/muse/TODO
+++ b/muse/TODO
@@ -4,10 +4,6 @@
----------------------------------------------------------------------------
BUGS
- - fix song len after importing midi
- - set song "dirty" after importing midi
- - update midi gm template
-
- updating the gui during midi recording is too slow;
a new, faster implementation is needed
diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp
index 53f72664..f8b5410b 100644
--- a/muse/muse/audio.cpp
+++ b/muse/muse/audio.cpp
@@ -38,8 +38,10 @@
#include "synth.h"
#include "midioutport.h"
#include "midiinport.h"
+#include "midichannel.h"
+#include "midictrl.h"
+#include "sync.h"
-extern double curTime();
extern bool initJackAudio();
Audio* audio;
@@ -579,11 +581,9 @@ void Audio::seek(const Pos& p)
if (state != LOOP2 && !freewheel())
audioPrefetch->msgSeek(_pos.frame());
- midiBusy = true;
- midiSeq->processSeek(); // handle stuck notes and set
- // controller for new position
- midiBusy = false;
-
+ MidiOutPortList* ol = song->midiOutPorts();
+ for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i)
+ (*i)->seek(_curTickPos, _pos.frame());
sendMsgToGui(MSG_SEEK);
}
@@ -609,8 +609,10 @@ void Audio::startRolling()
state = PLAY;
sendMsgToGui(MSG_PLAY);
- midiSeq->msgStart();
-
+ MidiOutPortList* ol = song->midiOutPorts();
+ for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i)
+ (*i)->start();
+
if (precountEnableFlag
&& song->click()
&& !extSyncFlag
@@ -650,7 +652,9 @@ void Audio::startRolling()
void Audio::stopRolling()
{
state = STOP;
- midiSeq->msgStop();
+ MidiOutPortList* ol = song->midiOutPorts();
+ for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i)
+ (*i)->stop();
recording = false;
endRecordPos = _pos;
_bounce = 0;
diff --git a/muse/muse/conf.cpp b/muse/muse/conf.cpp
index 65b1c229..315f163f 100644
--- a/muse/muse/conf.cpp
+++ b/muse/muse/conf.cpp
@@ -260,6 +260,14 @@ void readConfiguration(QDomNode node)
config.projectPath = s;
else if (tag == "templatePath")
config.templatePath = s;
+ else if (tag == "importMidiPath") {
+ config.importMidiPath = s;
+ lastMidiPath = museUser + "/" + s;
+ }
+ else if (tag == "importWavePath") {
+ config.importWavePath = s;
+ lastWavePath = museUser + "/" + s;
+ }
else if (tag == "PianoRoll")
PianoRoll::readConfiguration(node);
else if (tag == "DrumEdit")
@@ -477,6 +485,8 @@ void MusE::writeGlobalConfiguration(Xml& xml) const
xml.intTag("createDefaultMidiInput", config.createDefaultMidiInput);
xml.strTag("projectPath", config.projectPath);
xml.strTag("templatePath", config.templatePath);
+ xml.strTag("importMidiPath", config.importMidiPath);
+ xml.strTag("importWavePath", config.importWavePath);
PianoRoll::writeConfiguration(xml);
DrumEdit::writeConfiguration(xml);
diff --git a/muse/muse/driver/jack.cpp b/muse/muse/driver/jack.cpp
index 34d33507..5e909cda 100644
--- a/muse/muse/driver/jack.cpp
+++ b/muse/muse/driver/jack.cpp
@@ -733,9 +733,9 @@ void JackAudio::seekTransport(unsigned frame)
Port JackAudio::findPort(const QString& name)
{
- Port p(jack_port_by_name(_client, name.toLatin1().data()));
-// printf("Jack::findPort <%s>, %p\n", name.toLatin1().data(), p);
- return p;
+ jack_port_t* port = jack_port_by_name(_client, name.toLatin1().data());
+// printf("Jack::findPort <%s>, %p\n", name.toLatin1().data(), port);
+ return (port == 0) ? Port() : Port(port);
}
//---------------------------------------------------------
diff --git a/muse/muse/driver/port.h b/muse/muse/driver/port.h
index 7386a7f3..8b1dab47 100644
--- a/muse/muse/driver/port.h
+++ b/muse/muse/driver/port.h
@@ -23,6 +23,10 @@
#include <jack/jack.h>
+//---------------------------------------------------------
+// Port
+//---------------------------------------------------------
+
class Port {
enum { JACK_TYPE, ALSA_TYPE, ZERO_TYPE } type;
union {
@@ -55,9 +59,9 @@ class Port {
else
return true;
}
- unsigned char alsaPort() const { return _alsaPort; }
+ unsigned char alsaPort() const { return _alsaPort; }
unsigned char alsaClient() const { return _alsaClient; }
- jack_port_t* jackPort() const { return _jackPort; }
+ jack_port_t* jackPort() const { return _jackPort; }
};
#endif
diff --git a/muse/muse/gconfig.cpp b/muse/muse/gconfig.cpp
index 78d24194..3fb98749 100644
--- a/muse/muse/gconfig.cpp
+++ b/muse/muse/gconfig.cpp
@@ -123,4 +123,6 @@ GlobalConfigValues config = {
true, // createDefaultMidiInput
QString("MusE/projects"), // projectPath
QString("MusE/templates"), // templatePath
+ QString("MusE/"), // midi import path
+ QString("MusE/"), // wave import path
};
diff --git a/muse/muse/gconfig.h b/muse/muse/gconfig.h
index 494ea6ff..58299403 100644
--- a/muse/muse/gconfig.h
+++ b/muse/muse/gconfig.h
@@ -124,6 +124,8 @@ struct GlobalConfigValues {
bool createDefaultMidiInput;
QString projectPath;
QString templatePath;
+ QString importMidiPath;
+ QString importWavePath;
};
extern GlobalConfigValues config;
diff --git a/muse/muse/importmidi.cpp b/muse/muse/importmidi.cpp
index 80dfa9fd..896cf5f3 100644
--- a/muse/muse/importmidi.cpp
+++ b/muse/muse/importmidi.cpp
@@ -127,9 +127,9 @@ void MusE::importMidi(const QString &file)
if (file.isEmpty()) {
fn = getOpenFileName(lastMidiPath, pattern, this,
tr("MusE: Import Midi"));
+ lastMidiPath = fn;
if (fn.isEmpty())
return;
- lastMidiPath = fn;
}
else
fn = file;
@@ -206,7 +206,7 @@ void MusE::importMidi(const QString &file)
QString msg(tr("File <%1> read error"));
QMessageBox::critical(this, header, msg.arg(s));
}
- importMidi(fn, true);
+ addMidiFile(fn);
tr_id->setChecked(config.transportVisible);
bt_id->setChecked(config.bigTimeVisible);
@@ -282,21 +282,21 @@ void MusE::importMidi(const QString &file)
}
else {
// add to project
- importMidi(fn, true);
+ addMidiFile(fn);
song->update(-1);
}
}
//---------------------------------------------------------
-// importMidi
+// addMidiFile
// return true on error
//---------------------------------------------------------
-bool MusE::importMidi(const QString name, bool merge)
+void MusE::addMidiFile(const QString name)
{
QFile* fp = fileOpen(this, name, QString(".mid"), QIODevice::ReadOnly);
if (fp == 0)
- return true;
+ return;
MidiFile mf;
bool rv = mf.read(fp);
fp->close();
@@ -308,7 +308,7 @@ bool MusE::importMidi(const QString name, bool merge)
s += tr("\nfailed: ");
s += mf.error();
QMessageBox::critical(this, QString("MusE"), s);
- return rv;
+ return;
}
MidiFileTrackList* etl = mf.trackList();
int division = mf.division();
@@ -316,7 +316,7 @@ bool MusE::importMidi(const QString name, bool merge)
MidiOutPort* outPort = 0;
MidiInPort* inPort = 0;
- if (!merge || song->midiOutPorts()->empty()) {
+ if (song->midiOutPorts()->empty()) {
outPort = new MidiOutPort();
outPort->setDefaultName();
song->insertTrack0(outPort, -1);
@@ -427,8 +427,9 @@ bool MusE::importMidi(const QString name, bool merge)
continue;
MidiTrack* track = new MidiTrack();
-//TODO3 if ((*t)->isDrumTrack)
-// track->setUseDrumMap(true);
+ MidiChannel* mc = outPort->channel(channel);
+ if ((*t)->isDrumTrack)
+ mc->setUseDrumMap(true);
track->outRoutes()->push_back(Route(outPort->channel(channel), -1, Route::TRACK));
if (inPort && config.connectToAllMidiTracks) {
for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
@@ -446,19 +447,18 @@ bool MusE::importMidi(const QString name, bool merge)
if (event.type() == Controller) {
int ctrl = event.dataA();
MidiInstrument* instr = outPort->instrument();
- MidiChannel* mc = outPort->channel(channel);
mc->addMidiController(instr, ctrl);
CVal val;
val.i = event.dataB();
mc->addControllerVal(ctrl, event.tick(), val);
}
}
-#if 0 //TODO3
if (channel == 9) {
- track->setUseDrumMap(true);
+ mc->setUseDrumMap(true);
//
// remap drum pitch with drumInmap
//
+#if 0 //TODO
EventList* tevents = track->events();
for (iEvent i = tevents->begin(); i != tevents->end(); ++i) {
Event ev = i->second;
@@ -467,8 +467,8 @@ bool MusE::importMidi(const QString name, bool merge)
ev.setPitch(pitch);
}
}
- }
#endif
+ }
processTrack(track);
if (track->name().isEmpty())
track->setDefaultName();
@@ -490,40 +490,36 @@ bool MusE::importMidi(const QString name, bool merge)
}
}
- if (!merge) {
- TrackList* tl = song->tracks();
- if (!tl->empty()) {
- Track* track = tl->front();
- track->setSelected(true);
- }
- unsigned int l = 1;
- MidiTrackList* mtl = song->midis();
- for (iMidiTrack t = mtl->begin(); t != mtl->end(); ++t) {
- MidiTrack* track = *t;
- PartList* parts = track->parts();
- for (iPart p = parts->begin(); p != parts->end(); ++p) {
- unsigned last = p->second->tick() + p->second->lenTick();
- if (last > l)
- l = last;
- }
+ TrackList* tl = song->tracks();
+ if (!tl->empty()) {
+ Track* track = tl->front();
+ track->setSelected(true);
+ }
+ unsigned int l = 1;
+ MidiTrackList* mtl = song->midis();
+ for (iMidiTrack t = mtl->begin(); t != mtl->end(); ++t) {
+ MidiTrack* track = *t;
+ PartList* parts = track->parts();
+ for (iPart p = parts->begin(); p != parts->end(); ++p) {
+ unsigned last = p->second->tick() + p->second->lenTick();
+ if (last > l)
+ l = last;
}
- song->setLen(l);
-
- AL::TimeSignature sig = AL::sigmap.timesig(0);
- int z = sig.z;
- int n = sig.n;
+ }
+ song->setLen(l);
+ AL::TimeSignature sig = AL::sigmap.timesig(0);
+ int z = sig.z;
+ int n = sig.n;
- transport->setTimesig(z, n);
-// int tempo = AL::tempomap.tempo(0);
-// transport->setTempo(tempo);
+ transport->setTimesig(z, n);
+// int tempo = AL::tempomap.tempo(0);
+// transport->setTempo(tempo);
- bool masterF = !AL::tempomap.empty();
- song->setMasterFlag(masterF);
- transport->setMasterFlag(masterF);
+ bool masterF = !AL::tempomap.empty();
+ song->setMasterFlag(masterF);
+ transport->setMasterFlag(masterF);
- song->updatePos();
- }
- return false;
+ song->updatePos();
}
//---------------------------------------------------------
diff --git a/muse/muse/midi.cpp b/muse/muse/midi.cpp
index 3bab9108..47556328 100644
--- a/muse/muse/midi.cpp
+++ b/muse/muse/midi.cpp
@@ -641,10 +641,9 @@ void Audio::initDevices()
void Audio::processMidi()
{
- midiBusy = true;
MidiOutPortList* ol = song->midiOutPorts();
for (iMidiOutPort id = ol->begin(); id != ol->end(); ++id) {
- (*id)->process(_curTickPos, _nextTickPos);
+ (*id)->process(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize);
}
MidiInPortList* il = song->midiInPorts();
@@ -664,6 +663,5 @@ void Audio::processMidi()
}
port->afterProcess();
}
- midiBusy = false;
}
diff --git a/muse/muse/midioutport.cpp b/muse/muse/midioutport.cpp
index 845f6feb..371ce55a 100644
--- a/muse/muse/midioutport.cpp
+++ b/muse/muse/midioutport.cpp
@@ -21,6 +21,7 @@
#include "song.h"
#include "midiplugin.h"
#include "midictrl.h"
+#include "al/al.h"
#include "al/tempo.h"
#include "al/xml.h"
#include "driver/mididev.h"
@@ -28,6 +29,9 @@
#include "audio.h"
#include "midioutport.h"
#include "midichannel.h"
+#include "midiseq.h"
+#include "sync.h"
+#include "gconfig.h"
//---------------------------------------------------------
// MidiOutPort
@@ -382,14 +386,18 @@ void MidiOutPort::playMidiEvent(MidiEvent* ev)
}
}
-//---------------------------------------------------------
+//-------------------------------------------------------------------
// process
-// "play" events for this process cycle
-// from/to are midi ticks
-// if (from != to) then transport state is "playing"
-//---------------------------------------------------------
-
-void MidiOutPort::process(unsigned from, unsigned to)
+// Collect all midi events for the current process cycle and put
+// into _schedEvents queue. For note on events create the proper
+// note off events. The note off events maybe played after the
+// current process cycle.
+// From _schedEvents queue copy all events for the current cycle
+// to all output routes. Events routed to ALSA go into the
+// _playEvents queue which is processed by the MidiSeq thread.
+//-------------------------------------------------------------------
+
+void MidiOutPort::process(unsigned fromTick, unsigned toTick, unsigned, unsigned toFrame)
{
if (mute())
return;
@@ -399,12 +407,12 @@ void MidiOutPort::process(unsigned from, unsigned to)
el.add(eventFifo.get());
// collect port controller
- if (from != to) {
+ if (fromTick != toTick) { // if rolling
CtrlList* cl = controller();
for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
Ctrl* c = ic->second;
- iCtrlVal is = c->lower_bound(from);
- iCtrlVal ie = c->lower_bound(to);
+ iCtrlVal is = c->lower_bound(fromTick);
+ iCtrlVal ie = c->lower_bound(toTick);
for (iCtrlVal ic = is; ic != ie; ++ic) {
unsigned frame = AL::tempomap.tick2frame(ic->first);
Event ev(Controller);
@@ -422,12 +430,12 @@ void MidiOutPort::process(unsigned from, unsigned to)
if (mc->mute() || mc->noInRoute())
continue;
// collect channel controller
- if (from != to) {
+ if (fromTick != toTick) {
CtrlList* cl = mc->controller();
for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
Ctrl* c = ic->second;
- iCtrlVal is = c->lower_bound(from);
- iCtrlVal ie = c->lower_bound(to);
+ iCtrlVal is = c->lower_bound(fromTick);
+ iCtrlVal ie = c->lower_bound(toTick);
for (; is != ie; ++is) {
unsigned frame = AL::tempomap.tick2frame(is->first);
Event ev(Controller);
@@ -445,7 +453,7 @@ void MidiOutPort::process(unsigned from, unsigned to)
if (track->isMute())
continue;
MPEventList ell;
- track->getEvents(from, to, 0, &ell);
+ track->getEvents(fromTick, toTick, 0, &ell);
int velo = 0;
for (iMPEvent i = ell.begin(); i != ell.end(); ++i) {
MidiEvent ev(*i);
@@ -460,29 +468,43 @@ void MidiOutPort::process(unsigned from, unsigned to)
}
addMidiMeter(portVelo);
- MPEventList ol;
- pipeline()->apply(from, to, &el, &ol);
+ pipeline()->apply(fromTick, toTick, &el, &_schedEvents);
//
// route events to destination
//
- for (iMPEvent i = ol.begin(); i != ol.end(); ++i) {
- for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) {
- switch (r->type) {
- case Route::MIDIPORT:
- _playEvents.add(*i); // schedule
- break;
- case Route::SYNTIPORT:
- ((SynthI*)(r->track))->playEvents()->insert(*i);
- break;
- case Route::JACKMIDIPORT:
- audioDriver->putEvent(jackPort(0), *i);
- break;
- default:
- fprintf(stderr, "MidiOutPort::process(): invalid routetype\n");
- break;
- }
+ for (iMPEvent i = _schedEvents.begin(); i != _schedEvents.end(); ++i) {
+ if (i->time() >= toFrame) {
+ _schedEvents.erase(_schedEvents.begin(), i);
+ break;
+ }
+ routeEvent(*i);
+ }
+ }
+
+//---------------------------------------------------------
+// routeEvent
+//---------------------------------------------------------
+
+void MidiOutPort::routeEvent(const MidiEvent& event)
+ {
+ for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) {
+ switch (r->type) {
+ case Route::MIDIPORT:
+ midiBusy = true;
+ _playEvents.insert(event); // schedule
+ midiBusy = false;
+ break;
+ case Route::SYNTIPORT:
+ ((SynthI*)(r->track))->playEvents()->insert(event);
+ break;
+ case Route::JACKMIDIPORT:
+ audioDriver->putEvent(jackPort(0), event);
+ break;
+ default:
+ fprintf(stderr, "MidiOutPort::process(): invalid routetype\n");
+ break;
}
}
}
@@ -506,3 +528,145 @@ void MidiOutPort::setSendSync(bool val)
_sendSync = val;
emit sendSyncChanged(val);
}
+
+//---------------------------------------------------------
+// seek
+//---------------------------------------------------------
+
+void MidiOutPort::seek(unsigned tickPos, unsigned framePos)
+ {
+ if (genMCSync && sendSync()) {
+ int beat = (tickPos * 4) / config.division;
+ sendStop();
+ sendSongpos(beat);
+ sendContinue();
+ }
+ if (mute())
+ return;
+
+// if (pos == 0 && !song->record())
+// audio->initDevices();
+
+ //---------------------------------------------------
+ // stop all notes
+ //---------------------------------------------------
+
+ for (iMPEvent i = _schedEvents.begin(); i != _schedEvents.end(); ++i) {
+ MidiEvent ev = *i;
+ if (ev.isNoteOff()) {
+ ev.setTime(framePos);
+ routeEvent(ev);
+ }
+ }
+ _schedEvents.clear();
+
+ //---------------------------------------------------
+ // set all controller
+ //---------------------------------------------------
+
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
+ MidiChannel* mc = channel(ch);
+ if (mc->mute() || mc->noInRoute() || !mc->autoRead())
+ continue;
+ CtrlList* cll = mc->controller();
+ for (iCtrl ivl = cll->begin(); ivl != cll->end(); ++ivl) {
+ Ctrl* c = ivl->second;
+ int val = c->value(tickPos).i;
+ if (val != CTRL_VAL_UNKNOWN && val != c->curVal().i) {
+ routeEvent(MidiEvent(0, ch, ME_CONTROLLER, c->id(), val));
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// stop
+//---------------------------------------------------------
+
+void MidiOutPort::stop()
+ {
+ int frame = AL::tempomap.tick2frame(audio->curTickPos());
+
+ //---------------------------------------------------
+ // stop all notes
+ //---------------------------------------------------
+
+ for (iMPEvent i = _schedEvents.begin(); i != _schedEvents.end(); ++i) {
+ MidiEvent ev = *i;
+ if (ev.isNoteOff()) {
+ ev.setTime(frame);
+ routeEvent(ev);
+ }
+ }
+ _schedEvents.clear();
+
+ //---------------------------------------------------
+ // reset sustain
+ //---------------------------------------------------
+
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
+ MidiChannel* mc = channel(ch);
+ if (mc->noInRoute())
+ continue;
+ if (mc->hwCtrlState(CTRL_SUSTAIN) != CTRL_VAL_UNKNOWN) {
+ MidiEvent ev(0, 0, ME_CONTROLLER, CTRL_SUSTAIN, 0);
+ ev.setChannel(mc->channelNo());
+ routeEvent(ev);
+ }
+ }
+
+ if (sendSync()) {
+ if (genMMC) {
+ unsigned char mmcPos[] = {
+ 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
+ 0, 0, 0, 0, 0
+ };
+ MTC mtc(double(frame) / double(AL::sampleRate));
+ mmcPos[6] = mtc.h() | (AL::mtcType << 5);
+ mmcPos[7] = mtc.m();
+ mmcPos[8] = mtc.s();
+ mmcPos[9] = mtc.f();
+ mmcPos[10] = mtc.sf();
+//TODO mp->sendSysex(mmcStopMsg, sizeof(mmcStopMsg));
+// mp->sendSysex(mmcPos, sizeof(mmcPos));
+ }
+ if (genMCSync) { // Midi Clock
+ // send STOP and
+ // "set song position pointer"
+// mp->sendStop();
+// mp->sendSongpos(audio->curTickPos() * 4 / config.division);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// start
+//---------------------------------------------------------
+
+void MidiOutPort::start()
+ {
+#if 0
+ if (!(genMMC || genMCSync))
+ return;
+ if (!sendSync())
+ return;
+ if (genMMC)
+ sendSysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
+ if (genMCSync) {
+ if (audio->curTickPos())
+ sendContinue();
+ else
+ sendStart();
+ }
+#endif
+ }
+
+//---------------------------------------------------------
+// reset
+//---------------------------------------------------------
+
+void MidiOutPort::reset()
+ {
+ instrument()->reset(this);
+ }
+
diff --git a/muse/muse/midioutport.h b/muse/muse/midioutport.h
index 70e3c97c..3f376c43 100644
--- a/muse/muse/midioutport.h
+++ b/muse/muse/midioutport.h
@@ -33,10 +33,11 @@ class MidiOutPort : public MidiTrackBase {
MidiInstrument* _instrument;
MidiChannel* _channel[MIDI_CHANNELS];
- bool _sendSync; // this port sends mtc mmc events
+ bool _sendSync; // this port sends mtc/mmc events
int _deviceId; // 0-126; 127 == all
- MPEventList _playEvents; // scheduled events to play
+ MPEventList _schedEvents; // scheduled events by process()
+ MPEventList _playEvents; // event queue for MidiSeq
// fifo for midi events send from gui
// direct to midi port:
@@ -72,7 +73,7 @@ class MidiOutPort : public MidiTrackBase {
MPEventList* playEvents() { return &_playEvents; }
- void process(unsigned from, unsigned to);
+ void process(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame);
void playMidiEvent(MidiEvent*);
@@ -91,6 +92,11 @@ class MidiOutPort : public MidiTrackBase {
int deviceId() const { return _deviceId; }
void setDeviceId(int val) { _deviceId = val; }
+
+ void seek(unsigned, unsigned);
+ void stop();
+ void start();
+ void reset();
};
#endif
diff --git a/muse/muse/midiseq.cpp b/muse/muse/midiseq.cpp
index f569237d..028e0c0d 100644
--- a/muse/muse/midiseq.cpp
+++ b/muse/muse/midiseq.cpp
@@ -69,18 +69,9 @@ void MidiSeq::processMsg(const ThreadMsg* m)
{
AudioMsg* msg = (AudioMsg*)m;
switch (msg->id) {
- case MS_START:
- processStart();
- break;
- case MS_STOP:
- processStop();
- break;
case MS_SET_RTC:
initRealtimeTimer();
break;
- case SEQM_RESET_DEVICES:
- resetDevices();
- break;
case SEQM_ADD_TRACK:
song->insertTrack2(msg->track);
updatePollFd();
@@ -98,9 +89,6 @@ void MidiSeq::processMsg(const ThreadMsg* m)
case SEQM_CHANGE_PART:
song->cmdChangePart((Part*)msg->p1, (Part*)msg->p2);
break;
- case SEQM_IDLE:
- idle = msg->a;
- break;
case SEQM_MOVE_TRACK:
song->moveTrack((Track*)(msg->p1), (Track*)(msg->p2));
break;
@@ -114,198 +102,12 @@ void MidiSeq::processMsg(const ThreadMsg* m)
}
//---------------------------------------------------------
-// processStart
-//---------------------------------------------------------
-
-void MidiSeq::processStart()
- {
- if (genMMC || genMCSync) {
- MidiOutPortList* ol = song->midiOutPorts();
- for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i) {
- MidiOutPort* mp = *i;
- if (!mp->sendSync())
- continue;
- if (genMMC)
- mp->sendSysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
- if (genMCSync) {
- if (audio->curTickPos())
- mp->sendContinue();
- else
- mp->sendStart();
- }
- }
- }
- }
-
-//---------------------------------------------------------
-// processStop
-// synced with audio process()
-//---------------------------------------------------------
-
-void MidiSeq::processStop()
- {
- //---------------------------------------------------
- // stop stuck notes
- //---------------------------------------------------
-
- MidiOutPortList* ol = song->midiOutPorts();
- for (iMidiOutPort id = ol->begin(); id != ol->end(); ++id) {
- MidiOutPort* md = *id;
- if (md->noOutRoute())
- continue;
- MPEventList* pel = md->playEvents();
- for (iMPEvent i = pel->begin(); i != pel->end(); ++i) {
- MidiEvent ev = *i;
- if (ev.isNoteOff()) {
- ev.setTime(0);
- md->putEvent(ev);
- }
- }
- pel->clear();
- }
-
- //---------------------------------------------------
- // reset sustain
- //---------------------------------------------------
-
- MidiChannelList* mcl = song->midiChannel();
- for (iMidiChannel i = mcl->begin(); i != mcl->end(); ++i) {
- MidiChannel* mc = *i;
- if (mc->noInRoute())
- continue;
- MidiOutPort* mp = mc->port();
- if (mc->hwCtrlState(CTRL_SUSTAIN) != CTRL_VAL_UNKNOWN) {
- MidiEvent ev(0, 0, ME_CONTROLLER, CTRL_SUSTAIN, 0);
- ev.setChannel(mc->channelNo());
- mp->putEvent(ev);
- }
- }
-
- if (genMMC || genMCSync) {
- MidiOutPortList* ol = song->midiOutPorts();
- for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i) {
- MidiOutPort* mp = *i;
- if (!mp->sendSync())
- continue;
- if (genMMC) {
- unsigned char mmcPos[] = {
- 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
- 0, 0, 0, 0, 0
- };
- int frame = AL::tempomap.tick2frame(audio->curTickPos());
- MTC mtc(double(frame) / double(AL::sampleRate));
- mmcPos[6] = mtc.h() | (AL::mtcType << 5);
- mmcPos[7] = mtc.m();
- mmcPos[8] = mtc.s();
- mmcPos[9] = mtc.f();
- mmcPos[10] = mtc.sf();
- mp->sendSysex(mmcStopMsg, sizeof(mmcStopMsg));
- mp->sendSysex(mmcPos, sizeof(mmcPos));
- }
- if (genMCSync) { // Midi Clock
- // send STOP and
- // "set song position pointer"
- mp->sendStop();
- mp->sendSongpos(audio->curTickPos() * 4 / config.division);
- }
- }
- }
- }
-
-//---------------------------------------------------------
-// resetDevices
-//---------------------------------------------------------
-
-void MidiSeq::resetDevices()
- {
- MidiOutPortList* ol = song->midiOutPorts();
- for (iMidiOutPort id = ol->begin(); id != ol->end(); ++id) {
- MidiOutPort* md = *id;
- MidiInstrument* instr = md->instrument();
- instr->reset(md);
- }
- }
-
-//---------------------------------------------------------
-// processSeek
-// synced with audio process()
-//---------------------------------------------------------
-
-void MidiSeq::processSeek()
- {
- int pos = audio->curTickPos();
- if (genMCSync) {
- MidiOutPortList* ol = song->midiOutPorts();
- for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i) {
- MidiOutPort* mp = *i;
- if (!mp->sendSync())
- continue;
- int beat = (pos * 4) / config.division;
- mp->sendStop();
- mp->sendSongpos(beat);
- mp->sendContinue();
- }
- }
-
-// if (pos == 0 && !song->record())
-// audio->initDevices();
-
- //---------------------------------------------------
- // set all controller
- //---------------------------------------------------
-
- MidiOutPortList* opl = song->midiOutPorts();
-
- for (iMidiOutPort i = opl->begin(); i != opl->end(); ++i) {
- MidiOutPort* op = *i;
- if (op->mute())
- continue;
- MPEventList* el = op->playEvents();
- if (audio->isPlaying()) {
- // stop all notes
- for (iMPEvent i = el->begin(); i != el->end(); ++i) {
- MidiEvent ev = *i;
- if (ev.isNoteOff()) {
- ev.setTime(0);
- op->putEvent(ev);
- // el->add(ev);
- }
- }
- el->clear();
- }
-// else
-// el->erase(el->begin(), op->nextPlayEvent());
- for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
- MidiChannel* mc = op->channel(ch);
- if (mc->mute() || mc->noInRoute() || !mc->autoRead())
- continue;
- CtrlList* cll = mc->controller();
- for (iCtrl ivl = cll->begin(); ivl != cll->end(); ++ivl) {
- Ctrl* c = ivl->second;
- int val = c->value(pos).i;
- if (val != CTRL_VAL_UNKNOWN && val != c->curVal().i) {
- op->putEvent(MidiEvent(0, ch, ME_CONTROLLER, c->id(), val));
- }
- }
- }
-// op->setNextPlayEvent(op->playEvents()->begin());
- }
- }
-
-//---------------------------------------------------------
// MidiSeq
//---------------------------------------------------------
MidiSeq::MidiSeq(const char* name)
: Thread(name)
{
- idle = false;
- midiClock = 0;
- mclock1 = 0.0;
- mclock2 = 0.0;
- songtick1 = songtick2 = 0;
- lastTempo = 0;
- storedtimediffs = 0;
timer = 0;
}
@@ -346,10 +148,9 @@ void MidiSeq::threadStart(void*)
printf("midi thread %d _NOT_ running SCHED_FIFO\n", getpid());
else if (debugMsg) {
struct sched_param rt_param;
- int rv;
memset(&rt_param, 0, sizeof(sched_param));
int type;
- rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
+ int rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
if (rv == -1)
perror("get scheduler parameter");
printf("midiseq thread running SCHED_FIFO priority %d\n",
@@ -454,13 +255,14 @@ bool MidiSeq::start(int prio)
return false;
}
+#if 0
//---------------------------------------------------------
// processMidiClock
//---------------------------------------------------------
void MidiSeq::processMidiClock()
{
-/* if (genMCSync)
+ if (genMCSync)
midiPorts[txSyncPort].sendClock();
if (state == START_PLAY) {
// start play on sync
@@ -477,16 +279,15 @@ void MidiSeq::processMidiClock()
rtcTickStart = rtcTick - lrint(cpos * realRtcTicks);
endSlice = playTickPos;
- recTick = playTickPos;
lastTickPos = playTickPos;
tempoSN = tempomap.tempoSN();
startRecordPos.setPosTick(playTickPos);
}
-*/
midiClock += config.division/24;
}
+#endif
//---------------------------------------------------------
// midiTick
@@ -509,26 +310,15 @@ void MidiSeq::processTimerTick()
timer->getTimerTicks(); // read elapsed rtc timer ticks
- if (idle)
- return;
-
if (midiBusy) {
- // we hit audio: midiSeq->msgProcess
// miss this timer tick
return;
}
- unsigned curFrame = audioDriver->framePos();
-
-/* if (!extSyncFlag.value()) {
- int curTick = AL::tempomap.frame2tick(curFrame);
- if (curTick >= midiClock)
- processMidiClock();
- }
- */
-
//
- // play all events upto curFrame
+ // schedule all events upto framePos-segmentSize
+ // (previous segment)
//
+ unsigned curFrame = audioDriver->framePos() - segmentSize;
MidiOutPortList* ol = song->midiOutPorts();
for (iMidiOutPort id = ol->begin(); id != ol->end(); ++id) {
MidiOutPort* mp = *id;
@@ -555,7 +345,5 @@ void MidiSeq::msgMsg(int id)
Thread::sendMsg(&msg);
}
-void MidiSeq::msgStop() { msgMsg(MS_STOP); }
-void MidiSeq::msgStart() { msgMsg(MS_START); }
void MidiSeq::msgSetRtc() { msgMsg(MS_SET_RTC); }
diff --git a/muse/muse/midiseq.h b/muse/muse/midiseq.h
index 8f29a292..91a90b1a 100644
--- a/muse/muse/midiseq.h
+++ b/muse/muse/midiseq.h
@@ -41,29 +41,23 @@ class MTC;
class MidiSeq : public Thread {
int realRtcTicks;
Timer* timer;
- int idle;
int midiClock;
/* Testing */
- int recTick; // ext sync tick position
- int lastTickPos; // position of last sync tick
+// int lastTickPos; // position of last sync tick
// run values:
- unsigned _midiTick;
- double mclock1, mclock2;
- double songtick1, songtick2;
- int recTick1, recTick2;
- int lastTempo;
- double timediff[24];
- int storedtimediffs;
+// unsigned _midiTick;
+// double mclock1, mclock2;
+// double songtick1, songtick2;
+// int recTick1, recTick2;
+// int lastTempo;
+// double timediff[24];
+// int storedtimediffs;
/* Testing */
bool initRealtimeTimer();
static void midiTick(void* p, void*);
void processTimerTick();
- void processStart();
- void processStop();
- void resetDevices();
- void processMidiClock();
virtual void processMsg(const ThreadMsg*);
void updatePollFd();
@@ -84,12 +78,10 @@ class MidiSeq : public Thread {
void msgMsg(int id);
void msgStart();
- void msgStop();
void msgSetRtc();
void msgAddSynthI(SynthI* synth);
void msgRemoveSynthI(SynthI* synth);
- void processSeek();
};
extern MidiSeq* midiSeq;
diff --git a/muse/muse/muse.cpp b/muse/muse/muse.cpp
index 0b5a2967..25a0a1ff 100644
--- a/muse/muse/muse.cpp
+++ b/muse/muse/muse.cpp
@@ -2838,15 +2838,16 @@ int main(int argc, char* argv[])
{
museUser = QString(getenv("MUSEHOME"));
if (museUser.isEmpty())
- museUser = QString(getenv("HOME"));
+ museUser = QDir::homePath();
QString museGlobal;
const char* p = getenv("MUSE");
museGlobal = p ? p : INSTPREFIX;
museGlobalLib = museGlobal + "/lib/" INSTALL_NAME;
museGlobalShare = museGlobal + "/share/" INSTALL_NAME;
-
- configName = museUser + QString("/." INSTALL_NAME);
+ configName = museUser + QString("/." INSTALL_NAME);
+ lastMidiPath = museUser + "/" + ::config.importMidiPath;
+ lastWavePath = museUser + "/" + ::config.importWavePath;
srand(time(0)); // initialize random number generator
initMidiController();
diff --git a/muse/muse/muse.h b/muse/muse/muse.h
index ee347719..5045df19 100644
--- a/muse/muse/muse.h
+++ b/muse/muse/muse.h
@@ -173,6 +173,7 @@ class MusE : public QMainWindow // , public Ui::MuseBase
bool leaveProject();
virtual void focusInEvent(QFocusEvent*);
+ void addMidiFile(const QString name);
signals:
void configChanged();
@@ -276,7 +277,6 @@ class MusE : public QMainWindow // , public Ui::MuseBase
MusE();
Arranger* arranger;
QRect configGeometryMain;
- bool importMidi(const QString name, bool merge);
void kbAccel(int);
void changeConfig(bool writeFlag);
diff --git a/muse/muse/preferences.cpp b/muse/muse/preferences.cpp
index e2385155..52773b53 100644
--- a/muse/muse/preferences.cpp
+++ b/muse/muse/preferences.cpp
@@ -328,6 +328,8 @@ PreferencesDialog::PreferencesDialog(Arranger* a, QWidget* parent)
showSplash->setChecked(config->showSplashScreen);
projectPath->setText(config->projectPath);
templatePath->setText(config->templatePath);
+ midiImportPath->setText(config->importMidiPath);
+ waveImportPath->setText(config->importWavePath);
stopActive->setChecked(midiRCList.isActive(RC_STOP));
playActive->setChecked(midiRCList.isActive(RC_PLAY));
@@ -360,7 +362,6 @@ PreferencesDialog::PreferencesDialog(Arranger* a, QWidget* parent)
waveEditorWidth->setValue(WaveEdit::initWidth);
waveEditorHeight->setValue(WaveEdit::initHeight);
-
connect(recordStop, SIGNAL(clicked(bool)), SLOT(recordStopToggled(bool)));
connect(recordRecord, SIGNAL(clicked(bool)), SLOT(recordRecordToggled(bool)));
connect(recordGotoLeftMark, SIGNAL(clicked(bool)), SLOT(recordGotoLeftMarkToggled(bool)));
@@ -587,8 +588,13 @@ void PreferencesDialog::apply()
::config.useJackFreewheelMode = freewheelMode->isChecked();
::config.showSplashScreen = showSplash->isChecked();
- ::config.projectPath = projectPath->text();
- ::config.templatePath = templatePath->text();
+ ::config.projectPath = projectPath->text();
+ ::config.templatePath = templatePath->text();
+ ::config.importMidiPath = midiImportPath->text();
+ ::config.importWavePath = waveImportPath->text();
+
+ lastMidiPath = museUser + "/" + ::config.importMidiPath;
+ lastWavePath = museUser + "/" + ::config.importWavePath;
PianoRoll::initWidth = pianorollWidth->value();
PianoRoll::initHeight = pianorollHeight->value();
diff --git a/muse/muse/preferences.ui b/muse/muse/preferences.ui
index 7e690d89..c7adf58f 100644
--- a/muse/muse/preferences.ui
+++ b/muse/muse/preferences.ui
@@ -5,8 +5,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>731</width>
- <height>590</height>
+ <width>665</width>
+ <height>631</height>
</rect>
</property>
<property name="windowTitle" >
@@ -22,7 +22,7 @@
<item>
<widget class="QTabWidget" name="tabWidget" >
<property name="currentIndex" >
- <number>6</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
@@ -139,16 +139,29 @@
<property name="spacing" >
<number>6</number>
</property>
+ <item row="1" column="3" >
+ <widget class="QLineEdit" name="waveImportPath" />
+ </item>
+ <item row="0" column="3" >
+ <widget class="QLineEdit" name="midiImportPath" />
+ </item>
<item row="1" column="1" >
<widget class="QLineEdit" name="templatePath" />
</item>
<item row="0" column="1" >
<widget class="QLineEdit" name="projectPath" />
</item>
- <item row="1" column="0" >
- <widget class="QLabel" name="label_35" >
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_36" >
<property name="text" >
- <string>Templates</string>
+ <string>Midi Import</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QLabel" name="label_37" >
+ <property name="text" >
+ <string>Wave Import</string>
</property>
</widget>
</item>
@@ -159,6 +172,13 @@
</property>
</widget>
</item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_35" >
+ <property name="text" >
+ <string>Templates</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
@@ -2228,14 +2248,14 @@
<header>quantcombo.h</header>
</customwidget>
<customwidget>
- <class>RecordButton</class>
+ <class>GreendotButton</class>
<extends>QToolButton</extends>
- <header>recordbutton.h</header>
+ <header>greendotbutton.h</header>
</customwidget>
<customwidget>
- <class>GreendotButton</class>
+ <class>RecordButton</class>
<extends>QToolButton</extends>
- <header>greendotbutton.h</header>
+ <header>recordbutton.h</header>
</customwidget>
<customwidget>
<class>RasterCombo</class>
diff --git a/muse/muse/route.cpp b/muse/muse/route.cpp
index 39f9a802..8b4a9ca6 100644
--- a/muse/muse/route.cpp
+++ b/muse/muse/route.cpp
@@ -253,10 +253,13 @@ QString Route::name() const
case SYNTIPORT:
return track2name(track);
case AUDIOPORT:
- return audioDriver->portName(port);
case JACKMIDIPORT:
+ if (port.isZero())
+ return QString("0");
return audioDriver->portName(port);
case MIDIPORT:
+ if (port.isZero())
+ return QString("0");
return midiDriver->portName(port);
case AUXPLUGIN:
return plugin->pluginInstance()->name();
diff --git a/muse/muse/sync.cpp b/muse/muse/sync.cpp
index 98946a9b..2176453b 100644
--- a/muse/muse/sync.cpp
+++ b/muse/muse/sync.cpp
@@ -71,6 +71,7 @@ enum {
void MidiSeq::mmcInput(int id, int cmd, const Pos& pos)
{
+#if 0
int rxDeviceId = 127;
if (!extSyncFlag || !acceptMMC || (id != 127 && id != rxDeviceId))
@@ -120,6 +121,7 @@ void MidiSeq::mmcInput(int id, int cmd, const Pos& pos)
printf("MMC id %x cmd %x, unknown\n", id, cmd);
break;
}
+#endif
}
//---------------------------------------------------------
@@ -129,6 +131,7 @@ void MidiSeq::mmcInput(int id, int cmd, const Pos& pos)
void MidiSeq::mtcInputQuarter(int, unsigned char c)
{
+#if 0
static int hour, min, sec, frame;
if (!extSyncFlag)
@@ -186,6 +189,7 @@ void MidiSeq::mtcInputQuarter(int, unsigned char c)
mtcCurTime.incQuarter();
mtcSyncMsg(mtcCurTime, false);
}
+#endif
}
//---------------------------------------------------------
@@ -195,6 +199,7 @@ void MidiSeq::mtcInputQuarter(int, unsigned char c)
void MidiSeq::mtcInputFull(const unsigned char* p, int n)
{
+#if 0
if (debugSync)
printf("mtcInputFull\n");
if (!extSyncFlag)
@@ -222,6 +227,7 @@ void MidiSeq::mtcInputFull(const unsigned char* p, int n)
mtcState = 0;
mtcValid = true;
mtcLost = 0;
+#endif
}
//---------------------------------------------------------
@@ -230,6 +236,7 @@ void MidiSeq::mtcInputFull(const unsigned char* p, int n)
void MidiSeq::nonRealtimeSystemSysex(const unsigned char* p, int n)
{
+#if 0
// int chan = p[2];
switch(p[3]) {
case 4:
@@ -240,6 +247,7 @@ void MidiSeq::nonRealtimeSystemSysex(const unsigned char* p, int n)
dump(p, n);
break;
}
+#endif
}
//---------------------------------------------------------
@@ -252,6 +260,7 @@ void MidiSeq::nonRealtimeSystemSysex(const unsigned char* p, int n)
void MidiSeq::setSongPosition(int port, int midiBeat)
{
+#if 0
if (midiInputTrace)
printf("set song position port:%d %d\n", port, midiBeat);
if (!extSyncFlag)
@@ -260,6 +269,7 @@ void MidiSeq::setSongPosition(int port, int midiBeat)
audioDriver->seekTransport(pos.frame());
if (debugSync)
printf("setSongPosition %d\n", pos.tick());
+#endif
}
//---------------------------------------------------------
@@ -269,6 +279,7 @@ void MidiSeq::setSongPosition(int port, int midiBeat)
void MidiSeq::realtimeSystemInput(int port, int c)
{
+#if 0
if (midiInputTrace)
printf("realtimeSystemInput port:%d 0x%x\n", port+1, c);
@@ -443,6 +454,7 @@ void MidiSeq::realtimeSystemInput(int port, int c)
case 0xff: // system reset
break;
}
+#endif
}
@@ -484,4 +496,3 @@ void MidiSeq::mtcSyncMsg(const MTC& /*mtc*/, bool /*seekFlag*/)
#endif
}
-