merge with master, fixing conflicts in 3 wscript files

This commit is contained in:
Paul Davis 2013-10-09 14:00:42 -04:00
commit 2a6a16f980
64 changed files with 4195 additions and 3528 deletions

View file

@ -63,7 +63,7 @@ deinstantiate ()
static bool
already_configured ()
{
return JackConnection::server_running ();
return !JackConnection::in_control ();
}
static ARDOUR::AudioBackendInfo _descriptor = {

View file

@ -37,6 +37,7 @@
#include "jack_audiobackend.h"
#include "jack_connection.h"
#include "jack_utils.h"
#include "jack_session.h"
#include "i18n.h"
@ -45,6 +46,7 @@ using namespace PBD;
using std::string;
using std::vector;
#define GET_PRIVATE_JACK_POINTER(localvar) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
@ -63,6 +65,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
, _target_systemic_output_latency (0)
, _current_sample_rate (0)
, _current_buffer_size (0)
, _session (0)
{
_jack_connection->Connected.connect_same_thread (jack_connection_connection, boost::bind (&JACKAudioBackend::when_connected_to_jack, this));
_jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
@ -513,7 +516,10 @@ JACKAudioBackend::start ()
{
if (!available()) {
if (!_jack_connection->server_running()) {
if (_jack_connection->in_control()) {
/* we will be starting JACK, so set up the
command that JACK will use when it (auto-)starts
*/
setup_jack_startup_command ();
}
@ -744,7 +750,8 @@ JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_
ARDOUR::Session* session = engine.session();
if (session) {
session->jack_timebase_callback (state, nframes, pos, new_position);
JACKSession jsession (session);
jsession.timebase_callback (state, nframes, pos, new_position);
}
}
@ -789,7 +796,6 @@ JACKAudioBackend::_xrun_callback (void *arg)
return 0;
}
#ifdef HAVE_JACK_SESSION
void
JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
{
@ -797,10 +803,10 @@ JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
ARDOUR::Session* session = jab->engine.session();
if (session) {
session->jack_session_event (event);
JACKSession jsession (session);
jsession.session_event (event);
}
}
#endif
void
JACKAudioBackend::_freewheel_callback (int onoff, void *arg)
@ -822,25 +828,72 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar
}
int
JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
JACKAudioBackend::create_process_thread (boost::function<void()> f)
{
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
ThreadData* td = new ThreadData (this, f, stacksize);
if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
jack_native_thread_t thread_id;
ThreadData* td = new ThreadData (this, f, thread_stack_size());
if (jack_client_create_thread (_priv_jack, &thread_id, jack_client_real_time_priority (_priv_jack),
jack_is_realtime (_priv_jack), _start_process_thread, td)) {
return -1;
}
return 0;
_jack_threads.push_back(thread_id);
return 0;
}
int
JACKAudioBackend::wait_for_process_thread_exit (AudioBackendNativeThread thr)
JACKAudioBackend::join_process_threads ()
{
void* status;
/* this doesn't actively try to stop the thread, it just waits till it exits */
return pthread_join (thr, &status);
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
int ret = 0;
for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin ();
i != _jack_threads.end(); i++) {
#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS)
if (jack_client_stop_thread (_priv_jack, *i) != 0) {
#else
void* status;
if (pthread_join (*i, &status) != 0) {
#endif
error << "AudioEngine: cannot stop process thread" << endmsg;
ret += -1;
}
}
_jack_threads.clear();
return ret;
}
bool
JACKAudioBackend::in_process_thread ()
{
for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin ();
i != _jack_threads.end(); i++) {
#ifdef COMPILER_MINGW
if (*i == GetCurrentThread()) {
return true;
}
#else // pthreads
if (pthread_equal (*i, pthread_self()) != 0) {
return true;
}
#endif
}
return false;
}
uint32_t
JACKAudioBackend::process_thread_count ()
{
return _jack_threads.size();
}
void*
@ -960,6 +1013,7 @@ JACKAudioBackend::disconnected (const char* why)
engine.halted_callback (why); /* EMIT SIGNAL */
}
}
float
JACKAudioBackend::cpu_load() const
{

View file

@ -30,15 +30,14 @@
#include <boost/shared_ptr.hpp>
#include <jack/jack.h>
#ifdef HAVE_JACK_SESSION
#include <jack/session.h>
#endif
#include "ardour/audio_backend.h"
namespace ARDOUR {
class JackConnection;
class JACKSession;
class JACKAudioBackend : public AudioBackend {
public:
@ -103,8 +102,10 @@ class JACKAudioBackend : public AudioBackend {
size_t raw_buffer_size (DataType t);
int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize);
int wait_for_process_thread_exit (AudioBackendNativeThread);
int create_process_thread (boost::function<void()> func);
int join_process_threads ();
bool in_process_thread ();
uint32_t process_thread_count ();
void transport_start ();
void transport_stop ();
@ -184,6 +185,8 @@ class JACKAudioBackend : public AudioBackend {
bool _freewheeling;
std::map<DataType,size_t> _raw_buffer_sizes;
std::vector<jack_native_thread_t> _jack_threads;
static int _xrun_callback (void *arg);
static void* _process_thread (void *arg);
static int _sample_rate_callback (pframes_t nframes, void *arg);
@ -192,9 +195,7 @@ class JACKAudioBackend : public AudioBackend {
static int _jack_sync_callback (jack_transport_state_t, jack_position_t*, void *arg);
static void _freewheel_callback (int , void *arg);
static void _latency_callback (jack_latency_callback_mode_t, void*);
#ifdef HAVE_JACK_SESSION
static void _session_callback (jack_session_event_t *event, void *arg);
#endif
void jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int);
int jack_sync_callback (jack_transport_state_t, jack_position_t*);
@ -257,6 +258,12 @@ class JACKAudioBackend : public AudioBackend {
void when_connected_to_jack ();
PBD::ScopedConnection jack_connection_connection;
/* Object to manage interactions with Session in a way that
keeps JACK out of libardour directly
*/
JACKSession* _session;
};
} // namespace

View file

@ -36,6 +36,8 @@ using std::vector;
using std::cerr;
using std::endl;
bool JackConnection::_in_control = false;
static void jack_halted_callback (void* arg)
{
JackConnection* jc = static_cast<JackConnection*> (arg);
@ -54,17 +56,9 @@ JackConnection::JackConnection (const std::string& arg1, const std::string& arg2
, _client_name (arg1)
, session_uuid (arg2)
{
_in_control = !server_running();
}
/* See if the server is already up
*/
JackConnection::~JackConnection ()
{
close ();
}
bool
JackConnection::server_running ()
{
EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
@ -83,10 +77,15 @@ JackConnection::server_running ()
if (status == 0) {
jack_client_close (c);
return true;
_in_control = false;
} else {
_in_control = true;
}
}
return false;
JackConnection::~JackConnection ()
{
close ();
}
int
@ -106,19 +105,6 @@ JackConnection::open ()
global_epa->restore ();
}
/* check to see if the server is already running so that we know if we
* are starting it.
*/
jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
if (status == 0) {
_in_control = false;
jack_client_close (c);
} else {
_in_control = true;
}
/* ensure that PATH or equivalent includes likely locations of the JACK
* server, in case the user's default does not.
*/

View file

@ -27,15 +27,13 @@ class JackConnection {
void halted_callback ();
void halted_info_callback (jack_status_t, const char*);
bool in_control() const { return _in_control; }
static bool in_control() { return _in_control; }
static bool server_running();
private:
jack_client_t* volatile _jack;
std::string _client_name;
std::string session_uuid;
bool _in_control;
static bool _in_control;
};
} // namespace

View file

@ -0,0 +1,193 @@
/*
Copyright (C) 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.
*/
#include <time.h>
#include <glibmm/miscutils.h>
#include <jack/jack.h>
#include "ardour/audioengine.h"
#include "ardour/filename_extensions.h"
#include "ardour/session.h"
#include "ardour/session_directory.h"
#include "ardour/tempo.h"
#include "jack_session.h"
using namespace ARDOUR;
using std::string;
JACKSession::JACKSession (Session* s)
: SessionHandlePtr (s)
{
}
JACKSession::~JACKSession ()
{
}
void
JACKSession::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 (_session->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 (_session->save_state (timebuf)) {
event->flags = JackSessionSaveError;
} else {
std::string xml_path (_session->session_directory().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) {
_session->Quit (); /* EMIT SIGNAL */
}
jack_session_event_free (event);
}
void
JACKSession::timebase_callback (jack_transport_state_t /*state*/,
pframes_t /*nframes*/,
jack_position_t* pos,
int /*new_position*/)
{
Timecode::BBT_Time bbt;
TempoMap& tempo_map (_session->tempo_map());
framepos_t tf = _session->transport_frame ();
/* BBT info */
TempoMetric metric (tempo_map.metric_at (tf));
try {
tempo_map.bbt_time_rt (tf, 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 = _session->frame_rate() / _session->timecode_frames_per_second();
pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
#endif
#ifdef HAVE_JACK_TIMCODE_SUPPORT
/* This is not yet defined in JACK */
/* Timecode info */
pos->timecode_offset = _session->config.get_timecode_offset();
t.timecode_frame_rate = _session->timecode_frames_per_second();
pos->valid = jack_position_bits_t (pos->valid | JackPositionTimecode);
#endif
#ifdef HAVE_JACK_LOOPING_SUPPORT
/* This is not yet defined in JACK */
if (_transport_speed) {
if (play_loop) {
Location* location = _session->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
}

View file

@ -0,0 +1,47 @@
/*
Copyright (C) 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.
*/
#ifndef __ardour_jack_audiobackend_jack_session_h__
#define __ardour_jack_audiobackend_jack_session_h__
#include <jack/session.h>
#include <jack/transport.h>
#include "ardour/types.h"
#include "ardour/session_handle.h"
namespace ARDOUR {
class Session;
class JACKSession : public ARDOUR::SessionHandlePtr
{
public:
JACKSession (ARDOUR::Session* s);
~JACKSession ();
void session_event (jack_session_event_t* event);
void timebase_callback (jack_transport_state_t /*state*/,
ARDOUR::pframes_t /*nframes*/,
jack_position_t* pos,
int /*new_position*/);
};
} /* namespace */
#endif /* __ardour_jack_audiobackend_jack_session_h__ */

View file

@ -37,10 +37,10 @@ def build(bld):
'jack_connection.cc',
'jack_audiobackend.cc',
'jack_portengine.cc',
'jack_utils.cc'
'jack_utils.cc',
'jack_session.cc',
]
obj.includes = ['.']
obj.cxxflags = [ '-fPIC' ]
obj.name = 'jack_audiobackend'
obj.target = 'jack_audiobackend'
if Options.options.dist_target == 'mingw':