audioengine branch can now load and run at least one test session.

currently hard-coded to deal only with the situation where JACK is already running
This commit is contained in:
Paul Davis 2013-08-03 11:57:56 -04:00
parent df59a000b7
commit 1c4d00e8b7
13 changed files with 131 additions and 72 deletions

View File

@ -61,6 +61,7 @@
#include "midi++/manager.h"
#include "ardour/ardour.h"
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
#include "ardour/audiofilesource.h"
#include "ardour/automation_watch.h"
@ -373,6 +374,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
_process_thread->init ();
DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
attach_to_engine ();
}
GlobalPortMatrixWindow*
@ -384,18 +387,10 @@ ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
return new GlobalPortMatrixWindow (_session, type);
}
int
ARDOUR_UI::create_engine ()
void
ARDOUR_UI::attach_to_engine ()
{
// this gets called every time by new_session()
if (engine) {
return 0;
}
loading_message (_("Starting audio engine"));
AudioEngine* engine = AudioEngine::instance();
engine = AudioEngine::instance();
engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
@ -405,8 +400,6 @@ ARDOUR_UI::create_engine ()
engine->BackendAvailable.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::post_engine, this));
ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
return 0;
}
void
@ -414,7 +407,7 @@ ARDOUR_UI::post_engine ()
{
cerr << "Backend available!\n";
/* Things to be done once we create the AudioEngine
/* Things to be done once we have a backend running in the AudioEngine
*/
ARDOUR::init_post_engine ();
@ -2572,6 +2565,17 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
int ret = -1;
bool likely_new = false;
/* if the audio/midi backend does not require setup, get our use of it underway
* right here
*/
if (!EngineControl::need_setup()) {
vector<const AudioBackendInfo*> backends = AudioEngine::instance()->available_backends();
cerr << "Setting up backend " << backends.front()->name;
AudioEngine::instance()->set_backend (backends.front()->name, ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid);
AudioEngine::instance()->start ();
}
/* deal with any existing DIRTY session now, rather than later. don't
* treat a non-dirty session this way, so that it stays visible
* as we bring up the new session dialog.
@ -2693,10 +2697,6 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
}
}
if (create_engine ()) {
break;
}
if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
if (likely_new && !nsm) {

View File

@ -263,7 +263,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
session_add_midi_route (false);
}*/
int create_engine ();
void attach_to_engine ();
void post_engine ();
gint exit_on_main_window_close (GdkEventAny *);

View File

@ -44,6 +44,8 @@
#include <gtkmm/stock.h>
#include <gtkmm2ext/utils.h>
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
#include "ardour/rc_configuration.h"
#include "pbd/convert.h"
@ -594,33 +596,13 @@ EngineControl::build_command_line (vector<string>& cmd)
bool
EngineControl::need_setup ()
{
return !engine_running();
}
vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
bool
EngineControl::engine_running ()
{
EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
/* revert all environment settings back to whatever they were when
* ardour started, because ardour's startup script may have reset
* something in ways that interfere with finding/starting JACK.
*/
if (global_epa) {
current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
global_epa->restore ();
}
jack_status_t status;
jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
if (status == 0) {
jack_client_close (c);
return true;
if (backends.size() == 1 && backends.front()->already_configured()) {
return false;
}
return false;
return true;
}
int

View File

@ -340,7 +340,7 @@ class AudioBackend {
virtual int create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize) = 0;
virtual void update_latencies () = 0;
protected:
AudioEngine& engine;
};
@ -353,6 +353,15 @@ struct AudioBackendInfo {
boost::shared_ptr<AudioBackend> (*backend_factory) (AudioEngine&);
boost::shared_ptr<PortEngine> (*portengine_factory) (PortManager&);
/** Return true if the underlying mechanism/API has been
* configured and does not need (re)configuration in order
* to be usable. Return false otherwise.
*
* Note that this may return true if (re)configuration is possible,
* but not required.
*/
bool (*already_configured)();
};
} // namespace

View File

@ -72,7 +72,7 @@ public:
virtual ~AudioEngine ();
int discover_backends();
std::vector<std::string> available_backends() const;
std::vector<const AudioBackendInfo*> available_backends() const;
std::string current_backend_name () const;
int set_backend (const std::string&, const std::string& arg1, const std::string& arg2);

View File

