#include "missing_plugin_dialog.h"
#include "mixer_ui.h"
#include "mouse_cursors.h"
+#include "nsm.h"
#include "opts.h"
#include "pingback.h"
#include "processor_box.h"
#include "rc_option_editor.h"
#include "route_time_axis.h"
#include "route_params_ui.h"
+#include "session_dialog.h"
#include "session_metadata_dialog.h"
#include "session_option_editor.h"
#include "shuttle_control.h"
/* start of private members */
- , _startup (0)
, nsm (0)
, _was_dirty (false)
, _mixer_on_top (false)
, about (X_("about"), _("About"))
, location_ui (X_("locations"), _("Locations"))
, route_params (X_("inspector"), _("Tracks and Busses"))
+ , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
, session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
, add_video_dialog (X_("add-video"), _("Add Tracks/Busses"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
, bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
, _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;
+
+ ui_config->ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
+ boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
+ ui_config->map_parameters (pc);
editor = 0;
mixer = 0;
WM::Manager::instance().register_window (&add_route_dialog);
WM::Manager::instance().register_window (&add_video_dialog);
WM::Manager::instance().register_window (&route_params);
+ WM::Manager::instance().register_window (&audio_midi_setup);
WM::Manager::instance().register_window (&bundle_manager);
WM::Manager::instance().register_window (&location_ui);
WM::Manager::instance().register_window (&big_clock_window);
(void) theme_manager.get (true);
- starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
- stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
-
_process_thread = new ProcessThread ();
_process_thread->init ();
msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
} else {
msgstr = string_compose (_("\
-`The audio backend has either been shutdown or it\n\
+The audio backend has either been shutdown or it\n\
disconnected %1 because %1\n\
was not fast enough. Try to restart\n\
the audio backend and save the session."), PROGRAM_NAME);
ARDOUR_UI::~ARDOUR_UI ()
{
+ if (ui_config->dirty()) {
+ ui_config->save_state();
+ }
+
delete keyboard;
delete editor;
delete mixer;
#endif
}
-void
-ARDOUR_UI::startup ()
+int
+ARDOUR_UI::starting ()
{
Application* app = Application::instance ();
- char *nsm_url;
+ const char *nsm_url;
+ bool brand_new_user = ArdourStartup::required ();
app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
app->ready ();
- nsm_url = getenv ("NSM_URL");
+ /* we need to create this early because it may need to set the
+ * audio backend end up.
+ */
+
+ try {
+ audio_midi_setup.get (true);
+ } catch (...) {
+ return -1;
+ }
- if (nsm_url) {
+ if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
nsm = new NSM_Client;
if (!nsm->init (nsm_url)) {
nsm->announce (PROGRAM_NAME, ":dirty:", "ardour3");
for ( i = 0; i < 5000; ++i) {
nsm->check ();
usleep (i);
- if (nsm->is_active())
+ if (nsm->is_active()) {
break;
+ }
+ }
+ if (i == 5000) {
+ error << _("NSM server did not announce itself") << endmsg;
+ return -1;
}
// wait for open command from nsm server
for ( i = 0; i < 5000; ++i) {
nsm->check ();
usleep (1000);
- if (nsm->client_id ())
+ if (nsm->client_id ()) {
break;
+ }
+ }
+
+ if (i == 5000) {
+ error << _("NSM: no client ID provided") << endmsg;
+ return -1;
}
if (_session && nsm) {
_session->set_nsm_state( nsm->is_active() );
+ } else {
+ error << _("NSM: no session created") << endmsg;
+ return -1;
}
// nsm requires these actions disabled
}
}
- }
- else {
+ } else {
delete nsm;
nsm = 0;
+ error << _("NSM: initialization failed") << endmsg;
+ return -1;
}
- }
- else if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
- exit (1);
+ } else {
+
+ if (brand_new_user) {
+ ArdourStartup s;
+ s.present ();
+ main().run();
+ s.hide ();
+ switch (s.response ()) {
+ case Gtk::RESPONSE_OK:
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ /* go get a session */
+
+ const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
+
+ if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
+ return -1;
+ }
}
use_config ();
_status_bar_visibility.update ();
BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
-}
-
-void
-ARDOUR_UI::no_memory_warning ()
-{
- XMLNode node (X_("no-memory-warning"));
- Config->add_instant_xml (node);
+ return 0;
}
void
VBox* vbox = msg.get_vbox();
HBox hbox;
CheckButton cb (_("Do not show this window again"));
-
- cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
-
hbox.pack_start (cb, true, false);
vbox->pack_start (hbox);
cb.show();
editor->ensure_float (msg);
msg.run ();
+
+ if (cb.get_active()) {
+ XMLNode node (X_("no-memory-warning"));
+ Config->add_instant_xml (node);
+ }
}
}
}
should also be changed.
*/
- float const c = AudioEngine::instance()->get_cpu_load ();
+ float const c = AudioEngine::instance()->get_dsp_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);
}
#if 0
if (_session->config.get_external_sync()) {
switch (Config->get_sync_source()) {
- case JACK:
+ case Engine:
break;
default:
/* transport controlled by the master */
if (_session->config.get_external_sync()) {
switch (Config->get_sync_source()) {
- case JACK:
+ case Engine:
break;
default:
/* transport controlled by the master */
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
- prompter.set_title (_("Take Snapshot"));
- prompter.set_prompt (_("Name of new snapshot"));
+ if (switch_to_it) {
+ prompter.set_title (_("Save as..."));
+ prompter.set_prompt (_("New session name"));
+ } else {
+ prompter.set_title (_("Take Snapshot"));
+ prompter.set_prompt (_("Name of new snapshot"));
+ }
if (!switch_to_it) {
char timebuf[128];
}
int
-ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::string& session_name)
+ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
{
BusProfile bus_profile;
/* get settings from advanced section of NSD */
- if (_startup->create_master_bus()) {
- bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
+ if (sd.create_master_bus()) {
+ bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
} else {
bus_profile.master_out_channels = 0;
}
- if (_startup->connect_inputs()) {
+ if (sd.connect_inputs()) {
bus_profile.input_ac = AutoConnectPhysical;
} else {
bus_profile.input_ac = AutoConnectOption (0);
bus_profile.output_ac = AutoConnectOption (0);
- if (_startup->connect_outputs ()) {
- if (_startup->connect_outs_to_master()) {
+ if (sd.connect_outputs ()) {
+ if (sd.connect_outs_to_master()) {
bus_profile.output_ac = AutoConnectMaster;
- } else if (_startup->connect_outs_to_physical()) {
+ } else if (sd.connect_outs_to_physical()) {
bus_profile.output_ac = AutoConnectPhysical;
}
}
- bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
- bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
+ bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
+ bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
}
if (build_session (session_path, session_name, bus_profile)) {
string template_name;
int ret = -1;
bool likely_new = false;
+ bool cancel_not_quit;
/* deal with any existing DIRTY session now, rather than later. don't
* treat a non-dirty session this way, so that it stays visible
ARDOUR_UI::instance()->video_timeline->sync_session_state();
}
+ /* if there is already a session, relabel the button
+ on the SessionDialog so that we don't Quit directly
+ */
+ cancel_not_quit = (_session != 0);
+
if (_session && _session->dirty()) {
if (unload_session (false)) {
/* unload cancelled by user */
template_name = load_template;
}
+ session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
+ session_path = ARDOUR_COMMAND_LINE::session_name;
+
+ if (!session_path.empty()) {
+ if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
+ if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
+ /* session/snapshot file, change path to be dir */
+ session_path = Glib::path_get_dirname (session_path);
+ }
+ }
+ }
+
+ SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
+
while (ret != 0) {
if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
} else {
session_path = "";
session_name = "";
+ session_dialog.clear_given ();
}
-
- delete _startup;
- _startup = new ArdourStartup (should_be_new, session_name, session_path, load_template);
- if (!_startup->ready_without_display()) {
- _startup->present ();
- main().run();
- _startup->hide ();
- }
-
- switch (_startup->response()) {
- case RESPONSE_OK:
- break;
- default:
- if (quit_on_cancel) {
- exit (1);
- } else {
- return ret;
+ if (should_be_new || session_name.empty()) {
+ /* need the dialog to get info from user */
+
+ cerr << "run dialog\n";
+
+ switch (session_dialog.run()) {
+ case RESPONSE_ACCEPT:
+ break;
+ default:
+ if (quit_on_cancel) {
+ exit (1);
+ } else {
+ return ret;
+ }
}
+
+ session_dialog.hide ();
}
/* if we run the startup dialog again, offer more than just "new session" */
should_be_new = false;
- session_name = _startup->session_name (likely_new);
-
+ session_name = session_dialog.session_name (likely_new);
+ session_path = session_dialog.session_folder ();
+
if (nsm) {
likely_new = true;
}
continue;
}
- if (_startup->use_session_template()) {
- template_name = _startup->session_template_name();
+ if (session_dialog.use_session_template()) {
+ template_name = session_dialog.session_template_name();
_session_is_new = true;
}
} else {
- session_path = _startup->session_folder();
+ session_path = session_dialog.session_folder();
char illegal = Session::session_name_is_legal (session_name);
if (illegal) {
- MessageDialog msg (*_startup,
+ MessageDialog msg (session_dialog,
string_compose (_("To ensure compatibility with various systems\n"
"session names may not contain a '%1' character"),
illegal));
if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
+
if (likely_new && !nsm) {
std::string existing = Glib::build_filename (session_path, session_name);
} else {
if (!likely_new) {
- if (_startup) {
- pop_back_splash (*_startup);
- } else {
- hide_splash ();
- }
-
+ pop_back_splash (session_dialog);
MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
msg.run ();
ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
}
char illegal = Session::session_name_is_legal(session_name);
+
if (illegal) {
- pop_back_splash (*_startup);
- MessageDialog msg (*_startup, string_compose(_("To ensure compatibility with various systems\n"
- "session names may not contain a '%1' character"), illegal));
+ pop_back_splash (session_dialog);
+ MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
+ "session names may not contain a '%1' character"), illegal));
msg.run ();
ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
continue;
if (likely_new && template_name.empty()) {
- ret = build_session_from_nsd (session_path, session_name);
+ ret = build_session_from_dialog (session_dialog, session_path, session_name);
} else {
_session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
exit (1);
}
+
+ /* clear this to avoid endless attempts to load the
+ same session.
+ */
+
+ ARDOUR_COMMAND_LINE::session_name = "";
}
}
Gtk::MESSAGE_INFO,
BUTTONS_OK);
+ msg.set_keep_above (true);
msg.set_title (_("Loading Error"));
- msg.set_secondary_text (_("Click the Refresh button to try again."));
- msg.add_button (Stock::REFRESH, 1);
msg.set_position (Gtk::WIN_POS_CENTER);
pop_back_splash (msg);
msg.present ();
-
- int response = msg.run ();
-
- switch (response) {
- case 1:
- break;
- default:
- exit (1);
- }
-
+ (void) msg.run ();
msg.hide ();
goto out;
}
}
+ if (!new_session->writable()) {
+ MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
+ true,
+ Gtk::MESSAGE_INFO,
+ BUTTONS_OK);
+
+ msg.set_keep_above (true);
+ msg.set_title (_("Read-only Session"));
+ msg.set_position (Gtk::WIN_POS_CENTER);
+ pop_back_splash (msg);
+ msg.present ();
+ (void) msg.run ();
+ msg.hide ();
+ }
+
+
/* Now the session been created, add the transport controls */
new_session->add_controllable(roll_controllable);
new_session->add_controllable(stop_controllable);
display_cleanup_results (rep, _("deleted file"), true);
}
+void
+ARDOUR_UI::setup_order_hint ()
+{
+ uint32_t order_hint = 0;
+
+ /*
+ we want the new routes to have their order keys set starting from
+ the highest order key in the selection + 1 (if available).
+ */
+ if (add_route_dialog->get_transient_for () == mixer->get_toplevel()) {
+ for (RouteUISelection::iterator s = mixer->selection().routes.begin(); s != mixer->selection().routes.end(); ++s) {
+ if ((*s)->route()->order_key() > order_hint) {
+ order_hint = (*s)->route()->order_key();
+ }
+ }
+
+ if (!mixer->selection().routes.empty()) {
+ order_hint++;
+ }
+
+ } else {
+ for (TrackSelection::iterator s = editor->get_selection().tracks.begin(); s != editor->get_selection().tracks.end(); ++s) {
+ RouteTimeAxisView* tav = dynamic_cast<RouteTimeAxisView*> (*s);
+ if (tav->route()->order_key() > order_hint) {
+ order_hint = tav->route()->order_key();
+ }
+ }
+
+ if (!editor->get_selection().tracks.empty()) {
+ order_hint++;
+ }
+ }
+
+ _session->set_order_hint (order_hint);
+
+ /* create a gap in the existing route order keys to accomodate new routes.*/
+
+ boost::shared_ptr <RouteList> rd = _session->get_routes();
+ for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
+ boost::shared_ptr<Route> rt (*ri);
+
+ if (rt->is_monitor()) {
+ continue;
+ }
+
+ if (rt->order_key () >= order_hint) {
+ rt->set_order_key (rt->order_key () + add_route_dialog->count());
+ }
+ }
+}
+
void
ARDOUR_UI::add_route (Gtk::Window* float_window)
{
}
if (float_window) {
+ add_route_dialog->unset_transient_for ();
add_route_dialog->set_transient_for (*float_window);
}
return;
}
+ setup_order_hint();
+
PBD::ScopedConnection idle_connection;
if (count > 8) {
if (!transcode_video_dialog->get_audiofile().empty()) {
editor->embed_audio_from_video(
transcode_video_dialog->get_audiofile(),
- video_timeline->get_offset()
+ video_timeline->get_offset(),
+ (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
);
}
switch (transcode_video_dialog->import_option()) {
int
ARDOUR_UI::pending_state_dialog ()
{
- HBox* hbox = new HBox();
- Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
+ HBox* hbox = manage (new HBox());
+ Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
ArdourDialog dialog (_("Crash Recovery"), true);
Label message (string_compose (_("\
This session appears to have been in the\n\
/* 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 ()) {
ARDOUR_UI::reconnect_to_engine ()
{
if (AudioEngine::instance()->start ()) {
- MessageDialog msg (*editor, _("Could not reconnect to the Audio/MIDI engine"));
- msg.run ();
+ if (editor) {
+ MessageDialog msg (*editor, _("Could not reconnect to the Audio/MIDI engine"));
+ msg.run ();
+ } else {
+ MessageDialog msg (_("Could not reconnect to the Audio/MIDI engine"));
+ msg.run ();
+ }
return -1;
}
}
}
-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);
+ audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
+ audio_midi_setup->set_position (WIN_POS_CENTER);
- switch (_audio_midi_setup->run()) {
+ switch (audio_midi_setup->run()) {
case Gtk::RESPONSE_OK:
return 0;
case Gtk::RESPONSE_APPLY:
return -1;
}
}
+
+