split up session code that uses parts of the JACK API (timebase + session event handling) and connect it directly to the jack audiobackend
i've made the audiobackend call the session directly so that only one object (ARDOUR::Session) has a need for the JACK types and only one .cc file (session_jack.cc) needs jack.h. having ARDOUR::AudioEngine act as an intermediary would be cleaner conceptually but would end up causing two different ARDOUR objects to have jack types in their own API.
This commit is contained in:
parent
da74519911
commit
a34d707175
@ -161,10 +161,6 @@ ARDOUR_UI::set_session (Session *s)
|
||||
_session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
|
||||
_session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
|
||||
|
||||
#ifdef HAVE_JACK_SESSION
|
||||
engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, boost::bind (&Session::jack_session_event, _session, _1), gui_context());
|
||||
#endif
|
||||
|
||||
/* Clocks are on by default after we are connected to a session, so show that here.
|
||||
*/
|
||||
|
||||
|
@ -129,7 +129,8 @@ public:
|
||||
|
||||
void set_session (Session *);
|
||||
void remove_session (); // not a replacement for SessionHandle::session_going_away()
|
||||
|
||||
Session* session() const { return _session; }
|
||||
|
||||
class NoBackendAvailable : public std::exception {
|
||||
public:
|
||||
virtual const char *what() const throw() { return "could not connect to engine backend"; }
|
||||
@ -148,12 +149,7 @@ public:
|
||||
PBD::Signal1<int, pframes_t> Freewheel;
|
||||
|
||||
PBD::Signal0<void> Xrun;
|
||||
|
||||
|
||||
#ifdef HAVE_JACK_SESSION
|
||||
PBD::Signal1<void,jack_session_event_t *> JackSessionEvent;
|
||||
#endif
|
||||
|
||||
/* this signal is emitted if the sample rate changes */
|
||||
|
||||
PBD::Signal1<void, framecnt_t> SampleRateChanged;
|
||||
|
@ -381,9 +381,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||
framecnt_t worst_track_latency () const { return _worst_track_latency; }
|
||||
framecnt_t worst_playback_latency () const { return _worst_output_latency + _worst_track_latency; }
|
||||
|
||||
#ifdef HAVE_JACK_SESSION
|
||||
void jack_session_event (jack_session_event_t* event);
|
||||
#endif
|
||||
int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false);
|
||||
int restore_state (std::string snapshot_name);
|
||||
int save_template (std::string template_name);
|
||||
@ -863,6 +860,15 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||
boost::shared_ptr<IO> ltc_input_io() { return _ltc_input; }
|
||||
boost::shared_ptr<IO> ltc_output_io() { return _ltc_output; }
|
||||
|
||||
/* Callbacks specifically related to JACK, and called directly
|
||||
* from the JACK audio backend.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_JACK_SESSION
|
||||
void jack_session_event (jack_session_event_t* event);
|
||||
#endif
|
||||
void jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int);
|
||||
|
||||
protected:
|
||||
friend class AudioEngine;
|
||||
void set_block_size (pframes_t nframes);
|
||||
@ -1436,9 +1442,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||
*/
|
||||
std::list<GQuark> _current_trans_quarks;
|
||||
|
||||
// void timebase_callback (TransportState, pframes_t, jack_position_t*, int);
|
||||
int jack_sync_callback (TransportState, framepos_t);
|
||||
void reset_jack_connection (jack_client_t* jack);
|
||||
int backend_sync_callback (TransportState, framepos_t);
|
||||
|
||||
void process_rtop (SessionEvent*);
|
||||
|
||||
void update_latency (bool playback);
|
||||
|
@ -891,21 +891,11 @@ AudioEngine::thread_init_callback (void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* XXXX
|
||||
void
|
||||
AudioEngine::timebase_callback (TransportState state, pframes_t nframes, jack_position_t pos, int new_position)
|
||||
{
|
||||
if (_session && _session->synced_to_jack()) {
|
||||
// _session->timebase_callback (state, nframes, pos, new_position);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
AudioEngine::sync_callback (TransportState state, framepos_t position)
|
||||
{
|
||||
if (_session) {
|
||||
return _session->jack_sync_callback (state, position);
|
||||
return _session->backend_sync_callback (state, position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,7 +28,9 @@
|
||||
#include "jack/thread.h"
|
||||
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
#include "ardour/jack_audiobackend.h"
|
||||
#include "ardour/jack_connection.h"
|
||||
#include "ardour/jack_portengine.h"
|
||||
@ -680,32 +682,14 @@ JACKAudioBackend::_jack_timebase_callback (jack_transport_state_t state, pframes
|
||||
}
|
||||
|
||||
void
|
||||
JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t /*nframes*/,
|
||||
jack_position_t* pos, int /*new_position*/)
|
||||
JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
|
||||
jack_position_t* pos, int new_position)
|
||||
{
|
||||
TransportState tstate;
|
||||
framepos_t position;
|
||||
ARDOUR::Session* session = engine.session();
|
||||
|
||||
switch (state) {
|
||||
case JackTransportStopped:
|
||||
tstate = TransportStopped;
|
||||
break;
|
||||
case JackTransportRolling:
|
||||
tstate = TransportRolling;
|
||||
break;
|
||||
case JackTransportLooping:
|
||||
tstate = TransportLooping;
|
||||
break;
|
||||
case JackTransportStarting:
|
||||
tstate = TransportStarting;
|
||||
break;
|
||||
if (session) {
|
||||
session->jack_timebase_callback (state, nframes, pos, new_position);
|
||||
}
|
||||
|
||||
if (pos) {
|
||||
position = pos->frame;
|
||||
}
|
||||
|
||||
// engine.timebase_callback (tstate, nframes, position, new_position);
|
||||
}
|
||||
|
||||
int
|
||||
@ -754,8 +738,10 @@ void
|
||||
JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
|
||||
{
|
||||
JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
|
||||
if (ae->connected()) {
|
||||
ae->engine.JackSessionEvent (event); /* EMIT SIGNAL */
|
||||
ARDOUR::Session* session = ae->engine.session();
|
||||
|
||||
if (session) {
|
||||
session->jack_session_event (event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
185
libs/ardour/session_jack.cc
Normal file
185
libs/ardour/session_jack.cc
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
Copyright (C) 1999-2013 Paul Davis
|
||||
|
||||
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; 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
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifdef WAF_BUILD
|
||||
#include "libardour-config.h"
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include "jack/jack.h"
|
||||
#include "jack/session.h"
|
||||
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/filename_extensions.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/session_directory.h"
|
||||
#include "ardour/tempo.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using std::string;
|
||||
|
||||
#ifdef HAVE_JACK_SESSION
|
||||
void
|
||||
Session::jack_session_event (jack_session_event_t* event)
|
||||
{
|
||||
char timebuf[128], *tmp;
|
||||
time_t n;
|
||||
struct tm local_time;
|
||||
|
||||
time (&n);
|
||||
localtime_r (&n, &local_time);
|
||||
strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
|
||||
|
||||
while ((tmp = strchr(timebuf, ':'))) { *tmp = '.'; }
|
||||
|
||||
if (event->type == JackSessionSaveTemplate)
|
||||
{
|
||||
if (save_template( timebuf )) {
|
||||
event->flags = JackSessionSaveError;
|
||||
} else {
|
||||
string cmd ("ardour3 -P -U ");
|
||||
cmd += event->client_uuid;
|
||||
cmd += " -T ";
|
||||
cmd += timebuf;
|
||||
|
||||
event->command_line = strdup (cmd.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (save_state (timebuf)) {
|
||||
event->flags = JackSessionSaveError;
|
||||
} else {
|
||||
std::string xml_path (_session_dir->root_path());
|
||||
std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
|
||||
xml_path = Glib::build_filename (xml_path, legalized_filename);
|
||||
|
||||
string cmd ("ardour3 -P -U ");
|
||||
cmd += event->client_uuid;
|
||||
cmd += " \"";
|
||||
cmd += xml_path;
|
||||
cmd += '\"';
|
||||
|
||||
event->command_line = strdup (cmd.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* this won't be called if the port engine in use is not JACK, so we do
|
||||
not have to worry about the type of PortEngine::private_handle()
|
||||
*/
|
||||
|
||||
jack_client_t* jack_client = (jack_client_t*) AudioEngine::instance()->port_engine().private_handle();
|
||||
|
||||
if (jack_client) {
|
||||
jack_session_reply (jack_client, event);
|
||||
}
|
||||
|
||||
if (event->type == JackSessionSaveAndQuit) {
|
||||
Quit (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
jack_session_event_free( event );
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Session::jack_timebase_callback (jack_transport_state_t /*state*/,
|
||||
pframes_t /*nframes*/,
|
||||
jack_position_t* pos,
|
||||
int /*new_position*/)
|
||||
{
|
||||
Timecode::BBT_Time bbt;
|
||||
|
||||
/* BBT info */
|
||||
|
||||
if (_tempo_map) {
|
||||
|
||||
TempoMetric metric (_tempo_map->metric_at (_transport_frame));
|
||||
|
||||
try {
|
||||
_tempo_map->bbt_time_rt (_transport_frame, bbt);
|
||||
|
||||
pos->bar = bbt.bars;
|
||||
pos->beat = bbt.beats;
|
||||
pos->tick = bbt.ticks;
|
||||
|
||||
// XXX still need to set bar_start_tick
|
||||
|
||||
pos->beats_per_bar = metric.meter().divisions_per_bar();
|
||||
pos->beat_type = metric.meter().note_divisor();
|
||||
pos->ticks_per_beat = Timecode::BBT_Time::ticks_per_beat;
|
||||
pos->beats_per_minute = metric.tempo().beats_per_minute();
|
||||
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
|
||||
|
||||
} catch (...) {
|
||||
/* no message */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_JACK_VIDEO_SUPPORT
|
||||
//poke audio video ratio so Ardour can track Video Sync
|
||||
pos->audio_frames_per_video_frame = frame_rate() / timecode_frames_per_second();
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Timecode info */
|
||||
|
||||
pos->timecode_offset = config.get_timecode_offset();
|
||||
t.timecode_frame_rate = timecode_frames_per_second();
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackPositionTimecode;
|
||||
|
||||
if (_transport_speed) {
|
||||
|
||||
if (play_loop) {
|
||||
|
||||
Location* location = _locations.auto_loop_location();
|
||||
|
||||
if (location) {
|
||||
|
||||
t.transport_state = JackTransportLooping;
|
||||
t.loop_start = location->start();
|
||||
t.loop_end = location->end();
|
||||
t.valid = jack_transport_bits_t (t.valid | JackTransportLoop);
|
||||
|
||||
} else {
|
||||
|
||||
t.loop_start = 0;
|
||||
t.loop_end = 0;
|
||||
t.transport_state = JackTransportRolling;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
t.loop_start = 0;
|
||||
t.loop_end = 0;
|
||||
t.transport_state = JackTransportRolling;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 1999-2002 Paul Davis
|
||||
Copyright (C) 1999-2013 Paul Davis
|
||||
|
||||
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
|
||||
@ -689,70 +689,6 @@ Session::remove_state (string snapshot_name)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_JACK_SESSION
|
||||
void
|
||||
Session::jack_session_event (jack_session_event_t * event)
|
||||
{
|
||||
char timebuf[128], *tmp;
|
||||
time_t n;
|
||||
struct tm local_time;
|
||||
|
||||
time (&n);
|
||||
localtime_r (&n, &local_time);
|
||||
strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
|
||||
|
||||
while ((tmp = strchr(timebuf, ':'))) { *tmp = '.'; }
|
||||
|
||||
if (event->type == JackSessionSaveTemplate)
|
||||
{
|
||||
if (save_template( timebuf )) {
|
||||
event->flags = JackSessionSaveError;
|
||||
} else {
|
||||
string cmd ("ardour3 -P -U ");
|
||||
cmd += event->client_uuid;
|
||||
cmd += " -T ";
|
||||
cmd += timebuf;
|
||||
|
||||
event->command_line = strdup (cmd.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (save_state (timebuf)) {
|
||||
event->flags = JackSessionSaveError;
|
||||
} else {
|
||||
std::string xml_path (_session_dir->root_path());
|
||||
std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
|
||||
xml_path = Glib::build_filename (xml_path, legalized_filename);
|
||||
|
||||
string cmd ("ardour3 -P -U ");
|
||||
cmd += event->client_uuid;
|
||||
cmd += " \"";
|
||||
cmd += xml_path;
|
||||
cmd += '\"';
|
||||
|
||||
event->command_line = strdup (cmd.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* this won't be called if the port engine in use is not JACK, so we do
|
||||
not have to worry about the type of PortEngine::private_handle()
|
||||
*/
|
||||
|
||||
jack_client_t* jack_client = (jack_client_t*) AudioEngine::instance()->port_engine().private_handle();
|
||||
|
||||
if (jack_client) {
|
||||
jack_session_reply (jack_client, event);
|
||||
}
|
||||
|
||||
if (event->type == JackSessionSaveAndQuit) {
|
||||
Quit (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
jack_session_event_free( event );
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @param snapshot_name Name to save under, without .ardour / .pending prefix */
|
||||
int
|
||||
Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
|
||||
|
@ -180,7 +180,7 @@ Session::timecode_time (Timecode::Time &t)
|
||||
}
|
||||
|
||||
int
|
||||
Session::jack_sync_callback (TransportState state, framepos_t pos)
|
||||
Session::backend_sync_callback (TransportState state, framepos_t pos)
|
||||
{
|
||||
bool slave = synced_to_jack();
|
||||
|
||||
@ -218,91 +218,6 @@ Session::jack_sync_callback (TransportState state, framepos_t pos)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* XXX REQUIRES SOMEWAY TO EFFICIENTLY ACCESS jack_position_t WITHOUT BRIDGING
|
||||
* THE ENTIRE DATA STRUCTURE
|
||||
*/
|
||||
#if 0
|
||||
void
|
||||
Session::jack_timebase_callback (TransportState /*state*/,
|
||||
pframes_t /*nframes*/,
|
||||
framepos_t pos,
|
||||
int /*new_position*/)
|
||||
{
|
||||
Timecode::BBT_Time bbt;
|
||||
|
||||
/* BBT info */
|
||||
|
||||
if (_tempo_map) {
|
||||
|
||||
TempoMetric metric (_tempo_map->metric_at (_transport_frame));
|
||||
|
||||
try {
|
||||
_tempo_map->bbt_time_rt (_transport_frame, bbt);
|
||||
|
||||
pos->bar = bbt.bars;
|
||||
pos->beat = bbt.beats;
|
||||
pos->tick = bbt.ticks;
|
||||
|
||||
// XXX still need to set bar_start_tick
|
||||
|
||||
pos->beats_per_bar = metric.meter().divisions_per_bar();
|
||||
pos->beat_type = metric.meter().note_divisor();
|
||||
pos->ticks_per_beat = Timecode::BBT_Time::ticks_per_beat;
|
||||
pos->beats_per_minute = metric.tempo().beats_per_minute();
|
||||
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
|
||||
|
||||
} catch (...) {
|
||||
/* no message */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_JACK_VIDEO_SUPPORT
|
||||
//poke audio video ratio so Ardour can track Video Sync
|
||||
pos->audio_frames_per_video_frame = frame_rate() / timecode_frames_per_second();
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Timecode info */
|
||||
|
||||
pos->timecode_offset = config.get_timecode_offset();
|
||||
t.timecode_frame_rate = timecode_frames_per_second();
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackPositionTimecode;
|
||||
|
||||
if (_transport_speed) {
|
||||
|
||||
if (play_loop) {
|
||||
|
||||
Location* location = _locations.auto_loop_location();
|
||||
|
||||
if (location) {
|
||||
|
||||
t.transport_state = JackTransportLooping;
|
||||
t.loop_start = location->start();
|
||||
t.loop_end = location->end();
|
||||
t.valid = jack_transport_bits_t (t.valid | JackTransportLoop);
|
||||
|
||||
} else {
|
||||
|
||||
t.loop_start = 0;
|
||||
t.loop_end = 0;
|
||||
t.transport_state = JackTransportRolling;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
t.loop_start = 0;
|
||||
t.loop_end = 0;
|
||||
t.transport_state = JackTransportRolling;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* jack data structure issues */
|
||||
|
||||
ARDOUR::framecnt_t
|
||||
Session::convert_to_frames (AnyTime const & position)
|
||||
|
@ -180,6 +180,7 @@ libardour_sources = [
|
||||
'session_events.cc',
|
||||
'session_export.cc',
|
||||
'session_handle.cc',
|
||||
'session_jack.cc',
|
||||
'session_ltc.cc',
|
||||
'session_metadata.cc',
|
||||
'session_midi.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user