diff options
author | Florian Jung <flo@windfisch.org> | 2011-09-10 17:06:00 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-09-10 17:06:00 +0000 |
commit | 24f84a489364741eb3fc126a3f83d91a86b65e27 (patch) | |
tree | 63a4e20aaf4a2ebd2462c91b574eddceeac31170 /muse2/muse/driver | |
parent | 38c5cccc7273247353264bb7dc97f42296d8e259 (diff) | |
parent | 2120ea4f083228dde0d7307203391a4ec8f57e2d (diff) |
merged the first bunch of orcans changes
STILL WAIT WITH COMMITTING NEW STUFF! i have to merge the rest as well!
this is a bit buggy (connect errors, not tested much), but doesn't
segfault immediately
Diffstat (limited to 'muse2/muse/driver')
-rw-r--r-- | muse2/muse/driver/CMakeLists.txt | 11 | ||||
-rw-r--r-- | muse2/muse/driver/alsamidi.cpp | 392 | ||||
-rw-r--r-- | muse2/muse/driver/alsamidi.h | 35 | ||||
-rw-r--r-- | muse2/muse/driver/alsatimer.cpp | 15 | ||||
-rw-r--r-- | muse2/muse/driver/alsatimer.h | 15 | ||||
-rw-r--r-- | muse2/muse/driver/audiodev.h | 15 | ||||
-rw-r--r-- | muse2/muse/driver/dummyaudio.cpp | 77 | ||||
-rw-r--r-- | muse2/muse/driver/jack.cpp | 137 | ||||
-rw-r--r-- | muse2/muse/driver/jackaudio.h | 20 | ||||
-rw-r--r-- | muse2/muse/driver/jackmidi.cpp | 898 | ||||
-rw-r--r-- | muse2/muse/driver/jackmidi.h | 104 | ||||
-rw-r--r-- | muse2/muse/driver/rtctimer.cpp | 25 | ||||
-rw-r--r-- | muse2/muse/driver/rtctimer.h | 17 | ||||
-rw-r--r-- | muse2/muse/driver/timerdev.h | 15 |
14 files changed, 634 insertions, 1142 deletions
diff --git a/muse2/muse/driver/CMakeLists.txt b/muse2/muse/driver/CMakeLists.txt index 0f9857f1..2833da04 100644 --- a/muse2/muse/driver/CMakeLists.txt +++ b/muse2/muse/driver/CMakeLists.txt @@ -3,10 +3,12 @@ # Linux Music Editor # $Id:$ # -# Copyright (C) 2002-2006 by Werner Schweer and others +# Copyright (C) 1999-2011 by Werner Schweer and others # # This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2. +# it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,8 +16,9 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #============================================================================= ## diff --git a/muse2/muse/driver/alsamidi.cpp b/muse2/muse/driver/alsamidi.cpp index c7ae07b5..9a62dbdd 100644 --- a/muse2/muse/driver/alsamidi.cpp +++ b/muse2/muse/driver/alsamidi.cpp @@ -3,6 +3,22 @@ // Linux Music Editor // $Id: alsamidi.cpp,v 1.8.2.7 2009/11/19 04:20:33 terminator356 Exp $ // (C) Copyright 2000-2001 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #include <stdio.h> @@ -10,16 +26,18 @@ #include "alsamidi.h" #include "globals.h" #include "midi.h" -#include "mididev.h" +//#include "mididev.h" #include "../midiport.h" #include "../midiseq.h" #include "../midictrl.h" #include "../audio.h" -#include "mpevent.h" +//#include "mpevent.h" //#include "sync.h" #include "utils.h" #include "audiodev.h" #include "xml.h" +#include "part.h" +#include "gconfig.h" static int alsaSeqFdi = -1; static int alsaSeqFdo = -1; @@ -35,6 +53,8 @@ MidiAlsaDevice::MidiAlsaDevice(const snd_seq_addr_t& a, const QString& n) : MidiDevice(n) { adr = a; + stopPending = false; + seekPending = false; init(); } @@ -117,7 +137,7 @@ void MidiAlsaDevice::close() // Allocated on stack, no need to call snd_seq_port_subscribe_free() later. snd_seq_port_subscribe_alloca(&subs); - // Changed by T356. This function appears to be called only by MidiPort::setMidiDevice(), + // This function appears to be called only by MidiPort::setMidiDevice(), // which closes then opens the device. // Because the open flags are set BEFORE setMidiDevice() is called, we must ignore the flags. // @@ -131,7 +151,7 @@ void MidiAlsaDevice::close() // dst 16:0 // only sometimes (not when playing notes), but with jack midi turned on, // we don't get the messages. With jack stopped we get the messages - // no matter if jack midi is turned on or not. + // no matter if jack midi is turned on or not. Tim. //if (_openFlags & 1) { //if (!(_openFlags & 1)) @@ -176,95 +196,27 @@ void MidiAlsaDevice::close() void MidiAlsaDevice::writeRouting(int level, Xml& xml) const { - // p3.3.45 // If this device is not actually in use by the song, do not write any routes. - // This prevents bogus routes from being saved and propagated in the med file. + // This prevents bogus routes from being saved and propagated in the med file. Tim. if(midiPort() == -1) return; QString s; - /* - //if(rwFlags() & 2) // Readable - { - //RouteList* rl = _inRoutes; - //for (ciRoute r = rl->begin(); r != rl->end(); ++r) - for (ciRoute r = _inRoutes.begin(); r != _inRoutes.end(); ++r) - { - // Since an ALSA midi device supports read + write, this is the only way we can tell if this route is using the device as input. - if(r->type == Route::TRACK_ROUTE) - continue; - - if(!r->name().isEmpty()) - { - xml.tag(level++, "Route"); - - //xml.strTag(level, "srcNode", r->name()); - xml.tag(level, "source type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - - //xml.strTag(level, "dstNode", name()); - xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, name().toLatin1().constData()); - - xml.etag(level--, "Route"); - } - } - } - */ - for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) { - //if(r->type != Route::TRACK_ROUTE) - //{ - // printf("MidiAlsaDevice::writeRouting Warning out route is not TRACK_ROUTE type\n"); - // continue; - //} - if(!r->name().isEmpty()) { - //xml.tag(level++, "Route"); - s = QT_TRANSLATE_NOOP("@default", "Route"); if(r->channel != -1) s += QString(QT_TRANSLATE_NOOP("@default", " channel=\"%1\"")).arg(r->channel); xml.tag(level++, s.toLatin1().constData()); - - /* - //xml.strTag(level, "srcNode", name()); - if(r->channel != -1) - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, r->channel, name().toLatin1().constData()); - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, r->channel, name().toLatin1().constData()); - xml.tag(level, "source devtype=\"%d\" channel=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, r->channel, name().toLatin1().constData()); - else - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, name().toLatin1().constData()); - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, name().toLatin1().constData()); - */ - //xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, name().toLatin1().constData()); - xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, Xml::xmlString(name()).toLatin1().constData()); - - /* - //xml.strTag(level, "dstNode", r->name()); - if(r->channel != -1) - { - if(r->type == Route::MIDI_DEVICE_ROUTE) - xml.tag(level, "dest devtype=\"%d\" channel=\"%d\" name=\"%s\"/", r->device->deviceType(), r->channel, r->name().toLatin1().constData()); - else - xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", r->type, r->channel, r->name().toLatin1().constData()); - } - else - { - if(r->type == Route::MIDI_DEVICE_ROUTE) - xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", r->device->deviceType(), r->name().toLatin1().constData()); - else - xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - } - */ - + xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, Xml::xmlString(name()).toLatin1().constData()); s = QT_TRANSLATE_NOOP("@default", "dest"); if(r->type == Route::MIDI_DEVICE_ROUTE) s += QString(QT_TRANSLATE_NOOP("@default", " devtype=\"%1\"")).arg(r->device->deviceType()); else if(r->type != Route::TRACK_ROUTE) s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type); - //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name()); s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name())); xml.tag(level, s.toLatin1().constData()); @@ -279,7 +231,7 @@ void MidiAlsaDevice::writeRouting(int level, Xml& xml) const bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) { - if (midiOutputTrace) { + if (MusEGlobal::midiOutputTrace) { printf("MidiOut: midiAlsa: "); e.dump(); } @@ -311,12 +263,9 @@ bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) int a = e.dataA(); int b = e.dataB(); int chn = e.channel(); - // p3.3.37 - //if (a < 0x1000) { // 7 Bit Controller if (a < CTRL_14_OFFSET) { // 7 Bit Controller snd_seq_ev_set_controller(&event, chn, a, b); } - //else if (a < 0x20000) { // 14 bit high resolution controller else if (a < CTRL_RPN_OFFSET) { // 14 bit high resolution controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; @@ -324,7 +273,6 @@ bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) snd_seq_ev_set_controller(&event, chn, a, b); event.type = SND_SEQ_EVENT_CONTROL14; } - //else if (a < 0x30000) { // RPN 7-Bit Controller else if (a < CTRL_NRPN_OFFSET) { // RPN 7-Bit Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; @@ -333,7 +281,6 @@ bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) snd_seq_ev_set_controller(&event, chn, a, b); event.type = SND_SEQ_EVENT_REGPARAM; } - //else if (a < 0x40000) { // NRPN 7-Bit Controller else if (a < CTRL_INTERNAL_OFFSET) { // NRPN 7-Bit Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; @@ -342,7 +289,6 @@ bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) snd_seq_ev_set_controller(&event, chn, a, b); event.type = SND_SEQ_EVENT_NONREGPARAM; } - //else if (a < 0x60000) { // RPN14 Controller else if (a < CTRL_NRPN14_OFFSET) { // RPN14 Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; @@ -350,7 +296,6 @@ bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) snd_seq_ev_set_controller(&event, chn, a, b); event.type = SND_SEQ_EVENT_REGPARAM; } - //else if (a < 0x70000) { // NRPN14 Controller else if (a < CTRL_NONE_OFFSET) { // NRPN14 Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; @@ -451,13 +396,257 @@ bool MidiAlsaDevice::putEvent(snd_seq_event_t* event) } //--------------------------------------------------------- +// processMidi +// Called from ALSA midi sequencer thread only. +//--------------------------------------------------------- + +void MidiAlsaDevice::processMidi() +{ + bool stop = stopPending; // Snapshots + bool seek = seekPending; // + seekPending = stopPending = false; + // Transfer the stuck notes FIFO to the play events list. + // FIXME It would be faster to have MidiAlsaDevice automatically add the stuck note so that only + // one FIFO would be needed. But that requires passing an extra 'tick' and 'off velocity' in + // addScheduledEvent, which felt too weird. + while(!stuckNotesFifo.isEmpty()) + _stuckNotes.add(stuckNotesFifo.get()); + + bool extsync = extSyncFlag.value(); + //int frameOffset = getFrameOffset(); + //int nextTick = audio->nextTick(); + + // We're in the ALSA midi thread. audio->isPlaying() might not be true during seek right now. + //if(stop || (seek && audio->isPlaying())) + if(stop || seek) + { + //--------------------------------------------------- + // Clear all notes and handle stuck notes + //--------------------------------------------------- + playEventFifo.clear(); + _playEvents.clear(); + //printf("transferring stuck notes\n"); + for(iMPEvent i = _stuckNotes.begin(); i != _stuckNotes.end(); ++i) + { + //printf(" stuck note\n"); + MidiPlayEvent ev = *i; + ev.setTime(0); + _playEvents.add(ev); + } + _stuckNotes.clear(); + } + else + { + // Transfer the play events FIFO to the play events list. + while(!playEventFifo.isEmpty()) + _playEvents.add(playEventFifo.get()); + + /* TODO Handle these more directly than putting them into play events list. + //if(audio->isPlaying()) + { + iMPEvent k; + for (k = _stuckNotes.begin(); k != _stuckNotes.end(); ++k) { + if (k->time() >= nextTick) + break; + MidiPlayEvent ev(*k); + if(extsync) // p3.3.25 + ev.setTime(k->time()); + else + ev.setTime(tempomap.tick2frame(k->time()) + frameOffset); + _playEvents.add(ev); + } + _stuckNotes.erase(_stuckNotes.begin(), k); + } + */ + processStuckNotes(); + } + + /* Instead, done immediately in handleStop and handleSeek using putEvent. + if(stop) + { + // reset sustain... + MidiPort* mp = &midiPorts[_port]; + for(int ch = 0; ch < MIDI_CHANNELS; ++ch) + { + if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127) + { + //printf("send clear sustain!!!!!!!! port %d ch %d\n", i,ch); + MidiPlayEvent ev(0, _port, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0); + _playEvents.add(ev); + } + } + } + if(seek) + { + // Send new contoller values... + for(iMidiCtrlValList ivl = cll->begin(); ivl != cll->end(); ++ivl) + { + MidiCtrlValList* vl = ivl->second; + iMidiCtrlVal imcv = vl->iValue(pos); + if(imcv != vl->end()) { + Part* p = imcv->second.part; + unsigned t = (unsigned)imcv->first; + // Do not add values that are outside of the part. + if(p && t >= p->tick() && t < (p->tick() + p->lenTick()) ) + _playEvents.add(MidiPlayEvent(0, _port, ivl->first >> 24, ME_CONTROLLER, vl->num(), imcv->second.val)); + } + } + } */ + + if (_playEvents.empty()) + return; + + int port = midiPort(); + MidiPort* mp = port != -1 ? &midiPorts[port] : 0; + unsigned curFrame = audio->curFrame(); + int tickpos = audio->tickPos(); + + // Play all events up to current frame. + iMPEvent i = _playEvents.begin(); + for (; i != _playEvents.end(); ++i) { + if (i->time() > (extsync ? tickpos : curFrame)) // p3.3.25 Check: Should be nextTickPos? p4.0.34 + break; + if(mp){ + if (mp->sendEvent(*i)) + break; + } + else + if(putMidiEvent(*i)) + break; + } + _playEvents.erase(_playEvents.begin(), i); +} + +//--------------------------------------------------------- +// handleStop +//--------------------------------------------------------- + +void MidiAlsaDevice::handleStop() +{ + // If the device is not in use by a port, don't bother it. + if(_port == -1) + return; + + stopPending = true; // Trigger stop handling in processMidi. + + //--------------------------------------------------- + // reset sustain + //--------------------------------------------------- + + MidiPort* mp = &midiPorts[_port]; + for(int ch = 0; ch < MIDI_CHANNELS; ++ch) + { + if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127) + { + //printf("send clear sustain!!!!!!!! port %d ch %d\n", i,ch); + MidiPlayEvent ev(0, _port, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0); + putMidiEvent(ev); + } + } + + //--------------------------------------------------- + // send midi stop + //--------------------------------------------------- + + // Don't send if external sync is on. The master, and our sync routing system will take care of that. + if(!extSyncFlag.value()) + { + // Shall we check open flags? + //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1)) + //if(!(dev->openFlags() & 1)) + // return; + + MidiSyncInfo& si = mp->syncInfo(); + if(si.MMCOut()) + mp->sendMMCStop(); + + if(si.MRTOut()) + { + // Send STOP + mp->sendStop(); + + // Added check of option send continue not start. p3.3.31 + // Hmm, is this required? Seems to make other devices unhappy. + // (Could try now that this is in MidiDevice. p4.0.22 ) + //if(!si.sendContNotStart()) + // mp->sendSongpos(audio->tickPos() * 4 / config.division); + } + } +} + +//--------------------------------------------------------- +// handleSeek +//--------------------------------------------------------- + +void MidiAlsaDevice::handleSeek() +{ + // If the device is not in use by a port, don't bother it. + if(_port == -1) + return; + + seekPending = true; // Trigger seek handling in processMidi. + + MidiPort* mp = &midiPorts[_port]; + MidiCtrlValListList* cll = mp->controller(); + int pos = audio->tickPos(); + + //--------------------------------------------------- + // Send new contoller values + //--------------------------------------------------- + + for(iMidiCtrlValList ivl = cll->begin(); ivl != cll->end(); ++ivl) + { + MidiCtrlValList* vl = ivl->second; + iMidiCtrlVal imcv = vl->iValue(pos); + if(imcv != vl->end()) + { + Part* p = imcv->second.part; + unsigned t = (unsigned)imcv->first; + // Do not add values that are outside of the part. + if(p && t >= p->tick() && t < (p->tick() + p->lenTick()) ) + //_playEvents.add(MidiPlayEvent(0, _port, ivl->first >> 24, ME_CONTROLLER, vl->num(), imcv->second.val)); + // Hmm, play event list for immediate playback? Try putEvent instead. p4.0.34 + putMidiEvent(MidiPlayEvent(0, _port, ivl->first >> 24, ME_CONTROLLER, vl->num(), imcv->second.val)); + } + } + + //--------------------------------------------------- + // Send STOP and "set song position pointer" + //--------------------------------------------------- + + // Don't send if external sync is on. The master, and our sync routing system will take care of that. p3.3.31 + if(!extSyncFlag.value()) + { + if(mp->syncInfo().MRTOut()) + { + // Shall we check for device write open flag to see if it's ok to send?... + // This means obey what the user has chosen for read/write in the midi port config dialog, + // which already takes into account whether the device is writable or not. + //if(!(rwFlags() & 0x1) || !(openFlags() & 1)) + //if(!(openFlags() & 1)) + // continue; + + int beat = (pos * 4) / MusEConfig::config.division; + + //bool isPlaying = (state == PLAY); + bool isPlaying = audio->isPlaying(); // TODO Check this it includes LOOP1 and LOOP2 besides PLAY. p4.0.22 + + mp->sendStop(); + mp->sendSongpos(beat); + if(isPlaying) + mp->sendContinue(); + } + } +} + +//--------------------------------------------------------- // initMidiAlsa // return true on error //--------------------------------------------------------- bool initMidiAlsa() { - if (debugMsg) + if (MusEGlobal::debugMsg) printf("initMidiAlsa\n"); int error = snd_seq_open(&alsaSeq, "hw", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if (error < 0) { @@ -495,7 +684,7 @@ bool initMidiAlsa() if (capability & inCap) flags |= 2; dev->setrwFlags(flags); - if (debugMsg) + if (MusEGlobal::debugMsg) printf("ALSA port add: <%s>, %d:%d flags %d 0x%0x\n", snd_seq_port_info_get_name(pinfo), adr.client, adr.port, @@ -524,7 +713,6 @@ bool initMidiAlsa() } } - // p3.3.38 //snd_seq_set_client_name(alsaSeq, "MusE Sequencer"); snd_seq_set_client_name(alsaSeq, audioDevice->clientName()); @@ -750,7 +938,7 @@ void alsaProcessMidiInput() } if (mdev == 0 || curPort == -1) { - if (debugMsg) { + if (MusEGlobal::debugMsg) { fprintf(stderr, "no port %d:%d found for received alsa event\n", ev->source.client, ev->source.port); } @@ -758,31 +946,6 @@ void alsaProcessMidiInput() return; } - /* - if(curPort == -1) - { - if(mdev == 0) - { - if (debugMsg) - { - fprintf(stderr, "no port %d:%d found for received alsa event\n", - ev->source.client, ev->source.port); - } - } - else - { - // Allow the sync detect mechanisms to work, even if device is not assigned to a port. - if(ev->type == SND_SEQ_EVENT_CLOCK) - mdev->syncInfo().trigMCSyncDetect(); - else - if(ev->type == SND_SEQ_EVENT_TICK) - mdev->syncInfo().trigTickDetect(); - } - snd_seq_free_event(ev); - return; - } - */ - event.setType(0); // mark as unused event.setPort(curPort); event.setB(0); @@ -852,7 +1015,6 @@ void alsaProcessMidiInput() break; case SND_SEQ_EVENT_SYSEX: - // TODO: Deal with large sysex, which are broken up into chunks! // For now, do not accept if the first byte is not SYSEX or the last byte is not EOX, // meaning it's a chunk, possibly with more chunks to follow. @@ -901,13 +1063,7 @@ void alsaProcessMidiInput() break; } if(event.type()) - { mdev->recordEvent(event); - // p3.3.26 1/23/10 Moved to MidiDevice now. Anticipating Jack midi support, so don't make it ALSA specific. Tim. - //if(ev->type != SND_SEQ_EVENT_SYSEX) - // Trigger general activity indicator detector. Sysex has no channel, don't trigger. - // midiPorts[curPort].syncInfo().trigActDetect(event.channel()); - } snd_seq_free_event(ev); if (rv == 0) diff --git a/muse2/muse/driver/alsamidi.h b/muse2/muse/driver/alsamidi.h index a2480c5c..13e07ca4 100644 --- a/muse2/muse/driver/alsamidi.h +++ b/muse2/muse/driver/alsamidi.h @@ -3,6 +3,22 @@ // Linux Music Editor // $Id: alsamidi.h,v 1.2 2004/01/14 09:06:43 wschweer Exp $ // (C) Copyright 2001 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __ALSAMIDI_H__ @@ -11,6 +27,7 @@ #include <config.h> #include <alsa/asoundlib.h> +#include "mpevent.h" #include "mididev.h" class Xml; @@ -24,6 +41,13 @@ class MidiAlsaDevice : public MidiDevice { snd_seq_addr_t adr; private: + // Special for ALSA midi device: Play event list is processed in the ALSA midi sequencer thread. + // Need this FIFO, to decouple from audio thread which adds events to the list. + MidiFifo playEventFifo; + MidiFifo stuckNotesFifo; + volatile bool stopPending; + volatile bool seekPending; + virtual QString open(); virtual void close(); virtual void processInput() {} @@ -34,17 +58,22 @@ class MidiAlsaDevice : public MidiDevice { virtual bool putMidiEvent(const MidiPlayEvent&); public: - //MidiAlsaDevice() {} // p3.3.55 Removed MidiAlsaDevice(const snd_seq_addr_t&, const QString& name); virtual ~MidiAlsaDevice() {} - //virtual void* clientPort() { return (void*)&adr; } - // p3.3.55 virtual void* inClientPort() { return (void*)&adr; } // For ALSA midi, in/out client ports are the same. virtual void* outClientPort() { return (void*)&adr; } // That is, ALSA midi client ports can be both r/w. virtual void writeRouting(int, Xml&) const; virtual inline int deviceType() const { return ALSA_MIDI; } + // Schedule an event for playback. Returns false if event cannot be delivered. + virtual bool addScheduledEvent(const MidiPlayEvent& ev) { return !playEventFifo.put(ev); } + // Add a stuck note. Returns false if event cannot be delivered. + virtual bool addStuckNote(const MidiPlayEvent& ev) { return !stuckNotesFifo.put(ev); } + // Play all events up to current frame. + virtual void processMidi(); + virtual void handleStop(); + virtual void handleSeek(); }; extern bool initMidiAlsa(); diff --git a/muse2/muse/driver/alsatimer.cpp b/muse2/muse/driver/alsatimer.cpp index d851410d..dee661fe 100644 --- a/muse2/muse/driver/alsatimer.cpp +++ b/muse2/muse/driver/alsatimer.cpp @@ -7,6 +7,21 @@ // alsalib 1.0.7 // // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #include "alsatimer.h" diff --git a/muse2/muse/driver/alsatimer.h b/muse2/muse/driver/alsatimer.h index 211ba5ec..b906c02d 100644 --- a/muse2/muse/driver/alsatimer.h +++ b/muse2/muse/driver/alsatimer.h @@ -7,6 +7,21 @@ // alsalib 1.0.7 // // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __ALSATIMER_H__ diff --git a/muse2/muse/driver/audiodev.h b/muse2/muse/driver/audiodev.h index 4685b89a..3fe06fb9 100644 --- a/muse2/muse/driver/audiodev.h +++ b/muse2/muse/driver/audiodev.h @@ -4,6 +4,21 @@ // $Id: audiodev.h,v 1.5.2.2 2009/12/20 05:00:35 terminator356 Exp $ // // (C) Copyright 1999/2000 Werner Schweer (ws@seh.de) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __AUDIODEV_H__ diff --git a/muse2/muse/driver/dummyaudio.cpp b/muse2/muse/driver/dummyaudio.cpp index 55f091c2..4466e293 100644 --- a/muse2/muse/driver/dummyaudio.cpp +++ b/muse2/muse/driver/dummyaudio.cpp @@ -3,6 +3,21 @@ // Linux Music Editor // $Id: dummyaudio.cpp,v 1.3.2.16 2009/12/20 05:00:35 terminator356 Exp $ // (C) Copyright 2002-2003 Werner Schweer (ws@seh.de) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #include <stdio.h> @@ -83,7 +98,7 @@ class DummyAudioDevice : public AudioDevice { // p3.3.30 //if (nframes > dummyFrames) { //printf("error: segment size > 1024\n"); - if (nframes > segmentSize) { + if (nframes > MusEGlobal::segmentSize) { printf("DummyAudioDevice::getBuffer nframes > segment size\n"); exit(-1); @@ -125,7 +140,7 @@ class DummyAudioDevice : public AudioDevice { return _framePos; } virtual unsigned frameTime() const { - return lrint(curTime() * sampleRate); + return lrint(MusEUtil::curTime() * MusEGlobal::sampleRate); } virtual bool isRealtime() { return realtimeFlag; } //virtual int realtimePriority() const { return 40; } @@ -200,18 +215,20 @@ DummyAudioDevice::DummyAudioDevice() // Added by Tim. p3.3.15 // p3.3.30 //posix_memalign((void**)&buffer, 16, sizeof(float) * dummyFrames); - posix_memalign((void**)&buffer, 16, sizeof(float) * config.dummyAudioBufSize); + posix_memalign((void**)&buffer, 16, sizeof(float) * MusEConfig::config.dummyAudioBufSize); dummyThread = 0; realtimeFlag = false; seekflag = false; state = Audio::STOP; - //startTime = curTime(); + //startTime = MusEUtil::curTime(); _framePos = 0; playPos = 0; cmdQueue.clear(); } +namespace MusEApp { + //--------------------------------------------------------- // exitDummyAudio //--------------------------------------------------------- @@ -224,6 +241,8 @@ void exitDummyAudio() audioDevice = NULL; } +} // namespace MusEApp + //--------------------------------------------------------- // initDummyAudio //--------------------------------------------------------- @@ -274,13 +293,13 @@ static void* dummyLoop(void* ptr) //unsigned int tickRate = 25; // p3.3.30 - //sampleRate = 25600; - sampleRate = config.dummyAudioSampleRate; - //segmentSize = dummyFrames; - segmentSize = config.dummyAudioBufSize; + //MusEGlobal::sampleRate = 25600; + MusEGlobal::sampleRate = MusEConfig::config.dummyAudioSampleRate; + //MusEGlobal::segmentSize = dummyFrames; + MusEGlobal::segmentSize = MusEConfig::config.dummyAudioBufSize; #if 0 - //unsigned int tickRate = sampleRate / dummyFrames; - unsigned int tickRate = sampleRate / segmentSize; + //unsigned int tickRate = MusEGlobal::sampleRate / dummyFrames; + unsigned int tickRate = MusEGlobal::sampleRate / MusEGlobal::segmentSize; AlsaTimer timer; fprintf(stderr, "Get alsa timer for dummy driver:\n"); @@ -297,7 +316,7 @@ static void* dummyLoop(void* ptr) /* Depending on nature of the timer, the requested tickRate might not * be available. The return value is the nearest available frequency, - * so use this to reset our dummpy sampleRate to keep everything + * so use this to reset our dummpy MusEGlobal::sampleRate to keep everything * consistent. */ tickRate = timer.setTimerFreq( /*250*/ tickRate ); @@ -307,7 +326,7 @@ static void* dummyLoop(void* ptr) if(tickRate == 0) tickRate = timer.getTimerFreq(); - sampleRate = tickRate * segmentSize; + MusEGlobal::sampleRate = tickRate * MusEGlobal::segmentSize; timer.startTimer(); #endif @@ -320,7 +339,7 @@ static void* dummyLoop(void* ptr) /* - doSetuid(); + MusEGlobal::doSetuid(); struct sched_param rt_param; int rv; memset(&rt_param, 0, sizeof(sched_param)); @@ -349,13 +368,13 @@ static void* dummyLoop(void* ptr) fprintf(stderr, "Unable to set thread to SCHED_FIFO\n"); } } - undoSetuid(); + MusEGlobal::undoSetuid(); */ #ifndef __APPLE__ - doSetuid(); + MusEGlobal::doSetuid(); //if (realTimePriority) { - if (realTimeScheduling) { + if (MusEGlobal::realTimeScheduling) { // // check if we really got realtime priviledges // @@ -367,7 +386,7 @@ static void* dummyLoop(void* ptr) { if (policy != SCHED_FIFO) printf("audio dummy thread _NOT_ running SCHED_FIFO\n"); - else if (debugMsg) { + else if (MusEGlobal::debugMsg) { struct sched_param rt_param; memset(&rt_param, 0, sizeof(sched_param)); int type; @@ -379,7 +398,7 @@ static void* dummyLoop(void* ptr) } } } - undoSetuid(); + MusEGlobal::undoSetuid(); #endif #if 0 @@ -423,8 +442,8 @@ static void* dummyLoop(void* ptr) } } } - audio->process(segmentSize); - int increment = segmentSize; // 1 //tickRate / sampleRate * segmentSize; + audio->process(MusEGlobal::segmentSize); + int increment = MusEGlobal::segmentSize; // 1 //tickRate / MusEGlobal::sampleRate * MusEGlobal::segmentSize; drvPtr->_framePos+=increment; if (drvPtr->state == Audio::PLAY) { @@ -437,12 +456,12 @@ static void* dummyLoop(void* ptr) { //if(audioState == AUDIO_RUNNING) if(audio->isRunning()) - //audio->process(segmentSize, drvPtr->state); - audio->process(segmentSize); + //audio->process(MusEGlobal::segmentSize, drvPtr->state); + audio->process(MusEGlobal::segmentSize); //else if (audioState == AUDIO_START1) // audioState = AUDIO_START2; - //usleep(dummyFrames*1000000/AL::sampleRate); - usleep(segmentSize*1000000/sampleRate); + //usleep(dummyFrames*1000000/AL::MusEGlobal::sampleRate); + usleep(MusEGlobal::segmentSize*1000000/MusEGlobal::sampleRate); //if(dummyAudio->seekflag) if(drvPtr->seekflag) { @@ -456,9 +475,9 @@ static void* dummyLoop(void* ptr) //if(dummyAudio->state == Audio::PLAY) // dummyAudio->pos += dummyFrames; - drvPtr->_framePos += segmentSize; + drvPtr->_framePos += MusEGlobal::segmentSize; if(drvPtr->state == Audio::PLAY) - drvPtr->playPos += segmentSize; + drvPtr->playPos += MusEGlobal::segmentSize; } #endif @@ -472,7 +491,7 @@ void DummyAudioDevice::start(int priority) _realTimePriority = priority; pthread_attr_t* attributes = 0; - if (realTimeScheduling && _realTimePriority > 0) { + if (MusEGlobal::realTimeScheduling && _realTimePriority > 0) { attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t)); pthread_attr_init(attributes); @@ -499,11 +518,11 @@ void DummyAudioDevice::start(int priority) int rv = pthread_create(&dummyThread, attributes, ::dummyLoop, this); if(rv) { - // p4.0.16: realTimeScheduling is unreliable. It is true even in some clearly non-RT cases. + // p4.0.16: MusEGlobal::realTimeScheduling is unreliable. It is true even in some clearly non-RT cases. // I cannot seem to find a reliable answer to the question of "are we RT or not". // MusE was failing with a stock kernel because of PTHREAD_EXPLICIT_SCHED. // So we'll just have to try again without attributes. - if (realTimeScheduling && _realTimePriority > 0) + if (MusEGlobal::realTimeScheduling && _realTimePriority > 0) rv = pthread_create(&dummyThread, NULL, ::dummyLoop, this); } diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp index 529e8a60..31179ea3 100644 --- a/muse2/muse/driver/jack.cpp +++ b/muse2/muse/driver/jack.cpp @@ -3,6 +3,21 @@ // Linux Music Editor // $Id: jack.cpp,v 1.30.2.17 2009/12/20 05:00:35 terminator356 Exp $ // (C) Copyright 2002 Werner Schweer (ws@seh.de) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #include "config.h" @@ -39,8 +54,8 @@ //#include "errorhandler.h" #ifndef RTCAP -extern void doSetuid(); -extern void undoSetuid(); +extern void MusEGlobal::doSetuid(); +extern void MusEGlobal::undoSetuid(); #endif #ifdef VST_SUPPORT @@ -69,19 +84,6 @@ inline bool checkJackClient(jack_client_t* _client) } return true; } -//--------------------------------------------------------- -// checkAudioDevice - make sure audioDevice exists -//--------------------------------------------------------- -bool checkAudioDevice() - { - if (audioDevice == NULL) { - if(debugMsg) - printf("Muse:checkAudioDevice: no audioDevice\n"); - return false; - } - return true; - } - //--------------------------------------------------------- // jack_thread_init @@ -89,7 +91,7 @@ bool checkAudioDevice() static void jack_thread_init (void* ) // data { - doSetuid(); + MusEGlobal::doSetuid(); /* if (jackAudio->isRealtime()) { struct sched_param rt_param; @@ -123,7 +125,7 @@ static void jack_thread_init (void* ) // data if (loadVST) fst_adopt_thread(); #endif - undoSetuid(); + MusEGlobal::undoSetuid(); } /* @@ -272,11 +274,11 @@ int JackAudioDevice::processAudio(jack_nframes_t frames, void*) // if (JACK_DEBUG) // printf("processAudio - >>>>\n"); - segmentSize = frames; + MusEGlobal::segmentSize = frames; if (audio->isRunning()) audio->process((unsigned long)frames); else { - if (debugMsg) + if (MusEGlobal::debugMsg) puts("jack calling when audio is disconnected!\n"); } // if (JACK_DEBUG) @@ -396,7 +398,7 @@ static void processShutdown(void*) audio->shutdown(); int c=0; - while(midiSeqRunning == true) { + while(MusEGlobal::midiSeqRunning == true) { if(c++ >10) { fprintf(stderr, "sequencer still running, something is very wrong.\n"); break; @@ -540,13 +542,13 @@ bool initJackAudio() if (JACK_DEBUG) printf("initJackAudio()\n"); - if (debugMsg) { + if (MusEGlobal::debugMsg) { fprintf(stderr,"initJackAudio()\n"); jack_set_error_function(jackError); } else jack_set_error_function(noJackError); - doSetuid(); + MusEGlobal::doSetuid(); //jack_client_t* client = 0; //int i = 0; @@ -574,25 +576,25 @@ bool initJackAudio() if (status & JackVersionError) printf("jack server has wrong version\n"); printf("cannot create jack client\n"); - undoSetuid(); // p3.3.51 + MusEGlobal::undoSetuid(); // p3.3.51 return true; } - if (debugMsg) + if (MusEGlobal::debugMsg) fprintf(stderr, "initJackAudio(): client %s opened.\n", jack_get_client_name(client)); if (client) { jack_set_error_function(jackError); //jackAudio = new JackAudioDevice(client, jackIdString); jackAudio = new JackAudioDevice(client, jack_get_client_name(client)); - if (debugMsg) + if (MusEGlobal::debugMsg) fprintf(stderr, "initJackAudio(): registering client...\n"); jackAudio->registerClient(); - sampleRate = jack_get_sample_rate(client); - segmentSize = jack_get_buffer_size(client); + MusEGlobal::sampleRate = jack_get_sample_rate(client); + MusEGlobal::segmentSize = jack_get_buffer_size(client); jack_set_thread_init_callback(client, (JackThreadInitCallback) jack_thread_init, 0); //jack_set_timebase_callback(client, 0, (JackTimebaseCallback) timebase_callback, 0); } - undoSetuid(); + MusEGlobal::undoSetuid(); /* // setup midi input/output @@ -647,14 +649,14 @@ static int bufsize_callback(jack_nframes_t n, void*) static void freewheel_callback(int starting, void*) { - if (debugMsg || JACK_DEBUG) + if (MusEGlobal::debugMsg || JACK_DEBUG) printf("JACK: freewheel_callback: starting%d\n", starting); audio->setFreewheel(starting); } static int srate_callback(jack_nframes_t n, void*) { - if (debugMsg || JACK_DEBUG) + if (MusEGlobal::debugMsg || JACK_DEBUG) printf("JACK: sample rate changed: %d\n", n); return 0; } @@ -665,7 +667,7 @@ static int srate_callback(jack_nframes_t n, void*) static void registration_callback(jack_port_id_t, int, void*) { - if(debugMsg || JACK_DEBUG) + if(MusEGlobal::debugMsg || JACK_DEBUG) printf("JACK: registration changed\n"); audio->sendMsgToGui('R'); @@ -743,7 +745,7 @@ void JackAudioDevice::connectJackMidiPorts() // Ignore our own client ports. if(jack_port_is_mine(_client, port)) { - if(debugMsg) + if(MusEGlobal::debugMsg) printf(" ignoring own port: %s\n", *p); continue; } @@ -754,7 +756,7 @@ void JackAudioDevice::connectJackMidiPorts() //if(strncmp(buffer, "MusE", 4) == 0) // continue; - if(debugMsg) + if(MusEGlobal::debugMsg) printf(" found port: %s ", buffer); // If there are aliases for this port, use the first one - much better for identifying. @@ -770,7 +772,7 @@ void JackAudioDevice::connectJackMidiPorts() //char* namep = (na >= 1) ? aliases[0] : buffer; char* namep = aliases[0]; - if(debugMsg) + if(MusEGlobal::debugMsg) printf("alias: %s\n", aliases[0]); //int flags = 0; @@ -847,7 +849,7 @@ void JackAudioDevice::connectJackMidiPorts() static void client_registration_callback(const char *name, int isRegister, void*) { - if (debugMsg || JACK_DEBUG) + if (MusEGlobal::debugMsg || JACK_DEBUG) printf("JACK: client registration changed:%s register:%d\n", name, isRegister); } @@ -857,7 +859,7 @@ static void client_registration_callback(const char *name, int isRegister, void* static void port_connect_callback(jack_port_id_t a, jack_port_id_t b, int isConnect, void*) { - if (debugMsg || JACK_DEBUG) + if (MusEGlobal::debugMsg || JACK_DEBUG) { //jack_port_t* ap = jack_port_by_id(_client, a); //jack_port_t* bp = jack_port_by_id(_client, b); @@ -880,7 +882,7 @@ static int graph_callback(void*) // context, so we send a message to the gui thread which in turn // calls graphChanged() audio->sendMsgToGui('C'); - if (debugMsg) + if (MusEGlobal::debugMsg) printf("JACK: graph changed\n"); return 0; } @@ -1368,6 +1370,26 @@ void* JackAudioDevice::registerOutPort(const char* name, bool midi) return p; } +namespace MusEGlobal { + +//--------------------------------------------------------- +// checkAudioDevice - make sure audioDevice exists +//--------------------------------------------------------- + +bool checkAudioDevice() + { + if (audioDevice == NULL) { + if(MusEGlobal::debugMsg) + printf("Muse:checkAudioDevice: no audioDevice\n"); + return false; + } + return true; + } + +} // namespace MusEGlobal + +namespace MusEApp { + //--------------------------------------------------------- // exitJackAudio //--------------------------------------------------------- @@ -1386,6 +1408,7 @@ void exitJackAudio() audioDevice = NULL; } +} // namespace MusEApp //--------------------------------------------------------- // connect @@ -1458,10 +1481,10 @@ void JackAudioDevice::start(int /*priority*/) printf("JackAudioDevice::start()\n"); if(!checkJackClient(_client)) return; - doSetuid(); + MusEGlobal::doSetuid(); if (jack_activate(_client)) { - undoSetuid(); // p3.3.51 + MusEGlobal::undoSetuid(); // p3.3.51 fprintf (stderr, "JACK: cannot activate client\n"); exit(-1); } @@ -1503,7 +1526,7 @@ void JackAudioDevice::start(int /*priority*/) // Connect the Jack midi client ports to device ports. connectJackMidiPorts(); - undoSetuid(); + MusEGlobal::undoSetuid(); //MUSE_DEBUG("JackAudioDevice::start()\n"); fflush(stdin); @@ -1594,7 +1617,7 @@ int JackAudioDevice::framesSinceCycleStart() const int JackAudioDevice::frameDelay() const { - jack_nframes_t n = (segmentSize * (segmentCount-1)) - jack_frames_since_cycle_start(client); + jack_nframes_t n = (MusEGlobal::segmentSize * (segmentCount-1)) - jack_frames_since_cycle_start(client); return (int)n; } #endif @@ -1625,7 +1648,7 @@ std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases) strncpy(buffer, *p, nsz); //if (strncmp(buffer, "MusE", 4) == 0) //{ - // if(debugMsg) + // if(MusEGlobal::debugMsg) // printf("JackAudioDevice::outputPorts ignoring own MusE port: %s\n", *p); // continue; //} @@ -1633,7 +1656,7 @@ std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases) // Ignore our own client ports. if(jack_port_is_mine(_client, port)) { - if(debugMsg) + if(MusEGlobal::debugMsg) printf("JackAudioDevice::outputPorts ignoring own port: %s\n", *p); continue; } @@ -1698,7 +1721,7 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases) strncpy(buffer, *p, nsz); //if (strncmp(buffer, "MusE", 4) == 0) //{ - // if(debugMsg) + // if(MusEGlobal::debugMsg) // printf("JackAudioDevice::inputPorts ignoring own MusE port: %s\n", *p); // continue; //} @@ -1706,7 +1729,7 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases) // Ignore our own client ports. if(jack_port_is_mine(_client, port)) { - if(debugMsg) + if(MusEGlobal::debugMsg) printf("JackAudioDevice::inputPorts ignoring own port: %s\n", *p); continue; } @@ -1842,14 +1865,14 @@ void JackAudioDevice::setFreewheel(bool f) bool JackAudioDevice::dummySync(int state) { // Roughly segment time length. - //timespec ts = { 0, (1000000000 * segmentSize) / sampleRate }; // In nanoseconds. - unsigned int sl = (1000000 * segmentSize) / sampleRate; // In microseconds. + //timespec ts = { 0, (1000000000 * MusEGlobal::segmentSize) / MusEGlobal::sampleRate }; // In nanoseconds. + unsigned int sl = (1000000 * MusEGlobal::segmentSize) / MusEGlobal::sampleRate; // In microseconds. - double ct = curTime(); + double ct = MusEUtil::curTime(); // Wait for a default maximum of 5 seconds. // Similar to how Jack is supposed to wait a default of 2 seconds for slow clients. // TODO: Make this timeout a 'settings' option so it can be applied both to Jack and here. - while((curTime() - ct) < 5.0) + while((MusEUtil::curTime() - ct) < 5.0) { // Is MusE audio ready to roll? if(audio->sync(state, dummyPos)) @@ -2057,7 +2080,7 @@ int JackAudioDevice::setMaster(bool f) { // Make Muse the Jack timebase master. Do it unconditionally (second param = 0). r = jack_set_timebase_callback(_client, 0, (JackTimebaseCallback) timebase_callback, 0); - if(debugMsg || JACK_DEBUG) + if(MusEGlobal::debugMsg || JACK_DEBUG) { if(r) printf("JackAudioDevice::setMaster jack_set_timebase_callback failed: result:%d\n", r); @@ -2072,7 +2095,7 @@ int JackAudioDevice::setMaster(bool f) else { r = jack_release_timebase(_client); - if(debugMsg || JACK_DEBUG) + if(MusEGlobal::debugMsg || JACK_DEBUG) { if(r) printf("JackAudioDevice::setMaster jack_release_timebase failed: result:%d\n", r); @@ -2087,7 +2110,7 @@ int JackAudioDevice::setMaster(bool f) void JackAudioDevice::scanMidiPorts() { - if(debugMsg) + if(MusEGlobal::debugMsg) printf("JackAudioDevice::scanMidiPorts:\n"); /* @@ -2103,7 +2126,7 @@ void JackAudioDevice::scanMidiPorts() // Ignore our own client ports. if(jack_port_is_mine(_client, port)) { - if(debugMsg) + if(MusEGlobal::debugMsg) printf(" ignoring own port: %s\n", *p); continue; } @@ -2115,7 +2138,7 @@ void JackAudioDevice::scanMidiPorts() //if(strncmp(buffer, "MusE", 4) == 0) // continue; - if(debugMsg) + if(MusEGlobal::debugMsg) printf(" found port: %s ", buffer); // If there are aliases for this port, use the first one - much better for identifying. @@ -2131,7 +2154,7 @@ void JackAudioDevice::scanMidiPorts() //char* namep = (na >= 1) ? aliases[0] : buffer; //char* namep = aliases[0]; //names.insert(std::string(*p)); - if(debugMsg) + if(MusEGlobal::debugMsg) printf("alias: %s\n", aliases[0]); names.insert(std::string(aliases[0])); @@ -2151,7 +2174,7 @@ void JackAudioDevice::scanMidiPorts() for(std::list<MidiDevice*>::iterator imd = to_del.begin(); imd != to_del.end(); ++imd) { - if(debugMsg) + if(MusEGlobal::debugMsg) printf(" removing port device:%s\n", (*imd)->name().toLatin1()); midiDevices.remove(*imd); // This will close (and unregister) the client port. @@ -2212,7 +2235,7 @@ void JackAudioDevice::scanMidiPorts() //JackPort jp(0, QString(buffer), flags); //portList.append(jp); - if(debugMsg) + if(MusEGlobal::debugMsg) printf(" adding port device:%s\n", qname.toLatin1()); MidiJackDevice* dev = new MidiJackDevice(0, qname); diff --git a/muse2/muse/driver/jackaudio.h b/muse2/muse/driver/jackaudio.h index 5be0797f..d116a2ff 100644 --- a/muse2/muse/driver/jackaudio.h +++ b/muse2/muse/driver/jackaudio.h @@ -3,6 +3,21 @@ // Linux Music Editor // $Id: jackaudio.h,v 1.20.2.4 2009/12/20 05:00:35 terminator356 Exp $ // (C) Copyright 2002 Werner Schweer (ws@seh.de) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __JACKAUDIO_H__ @@ -13,10 +28,13 @@ class MidiPlayEvent; +namespace MusEGlobal { +bool checkAudioDevice(); +} + //--------------------------------------------------------- // JackAudioDevice //--------------------------------------------------------- -bool checkAudioDevice(); class JackAudioDevice : public AudioDevice { diff --git a/muse2/muse/driver/jackmidi.cpp b/muse2/muse/driver/jackmidi.cpp index e514af7a..a4577f0b 100644 --- a/muse2/muse/driver/jackmidi.cpp +++ b/muse2/muse/driver/jackmidi.cpp @@ -3,6 +3,22 @@ // Linux Music Editor // $Id: jackmidi.cpp,v 1.1.1.1 2010/01/27 09:06:43 terminator356 Exp $ // (C) Copyright 1999-2010 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #include <QString> @@ -33,128 +49,16 @@ extern unsigned int volatile lastExtMidiSyncTick; -///int jackmidi_pi[2]; -///int jackmidi_po[2]; - -//extern muse_jack_midi_buffer jack_midi_out_data[JACK_MIDI_CHANNELS]; -//extern muse_jack_midi_buffer jack_midi_in_data[JACK_MIDI_CHANNELS]; -///extern jack_port_t *midi_port_in[JACK_MIDI_CHANNELS]; -///extern jack_port_t *midi_port_out[JACK_MIDI_CHANNELS]; - -///MidiJackDevice* gmdev = NULL; - -///int* jackSeq; -//static snd_seq_addr_t musePort; - -//int MidiJackDevice::_nextOutIdNum = 0; -//int MidiJackDevice::_nextInIdNum = 0; - -//int JackMidiPortList::_nextOutIdNum = 0; -//int JackMidiPortList::_nextInIdNum = 0; - -//JackMidiPortList jackMidiClientPorts; - - -/* -//--------------------------------------------------------- -// JackMidiPortList -//--------------------------------------------------------- - -JackMidiPortList::JackMidiPortList() -{ - -} - -JackMidiPortList::~JackMidiPortList() -{ - -} - -iJackMidiPort JackMidiPortList::createClientPort(int flags) // 1 = writable, 2 = readable - do not mix -{ - if(flags & 1) - { - char buf[80]; - snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum); - jack_port_t* _client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true); - if(_client_jackport == NULL) - { - fprintf(stderr, "JackMidiPortList::createClientPort failed to register jack-midi-out\n"); - //return QString("Could not register jack-midi-out client port"); - return end(); - } - else - { - JackMidiPort jmp(_client_jackport, QString(buf), flags); - _nextOutIdNum++; - return insert(begin(), std::pair<jack_port_t*, JackMidiPort>(_client_jackport, jmp)); - } - } - else - if(flags & 2) - { - char buf[80]; - snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum); - jack_port_t* _client_jackport = (jack_port_t*)audioDevice->registerInPort(buf, true); - if(_client_jackport == NULL) - { - fprintf(stderr, "JackMidiPortList::createClientPort failed to register jack-midi-in\n"); - return end(); - } - else - { - JackMidiPort jmp(_client_jackport, QString(buf), flags); - _nextInIdNum++; - return insert(begin(), std::pair<jack_port_t*, JackMidiPort>(_client_jackport, jmp)); - } - } - return end(); -} - -// Return true if removed. -bool JackMidiPortList::removeClientPort(jack_port_t* port) -{ - iJackMidiPort ijp = find(port); - if(ijp == end()) - return false; - - // Is output? - if(ijp->second._flags & 1) - _nextOutIdNum--; - // Is input? - if(ijp->second._flags & 2) - _nextInIdNum--; - - erase(ijp); - - audioDevice->unregisterPort(port); - - return true; -} -*/ - //--------------------------------------------------------- // MidiJackDevice // in_jack_port or out_jack_port can be null //--------------------------------------------------------- -//MidiJackDevice::MidiJackDevice(const int& a, const QString& n) -//MidiJackDevice::MidiJackDevice(jack_port_t* jack_port, const QString& n) -// p3.3.55 -//MidiJackDevice::MidiJackDevice(jack_port_t* in_jack_port, jack_port_t* out_jack_port, const QString& n) MidiJackDevice::MidiJackDevice(const QString& n) : MidiDevice(n) { - //_client_jackport = 0; - - //_client_jackport = jack_port; - // p3.3.55 - //_in_client_jackport = in_jack_port; - //_out_client_jackport = out_jack_port; _in_client_jackport = NULL; _out_client_jackport = NULL; - - //adr = a; init(); } @@ -164,10 +68,6 @@ MidiJackDevice::~MidiJackDevice() printf("MidiJackDevice::~MidiJackDevice()\n"); #endif - //if(_client_jackport) - // audioDevice->unregisterPort(_client_jackport); - // p3.3.55 - if(audioDevice) { if(_in_client_jackport) @@ -179,69 +79,13 @@ MidiJackDevice::~MidiJackDevice() //close(); } -/* -//--------------------------------------------------------- -// select[RW]fd -//--------------------------------------------------------- - -int MidiJackDevice::selectRfd() -{ - return jackmidi_pi[0]; -} - -int MidiJackDevice::selectWfd() -{ - return jackmidi_po[0]; -} -*/ - //--------------------------------------------------------- // createJackMidiDevice // If name parameter is blank, creates a new (locally) unique one. //--------------------------------------------------------- -//QString MidiJackDevice::createJackMidiDevice(int rwflags) // 1:Writable 2: Readable. Do not mix. -//MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1:Writable 2: Readable. Do not mix. -MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // p3.3.55 1:Writable 2: Readable 3: Writable + Readable +MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1:Writable 2: Readable 3: Writable + Readable { -/// _openFlags &= _rwFlags; // restrict to available bits - -/// #ifdef JACK_MIDI_DEBUG -/// printf("MidiJackDevice::open %s\n", name.toLatin1().constData()); -/// #endif - - //jack_port_t* jp = jack_port_by_name(_client, name().toLatin1().constData()); -/// jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().toLatin1().constData()); - -/// if(!jp) -/// { -/// printf("MidiJackDevice::open: Jack midi port %s not found!\n", name().toLatin1().constData()); -/// _writeEnable = false; -/// _readEnable = false; -/// return QString("Jack midi port not found"); -/// } - -/// int pf = jack_port_flags(jp); - - //if(!name.isEmpty()) - //{ - // Does not work. - // if(audioDevice->findPort(name.toLatin1().constData())) - // { - // fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Given port name %s already exists!\n", name.toLatin1().constData()); - // return 0; - // } - //} - - //jack_port_t* client_jackport = NULL; - // p3.3.55 - ///jack_port_t* in_client_jackport = NULL; - ///jack_port_t* out_client_jackport = NULL; - - //char buf[80]; - - - // p3.3.55 int ni = 0; if(name.isEmpty()) { @@ -258,188 +102,7 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // p return 0; } - // If Jack port can receive data from us and we actually want to... - //if((pf & JackPortIsInput) && (_openFlags & 1)) - ///if(rwflags & 1) - ///{ - /* p3.3.55 Removed. - if(name.isEmpty()) - { - //snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum); - for(int i = 0; ; ++i) - { - //snprintf(buf, 80, "midi-out-%d", i); - name.sprintf("midi-out-%d", i); - - if(!midiDevices.find(name)) - { - // Does not work. - //if(!audioDevice->findPort(buf)) - // break; - //client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true); - if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 - { - //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true); - out_client_jackport = (jack_port_t*)audioDevice->registerOutPort((name + QString("_out")).toLatin1().constData(), true); // p3.3.55 - //if(client_jackport) - if(out_client_jackport) // p3.3.55 - break; - } - else - break; - } - - if(i == 65535) - { - fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Can't find unused output port name!\n"); - return 0; - } - } - //name = QString(buf); - } - else - */ - - /* - { - if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 - { - //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true); - out_client_jackport = (jack_port_t*)audioDevice->registerOutPort((name + QString(JACK_MIDI_OUT_PORT_SUFFIX)).toLatin1().constData(), true); // p3.3.55 - //if(!client_jackport) - if(!out_client_jackport) // p3.3.55 - { - //fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed creating output port name %s\n", name.toLatin1().constData()); - fprintf(stderr, "MusE: createJackMidiDevice failed creating output port name %s\n", (name + QString(JACK_MIDI_OUT_PORT_SUFFIX)).toLatin1().constData()); // p3.3.55 - - //return 0; - rwflags &= ~1; // p3.3.55 Remove the output r/w flag, but continue on... - } - } - } - */ - - /* - else - { - client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true); - if(!client_jackport) - { - for(int i = 0; ; ++i) - { - snprintf(buf, 80, "midi-out-%d", i); - // Does not work! - //if(!audioDevice->findPort(buf)) - // break; - client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true); - if(client_jackport) - break; - - if(i == 65535) - { - fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Can't find unused output port name!\n"); - return 0; - } - } - name = QString(buf); - } - } - */ - - //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true); - //if(client_jackport == NULL) - //{ - // fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed to register jack midi client output port %s\n", name.toLatin1().constData()); - // return 0; - //} - //else - // _nextOutIdNum++; - - ///} - //else // Note docs say it can't be both input and output. // p3.3.55 Removed - - // If Jack port can send data to us and we actually want it... - //if((pf & JackPortIsOutput) && (_openFlags & 2)) - ///if(rwflags & 2) - ///{ - /* p3.3.55 Removed. - if(name.isEmpty()) - { - //snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum); - for(int i = 0; ; ++i) - { - //snprintf(buf, 80, "midi-in-%d", i); - name.sprintf("midi-in-%d", i); - - if(!midiDevices.find(name)) - { - // Does not work. - //if(!audioDevice->findPort(buf)) - // break; - //client_jackport = (jack_port_t*)audioDevice->registerInPort(buf, true); - if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 - { - //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true); - in_client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true); // p3.3.55 - //if(client_jackport) - if(in_client_jackport) // p3.3.55 - break; - } - else - break; - } - - if(i == 65535) - { - fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Can't find unused input port name!\n"); - return 0; - } - } - //name = QString(buf); - } - else - */ - - /* - { - if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 - { - //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true); - in_client_jackport = (jack_port_t*)audioDevice->registerInPort((name + QString(JACK_MIDI_IN_PORT_SUFFIX)).toLatin1().constData(), true); // p3.3.55 - //if(!client_jackport) - if(!in_client_jackport) // p3.3.55 - { - //fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed creating input port name %s\n", name.toLatin1().constData()); - fprintf(stderr, "MusE: createJackMidiDevice failed creating input port name %s\n", (name + QString(JACK_MIDI_IN_PORT_SUFFIX)).toLatin1().constData()); - - //return 0; - rwflags &= ~2; // p3.3.55 Remove the input r/w flag, but continue on... - } - } - } - */ - - //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true); - - //if(client_jackport == NULL) - //{ - // fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed to register jack midi client input port %s\n", name.toLatin1().constData()); - //_readEnable = false; - //return QString("Could not register jack-midi-in client port"); - // return 0; - //} - //else - // _nextInIdNum++; - - ///} - - //if(client_jackport == NULL) // p3.3.52 Removed. Allow the device to be created even if Jack isn't running. - // return 0; - - //MidiJackDevice* dev = new MidiJackDevice(client_jackport, name); - //MidiJackDevice* dev = new MidiJackDevice(in_client_jackport, out_client_jackport, name); // p3.3.55 - //MidiJackDevice* dev = new MidiJackDevice(NULL, NULL, name); // p3.3.55 - MidiJackDevice* dev = new MidiJackDevice(name); // p3.3.55 + MidiJackDevice* dev = new MidiJackDevice(name); dev->setrwFlags(rwflags); midiDevices.add(dev); return dev; @@ -456,9 +119,6 @@ void MidiJackDevice::setName(const QString& s) #endif _name = s; - //if(clientPort()) // p3.3.52 Added check. - // audioDevice->setPortName(clientPort(), s.toLatin1().constData()); - // p3.3.55 if(inClientPort()) audioDevice->setPortName(inClientPort(), (s + QString(JACK_MIDI_IN_PORT_SUFFIX)).toLatin1().constData()); if(outClientPort()) @@ -477,65 +137,7 @@ QString MidiJackDevice::open() printf("MidiJackDevice::open %s\n", name().toLatin1().constData()); #endif - /* - //jack_port_t* jp = jack_port_by_name(_client, name().toLatin1().constData()); - jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().toLatin1().constData()); - - if(!jp) - { - printf("MidiJackDevice::open: Jack midi port %s not found!\n", name().toLatin1().constData()); - _writeEnable = false; - _readEnable = false; - return QString("Jack midi port not found"); - } - - int pf = jack_port_flags(jp); - - // If Jack port can receive data from us and we actually want to... - if((pf & JackPortIsInput) && (_openFlags & 1)) - { - char buf[80]; - snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum); - _client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true); - if(_client_jackport == NULL) - { - fprintf(stderr, "MidiJackDevice::open failed to register jack-midi-out\n"); - _writeEnable = false; - return QString("Could not register jack-midi-out client port"); - } - else - { - _nextOutIdNum++; - // src, dest - ///audioDevice->connect(_client_jackport, jp); - _writeEnable = true; - } - } - else // Note docs say it can't be both input and output. - // If Jack port can send data to us and we actually want it... - if((pf & JackPortIsOutput) && (_openFlags & 2)) - { - char buf[80]; - snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum); - _client_jackport = (jack_port_t*)audioDevice->registerInPort(buf, true); - if(_client_jackport == NULL) - { - fprintf(stderr, "MidiJackDevice::open failed to register jack-midi-in\n"); - _readEnable = false; - return QString("Could not register jack-midi-in client port"); - } - else - { - _nextInIdNum++; - ///audioDevice->connect(jp, _client_jackport); - _readEnable = true; - } - } - */ - - QString s; - // p3.3.55 Moved from createJackMidiDevice() if(_openFlags & 1) { if(!_out_client_jackport) @@ -608,9 +210,6 @@ QString MidiJackDevice::open() _in_client_jackport = NULL; } - //if(client_jackport == NULL) // p3.3.52 Removed. Allow the device to be created even if Jack isn't running. - // return 0; - _writeEnable = bool(_openFlags & 1); _readEnable = bool(_openFlags & 2); @@ -627,10 +226,10 @@ void MidiJackDevice::close() printf("MidiJackDevice::close %s\n", name().toLatin1().constData()); #endif - // p3.3.55 TODO: I don't really want to unregister the + // TODO: I don't really want to unregister the // Jack midi ports because then we lose the connections // to Jack every time we click the read/write lights - // or change a port's device. + // or change a port's device. p3.3.55 /* if(_client_jackport) @@ -652,38 +251,6 @@ void MidiJackDevice::close() _writeEnable = false; _readEnable = false; - - /* - //jack_port_t* jp = jack_port_by_name(_client, name().toLatin1().constData()); - jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().toLatin1().constData()); - - if(!jp) - { - printf("MidiJackDevice::close: Jack midi port %s not found!\n", name().toLatin1().constData()); - _writeEnable = false; - _readEnable = false; - return; - } - - //int pf = jack_port_flags(jp); - - // If Jack port can receive data from us and we actually want to... - //if((pf & JackPortIsInput) && (_openFlags & 1)) - if(jack_port_connected_to(midi_port_out[0], name().toLatin1().constData())) - { - // src, dest -/// audioDevice->disconnect(midi_port_out[0], jp); - _writeEnable = false; - } - else // Note docs say it can't be both input and output. - // If Jack port can send data to us and we actually want it... - //if((pf & JackPortIsOutput) && (_openFlags & 2)) - if(jack_port_connected_to(midi_port_in[0], name().toLatin1().constData())) - { -/// audioDevice->disconnect(jp, midi_port_in[0]); - _readEnable = false; - } - */ } //--------------------------------------------------------- @@ -692,7 +259,6 @@ void MidiJackDevice::close() void MidiJackDevice::writeRouting(int level, Xml& xml) const { - // p3.3.45 // If this device is not actually in use by the song, do not write any routes. // This prevents bogus routes from being saved and propagated in the med file. if(midiPort() == -1) @@ -701,30 +267,17 @@ void MidiJackDevice::writeRouting(int level, Xml& xml) const QString s; if(rwFlags() & 2) // Readable { - //RouteList* rl = _inRoutes; - //for (ciRoute r = rl->begin(); r != rl->end(); ++r) for (ciRoute r = _inRoutes.begin(); r != _inRoutes.end(); ++r) { if(!r->name().isEmpty()) { xml.tag(level++, "Route"); - - //xml.strTag(level, "srcNode", r->name()); - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); s = QT_TRANSLATE_NOOP("@default", "source"); if(r->type != Route::TRACK_ROUTE) s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type); - - //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name()); s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name())); xml.tag(level, s.toLatin1().constData()); - - //xml.strTag(level, "dstNode", name()); - //xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, name().toLatin1().constData()); - //xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, name().toLatin1().constData()); - //xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, name().toLatin1().constData()); xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, Xml::xmlString(name()).toLatin1().constData()); - xml.etag(level--, "Route"); } } @@ -737,49 +290,14 @@ void MidiJackDevice::writeRouting(int level, Xml& xml) const s = QT_TRANSLATE_NOOP("@default", "Route"); if(r->channel != -1) s += QString(QT_TRANSLATE_NOOP("@default", " channel=\"%1\"")).arg(r->channel); - - //xml.tag(level++, "Route"); xml.tag(level++, s.toLatin1().constData()); - - /* - //xml.strTag(level, "srcNode", name()); - if(r->channel != -1) - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, r->channel, name().toLatin1().constData()); - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, r->channel, name().toLatin1().constData()); - xml.tag(level, "source devtype=\"%d\" channel=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, r->channel, name().toLatin1().constData()); - else - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, name().toLatin1().constData()); - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, name().toLatin1().constData()); - */ - //xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, name().toLatin1().constData()); - xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, Xml::xmlString(name()).toLatin1().constData()); - - /* - //xml.strTag(level, "dstNode", r->name()); - if(r->channel != -1) - { - if(r->type == Route::MIDI_DEVICE_ROUTE) - xml.tag(level, "dest devtype=\"%d\" channel=\"%d\" name=\"%s\"/", r->device->deviceType(), r->channel, r->name().toLatin1().constData()); - else - xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", r->type, r->channel, r->name().toLatin1().constData()); - } - else - { - if(r->type == Route::MIDI_DEVICE_ROUTE) - xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", r->device->deviceType(), r->name().toLatin1().constData()); - else - xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - } - */ - + xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, Xml::xmlString(name()).toLatin1().constData()); s = QT_TRANSLATE_NOOP("@default", "dest"); if(r->type == Route::MIDI_DEVICE_ROUTE) s += QString(QT_TRANSLATE_NOOP("@default", " devtype=\"%1\"")).arg(r->device->deviceType()); else if(r->type != Route::TRACK_ROUTE) s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type); - - //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name()); s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name())); xml.tag(level, s.toLatin1().constData()); @@ -787,33 +305,6 @@ void MidiJackDevice::writeRouting(int level, Xml& xml) const xml.etag(level--, "Route"); } } - - /* - else - if(rwFlags() & 1) // Writable - { - //RouteList* rl = _outRoutes; - //for (ciRoute r = rl->begin(); r != rl->end(); ++r) - for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) - { - if(!r->name().isEmpty()) - { - xml.tag(level++, "Route"); - - //xml.strTag(level, "srcNode", name()); - //if(r->channel != -1) - // xml.tag(level, "srcNode type=\"%d\" channel=\"%d\" name=\"%s\"", Route::JACK_MIDI_ROUTE, r->channel, name().toLatin1().constData()); - //else - xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, name().toLatin1().constData()); - - //xml.strTag(level, "dstNode", r->name()); - xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - - xml.etag(level--, "Route"); - } - } - } - */ } //--------------------------------------------------------- @@ -826,80 +317,8 @@ void MidiJackDevice::writeRouting(int level, Xml& xml) const */ bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& /*event*/) { - /* - int give, channel = event.channel(); - int x; - - if(channel >= JACK_MIDI_CHANNELS) return false; - - // buffer up events, because jack eats them in chunks, if - // the buffer is full, there isn't so much to do, than - // drop the event - - give = jack_midi_out_data[channel].give; - if(jack_midi_out_data[channel].buffer[give*4+3]){ - fprintf(stderr, "WARNING: muse-to-jack midi-buffer is full, channel=%u\n", channel); - return false; - } - // copy event(note-on etc..), pitch and volume - // see http://www.midi.org/techspecs/midimessages.php - switch(event.type()){ - case ME_NOTEOFF: - jack_midi_out_data[channel].buffer[give*4+0] = 0x80; - jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f; - jack_midi_out_data[channel].buffer[give*4+2] = event.dataB() & 0x7f; - break; - case ME_NOTEON: - jack_midi_out_data[channel].buffer[give*4+0] = 0x90; - jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f; - jack_midi_out_data[channel].buffer[give*4+2] = event.dataB() & 0x7f; - break; - case ME_CONTROLLER: - jack_midi_out_data[channel].buffer[give*4+0] = 0xb0; - jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f; - jack_midi_out_data[channel].buffer[give*4+2] = event.dataB() & 0x7f; - break; - case ME_PROGRAM: - jack_midi_out_data[channel].buffer[give*4+0] = 0xc0; - jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f; - jack_midi_out_data[channel].buffer[give*4+2] = 0; - break; - case ME_PITCHBEND: - jack_midi_out_data[channel].buffer[give*4+0] = 0xE0; - // convert muse pitch-bend to midi standard - x = 0x2000 + event.dataA(); - jack_midi_out_data[channel].buffer[give*4+1] = x & 0x7f; - jack_midi_out_data[channel].buffer[give*4+2] = (x >> 8) & 0x7f; - break; - default: - fprintf(stderr, "jack-midi-out %u WARNING: unknown event %x\n", channel, event.type()); - return false; - } - jack_midi_out_data[channel].buffer[give*4+3] = 1; // mark state of this slot - // finally increase give position - give++; - if(give >= JACK_MIDI_BUFFER_SIZE){ - give = 0; - } - jack_midi_out_data[channel].give = give; - return false; - */ - - return false; -} - -/* -//--------------------------------------------------------- -// putEvent -// return false if event is delivered -//--------------------------------------------------------- - -bool MidiJackDevice::putEvent(int* event) -{ - int *y; y = event; return false; } -*/ //--------------------------------------------------------- // recordEvent @@ -912,7 +331,7 @@ void MidiJackDevice::recordEvent(MidiRecordEvent& event) if(audio->isPlaying()) event.setLoopNum(audio->loopCount()); - if (midiInputTrace) { + if (MusEGlobal::midiInputTrace) { printf("Jack MidiInput: "); event.dump(); } @@ -964,11 +383,11 @@ void MidiJackDevice::recordEvent(MidiRecordEvent& event) processMidiInputTransformPlugins(event); - if (filterEvent(event, midiRecordType, false)) + if (filterEvent(event, MusEGlobal::midiRecordType, false)) return; if (!applyMidiInputTransformation(event)) { - if (midiInputTrace) + if (MusEGlobal::midiInputTrace) printf(" midi input transformation: event filtered\n"); return; } @@ -989,9 +408,8 @@ void MidiJackDevice::recordEvent(MidiRecordEvent& event) //if(_recordFifo.put(MidiPlayEvent(event))) // printf("MidiJackDevice::recordEvent: fifo overflow\n"); - // p3.3.38 // Do not bother recording if it is NOT actually being used by a port. - // Because from this point on, process handles things, by selected port. + // Because from this point on, process handles things, by selected port. p3.3.38 if(_port == -1) return; @@ -1010,8 +428,8 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) MidiRecordEvent event; event.setB(0); - // NOTE: From MusE-2. Not done here in Muse-1 (yet). - // move all events 2*segmentSize into the future to get + // NOTE: From muse_qt4_evolution. Not done here in Muse-2 (yet). + // move all events 2*MusEGlobal::segmentSize into the future to get // jitterfree playback // // cycle n-1 n n+1 @@ -1019,15 +437,11 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) // ^ ^ ^ // catch process play // -// const SeqTime* st = audio->seqTime(); - - //unsigned curFrame = st->startFrame() + segmentSize; -// unsigned curFrame = st->lastFrameTime; + //int frameOffset = audio->getFrameOffset(); unsigned pos = audio->pos().frame(); - //event.setTime(pos + ev->time); - event.setTime(extSyncFlag.value() ? lastExtMidiSyncTick : (pos + ev->time)); + event.setTime(extSyncFlag.value() ? lastExtMidiSyncTick : (pos + ev->time)); // p3.3.25 event.setChannel(*(ev->buffer) & 0xf); int type = *(ev->buffer) & 0xf0; @@ -1061,7 +475,7 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) // For now, do not accept if the last byte is not EOX, meaning it's a chunk with more chunks to follow. if(*(((unsigned char*)ev->buffer) + ev->size - 1) != ME_SYSEX_END) { - if(debugMsg) + if(MusEGlobal::debugMsg) printf("MidiJackDevice::eventReceived sysex chunks not supported!\n"); return; } @@ -1093,7 +507,7 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) //break; // return; default: - if(debugMsg) + if(MusEGlobal::debugMsg) printf("MidiJackDevice::eventReceived unsupported system event 0x%02x\n", type); return; } @@ -1101,13 +515,13 @@ void MidiJackDevice::eventReceived(jack_midi_event_t* ev) //return; break; default: - if(debugMsg) + if(MusEGlobal::debugMsg) printf("MidiJackDevice::eventReceived unknown event 0x%02x\n", type); //printf("MidiJackDevice::eventReceived unknown event 0x%02x size:%d buf:0x%02x 0x%02x 0x%02x ...0x%02x\n", type, ev->size, *(ev->buffer), *(ev->buffer + 1), *(ev->buffer + 2), *(ev->buffer + (ev->size - 1))); return; } - if (midiInputTrace) { + if (MusEGlobal::midiInputTrace) { printf("MidiInput<%s>: ", name().toLatin1().constData()); event.dump(); } @@ -1129,13 +543,10 @@ void MidiJackDevice::collectMidiEvents() if(!_readEnable) return; - //if(!_client_jackport) - if(!_in_client_jackport) // p3.3.55 + if(!_in_client_jackport) return; - //void* port_buf = jack_port_get_buffer(_client_jackport, segmentSize); - void* port_buf = jack_port_get_buffer(_in_client_jackport, segmentSize); // p3.3.55 - + void* port_buf = jack_port_get_buffer(_in_client_jackport, MusEGlobal::segmentSize); jack_midi_event_t event; jack_nframes_t eventCount = jack_midi_get_event_count(port_buf); for (jack_nframes_t i = 0; i < eventCount; ++i) @@ -1157,9 +568,7 @@ void MidiJackDevice::collectMidiEvents() bool MidiJackDevice::putEvent(const MidiPlayEvent& ev) { - //if(!_writeEnable) - if(!_writeEnable || !_out_client_jackport) // p4.0.15 - //return true; + if(!_writeEnable || !_out_client_jackport) return false; #ifdef JACK_MIDI_DEBUG @@ -1178,9 +587,7 @@ bool MidiJackDevice::putEvent(const MidiPlayEvent& ev) // return true if successful //--------------------------------------------------------- -//void JackAudioDevice::putEvent(Port port, const MidiEvent& e) bool MidiJackDevice::queueEvent(const MidiPlayEvent& e) -//bool MidiJackDevice::queueEvent(const MidiPlayEvent& e) { // Perhaps we can find use for this value later, together with the Jack midi MusE port(s). // No big deal if not. Not used for now. @@ -1194,14 +601,12 @@ bool MidiJackDevice::queueEvent(const MidiPlayEvent& e) // e.dump(); // } - //if(debugMsg) + //if(MusEGlobal::debugMsg) // printf("MidiJackDevice::queueEvent\n"); - //if(!_client_jackport) - if(!_out_client_jackport) // p3.3.55 + if(!_out_client_jackport) return false; - //void* pb = jack_port_get_buffer(_client_jackport, segmentSize); - void* pb = jack_port_get_buffer(_out_client_jackport, segmentSize); // p3.3.55 + void* pb = jack_port_get_buffer(_out_client_jackport, MusEGlobal::segmentSize); //unsigned frameCounter = ->frameTime(); int frameOffset = audio->getFrameOffset(); @@ -1210,10 +615,10 @@ bool MidiJackDevice::queueEvent(const MidiPlayEvent& e) if (ft < 0) ft = 0; - if (ft >= (int)segmentSize) { - printf("MidiJackDevice::queueEvent: Event time:%d out of range. offset:%d ft:%d (seg=%d)\n", e.time(), frameOffset, ft, segmentSize); - if (ft > (int)segmentSize) - ft = segmentSize - 1; + if (ft >= (int)MusEGlobal::segmentSize) { + printf("MidiJackDevice::queueEvent: Event time:%d out of range. offset:%d ft:%d (seg=%d)\n", e.time(), frameOffset, ft, MusEGlobal::segmentSize); + if (ft > (int)MusEGlobal::segmentSize) + ft = MusEGlobal::segmentSize - 1; } #ifdef JACK_MIDI_DEBUG @@ -1293,7 +698,7 @@ bool MidiJackDevice::queueEvent(const MidiPlayEvent& e) case ME_START: case ME_CONTINUE: case ME_STOP: - if(debugMsg) + if(MusEGlobal::debugMsg) printf("MidiJackDevice::queueEvent: event type %x not supported\n", e.type()); //return false; return true; // Absorb the event. Don't want it hanging around in the list. FIXME: Support these? p4.0.15 Tim. @@ -1325,7 +730,7 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) // Just do this 'standard midi 64T timing thing' for now until we figure out more precise external timings. // Does require relatively short audio buffers, in order to catch the resolution, but buffer <= 256 should be OK... // Tested OK so far with 128. - ///if(extSyncFlag.value()) + //if(extSyncFlag.value()) // p4.0.15 Or, is the event marked to be played immediately? // Nothing to do but stamp the event to be queued for frame 0+. if(t == 0 || extSyncFlag.value()) @@ -1362,17 +767,13 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) if(event.type() == ME_PITCHBEND) { int v = a + 8192; - // p3.3.44 //printf("MidiJackDevice::processEvent ME_PITCHBEND v:%d time:%d type:%d ch:%d A:%d B:%d\n", v, event.time(), event.type(), event.channel(), event.dataA(), event.dataB()); - if(!queueEvent(MidiPlayEvent(t, port, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f))) return false; } else if(event.type() == ME_CONTROLLER) { - //int a = event.dataA(); - //int b = event.dataB(); // Perhaps we can find use for this value later, together with the Jack midi MusE port(s). // No big deal if not. Not used for now. //int port = event.port(); @@ -1392,9 +793,7 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) if(a == CTRL_PITCH) { int v = b + 8192; - // p3.3.44 //printf("MidiJackDevice::processEvent CTRL_PITCH v:%d time:%d type:%d ch:%d A:%d B:%d\n", v, event.time(), event.type(), event.channel(), event.dataA(), event.dataB()); - if(!queueEvent(MidiPlayEvent(t, port, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f))) return false; } @@ -1405,8 +804,6 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) int hb = (b >> 16) & 0xff; int lb = (b >> 8) & 0xff; int pr = b & 0x7f; - - // p3.3.44 //printf("MidiJackDevice::processEvent CTRL_PROGRAM time:%d type:%d ch:%d A:%d B:%d hb:%d lb:%d pr:%d\n", // event.time(), event.type(), event.channel(), event.dataA(), event.dataB(), hb, lb, pr); @@ -1425,7 +822,7 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) // } } - else if (a == CTRL_MASTER_VOLUME) // Enabled p4.0.15 Tim. + else if (a == CTRL_MASTER_VOLUME) { unsigned char sysex[] = { 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00 @@ -1565,7 +962,7 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) } else { - if(debugMsg) + if(MusEGlobal::debugMsg) printf("MidiJackDevice::processEvent: unknown controller type 0x%x\n", a); //return false; // Just ignore it. } @@ -1581,65 +978,41 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) } //--------------------------------------------------------- -// processMidi called from audio process only. +// processMidi +// Called from audio thread only. //--------------------------------------------------------- void MidiJackDevice::processMidi() { - //if(!_client_jackport) - //if(!_out_client_jackport) // p3.3.55 - // return; + processStuckNotes(); - //void* port_buf = jack_port_get_buffer(_client_jackport, segmentSize); - //void* port_buf = jack_port_get_buffer(_out_client_jackport, segmentSize); // p3.3.55 void* port_buf = 0; - if(_out_client_jackport && _writeEnable) // p4.0.15 + if(_out_client_jackport && _writeEnable) { - port_buf = jack_port_get_buffer(_out_client_jackport, segmentSize); + port_buf = jack_port_get_buffer(_out_client_jackport, MusEGlobal::segmentSize); jack_midi_clear_buffer(port_buf); } while(!eventFifo.isEmpty()) { - ///MidiPlayEvent e(eventFifo.get()); - MidiPlayEvent e(eventFifo.peek()); // p4.0.15 - - ///int evTime = e.time(); - // Is event marked to be played immediately? p4.0.15 Moved into processEvent(). - ///if(evTime == 0) - ///{ - // Nothing to do but stamp the event to be queued for frame 0+. - //e.setTime(frameOffset + pos); - /// e.setTime(audio->getFrameOffset() + audio->pos().frame()); - ///} - - //#ifdef JACK_MIDI_DEBUG - //printf("MidiJackDevice::processMidi eventFifo time:%d type:%d ch:%d A:%d B:%d\n", e.time(), e.type(), e.channel(), e.dataA(), e.dataB()); - //#endif - - //el->insert(eventFifo.get()); - //el->insert(e); - ///processEvent(e); - // p4.0.15 Try to process only until full, keep rest for next cycle. If no out client port or no write enable, eat up events. + MidiPlayEvent e(eventFifo.peek()); + // Try to process only until full, keep rest for next cycle. If no out client port or no write enable, eat up events. p4.0.15 if(port_buf && !processEvent(e)) return; // Give up. The Jack buffer is full. Nothing left to do. eventFifo.remove(); // Successfully processed event. Remove it from FIFO. } - MPEventList* el = playEvents(); - if(el->empty()) + if(_playEvents.empty()) { //printf("MidiJackDevice::processMidi play events empty\n"); return; } - //printf("MidiJackDevice::processMidi play events:\n"); - ///iMPEvent i = nextPlayEvent(); - iMPEvent i = el->begin(); // p4.0.15 - for(; i != el->end(); ++i) + iMPEvent i = _playEvents.begin(); + for(; i != _playEvents.end(); ++i) { //printf("MidiJackDevice::processMidi playEvent time:%d type:%d ch:%d A:%d B:%d\n", i->time(), i->type(), i->channel(), i->dataA(), i->dataB()); - // p3.3.39 Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values. + // Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values. // Same code as in MidiPort::sendEvent() if(_port != -1) { @@ -1657,12 +1030,10 @@ void MidiJackDevice::processMidi() if(i->type() == ME_PITCHBEND) { //printf("MidiJackDevice::processMidi playEvents ME_PITCHBEND time:%d type:%d ch:%d A:%d B:%d\n", (*i).time(), (*i).type(), (*i).channel(), (*i).dataA(), (*i).dataB()); - int da = mp->limitValToInstrCtlRange(CTRL_PITCH, i->dataA()); if(!mp->setHwCtrlState(i->channel(), CTRL_PITCH, da)) continue; //mp->setHwCtrlState(i->channel(), CTRL_PITCH, da); - //(MidiPlayEvent(t, port, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f)); } else @@ -1674,25 +1045,11 @@ void MidiJackDevice::processMidi() } } - ///processEvent(*i); - // p4.0.15 Try to process only until full, keep rest for next cycle. If no out client port or no write enable, eat up events. - if(port_buf && !processEvent(*i)) - { - //setNextPlayEvent(i); - //return; + // Try to process only until full, keep rest for next cycle. If no out client port or no write enable, eat up events. p4.0.15 + if(port_buf && !processEvent(*i)) break; - } } - - ///setNextPlayEvent(i); - // p4.0.15 We are done with these events. Let us erase them here instead of Audio::processMidi. - // That way we can simply set the next play event to the beginning. - // This also allows other events to be inserted without the problems caused by the next play event - // being at the 'end' iterator and not being *easily* set to some new place beginning of the newer insertions. - // The way that MPEventList sorts made it difficult to predict where the iterator of the first newly inserted items was. - // The erasure in Audio::processMidi was missing some events because of that. - el->erase(el->begin(), i); - // setNextPlayEvent(el->begin()); // Removed p4.0.15 Tim. + _playEvents.erase(_playEvents.begin(), i); } @@ -1703,139 +1060,6 @@ void MidiJackDevice::processMidi() bool initMidiJack() { - /* - int adr = 0; - - memset(jack_midi_out_data, 0, JACK_MIDI_CHANNELS * sizeof(muse_jack_midi_buffer)); - memset(jack_midi_in_data, 0, JACK_MIDI_CHANNELS * sizeof(muse_jack_midi_buffer)); - - MidiJackDevice* dev = new MidiJackDevice(adr, QString("jack-midi")); - dev->setrwFlags(3); // set read and write flags - - if(pipe(jackmidi_pi) < 0){ - fprintf(stderr, "cant create midi-jack input pipe\n"); - } - if(pipe(jackmidi_po) < 0){ - fprintf(stderr, "cant create midi-jack output pipe\n"); - } - - midiDevices.add(dev); - - gmdev = dev; // proclaim the global jack-midi instance - - //jackScanMidiPorts(); - */ - return false; } -/* -struct JackPort { - int adr; - //char* name; - QString name; - int flags; - //JackPort(int a, const char* s, int f) { - JackPort(int a, const QString& s, int f) { - adr = a; - //name = strdup(s); - name = QString(s); - flags = f; - } - }; - - -static std::list<JackPort> portList; - -//--------------------------------------------------------- -// jackScanMidiPorts -//--------------------------------------------------------- - -void jackScanMidiPorts() -{ - int adr; - const char* name; - - portList.clear(); - adr = 0; - name = strdup("namex"); - portList.push_back(JackPort(adr, name, 0)); - // - // check for devices to add - // - for (std::list<JackPort>::iterator k = portList.begin(); k != portList.end(); ++k) { - iMidiDevice i = midiDevices.begin(); - for (;i != midiDevices.end(); ++i) { - //MidiJackDevice* d = dynamic_cast<MidiJackDevice*>(*i); - break; - //if (d == 0) continue; - //if ((k->adr.client == d->adr.client) && (k->adr.port == d->adr.port)) { - // break; - //} - } - if (i == midiDevices.end()) { - // add device - MidiJackDevice* dev = new MidiJackDevice(k->adr, QString(k->name)); - dev->setrwFlags(k->flags); - midiDevices.add(dev); - } - } -} -*/ - -/* -//--------------------------------------------------------- -// processInput -//--------------------------------------------------------- -static void handle_jack_midi_in(int channel) -{ - MidiRecordEvent event; - int t,n,v; - t = jack_midi_in_data[channel].buffer[0]; - n = jack_midi_in_data[channel].buffer[1]; - v = jack_midi_in_data[channel].buffer[2]; - - event.setType(0); // mark as unused - event.setPort(gmdev->midiPort()); - event.setB(0); - - if(t == 0x90){ // note on - fprintf(stderr, "jackProcessMidiInput note-on\n"); - event.setChannel(channel); - event.setType(ME_NOTEON); - event.setA(n); - event.setB(v); - }else if (t == 0x80){ // note off - fprintf(stderr, "jackProcessMidiInput note-off\n"); - event.setChannel(channel); - event.setType(ME_NOTEOFF); - event.setA(n); - event.setB(v); - }else{ - fprintf(stderr, "WARNING: unknown midi-in on channel %d: %x,%x,%x\n", - channel, t, n, v); - return; - } - if(event.type()){ - gmdev->recordEvent(event); - midiPorts[gmdev->midiPort()].syncInfo().trigActDetect(event.channel()); - } -} - -void MidiJackDevice::processInput() -{ - char buf; - int i,s; - read(gmdev->selectRfd(), &buf, 1); - - s = 1; - for(i = 0; i < JACK_MIDI_CHANNELS; i++){ - if(jack_midi_in_data[i].buffer[3]){ - s = 0; - handle_jack_midi_in(i); - jack_midi_in_data[i].buffer[3] = 0; - } - } -} - -*/ diff --git a/muse2/muse/driver/jackmidi.h b/muse2/muse/driver/jackmidi.h index 2dcf2fbb..e79e9288 100644 --- a/muse2/muse/driver/jackmidi.h +++ b/muse2/muse/driver/jackmidi.h @@ -3,6 +3,22 @@ // Linux Music Editor // $Id: jackmidi.h,v 1.1.1.1 2010/01/27 09:06:43 terminator356 Exp $ // (C) Copyright 1999-2010 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __JACKMIDI_H__ @@ -25,81 +41,17 @@ class MidiPlayEvent; //class RouteList; class Xml; -// Turn on to show multiple devices, work in progress, -// not working fully yet, can't seem to connect... -//#define JACK_MIDI_SHOW_MULTIPLE_DEVICES - // It appears one client port per remote port will be necessary. // Jack doesn't seem to like manipulation of non-local ports buffers. //#define JACK_MIDI_USE_MULTIPLE_CLIENT_PORTS -/* jack-midi channels */ -//#define JACK_MIDI_CHANNELS 32 - -/* jack-midi buffer size */ -//#define JACK_MIDI_BUFFER_SIZE 32 - -/* -typedef struct { - int give; - int take; - // 32 parallel midi events, where each event contains three - // midi-bytes and one busy-byte - char buffer[4 * JACK_MIDI_BUFFER_SIZE]; -} muse_jack_midi_buffer; -*/ - -/* -struct JackMidiPort -{ - jack_port_t* _jackPort; - QString _name; - int _flags; // 1 = writable, 2 = readable - do not mix - JackMidiPort(jack_port_t* jp, const QString& s, int f) - { - _jackPort = jp; - _name = QString(s); - _flags = f; - } -}; - -typedef std::map<jack_port_t*, JackMidiPort, std::less<jack_port_t*> >::iterator iJackMidiPort; -typedef std::map<jack_port_t*, JackMidiPort, std::less<jack_port_t*> >::const_iterator ciJackMidiPort; - -class JackMidiPortList : public std::map<jack_port_t*, JackMidiPort, std::less<jack_port_t*> > -{ - private: - static int _nextOutIdNum; - static int _nextInIdNum; - - public: - JackMidiPortList(); - ~JackMidiPortList(); - iJackMidiPort createClientPort(int flags); - bool removeClientPort(jack_port_t* port); -}; - -extern JackMidiPortList jackMidiClientPorts; -*/ - //--------------------------------------------------------- // MidiJackDevice //--------------------------------------------------------- class MidiJackDevice : public MidiDevice { - public: - //int adr; - private: - // fifo for midi events sent from gui - // direct to midi port: - //MidiFifo eventFifo; // Moved into MidiDevice p4.0.15 - - //static int _nextOutIdNum; - //static int _nextInIdNum; - //jack_port_t* _client_jackport; - // p3.3.55 jack_port_t* _in_client_jackport; jack_port_t* _out_client_jackport; @@ -119,49 +71,27 @@ class MidiJackDevice : public MidiDevice { void eventReceived(jack_midi_event_t*); public: - //MidiJackDevice() {} // p3.3.55 Removed. - //MidiJackDevice(const int&, const QString& name); - - //MidiJackDevice(jack_port_t* jack_port, const QString& name); - //MidiJackDevice(jack_port_t* in_jack_port, jack_port_t* out_jack_port, const QString& name); // p3.3.55 In or out port can be null. MidiJackDevice(const QString& name); - //static MidiDevice* createJackMidiDevice(QString /*name*/, int /*rwflags*/); // 1:Writable 2: Readable. Do not mix. - static MidiDevice* createJackMidiDevice(QString name = "", int rwflags = 3); // p3.3.55 1:Writable 2: Readable 3: Writable + Readable - + static MidiDevice* createJackMidiDevice(QString name = "", int rwflags = 3); // 1:Writable 2: Readable 3: Writable + Readable virtual inline int deviceType() const { return JACK_MIDI; } - virtual void setName(const QString&); virtual void processMidi(); virtual ~MidiJackDevice(); - //virtual int selectRfd(); - //virtual int selectWfd(); - //virtual void processInput(); virtual void recordEvent(MidiRecordEvent&); virtual bool putEvent(const MidiPlayEvent&); virtual void collectMidiEvents(); - //virtual jack_port_t* jackPort() { return _jackport; } - //virtual jack_port_t* clientJackPort() { return _client_jackport; } - - //virtual void* clientPort() { return (void*)_client_jackport; } - // p3.3.55 virtual void* inClientPort() { return (void*) _in_client_jackport; } virtual void* outClientPort() { return (void*) _out_client_jackport; } - //RouteList* routes() { return &_routes; } - //bool noRoute() const { return _routes.empty(); } virtual void writeRouting(int, Xml&) const; }; extern bool initMidiJack(); -//extern int jackSelectRfd(); -//extern int jackSelectWfd(); -//extern void jackProcessMidiInput(); -//extern void jackScanMidiPorts(); #endif diff --git a/muse2/muse/driver/rtctimer.cpp b/muse2/muse/driver/rtctimer.cpp index 1a3cefa6..8410bb04 100644 --- a/muse2/muse/driver/rtctimer.cpp +++ b/muse2/muse/driver/rtctimer.cpp @@ -5,8 +5,23 @@ // // Most code moved from midiseq.cpp by Werner Schweer. // - // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) // (C) Copyright -2004 Werner Schweer (werner@seh.de) + // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #include <linux/version.h> @@ -46,16 +61,16 @@ signed int RtcTimer::initTimer() fprintf(stderr,"RtcTimer::initTimer(): called on initialised timer!\n"); return -1; } - doSetuid(); + MusEGlobal::doSetuid(); timerFd = ::open("/dev/rtc", O_RDONLY); if (timerFd == -1) { fprintf(stderr, "fatal error: open /dev/rtc failed: %s\n", strerror(errno)); fprintf(stderr, "hint: check if 'rtc' kernel module is loaded, or used by something else\n"); - undoSetuid(); + MusEGlobal::undoSetuid(); return timerFd; } - if (!setTimerFreq(config.rtcTicks)) { + if (!setTimerFreq(MusEConfig::config.rtcTicks)) { // unable to set timer frequency return -1; } @@ -118,7 +133,7 @@ bool RtcTimer::startTimer() } if (ioctl(timerFd, RTC_PIE_ON, 0) == -1) { perror("MidiThread: start: RTC_PIE_ON failed"); - undoSetuid(); + MusEGlobal::undoSetuid(); return false; } return true; diff --git a/muse2/muse/driver/rtctimer.h b/muse2/muse/driver/rtctimer.h index fa58b032..5befdf22 100644 --- a/muse2/muse/driver/rtctimer.h +++ b/muse2/muse/driver/rtctimer.h @@ -5,8 +5,23 @@ // // Most code moved from midiseq.cpp // - // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) // (C) Copyright -2004 Werner Schweer (werner@seh.de) + // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __RTCTIMER_H__ diff --git a/muse2/muse/driver/timerdev.h b/muse2/muse/driver/timerdev.h index 944bc213..960cf2f4 100644 --- a/muse2/muse/driver/timerdev.h +++ b/muse2/muse/driver/timerdev.h @@ -7,6 +7,21 @@ // alsalib 1.0.7 // // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// //========================================================= #ifndef __TIMERDEV_H__ |