summaryrefslogtreecommitdiffstats
path: root/src/libs/engine/JackAudioDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/engine/JackAudioDriver.cpp')
-rw-r--r--src/libs/engine/JackAudioDriver.cpp384
1 files changed, 0 insertions, 384 deletions
diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp
deleted file mode 100644
index eff04653..00000000
--- a/src/libs/engine/JackAudioDriver.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/* This file is part of Ingen.
- * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
- *
- * Ingen 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.
- *
- * Ingen 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.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "JackAudioDriver.hpp"
-#include CONFIG_H_PATH
-#include "tuning.hpp"
-#include <iostream>
-#include <cstdlib>
-#include <raul/List.hpp>
-#include "Engine.hpp"
-#include "util.hpp"
-#include "Event.hpp"
-#include "ThreadManager.hpp"
-#include "QueuedEvent.hpp"
-#include "EventSource.hpp"
-#include "PostProcessor.hpp"
-#include "NodeImpl.hpp"
-#include "PatchImpl.hpp"
-#include "PortImpl.hpp"
-#include "MidiDriver.hpp"
-#include "DuplexPort.hpp"
-#include "EventSource.hpp"
-#include "AudioBuffer.hpp"
-#include "ProcessSlave.hpp"
-
-using namespace std;
-
-namespace Ingen {
-
-
-//// JackAudioPort ////
-
-JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort* patch_port)
- : DriverPort(patch_port)
- , Raul::List<JackAudioPort*>::Node(this)
- , _driver(driver)
- , _jack_port(NULL)
- , _jack_buffer(NULL)
-{
- assert(patch_port->poly() == 1);
-
- _jack_port = jack_port_register(_driver->jack_client(),
- patch_port->path().c_str(), JACK_DEFAULT_AUDIO_TYPE,
- (patch_port->is_input()) ? JackPortIsInput : JackPortIsOutput,
- 0);
-
- if (_jack_port == NULL) {
- cerr << "[JackAudioPort] ERROR: Failed to register port " << patch_port->path() << endl;
- throw JackAudioDriver::PortRegistrationFailedException();
- }
-
- patch_port->buffer(0)->clear();
- patch_port->fixed_buffers(true);
-}
-
-
-JackAudioPort::~JackAudioPort()
-{
- jack_port_unregister(_driver->jack_client(), _jack_port);
-}
-
-
-void
-JackAudioPort::prepare_buffer(jack_nframes_t nframes)
-{
- jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes);
-
- AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0);
-
- //cerr << "[JACK] " << _patch_port->path() << " buffer: " << patch_buf << endl;
-
- if (jack_buf != _jack_buffer) {
- patch_buf->set_data(jack_buf);
- _jack_buffer = jack_buf;
- }
-
- assert(patch_buf->data() == jack_buf);
-}
-
-
-//// JackAudioDriver ////
-
-JackAudioDriver::JackAudioDriver(Engine& engine,
- std::string server_name,
- jack_client_t* jack_client)
- : _engine(engine)
- , _jack_thread(NULL)
- , _client(jack_client)
- , _buffer_size(jack_client ? jack_get_buffer_size(jack_client) : 0)
- , _sample_rate(jack_client ? jack_get_sample_rate(jack_client) : 0)
- , _is_activated(false)
- , _local_client(true) // FIXME
- , _process_context(engine)
- , _root_patch(NULL)
-{
- if (!_client) {
- // Try supplied server name
- if (server_name != "") {
- _client = jack_client_open("Ingen", JackServerName, NULL, server_name.c_str());
- if (_client)
- cerr << "[JackAudioDriver] Connected to JACK server '" <<
- server_name << "'" << endl;
- }
-
- // Either server name not specified, or supplied server name does not exist
- // Connect to default server
- if (!_client) {
- _client = jack_client_open("Ingen", JackNullOption, NULL);
-
- if (_client)
- cerr << "[JackAudioDriver] Connected to default JACK server." << endl;
- }
-
- // Still failed
- if (!_client) {
- cerr << "[JackAudioDriver] Unable to connect to Jack. Exiting." << endl;
- exit(EXIT_FAILURE);
- }
-
- _buffer_size = jack_get_buffer_size(_client);
- _sample_rate = jack_get_sample_rate(_client);
- }
-
- jack_on_shutdown(_client, shutdown_cb, this);
-
- jack_set_thread_init_callback(_client, thread_init_cb, this);
- jack_set_sample_rate_callback(_client, sample_rate_cb, this);
- jack_set_buffer_size_callback(_client, buffer_size_cb, this);
-}
-
-
-JackAudioDriver::~JackAudioDriver()
-{
- deactivate();
-
- if (_local_client)
- jack_client_close(_client);
-}
-
-
-void
-JackAudioDriver::activate()
-{
- if (_is_activated) {
- cerr << "[JackAudioDriver] Jack driver already activated." << endl;
- return;
- }
-
- jack_set_process_callback(_client, process_cb, this);
-
- _is_activated = true;
-
- if (jack_activate(_client)) {
- cerr << "[JackAudioDriver] Could not activate Jack client, aborting." << endl;
- exit(EXIT_FAILURE);
- } else {
- cout << "[JackAudioDriver] Activated Jack client." << endl;
-/*#ifdef HAVE_LASH
- _engine.lash_driver()->set_jack_client_name(jack_client_get_name(_client));
-#endif*/
- }
-}
-
-
-void
-JackAudioDriver::deactivate()
-{
- if (_is_activated) {
-
- //for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i)
- // jack_port_unregister(_client, (*i)->jack_port());
-
- jack_deactivate(_client);
- _is_activated = false;
-
- _ports.clear();
-
- cout << "[JackAudioDriver] Deactivated Jack client." << endl;
-
- //_engine.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(DriverPort* port)
-{
- assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
-
- assert(dynamic_cast<JackAudioPort*>(port));
- _ports.push_back((JackAudioPort*)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.
- */
-DriverPort*
-JackAudioDriver::remove_port(const Path& path)
-{
- assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
-
- for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i)
- if ((*i)->patch_port()->path() == path)
- return _ports.erase(i)->elem(); // FIXME: LEAK
-
- cerr << "[JackAudioDriver::remove_port] WARNING: Unable to find Jack port " << path << endl;
- return NULL;
-}
-
-
-DriverPort*
-JackAudioDriver::port(const Path& path)
-{
- for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i)
- if ((*i)->patch_port()->path() == path)
- return (*i);
-
- return NULL;
-}
-
-
-DriverPort*
-JackAudioDriver::create_port(DuplexPort* patch_port)
-{
- try {
- if (patch_port->buffer_size() == _buffer_size)
- return new JackAudioPort(this, patch_port);
- else
- return NULL;
- } catch (...) {
- return NULL;
- }
-}
-
-
-DriverPort*
-JackAudioDriver::driver_port(const Path& path)
-{
- assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
-
- for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i)
- if ((*i)->patch_port()->path() == path)
- return (*i);
-
- return NULL;
-}
-
-
-/**** Jack Callbacks ****/
-
-
-
-/** Jack process callback, drives entire audio thread.
- *
- * \callgraph
- */
-int
-JackAudioDriver::_process_cb(jack_nframes_t nframes)
-{
- if (nframes == 0 || ! _is_activated)
- return 0;
-
- // FIXME: all of this time stuff is screwy
-
- // FIXME: support nframes != buffer_size, even though that never damn well happens
- assert(nframes == _buffer_size);
-
- // Jack can elect to not call this function for a cycle, if overloaded
- // FIXME: this doesn't make sense, and the start time isn't used anyway
- const jack_nframes_t start_of_current_cycle = jack_last_frame_time(_client);
-
- const jack_nframes_t end_of_current_cycle = start_of_current_cycle + nframes;
-#ifndef NDEBUG
- // FIXME: support changing cycle length
- const jack_nframes_t start_of_last_cycle = start_of_current_cycle - nframes;
- assert(start_of_current_cycle - start_of_last_cycle == nframes);
-#endif
-
- _transport_state = jack_transport_query(_client, &_position);
-
- _process_context.set_time_slice(nframes, start_of_current_cycle, end_of_current_cycle);
-
- for (Engine::ProcessSlaves::iterator i = _engine.process_slaves().begin();
- i != _engine.process_slaves().end(); ++i) {
- (*i)->context().set_time_slice(nframes, start_of_current_cycle, end_of_current_cycle);
- }
-
- // Process events that came in during the last cycle
- // (Aiming for jitter-free 1 block event latency, ideally)
- _engine.process_events(_process_context);
-
- // Set buffers of patch ports to Jack port buffers (zero-copy processing)
- for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) {
- assert(*i);
- (*i)->prepare_buffer(nframes);
- }
-
- assert(_engine.midi_driver());
- _engine.midi_driver()->pre_process(_process_context);
-
- // Run root patch
- if (_root_patch)
- _root_patch->process(_process_context);
-
- _engine.midi_driver()->post_process(_process_context);
-
- _engine.post_processor()->set_end_time(_process_context.end());
-
- return 0;
-}
-
-
-void
-JackAudioDriver::_thread_init_cb()
-{
- // Initialize thread specific data
- _jack_thread = Thread::create_for_this_thread("Jack");
- assert(&Thread::get() == _jack_thread);
- _jack_thread->set_context(THREAD_PROCESS);
- assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
-}
-
-void
-JackAudioDriver::_shutdown_cb()
-{
- cout << "[JackAudioDriver] Jack shutdown. Exiting." << endl;
- _engine.quit();
- _jack_thread = NULL;
-}
-
-
-int
-JackAudioDriver::_sample_rate_cb(jack_nframes_t nframes)
-{
- if (_is_activated) {
- cerr << "[JackAudioDriver] On-the-fly sample rate changing not supported (yet). Aborting." << endl;
- exit(EXIT_FAILURE);
- } else {
- _sample_rate = nframes;
- }
- return 0;
-}
-
-
-int
-JackAudioDriver::_buffer_size_cb(jack_nframes_t nframes)
-{
- if (_root_patch) {
- _root_patch->set_buffer_size(nframes);
- _buffer_size = nframes;
- }
- return 0;
-}
-
-
-} // namespace Ingen
-