diff options
Diffstat (limited to 'attic/muse_qt4_evolution/muse/jack.cpp')
-rw-r--r-- | attic/muse_qt4_evolution/muse/jack.cpp | 886 |
1 files changed, 0 insertions, 886 deletions
diff --git a/attic/muse_qt4_evolution/muse/jack.cpp b/attic/muse_qt4_evolution/muse/jack.cpp deleted file mode 100644 index bc372357..00000000 --- a/attic/muse_qt4_evolution/muse/jack.cpp +++ /dev/null @@ -1,886 +0,0 @@ -//============================================================================= -// MusE -// Linux Music Editor -// $Id:$ -// -// Copyright (C) 2002-2006 by Werner Schweer and others -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//============================================================================= - -#include "config.h" -#include "al/al.h" -#include "al/tempo.h" -#include "audio.h" -#include "globals.h" -#include "song.h" -#include "jackaudio.h" -#include "track.h" -#include "midiinport.h" - -#ifdef VST_SUPPORT -#include <fst.h> -#endif - -JackAudio* jackAudio; - -//--------------------------------------------------------- -// init -//--------------------------------------------------------- - -bool JackAudio::init() - { - return true; - } - -//--------------------------------------------------------- -// jack_thread_init -//--------------------------------------------------------- - -static void jack_thread_init (void* /*data*/) - { -#ifdef VST_SUPPORT - if (loadVST) - fst_adopt_thread(); -#endif - } - -//--------------------------------------------------------- -// timebase_callback -//--------------------------------------------------------- - -static void timebase_callback(jack_transport_state_t /* state */, - jack_nframes_t /* nframes */, - jack_position_t* pos, - int /* new_pos */, - void*) - { - AL::Pos p(pos->frame, AL::FRAMES); - pos->valid = JackPositionBBT; - p.mbt(&pos->bar, &pos->beat, &pos->tick); - pos->bar++; - pos->beat++; - pos->bar_start_tick = Pos(pos->bar, 0, 0).tick(); - // - // dummy: - // - pos->beats_per_bar = 4; - pos->beat_type = 4; - pos->ticks_per_beat = 384; - int tempo = AL::tempomap.tempo(p.tick()); - pos->beats_per_minute = (60000000.0 / tempo) * AL::tempomap.globalTempo()/100.0; - } - -//--------------------------------------------------------- -// processAudio -// JACK callback -//--------------------------------------------------------- - -int JackAudio::processAudio(jack_nframes_t frames, void*) - { - jackAudio->_frameCounter += frames; - - int jackState = jackAudio->getTransportState(); - segmentSize = frames; - if (audioState == AUDIO_RUNNING) - audio->process((unsigned long)frames, jackState); - else if (audioState == AUDIO_STOP) { - if (debugMsg) - puts("jack calling when audio is stopped!\n"); - } - else if (audioState == AUDIO_START1) - audioState = AUDIO_START2; - return 0; - } - -//--------------------------------------------------------- -// getTransportState -//--------------------------------------------------------- - -int JackAudio::getTransportState() - { - int jackState; - transportState = jack_transport_query(_client, &pos); - switch (jackAudio->transportState) { - case JackTransportStopped: - jackState = Audio::STOP; - break; - case JackTransportLooping: - case JackTransportRolling: - jackState = Audio::PLAY; - break; - case JackTransportStarting: - jackState = Audio::START_PLAY; - break; - default: - jackState = Audio::STOP; - break; - } - return jackState; - } - -//--------------------------------------------------------- -// processSync -// return TRUE (non-zero) when ready to roll. -//--------------------------------------------------------- - -static int processSync(jack_transport_state_t state, jack_position_t* pos, void*) - { - int audioState = Audio::STOP; - switch (state) { - case JackTransportStopped: - audioState = Audio::STOP; - break; - case JackTransportLooping: - case JackTransportRolling: - audioState = Audio::PLAY; - break; - case JackTransportStarting: - audioState = Audio::START_PLAY; - break; - } - unsigned frame = pos->frame; - return audio->sync(audioState, frame); - } - -//--------------------------------------------------------- -// processShutdown -//--------------------------------------------------------- - -static void processShutdown(void*) - { - audio->shutdown(); - - for (int i = 0; i < 10; ++i) { - if (audioState == AUDIO_STOP) - break; - sleep(1); - } - if (audioState == AUDIO_RUNNING) - fprintf(stderr, "MusE: sequencer still running, something is very wrong.\n"); - jackAudio->zeroClientPtr(); // jack disconnect client no longer valid - } - -//--------------------------------------------------------- -// jackError -//--------------------------------------------------------- - -static void jackError(const char* s) - { - fprintf(stderr, "JACK ERROR: %s\n", s); - } - -//--------------------------------------------------------- -// noJackError -//--------------------------------------------------------- - -static void noJackError(const char* /* s */) - { - } - -//--------------------------------------------------------- -// JackAudio -//--------------------------------------------------------- - -JackAudio::JackAudio(jack_client_t* cl, char* name) - : AudioDriver() - { - strcpy(jackRegisteredName, name); - _client = cl; - _frameCounter = 0; - } - -//--------------------------------------------------------- -// ~JackAudio -//--------------------------------------------------------- - -JackAudio::~JackAudio() - { - if (_client) { - if (jack_client_close(_client)) { - fprintf(stderr, "jack_client_close() failed: %s\n", - strerror(errno)); - } - } - _client = 0; - } - -//--------------------------------------------------------- -// getJackName() -//--------------------------------------------------------- - -char* JackAudio::getJackName() - { - return jackRegisteredName; - } - -//--------------------------------------------------------- -// restart -//--------------------------------------------------------- - -bool JackAudio::restart() - { - printf("JackAudio::restart\n"); - _client = jack_client_new(jackRegisteredName); - if (!_client) - return true; - registerClient(); - return false; - } - -//--------------------------------------------------------- -// bufsize_callback -//--------------------------------------------------------- - -static int bufsize_callback(jack_nframes_t n, void*) - { - printf("JACK: buffersize changed %d\n", n); - return 0; - } - -//--------------------------------------------------------- -// freewheel_callback -//--------------------------------------------------------- - -static void freewheel_callback(int starting, void*) - { - audio->setFreewheel(starting); - } - -//--------------------------------------------------------- -// srate_callback -//--------------------------------------------------------- - -static int srate_callback(jack_nframes_t n, void*) - { - if (debugMsg) - printf("JACK: sample rate changed: %d\n", n); - return 0; - } - -//--------------------------------------------------------- -// registration_callback -//--------------------------------------------------------- - -static void registration_callback(jack_port_id_t, int, void*) - { - if (debugMsg) - printf("JACK: registration changed\n"); - } - -//--------------------------------------------------------- -// graph_callback -// this is called from jack when the connections -// changed -//--------------------------------------------------------- - -static int graph_callback(void*) - { - // we cannot call JackAudio::graphChanged() from this - // context, so we send a message to the gui thread which in turn - // calls graphChanged() - - audio->sendMsgToGui(MSG_GRAPH_CHANGED); - if (debugMsg) - printf("JACK: graph changed!\n"); - return 0; - } - -//--------------------------------------------------------- -// JackAudio::graphChanged -// this is called from song in gui context triggered -// by graph_callback() -//--------------------------------------------------------- - -void JackAudio::graphChanged() - { - RouteList rr, ra; - - InputList* il = song->inputs(); - for (iAudioInput ii = il->begin(); ii != il->end(); ++ii) { - AudioInput* it = *ii; - int channels = it->channels(); - RouteList* irl = it->inRoutes(); - - for (int channel = 0; channel < channels; ++channel) { - jack_port_t* port = it->jackPort(channel).jackPort(); - if (port == 0) - continue; - const char** ports = jack_port_get_all_connections(_client, port); - - //--------------------------------------- - // check for disconnects - //--------------------------------------- - - foreach (const Route& r, *irl) { - if (r.dst.channel != channel) - continue; - const char* name = jack_port_name(r.src.port.jackPort()); - bool found = false; - for (const char** pn = ports; pn && *pn; ++pn) { - if (strcmp(*pn, name) == 0) { - found = true; - break; - } - } - if (!found) - rr.append(r); - } - - //--------------------------------------- - // check for connects - //--------------------------------------- - - if (ports) { - for (const char** pn = ports; *pn; ++pn) { - bool found = false; - foreach(const Route& r, *irl) { - if (r.dst.channel != channel) - continue; - const char* name = jack_port_name(r.src.port.jackPort()); - if (strcmp(*pn, name) == 0) { - found = true; - break; - } - } - if (!found) { - Route a; - Port port(jack_port_by_name(_client, *pn)); - a.src = RouteNode(port, -1, RouteNode::AUDIOPORT); - a.dst = RouteNode(it, channel); - ra.append(a); - } - } - free(ports); - } - } - } - -// printf(" input: remove %d add %d routes\n", rr.size(), ra.size()); - foreach(Route r, rr) - audio->msgRemoveRoute1(r); - foreach(Route r, ra) - audio->msgAddRoute1(r); - rr.clear(); - ra.clear(); - - OutputList* ol = song->outputs(); - for (iAudioOutput ii = ol->begin(); ii != ol->end(); ++ii) { - AudioOutput* it = *ii; - int channels = it->channels(); - for (int channel = 0; channel < channels; ++channel) { - jack_port_t* port = it->jackPort(channel).jackPort(); - if (port == 0) - continue; - const char** ports = jack_port_get_all_connections(_client, port); - RouteList* rl = it->outRoutes(); - - //--------------------------------------- - // check for disconnects - //--------------------------------------- - - foreach(const Route& r, *rl) { - if (r.src.channel != channel) - continue; - const char* name = jack_port_name(r.dst.port.jackPort()); - bool found = false; - const char** pn = ports; - while (pn && *pn) { - if (strcmp(*pn, name) == 0) { - found = true; - break; - } - ++pn; - } - if (!found) - rr.append(r); - } - - //--------------------------------------- - // check for connects - //--------------------------------------- - - if (ports) { - const char** pn = ports; - while (*pn) { - bool found = false; - foreach (const Route& r, *rl) { - if (r.src.channel != channel) - continue; - const char* name = jack_port_name(r.dst.port.jackPort()); - if (strcmp(*pn, name) == 0) { - found = true; - break; - } - } - if (!found) { - Route a; - Port port(jack_port_by_name(_client, *pn)); - a.src = RouteNode(it, channel, RouteNode::TRACK); - a.dst = RouteNode(port, -1, RouteNode::AUDIOPORT); - ra.append(a); - } - ++pn; - } - free(ports); - } - } - } -// printf(" output: remove %d add %d routes\n", rr.size(), ra.size()); - foreach(Route r, rr) - audio->msgRemoveRoute1(r); - foreach(Route r, ra) - audio->msgAddRoute1(r); - } - -//--------------------------------------------------------- -// register -//--------------------------------------------------------- - -void JackAudio::registerClient() - { - jack_set_process_callback(_client, processAudio, 0); - jack_set_sync_callback(_client, processSync, 0); - jack_on_shutdown(_client, processShutdown, 0); - jack_set_buffer_size_callback(_client, bufsize_callback, 0); - jack_set_sample_rate_callback(_client, srate_callback, 0); - jack_set_port_registration_callback(_client, registration_callback, 0); - jack_set_graph_order_callback(_client, graph_callback, 0); - jack_set_freewheel_callback (_client, freewheel_callback, 0); - jack_set_thread_init_callback(_client, (JackThreadInitCallback) jack_thread_init, 0); - jack_set_timebase_callback(_client, 0, timebase_callback, 0); - } - -//--------------------------------------------------------- -// registerInPort -//--------------------------------------------------------- - -Port JackAudio::registerInPort(const QString& name, bool midi) - { - const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE; - Port p(jack_port_register(_client, name.toLatin1().data(), type, JackPortIsInput, 0)); -// printf("JACK: registerInPort<%s>: <%s> %p\n", type, name.toLatin1().data(), p.jackPort()); - if (!p.jackPort()) - p.setZero(); - return p; - } - -//--------------------------------------------------------- -// registerOutPort -//--------------------------------------------------------- - -Port JackAudio::registerOutPort(const QString& name, bool midi) - { - const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE; - Port p(jack_port_register(_client, name.toLatin1().data(), type, JackPortIsOutput, 0)); -// printf("JACK: registerOutPort<%s>: <%s> %p\n", type, name.toLatin1().data(), p.jackPort()); - if (!p.jackPort()) - p.setZero(); - return p; - } - -//--------------------------------------------------------- -// exitJackAudio -//--------------------------------------------------------- - -void exitJackAudio() - { - if (jackAudio) - delete jackAudio; - } - -//--------------------------------------------------------- -// connect -// return false on error -//--------------------------------------------------------- - -bool JackAudio::connect(Port src, Port dst) - { - if (src.isZero() || dst.isZero()) { - fprintf(stderr, "JackAudio::connect(1): unknown jack ports (%d-%d)\n", - src.isZero(), dst.isZero()); - return false; - } - const char* sn = jack_port_name(src.jackPort()); - const char* dn = jack_port_name(dst.jackPort()); - - if (debugMsg) - printf("jack connect <%s>%p - <%s>%p\n", sn, src.jackPort(), dn, dst.jackPort()); - - if (sn == 0 || dn == 0) { - fprintf(stderr, "JackAudio::connect(2): unknown jack ports\n"); - return false; - } - int rv = jack_connect(_client, sn, dn); - if (rv) { - fprintf(stderr, "%d: jack connect <%s> - <%s> failed\n", - rv, sn, dn); - if (rv == EEXIST) - fprintf(stderr, " connection already made\n"); - else { - int pf = jack_port_flags(src.jackPort()); - if (!(pf & JackPortIsOutput)) - fprintf(stderr, " src is not an output port\n"); - pf = jack_port_flags(dst.jackPort()); - if (!(pf & JackPortIsInput)) - fprintf(stderr, " dst is not an input port\n"); - } - return false; - } - return true; - } - -//--------------------------------------------------------- -// disconnect -//--------------------------------------------------------- - -bool JackAudio::disconnect(Port src, Port dst) - { - const char* sn = jack_port_name(src.jackPort()); - const char* dn = jack_port_name(dst.jackPort()); - - if (debugMsg) - printf("jack disconnect <%s>%p - <%s>%p\n", sn, src.jackPort(), dn, dst.jackPort()); - - if (sn == 0 || dn == 0) { - fprintf(stderr, "JackAudio::disconnect: unknown jack ports\n"); - return false; - } - if (jack_disconnect(_client, sn, dn)) { - fprintf(stderr, "jack disconnect <%s> - <%s> failed\n", - sn, dn); - return false; - } - return true; - } - -//--------------------------------------------------------- -// start -//--------------------------------------------------------- - -void JackAudio::start(int) - { - if (jack_activate(_client)) { - fprintf (stderr, "JACK: cannot activate client\n"); - exit(-1); - } - } - -//--------------------------------------------------------- -// stop -//--------------------------------------------------------- - -void JackAudio::stop() - { - if (_client == 0) - return; - if (jack_deactivate(_client)) - fprintf (stderr, "JACK: cannot deactivate client\n"); - } - -//--------------------------------------------------------- -// outputPorts -//--------------------------------------------------------- - -QList<PortName> JackAudio::outputPorts(bool midi) - { - const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE; - const char** ports = jack_get_ports(_client, 0, type, JackPortIsOutput); - QList<PortName> clientList; - for (const char** p = ports; p && *p; ++p) { - jack_port_t* port = jack_port_by_name(_client, *p); - char buffer[128]; - strncpy(buffer, *p, 128); - if (strncmp(buffer, "MusE", 4) == 0) - continue; - PortName pn; - pn.name = QString(buffer); - pn.port = Port(port); - clientList.append(pn); - } - return clientList; - } - -//--------------------------------------------------------- -// inputPorts -//--------------------------------------------------------- - -QList<PortName> JackAudio::inputPorts(bool midi) - { - const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE; - const char** ports = jack_get_ports(_client, 0, type, JackPortIsInput); - QList<PortName> clientList; - for (const char** p = ports; p && *p; ++p) { - jack_port_t* port = jack_port_by_name(_client, *p); - char buffer[128]; - strncpy(buffer, *p, 128); - if (strncmp(buffer, "MusE", 4) == 0) - continue; - PortName pn; - pn.name = QString(buffer); - pn.port = Port(port); - clientList.append(pn); - } - return clientList; - } - -//--------------------------------------------------------- -// portName -//--------------------------------------------------------- - -QString JackAudio::portName(Port port) - { - const char* nameStrPtr = jack_port_name(port.jackPort()); - QString s(nameStrPtr); - return s; - } - -//--------------------------------------------------------- -// unregisterPort -//--------------------------------------------------------- - -void JackAudio::unregisterPort(Port p) - { - if (_client) { -// printf("JACK: unregister Port %p\n", p); - if (jack_port_unregister(_client, p.jackPort())) - fprintf(stderr, "jack unregister port %p failed\n", p.jackPort()); - } - } - -//--------------------------------------------------------- -// setFreewheel -//--------------------------------------------------------- - -void JackAudio::setFreewheel(bool f) - { -// printf("JACK: setFreewheel %d\n", f); - jack_set_freewheel(_client, f); - } - -//--------------------------------------------------------- -// startTransport -//--------------------------------------------------------- - -void JackAudio::startTransport() - { - jack_transport_start(_client); - } - -//--------------------------------------------------------- -// stopTransport -//--------------------------------------------------------- - -void JackAudio::stopTransport() - { - if (_client) - jack_transport_stop(_client); - } - -//--------------------------------------------------------- -// seekTransport -//--------------------------------------------------------- - -void JackAudio::seekTransport(unsigned frame) - { - jack_transport_locate(_client, frame); - } - -//--------------------------------------------------------- -// findPort -//--------------------------------------------------------- - -Port JackAudio::findPort(const QString& name) - { - if (_client == 0) { - printf("JackAudio(%p)::findPort(%s): _client==0\n", this, qPrintable(name)); - return Port(); - } - jack_port_t* port = jack_port_by_name(_client, name.toLatin1().data()); - return (port == 0) ? Port() : Port(port); - } - -//--------------------------------------------------------- -// realtimePriority -// return zero if not running realtime -// can only be called if JACK client thread is already -// running -//--------------------------------------------------------- - -int JackAudio::realtimePriority() const - { - pthread_t t = jack_client_thread_id(_client); - int policy; - struct sched_param param; - memset(¶m, 0, sizeof(param)); - int rv = pthread_getschedparam(t, &policy, ¶m); - if (rv) { - perror("MusE: get jack schedule parameter"); - return 0; - } - if (policy != SCHED_FIFO) { - printf("JACK is not running realtime\n"); - return 0; - } - return param.sched_priority; - } - -//--------------------------------------------------------- -// initJackAudio -// return true if JACK not found -//--------------------------------------------------------- - -bool initJackAudio() - { - if (debugMsg) { - fprintf(stderr, "init Jack Audio\n"); - jack_set_error_function(jackError); - } - else - jack_set_error_function(noJackError); - - jack_client_t* client = 0; - jack_status_t status; - jack_options_t options = JackNullOption; - client = jack_client_open("MusE", options, &status); - if (!client) { - if (status & JackServerStarted) - printf("jack server started...\n"); - if (status & JackServerFailed) - printf("cannot connect to jack server\n"); - if (status & JackServerError) - printf("communication with jack server failed\n"); - if (status & JackShmFailure) - printf("jack cannot access shared memory\n"); - if (status & JackVersionError) - printf("jack server has wrong version\n"); - printf("cannot create jack client\n"); - return true; - } - - if (debugMsg) - fprintf(stderr, "init Jack Audio: register device\n"); - - jack_set_error_function(jackError); - if (debugMsg) - fprintf(stderr, "init Jack Audio: register device\n"); - - jackAudio = new JackAudio(client, jack_get_client_name(client)); - if (debugMsg) - fprintf(stderr, "init Jack Audio: register client\n"); - jackAudio->registerClient(); - AL::sampleRate = jack_get_sample_rate(client); - segmentSize = jack_get_buffer_size(client); - audioDriver = jackAudio; - return false; - } - -//--------------------------------------------------------- -// putEvent -//--------------------------------------------------------- - -void JackAudio::putEvent(Port port, const MidiEvent& e) - { - if (midiOutputTrace) { - printf("MidiOut<%s>: jackMidi: ", portName(port).toLatin1().data()); - e.dump(); - } - void* pb = jack_port_get_buffer(port.jackPort(), segmentSize); - int ft = e.time() - _frameCounter; - if (ft < 0) - ft = 0; - if (ft >= (int)segmentSize) { - printf("JackAudio::putEvent: time out of range %d(seg=%d)\n", ft, segmentSize); - if (ft > (int)segmentSize) - ft = segmentSize - 1; - } - switch(e.type()) { - case ME_NOTEON: - case ME_NOTEOFF: - case ME_POLYAFTER: - case ME_CONTROLLER: - case ME_PITCHBEND: - { - unsigned char* p = jack_midi_event_reserve(pb, ft, 3); - if (p == 0) { - fprintf(stderr, "JackMidi: buffer overflow, event lost\n"); - return; - } - p[0] = e.type() | e.channel(); - p[1] = e.dataA(); - p[2] = e.dataB(); - } - break; - - case ME_PROGRAM: - case ME_AFTERTOUCH: - { - unsigned char* p = jack_midi_event_reserve(pb, ft, 2); - if (p == 0) { - fprintf(stderr, "JackMidi: buffer overflow, event lost\n"); - return; - } - p[0] = e.type() | e.channel(); - p[1] = e.dataA(); - } - break; - case ME_SYSEX: - { - const unsigned char* data = e.data(); - int len = e.len(); - unsigned char* p = jack_midi_event_reserve(pb, ft, len+2); - if (p == 0) { - fprintf(stderr, "JackMidi: buffer overflow, event lost\n"); - return; - } - p[0] = 0xf0; - p[len+1] = 0xf7; - memcpy(p+1, data, len); - } - break; - case ME_SONGPOS: - case ME_CLOCK: - case ME_START: - case ME_CONTINUE: - case ME_STOP: - printf("JackMidi: event type %x not supported\n", e.type()); - break; - } - } - -//--------------------------------------------------------- -// startMidiCycle -//--------------------------------------------------------- - -void JackAudio::startMidiCycle(Port port) - { - void* port_buf = jack_port_get_buffer(port.jackPort(), segmentSize); - jack_midi_clear_buffer(port_buf); - } - -//--------------------------------------------------------- -// collectMidiEvents -//--------------------------------------------------------- - -void JackAudio::collectMidiEvents(MidiInPort* track, Port port) - { - void* port_buf = jack_port_get_buffer(port.jackPort(), 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) { - jack_midi_event_get(&event, port_buf, i); - track->eventReceived(&event); - } - } - - |