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:
parent
df59a000b7
commit
1c4d00e8b7
|
@ -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) {
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue