mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-06 13:45:43 +01:00
merge with master, fixing conflicts in 3 wscript files
This commit is contained in:
commit
2a6a16f980
64 changed files with 4195 additions and 3528 deletions
|
|
@ -63,7 +63,7 @@ deinstantiate ()
|
|||
static bool
|
||||
already_configured ()
|
||||
{
|
||||
return JackConnection::server_running ();
|
||||
return !JackConnection::in_control ();
|
||||
}
|
||||
|
||||
static ARDOUR::AudioBackendInfo _descriptor = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
193
libs/backends/jack/jack_session.cc
Normal file
193
libs/backends/jack/jack_session.cc
Normal 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
|
||||
}
|
||||
|
||||
47
libs/backends/jack/jack_session.h
Normal file
47
libs/backends/jack/jack_session.h
Normal 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__ */
|
||||
|
|
@ -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':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue