diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 24f6511b4c..81c0be223c 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -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. */ diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 509d330f12..f05944797d 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -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 Freewheel; PBD::Signal0 Xrun; - -#ifdef HAVE_JACK_SESSION - PBD::Signal1 JackSessionEvent; -#endif - /* this signal is emitted if the sample rate changes */ PBD::Signal1 SampleRateChanged; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index c291220874..31f0658931 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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 ltc_input_io() { return _ltc_input; } boost::shared_ptr 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 _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); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 45cc33cdc1..2b9a50f1ef 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -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; } diff --git a/libs/ardour/jack_audiobackend.cc b/libs/ardour/jack_audiobackend.cc index a3bbaecb2d..ece8c4788e 100644 --- a/libs/ardour/jack_audiobackend.cc +++ b/libs/ardour/jack_audiobackend.cc @@ -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 (arg); - if (ae->connected()) { - ae->engine.JackSessionEvent (event); /* EMIT SIGNAL */ + ARDOUR::Session* session = ae->engine.session(); + + if (session) { + session->jack_session_event (event); } } #endif diff --git a/libs/ardour/session_jack.cc b/libs/ardour/session_jack.cc new file mode 100644 index 0000000000..af8a93fec3 --- /dev/null +++ b/libs/ardour/session_jack.cc @@ -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 + +#include + +#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 +} + diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index c4522f76e7..50905ef434 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -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) diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index 088712f625..0f2186c09b 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -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) diff --git a/libs/ardour/wscript b/libs/ardour/wscript index c140c6eb3a..57b68a0fde 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -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',