@ -101,6 +101,8 @@ class JACKAudioBackend : public AudioBackend {
void update_latencies ();
static bool already_configured();
private:
boost::shared_ptr<JackConnection> _jack_connection; //< shared with JACKPortEngine
bool _running;
@ -144,6 +146,8 @@ class JACKAudioBackend : public AudioBackend {
static void* _start_process_thread (void*);
ChanCount n_physical (unsigned long) const;
void preset_jack_startup_command ();
/* pffooo */

View File

@ -21,11 +21,14 @@ class JackConnection {
jack_client_t* jack() const { return _jack; }
PBD::Signal0<void> Connected;
PBD::Signal1<void,const char*> Disconnected;
void halted_callback ();
void halted_info_callback (jack_status_t, const char*);
static bool server_running();
private:
jack_client_t* volatile _jack;
std::string _client_name;

View File

@ -27,6 +27,8 @@
#include <boost/shared_ptr.hpp>
#include "pbd/signals.h"
#include "ardour/port_engine.h"
#include "ardour/types.h"
@ -115,6 +117,9 @@ class JACKPortEngine : public PortEngine
ChanCount n_physical (unsigned long flags) const;
void get_physical (DataType type, unsigned long flags, std::vector<std::string>& phy) const;
PBD::ScopedConnection jack_connection_connection;
void connected_to_jack ();
};
} // namespace

View File

@ -537,13 +537,13 @@ AudioEngine::backend_discover (const string& path)
return info;
}
vector<string>
vector<const AudioBackendInfo*>
AudioEngine::available_backends() const
{
vector<string> r;
vector<const AudioBackendInfo*> r;
for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
r.push_back (i->first);
r.push_back (i->second);
}
return r;
@ -581,17 +581,21 @@ AudioEngine::set_backend (const std::string& name, const std::string& arg1, cons
drop_backend ();
try {
cerr << "Instantiate " << b->second->name << " with " << arg1 << " + " << arg2 << endl;
if (b->second->instantiate (arg1, arg2)) {
cerr << "i failed\n";
throw failed_constructor ();
}
cerr << "bf\n";
_backend = b->second->backend_factory (*this);
cerr << "pf\n";
_impl = b->second->portengine_factory (*this);
cerr << "done\n";
} catch (...) {
error << string_compose (_("Could not create backend for %1"), name) << endmsg;
} catch (exception& e) {
error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
return -1;
}

View File

@ -72,6 +72,7 @@
#include "ardour/analyser.h"
#include "ardour/audio_library.h"
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
@ -333,15 +334,12 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
ARDOUR::AudioEngine::create ();
uint32_t backend_cnt;
vector<const AudioBackendInfo*> backends = AudioEngine::instance()->available_backends();
if ((backend_cnt = AudioEngine::instance()->available_backends().size()) == 0) {
error << _("No audio/MIDI backends are available") << endmsg;
return -1;
for (vector<const AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
cerr << "BACKEND: [" << (*i)->name << "] already configured " << (*i)->already_configured() << endl;
}
cerr << "We have " << backend_cnt << endl;
return 0;
}

View File

@ -354,12 +354,26 @@ JACKAudioBackend::raw_buffer_size(DataType t)
return (s != _raw_buffer_sizes.end()) ? s->second : 0;
}
void
JACKAudioBackend::preset_jack_startup_command ()
{
/* write parameter settings to ~/.jackdrc file so that next invocation
* of JACK (presumably from a call to jack_client_open() from this
* process) will do the right thing.
*/
}
/* ---- BASIC STATE CONTROL API: start/stop/pause/freewheel --- */
int
JACKAudioBackend::start ()
{
if (!connected()) {
if (!_jack_connection->server_running()) {
preset_jack_startup_command ();
}
std::cerr << "Open JACK connection\n";
_jack_connection->open ();
}

View File

@ -55,6 +55,33 @@ JackConnection::~JackConnection ()
close ();
}
bool
JackConnection::server_running ()
{
EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
/* revert all environment settings back to whatever they were when
* ardour started, because ardour's startup script may have reset
* something in ways that interfere with finding/starting JACK.
*/
if (global_epa) {
current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
global_epa->restore ();
}
jack_status_t status;
jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
if (status == 0) {
jack_client_close (c);
return true;
}
return false;
}
int
JackConnection::open ()
{

View File

@ -20,13 +20,16 @@
#include <string.h>
#include <stdint.h>
#include "pbd/failed_constructor.h"
#include "pbd/error.h"
#include "ardour/jack_portengine.h"
#include "ardour/jack_connection.h"
#include "ardour/port_manager.h"
#include "i18n.h"
using namespace ARDOUR;
using namespace PBD;
using std::string;
using std::vector;
@ -85,17 +88,7 @@ JACKPortEngine::JACKPortEngine (PortManager& pm, boost::shared_ptr<JackConnectio
: PortEngine (pm)
, _jack_connection (jc)
{
jack_client_t* client = _jack_connection->jack();
if (!client) {
throw failed_constructor ();
}
/* register callbacks for stuff that is our responsibility */
jack_set_port_registration_callback (client, _registration_callback, this);
jack_set_port_connect_callback (client, _connect_callback, this);
jack_set_graph_order_callback (client, _graph_order_callback, this);
_jack_connection->Connected.connect_same_thread (jack_connection_connection, boost::bind (&JACKPortEngine::connected_to_jack, this));
}
JACKPortEngine::~JACKPortEngine ()
@ -107,6 +100,24 @@ JACKPortEngine::~JACKPortEngine ()
_jack_connection.reset ();
}
void
JACKPortEngine::connected_to_jack ()
{
/* register callbacks for stuff that is our responsibility */
jack_client_t* client = _jack_connection->jack();
if (!client) {
/* how could this happen? it could ... */
error << _("Already disconnected from JACK before PortEngine could register callbacks") << endmsg;
return;
}
jack_set_port_registration_callback (client, _registration_callback, this);
jack_set_port_connect_callback (client, _connect_callback, this);
jack_set_graph_order_callback (client, _graph_order_callback, this);
}
void*
JACKPortEngine::private_handle() const
{
@ -294,8 +305,10 @@ JACKPortEngine::n_physical (unsigned long flags) const
if (ports) {
for (uint32_t i = 0; ports[i]; ++i) {
if (!strstr (ports[i], "Midi-Through")) {
DataType t (jack_port_type (jack_port_by_name (_priv_jack, ports[i])));
c.set (t, c.get (t) + 1);
DataType t = port_data_type (jack_port_by_name (_priv_jack, ports[i]));
if (t != DataType::NIL) {
c.set (t, c.get (t) + 1);
}
}
}