summaryrefslogtreecommitdiffstats
path: root/src/engine/JackAudioDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/JackAudioDriver.cpp')
-rw-r--r--src/engine/JackAudioDriver.cpp373
1 files changed, 0 insertions, 373 deletions
diff --git a/src/engine/JackAudioDriver.cpp b/src/engine/JackAudioDriver.cpp
deleted file mode 100644
index 0f5e3b1a..00000000
--- a/src/engine/JackAudioDriver.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
- *
- * Om 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; either version 2 of the License, or (at your option) any later
- * version.
- *
- * Om 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 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "JackAudioDriver.h"
-#include "config.h"
-#include "tuning.h"
-#include <iostream>
-#include <cstdlib>
-#include "Om.h"
-#include "OmApp.h"
-#include "util.h"
-#include "Event.h"
-#include "QueuedEvent.h"
-#include "EventSource.h"
-#include "PostProcessor.h"
-#include "util/Queue.h"
-#include "Node.h"
-#include "Patch.h"
-#include "Port.h"
-#include "PortInfo.h"
-#include "MidiDriver.h"
-#include "List.h"
-#include "PortBase.h"
-#ifdef HAVE_LASH
-#include "LashDriver.h"
-#endif
-
-using std::cout; using std::cerr; using std::endl;
-
-
-namespace Om {
-
-
-//// JackAudioPort ////
-
-JackAudioPort::JackAudioPort(JackAudioDriver* driver, PortBase<sample>* patch_port)
-: DriverPort(),
- ListNode<JackAudioPort*>(this),
- m_driver(driver),
- m_jack_port(NULL),
- m_jack_buffer(NULL),
- m_patch_port(patch_port)
-{
- assert(patch_port->tied_port() != NULL);
- assert(patch_port->poly() == 1);
-
- m_jack_port = jack_port_register(m_driver->jack_client(),
- patch_port->path().c_str(), JACK_DEFAULT_AUDIO_TYPE,
- (patch_port->port_info()->is_input()) ? JackPortIsInput : JackPortIsOutput,
- 0);
-
- m_jack_buffer = new DriverBuffer<jack_sample_t>(driver->buffer_size());
-
- patch_port->fixed_buffers(true);
-}
-
-
-JackAudioPort::~JackAudioPort()
-{
- jack_port_unregister(m_driver->jack_client(), m_jack_port);
-}
-
-
-void
-JackAudioPort::add_to_driver()
-{
- m_driver->add_port(this);
-}
-
-
-void
-JackAudioPort::remove_from_driver()
-{
- m_driver->remove_port(this);
-}
-
-void
-JackAudioPort::prepare_buffer(jack_nframes_t nframes)
-{
- // Technically this doesn't need to be done every time for output ports
- m_jack_buffer->set_data((jack_default_audio_sample_t*)
- jack_port_get_buffer(m_jack_port, nframes));
-
- assert(m_patch_port->tied_port() != NULL);
-
- // FIXME: fixed_buffers switch on/off thing can be removed once this shit
- // gets figured out and assertions can go away
- m_patch_port->fixed_buffers(false);
- m_patch_port->buffer(0)->join(m_jack_buffer);
- m_patch_port->tied_port()->buffer(0)->join(m_jack_buffer);
-
- m_patch_port->fixed_buffers(true);
-
- assert(m_patch_port->buffer(0)->data() == m_patch_port->tied_port()->buffer(0)->data());
- assert(m_patch_port->buffer(0)->data() == m_jack_buffer->data());
-}
-
-
-//// JackAudioDriver ////
-
-JackAudioDriver::JackAudioDriver()
-: m_client(NULL),
- m_buffer_size(0),
- m_sample_rate(0),
- m_is_activated(false),
- m_local_client(true),
- m_root_patch(NULL),
- m_start_of_current_cycle(0),
- m_start_of_last_cycle(0)
-{
- m_client = jack_client_new("Om");
- if (m_client == NULL) {
- cerr << "[JackAudioDriver] Unable to connect to Jack. Exiting." << endl;
- exit(EXIT_FAILURE);
- }
-
- jack_on_shutdown(m_client, shutdown_cb, this);
-
- m_buffer_size = jack_get_buffer_size(m_client);
- m_sample_rate = jack_get_sample_rate(m_client);
-
- jack_set_sample_rate_callback(m_client, sample_rate_cb, this);
- jack_set_buffer_size_callback(m_client, buffer_size_cb, this);
-}
-
-JackAudioDriver::JackAudioDriver(jack_client_t* jack_client)
-: m_client(jack_client),
- m_buffer_size(jack_get_buffer_size(jack_client)),
- m_sample_rate(jack_get_sample_rate(jack_client)),
- m_is_activated(false),
- m_local_client(false),
- m_start_of_current_cycle(0),
- m_start_of_last_cycle(0)
-{
- jack_on_shutdown(m_client, shutdown_cb, this);
-
- jack_set_sample_rate_callback(m_client, sample_rate_cb, this);
- jack_set_buffer_size_callback(m_client, buffer_size_cb, this);
-}
-
-
-JackAudioDriver::~JackAudioDriver()
-{
- deactivate();
-
- if (m_local_client)
- jack_client_close(m_client);
-}
-
-
-void
-JackAudioDriver::activate()
-{
- if (m_is_activated) {
- cerr << "[JackAudioDriver] Jack driver already activated." << endl;
- return;
- }
-
- jack_set_process_callback(m_client, process_cb, this);
-
- m_is_activated = true;
-
- if (jack_activate(m_client)) {
- cerr << "[JackAudioDriver] Could not activate Jack client, aborting." << endl;
- exit(EXIT_FAILURE);
- } else {
- cout << "[JackAudioDriver] Activated Jack client." << endl;
-#ifdef HAVE_LASH
- lash_driver->set_jack_client_name("Om"); // FIXME: unique name
-#endif
- }
-}
-
-
-void
-JackAudioDriver::deactivate()
-{
- if (m_is_activated) {
- // FIXME
- reinterpret_cast<EventSource*>(om->osc_receiver())->stop();
-
- jack_deactivate(m_client);
- m_is_activated = false;
-
- for (List<JackAudioPort*>::iterator i = m_ports.begin(); i != m_ports.end(); ++i)
- jack_port_unregister(m_client, (*i)->jack_port());
-
- m_ports.clear();
-
- cout << "[JackAudioDriver] Deactivated Jack client." << endl;
-
- om->post_processor()->stop();
- }
-}
-
-
-/** Add a Jack port.
- *
- * Realtime safe, this is to be called at the beginning of a process cycle to
- * insert (and actually begin using) a new port.
- *
- * See create_port() and remove_port().
- */
-void
-JackAudioDriver::add_port(JackAudioPort* port)
-{
- m_ports.push_back(port);
-}
-
-
-/** Remove a Jack port.
- *
- * Realtime safe. This is to be called at the beginning of a process cycle to
- * remove the port from the lists read by the audio thread, so the port
- * will no longer be used and can be removed afterwards.
- *
- * It is the callers responsibility to delete the returned port.
- */
-JackAudioPort*
-JackAudioDriver::remove_port(JackAudioPort* port)
-{
- for (List<JackAudioPort*>::iterator i = m_ports.begin(); i != m_ports.end(); ++i)
- if ((*i) == port)
- return m_ports.remove(i)->elem();
-
- cerr << "[JackAudioDriver::remove_port] WARNING: Failed to find Jack port to remove!" << endl;
- return NULL;
-}
-
-
-DriverPort*
-JackAudioDriver::create_port(PortBase<sample>* patch_port)
-{
- if (patch_port->buffer_size() == m_buffer_size)
- return new JackAudioPort(this, patch_port);
- else
- return NULL;
-}
-
-
-/** Process all the pending events for this cycle.
- *
- * Called from the realtime thread once every process cycle.
- */
-void
-JackAudioDriver::process_events(jack_nframes_t block_start, jack_nframes_t block_end)
-{
- Event* ev = NULL;
-
- /* Limit the maximum number of queued events to process per cycle. This
- * makes the process callback truly realtime-safe by preventing being
- * choked by events coming in faster than they can be processed.
- * FIXME: run the math on this and figure out a good value */
- const int MAX_SLOW_EVENTS = m_buffer_size / 100;
-
- int num_events_processed = 0;
- int offset = 0;
-
- // Process the "slow" events first, because it's possible some of the
- // RT events depend on them
-
- // FIXME
- while ((ev = reinterpret_cast<EventSource*>(om->osc_receiver())
- ->pop_earliest_event_before(block_end)) != NULL) {
- ev->execute(0); // QueuedEvents are not sample accurate
- om->post_processor()->push(ev);
- if (++num_events_processed > MAX_SLOW_EVENTS)
- break;
- }
-
- while (!om->event_queue()->is_empty()
- && om->event_queue()->front()->time_stamp() < block_end) {
- ev = om->event_queue()->pop();
- offset = ev->time_stamp() - block_start;
- if (offset < 0) offset = 0; // this can happen if we miss a cycle
- ev->execute(offset);
- om->post_processor()->push(ev);
- ++num_events_processed;
- }
-
- if (num_events_processed > 0)
- om->post_processor()->signal();
-}
-
-
-
-/**** Jack Callbacks ****/
-
-
-
-/** Jack process callback, drives entire audio thread.
- *
- * \callgraph
- */
-int
-JackAudioDriver::m_process_cb(jack_nframes_t nframes)
-{
- // FIXME: support nframes != buffer_size, even though that never damn well happens
- assert(nframes == m_buffer_size);
-
- // Note that jack can elect to not call this function for a cycle, if things aren't
- // keeping up
- m_start_of_current_cycle = jack_last_frame_time(m_client);
- m_start_of_last_cycle = m_start_of_current_cycle - nframes;
-
- assert(m_start_of_current_cycle - m_start_of_last_cycle == nframes);
-
- m_transport_state = jack_transport_query(m_client, &m_position);
-
- process_events(m_start_of_last_cycle, m_start_of_current_cycle);
- om->midi_driver()->prepare_block(m_start_of_last_cycle, m_start_of_current_cycle);
-
- // Set buffers of patch ports to Jack port buffers (zero-copy processing)
- for (List<JackAudioPort*>::iterator i = m_ports.begin(); i != m_ports.end(); ++i)
- (*i)->prepare_buffer(nframes);
-
- // Run root patch
- assert(m_root_patch != NULL);
- m_root_patch->run(nframes);
-
- return 0;
-}
-
-
-void
-JackAudioDriver::m_shutdown_cb()
-{
- cout << "[JackAudioDriver] Jack shutdown. Exiting." << endl;
- om->quit();
-}
-
-
-int
-JackAudioDriver::m_sample_rate_cb(jack_nframes_t nframes)
-{
- if (m_is_activated) {
- cerr << "[JackAudioDriver] Om does not support changing sample rate on the fly (yet). Aborting." << endl;
- exit(EXIT_FAILURE);
- } else {
- m_sample_rate = nframes;
- }
- return 0;
-}
-
-
-int
-JackAudioDriver::m_buffer_size_cb(jack_nframes_t nframes)
-{
- if (m_is_activated) {
- cerr << "[JackAudioDriver] Om does not support chanding buffer size on the fly (yet). Aborting." << endl;
- exit(EXIT_FAILURE);
- } else {
- m_buffer_size = nframes;
- }
- return 0;
-}
-
-
-} // namespace Om
-