#include <cerrno>
#include <fstream>
+#ifndef WIN32
+#include <sys/resource.h>
+#endif
+
#include <stdint.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
+#include <glib.h>
+#include <glib/gstdio.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm/accelmap.h>
#include "pbd/memento_command.h"
#include "pbd/openuri.h"
#include "pbd/file_utils.h"
+#include "pbd/localtime_r.h"
#include "gtkmm2ext/application.h"
#include "gtkmm2ext/bindings.h"
/* start of private members */
, _startup (0)
- , engine (0)
, nsm (0)
, _was_dirty (false)
, _mixer_on_top (false)
, _status_bar_visibility (X_("status-bar"))
, _feedback_exists (false)
-
+ , _audio_midi_setup (0)
{
Gtkmm2ext::init(localedir);
}
ui_config = new UIConfiguration();
+ _audio_midi_setup = new EngineControl;
editor = 0;
mixer = 0;
meterbridge = 0;
editor = 0;
- engine = 0;
_session_is_new = false;
session_selector_window = 0;
last_key_press_time = 0;
ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
+ /* handle Audio/MIDI setup when session requires it */
+
+ ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
+
/* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
/* and ambiguous files */
- ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2, _3));
+ ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
/* lets get this party started */
- try {
- if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization, localedir)) {
- throw failed_constructor ();
- }
-
- setup_gtk_ardour_enums ();
- setup_profile ();
-
- SessionEvent::create_per_thread_pool ("GUI", 512);
+ setup_gtk_ardour_enums ();
+ setup_profile ();
- } catch (failed_constructor& err) {
- error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg;
- // pass it on up
- throw;
- }
+ SessionEvent::create_per_thread_pool ("GUI", 512);
/* we like keyboards */
void
ARDOUR_UI::attach_to_engine ()
{
- 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());
- engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
-
- engine->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
-
+ AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
-
- /* if there is only one audio/midi backend, and it does not require setup, get our use of it underway
- * right here (we need to know the client name and potential session ID
- * to do this, which is why this is here, rather than in, say,
- * ARDOUR::init().
- */
-
- if (!AudioEngine::instance()->setup_required()) {
- const AudioBackendInfo* backend = AudioEngine::instance()->available_backends().front();
- AudioEngine::instance()->set_backend (backend->name, ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid);
- AudioEngine::instance()->start ();
- }
}
void
ARDOUR_UI::engine_stopped ()
{
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
- ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
- ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
+ ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
+ ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
}
void
first_time_engine_run = false;
}
- ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
- ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
+ ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
+ ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
Glib::RefPtr<Action> action;
const char* action_name = 0;
- switch (engine->samples_per_cycle()) {
+ switch (AudioEngine::instance()->samples_per_cycle()) {
case 32:
action_name = X_("JACKLatency32");
break;
update_disk_space ();
update_cpu_load ();
- update_sample_rate (engine->sample_rate());
+ update_sample_rate (AudioEngine::instance()->sample_rate());
update_timecode_format ();
}
}
return;
}
- ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
- ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
+ ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
+ ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
update_sample_rate (0);
*/
ARDOUR::init_post_engine ();
+
+ /* connect to important signals */
+
+ AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
+ AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
+ AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
_tooltips.enable();
void
ARDOUR_UI::check_memory_locking ()
{
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(WIN32)
/* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
return;
#else // !__APPLE__
XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
- if (engine->is_realtime() && memory_warning_node == 0) {
+ if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
struct rlimit limits;
int64_t ram;
}
halt_connection.disconnect ();
- engine->stop ();
+ AudioEngine::instance()->stop ();
quit ();
}
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
- if (!engine->connected()) {
+ if (!AudioEngine::instance()->connected()) {
snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"red\">none</span>"));
} else {
- framecnt_t rate = engine->sample_rate();
+ framecnt_t rate = AudioEngine::instance()->sample_rate();
if (rate == 0) {
/* no sample rate available */
if (fmod (rate, 1000.0) != 0.0) {
snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
(float) rate / 1000.0f,
- (engine->usecs_per_cycle() / 1000.0f));
+ (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
} else {
snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
rate/1000,
- (engine->usecs_per_cycle() / 1000.0f));
+ (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
}
}
}
should also be changed.
*/
- float const c = engine->get_cpu_load ();
+ float const c = AudioEngine::instance()->get_cpu_load ();
snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
cpu_load_label.set_markup (buf);
}
bool
ARDOUR_UI::check_audioengine ()
{
- if (engine) {
- if (!engine->connected()) {
- MessageDialog msg (string_compose (
- _("%1 is not connected to JACK\n"
- "You cannot open or close sessions in this condition"),
- PROGRAM_NAME));
- pop_back_splash (msg);
- msg.run ();
- return false;
- }
- return true;
- } else {
+ if (!AudioEngine::instance()->connected()) {
+ MessageDialog msg (string_compose (
+ _("%1 is not connected to any audio backend.\n"
+ "You cannot open or close sessions in this condition"),
+ PROGRAM_NAME));
+ pop_back_splash (msg);
+ msg.run ();
return false;
}
+ return true;
}
void
int unload_status;
int retval = -1;
- session_loaded = false;
-
- if (!check_audioengine()) {
- return -2;
+ if (_session) {
+ unload_status = unload_session ();
+
+ if (unload_status < 0) {
+ goto out;
+ } else if (unload_status > 0) {
+ retval = 0;
+ goto out;
+ }
}
- unload_status = unload_session ();
-
- if (unload_status < 0) {
- goto out;
- } else if (unload_status > 0) {
- retval = 0;
- goto out;
- }
+ session_loaded = false;
loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
try {
- new_session = new Session (*engine, path, snap_name, 0, mix_template);
+ new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
}
/* this one is special */
Session *new_session;
int x;
- if (!check_audioengine()) {
- return -1;
- }
-
session_loaded = false;
-
x = unload_session ();
if (x < 0) {
_session_is_new = true;
try {
- new_session = new Session (*engine, path, snap_name, &bus_profile);
+ new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
}
catch (...) {
if (icsd_docroot.empty()) {icsd_docroot = X_("/");}
struct stat sb;
- if (!lstat (icsd_docroot.c_str(), &sb) == 0 || !S_ISDIR(sb.st_mode)) {
+ if (!g_lstat (icsd_docroot.c_str(), &sb) == 0 || !S_ISDIR(sb.st_mode)) {
warning << _("Specified docroot is not an existing directory.") << endmsg;
continue;
}
- if ( (!lstat (icsd_exec.c_str(), &sb) == 0)
+#ifndef WIN32
+ if ( (!g_lstat (icsd_exec.c_str(), &sb) == 0)
|| (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
warning << _("Given Video Server is not an executable file.") << endmsg;
continue;
}
+#else
+ if ( (!g_lstat (icsd_exec.c_str(), &sb) == 0)
+ || (sb.st_mode & (S_IXUSR)) == 0 ) {
+ warning << _("Given Video Server is not an executable file.") << endmsg;
+ continue;
+ }
+#endif
char **argp;
argp=(char**) calloc(9,sizeof(char*));
return 1;
}
-
void
-ARDOUR_UI::disconnect_from_jack ()
+ARDOUR_UI::disconnect_from_engine ()
{
- if (engine) {
- /* drop connection to AudioEngine::Halted so that we don't act
- * as if the engine unexpectedly shut down
- */
- halt_connection.disconnect ();
-
- if (engine->stop ()) {
- MessageDialog msg (*editor, _("Could not disconnect from JACK"));
- msg.run ();
- } else {
- engine->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
- }
-
- update_sample_rate (0);
+ /* drop connection to AudioEngine::Halted so that we don't act
+ * as if the engine unexpectedly shut down
+ */
+ halt_connection.disconnect ();
+
+ if (AudioEngine::instance()->stop ()) {
+ MessageDialog msg (*editor, _("Could not disconnect from JACK"));
+ msg.run ();
+ } else {
+ AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
}
+
+ update_sample_rate (0);
}
void
-ARDOUR_UI::reconnect_to_jack ()
+ARDOUR_UI::reconnect_to_engine ()
{
- if (engine) {
- if (engine->start ()) {
- MessageDialog msg (*editor, _("Could not reconnect to JACK"));
- msg.run ();
- }
-
- update_sample_rate (0);
+ if (AudioEngine::instance()->start ()) {
+ MessageDialog msg (*editor, _("Could not reconnect to JACK"));
+ msg.run ();
}
+
+ update_sample_rate (0);
}
void
}
int
-ARDOUR_UI::ambiguous_file (std::string file, std::string /*path*/, std::vector<std::string> hits)
+ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
{
AmbiguousFileDialog dialog (file, hits);
reset_peak_display ();
}
}
+
+void
+ARDOUR_UI::toggle_audio_midi_setup ()
+{
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-audio-midi-setup"));
+ if (!act) {
+ return;
+ }
+
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
+
+ if (tact->get_active()) {
+ launch_audio_midi_setup ();
+ } else {
+ _audio_midi_setup->hide ();
+ }
+}
+
+void
+ARDOUR_UI::launch_audio_midi_setup ()
+{
+ if (!_audio_midi_setup) {
+ _audio_midi_setup = new EngineControl ();
+ }
+
+ _audio_midi_setup->present ();
+}
+
+int
+ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
+{
+ launch_audio_midi_setup ();
+
+ _audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
+
+ switch (_audio_midi_setup->run()) {
+ case Gtk::RESPONSE_OK:
+ return 0;
+ case Gtk::RESPONSE_APPLY:
+ return 0;
+ default:
+ return -1;
+ }
+}