2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define __STDC_FORMAT_MACROS 1
34 #include <sys/resource.h>
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
55 #include "midi++/manager.h"
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
76 typedef uint64_t microseconds_t;
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
86 #include "add_route_dialog.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
97 #include "engine_dialog.h"
101 using namespace ARDOUR;
103 using namespace Gtkmm2ext;
105 using namespace sigc;
107 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
108 UIConfiguration *ARDOUR_UI::ui_config = 0;
110 sigc::signal<void,bool> ARDOUR_UI::Blink;
111 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
112 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
113 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
117 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
119 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
120 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
121 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
122 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
126 preroll_button (_("pre\nroll")),
127 postroll_button (_("post\nroll")),
131 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
135 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
136 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
137 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
138 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
139 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
140 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
141 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
142 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
143 shuttle_controller_binding_proxy (shuttle_controllable),
145 roll_button (roll_controllable),
146 stop_button (stop_controllable),
147 goto_start_button (goto_start_controllable),
148 goto_end_button (goto_end_controllable),
149 auto_loop_button (auto_loop_controllable),
150 play_selection_button (play_selection_controllable),
151 rec_button (rec_controllable),
153 shuttle_units_button (_("% ")),
155 punch_in_button (_("Punch In")),
156 punch_out_button (_("Punch Out")),
157 auto_return_button (_("Auto Return")),
158 auto_play_button (_("Auto Play")),
159 auto_input_button (_("Auto Input")),
160 click_button (_("Click")),
161 time_master_button (_("time\nmaster")),
163 auditioning_alert_button (_("AUDITION")),
164 solo_alert_button (_("SOLO")),
166 error_log_button (_("Errors"))
169 using namespace Gtk::Menu_Helpers;
175 _auto_display_errors = false;
182 if (theArdourUI == 0) {
186 ui_config = new UIConfiguration();
187 theme_manager = new ThemeManager();
194 _session_is_new = false;
195 big_clock_window = 0;
196 session_selector_window = 0;
197 last_key_press_time = 0;
198 _will_create_new_session_automatically = false;
199 add_route_dialog = 0;
203 open_session_selector = 0;
204 have_configure_timeout = false;
205 have_disk_speed_dialog_displayed = false;
206 session_loaded = false;
207 last_speed_displayed = -1.0f;
208 ignore_dual_punch = false;
209 _mixer_on_top = false;
211 roll_button.unset_flags (Gtk::CAN_FOCUS);
212 stop_button.unset_flags (Gtk::CAN_FOCUS);
213 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
214 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
215 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
216 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
217 rec_button.unset_flags (Gtk::CAN_FOCUS);
219 last_configure_time= 0;
221 shuttle_grabbed = false;
223 shuttle_max_speed = 8.0f;
225 shuttle_style_menu = 0;
226 shuttle_unit_menu = 0;
228 // We do not have jack linked in yet so;
230 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
232 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
233 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
235 /* handle dialog requests */
237 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
239 /* handle pending state with a dialog */
241 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
243 /* handle sr mismatch with a dialog */
245 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
247 /* lets get this party started */
250 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
251 throw failed_constructor ();
254 setup_gtk_ardour_enums ();
255 Config->set_current_owner (ConfigVariableBase::Interface);
258 GainMeter::setup_slider_pix ();
259 RouteTimeAxisView::setup_slider_pix ();
261 } catch (failed_constructor& err) {
262 error << _("could not initialize Ardour.") << endmsg;
267 /* we like keyboards */
269 keyboard = new Keyboard;
273 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
274 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
280 ARDOUR_UI::run_startup (bool should_be_new)
283 _startup = new ArdourStartup ();
286 _startup->set_new_only (should_be_new);
287 _startup->present ();
291 /* we don't return here until the startup assistant is finished */
297 ARDOUR_UI::create_engine ()
299 // this gets called every time by new_session()
305 loading_message (_("Starting audio engine"));
308 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
315 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
316 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
317 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
318 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
326 ARDOUR_UI::post_engine ()
328 /* Things to be done once we create the AudioEngine
331 MIDI::Manager::instance()->set_api_data (engine->jack());
334 ActionManager::init ();
337 if (setup_windows ()) {
338 throw failed_constructor ();
341 check_memory_locking();
343 /* this is the first point at which all the keybindings are available */
345 if (ARDOUR_COMMAND_LINE::show_key_actions) {
346 vector<string> names;
347 vector<string> paths;
349 vector<AccelKey> bindings;
351 ActionManager::get_all_actions (names, paths, keys, bindings);
353 vector<string>::iterator n;
354 vector<string>::iterator k;
355 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
356 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
362 blink_timeout_tag = -1;
364 /* the global configuration object is now valid */
368 /* this being a GUI and all, we want peakfiles */
370 AudioFileSource::set_build_peakfiles (true);
371 AudioFileSource::set_build_missing_peakfiles (true);
373 /* set default clock modes */
375 if (Profile->get_sae()) {
376 primary_clock.set_mode (AudioClock::BBT);
377 secondary_clock.set_mode (AudioClock::MinSec);
379 primary_clock.set_mode (AudioClock::SMPTE);
380 secondary_clock.set_mode (AudioClock::BBT);
383 /* start the time-of-day-clock */
386 /* OS X provides an always visible wallclock, so don't be stupid */
387 update_wall_clock ();
388 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
391 update_disk_space ();
393 update_sample_rate (engine->frame_rate());
395 /* now start and maybe save state */
397 if (do_engine_start () == 0) {
398 if (session && _session_is_new) {
399 /* we need to retain initial visual
400 settings for a new session
402 session->save_state ("");
407 ARDOUR_UI::~ARDOUR_UI ()
409 save_ardour_state ();
414 delete add_route_dialog;
418 ARDOUR_UI::pop_back_splash ()
420 if (Splash::instance()) {
421 // Splash::instance()->pop_back();
422 Splash::instance()->hide ();
427 ARDOUR_UI::configure_timeout ()
429 if (last_configure_time == 0) {
430 /* no configure events yet */
434 /* force a gap of 0.5 seconds since the last configure event
437 if (get_microseconds() - last_configure_time < 500000) {
440 have_configure_timeout = false;
441 save_ardour_state ();
447 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
449 if (have_configure_timeout) {
450 last_configure_time = get_microseconds();
452 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
453 have_configure_timeout = true;
460 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
462 const XMLProperty* prop;
464 if ((prop = node.property ("roll")) != 0) {
465 roll_controllable->set_id (prop->value());
467 if ((prop = node.property ("stop")) != 0) {
468 stop_controllable->set_id (prop->value());
470 if ((prop = node.property ("goto-start")) != 0) {
471 goto_start_controllable->set_id (prop->value());
473 if ((prop = node.property ("goto-end")) != 0) {
474 goto_end_controllable->set_id (prop->value());
476 if ((prop = node.property ("auto-loop")) != 0) {
477 auto_loop_controllable->set_id (prop->value());
479 if ((prop = node.property ("play-selection")) != 0) {
480 play_selection_controllable->set_id (prop->value());
482 if ((prop = node.property ("rec")) != 0) {
483 rec_controllable->set_id (prop->value());
485 if ((prop = node.property ("shuttle")) != 0) {
486 shuttle_controllable->set_id (prop->value());
491 ARDOUR_UI::get_transport_controllable_state ()
493 XMLNode* node = new XMLNode(X_("TransportControllables"));
496 roll_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("roll"), buf);
498 stop_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("stop"), buf);
500 goto_start_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("goto_start"), buf);
502 goto_end_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("goto_end"), buf);
504 auto_loop_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("auto_loop"), buf);
506 play_selection_controllable->id().print (buf, sizeof (buf));
507 node->add_property (X_("play_selection"), buf);
508 rec_controllable->id().print (buf, sizeof (buf));
509 node->add_property (X_("rec"), buf);
510 shuttle_controllable->id().print (buf, sizeof (buf));
511 node->add_property (X_("shuttle"), buf);
517 ARDOUR_UI::save_ardour_state ()
519 if (!keyboard || !mixer || !editor) {
523 /* XXX this is all a bit dubious. add_extra_xml() uses
524 a different lifetime model from add_instant_xml().
527 XMLNode* node = new XMLNode (keyboard->get_state());
528 Config->add_extra_xml (*node);
529 Config->add_extra_xml (get_transport_controllable_state());
530 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
531 Config->add_extra_xml (_startup->engine_control()->get_state());
533 Config->save_state();
534 ui_config->save_state ();
536 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
537 XMLNode mnode(mixer->get_state());
540 session->add_instant_xml (enode);
541 session->add_instant_xml (mnode);
543 Config->add_instant_xml (enode);
544 Config->add_instant_xml (mnode);
547 Keyboard::save_keybindings ();
551 ARDOUR_UI::autosave_session ()
553 if (g_main_depth() > 1) {
554 /* inside a recursive main loop,
555 give up because we may not be able to
561 if (!Config->get_periodic_safety_backups()) {
566 session->maybe_write_autosave();
573 ARDOUR_UI::update_autosave ()
575 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
577 if (session->dirty()) {
578 if (_autosave_connection.connected()) {
579 _autosave_connection.disconnect();
582 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
583 Config->get_periodic_safety_backup_interval() * 1000);
586 if (_autosave_connection.connected()) {
587 _autosave_connection.disconnect();
593 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
597 title = _("Ardour could not start JACK");
599 title = _("Ardour could not connect to JACK.");
602 MessageDialog win (title,
608 win.set_secondary_text(_("There are several possible reasons:\n\
610 1) You requested audio parameters that are not supported..\n\
611 2) JACK is running as another user.\n\
613 Please consider the possibilities, and perhaps try different parameters."));
615 win.set_secondary_text(_("There are several possible reasons:\n\
617 1) JACK is not running.\n\
618 2) JACK is running as another user, perhaps root.\n\
619 3) There is already another client called \"ardour\".\n\
621 Please consider the possibilities, and perhaps (re)start JACK."));
625 win.set_transient_for (*toplevel);
629 win.add_button (Stock::OK, RESPONSE_CLOSE);
631 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
634 win.set_default_response (RESPONSE_CLOSE);
637 win.set_position (Gtk::WIN_POS_CENTER);
640 /* we just don't care about the result, but we want to block */
646 ARDOUR_UI::startup ()
648 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
650 if (audio_setup && _startup && _startup->engine_control()) {
651 _startup->engine_control()->set_state (*audio_setup);
654 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
658 goto_editor_window ();
660 BootMessage (_("Ardour is ready for use"));
665 ARDOUR_UI::no_memory_warning ()
667 XMLNode node (X_("no-memory-warning"));
668 Config->add_instant_xml (node);
672 ARDOUR_UI::check_memory_locking ()
675 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
679 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
681 if (engine->is_realtime() && memory_warning_node == 0) {
683 struct rlimit limits;
685 long pages, page_size;
687 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
690 ram = (int64_t) pages * (int64_t) page_size;
693 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
697 if (limits.rlim_cur != RLIM_INFINITY) {
699 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
702 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
703 "This might cause Ardour to run out of memory before your system "
704 "runs out of memory. \n\n"
705 "You can view the memory limit with 'ulimit -l', "
706 "and it is normally controlled by /etc/security/limits.conf"));
708 VBox* vbox = msg.get_vbox();
710 CheckButton cb (_("Do not show this window again"));
712 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
714 hbox.pack_start (cb, true, false);
715 vbox->pack_start (hbox);
722 editor->ensure_float (msg);
736 if (session->transport_rolling()) {
737 session->request_stop ();
741 if (session->dirty()) {
742 switch (ask_about_saving_session(_("quit"))) {
747 /* use the default name */
748 if (save_state_canfail ("")) {
749 /* failed - don't quit */
750 MessageDialog msg (*editor,
752 Ardour was unable to save your session.\n\n\
753 If you still wish to quit, please use the\n\n\
754 \"Just quit\" option."));
765 session->set_deletion_in_progress ();
768 ArdourDialog::close_all_dialogs ();
770 save_ardour_state ();
775 ARDOUR_UI::ask_about_saving_session (const string & what)
777 ArdourDialog window (_("ardour: save session?"));
778 Gtk::HBox dhbox; // the hbox for the image and text
779 Gtk::Label prompt_label;
780 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
784 msg = string_compose(_("Don't %1"), what);
785 window.add_button (msg, RESPONSE_REJECT);
786 msg = string_compose(_("Just %1"), what);
787 window.add_button (msg, RESPONSE_APPLY);
788 msg = string_compose(_("Save and %1"), what);
789 window.add_button (msg, RESPONSE_ACCEPT);
791 window.set_default_response (RESPONSE_ACCEPT);
793 Gtk::Button noquit_button (msg);
794 noquit_button.set_name ("EditorGTKButton");
799 if (session->snap_name() == session->name()) {
802 type = _("snapshot");
804 prompt = string_compose(_("The %1\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
805 type, session->snap_name());
807 prompt_label.set_text (prompt);
808 prompt_label.set_name (X_("PrompterLabel"));
809 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
811 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
812 dhbox.set_homogeneous (false);
813 dhbox.pack_start (*dimage, false, false, 5);
814 dhbox.pack_start (prompt_label, true, false, 5);
815 window.get_vbox()->pack_start (dhbox);
817 window.set_name (_("Prompter"));
818 window.set_position (Gtk::WIN_POS_MOUSE);
819 window.set_modal (true);
820 window.set_resizable (false);
826 window.set_keep_above (true);
829 ResponseType r = (ResponseType) window.run();
834 case RESPONSE_ACCEPT: // save and get out of here
836 case RESPONSE_APPLY: // get out of here
846 ARDOUR_UI::every_second ()
849 update_buffer_load ();
850 update_disk_space ();
855 ARDOUR_UI::every_point_one_seconds ()
857 update_speed_display ();
858 RapidScreenUpdate(); /* EMIT_SIGNAL */
863 ARDOUR_UI::every_point_zero_one_seconds ()
865 // august 2007: actual update frequency: 40Hz, not 100Hz
867 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
872 ARDOUR_UI::update_sample_rate (nframes_t ignored)
876 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
878 if (!engine->connected()) {
880 snprintf (buf, sizeof (buf), _("disconnected"));
884 nframes_t rate = engine->frame_rate();
886 if (fmod (rate, 1000.0) != 0.0) {
887 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
888 (float) rate/1000.0f,
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
891 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
893 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
897 sample_rate_label.set_text (buf);
901 ARDOUR_UI::update_cpu_load ()
904 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
905 cpu_load_label.set_text (buf);
909 ARDOUR_UI::update_buffer_load ()
914 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
915 session->playback_load(), session->capture_load());
916 buffer_load_label.set_text (buf);
918 buffer_load_label.set_text ("");
923 ARDOUR_UI::count_recenabled_streams (Route& route)
925 Track* track = dynamic_cast<Track*>(&route);
926 if (track && track->diskstream()->record_enabled()) {
927 rec_enabled_streams += track->n_inputs().n_total();
932 ARDOUR_UI::update_disk_space()
938 nframes_t frames = session->available_capture_duration();
940 nframes_t fr = session->frame_rate();
942 if (frames == max_frames) {
943 strcpy (buf, _("Disk: 24hrs+"));
945 rec_enabled_streams = 0;
946 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
948 if (rec_enabled_streams) {
949 frames /= rec_enabled_streams;
956 hrs = frames / (fr * 3600);
957 frames -= hrs * fr * 3600;
958 mins = frames / (fr * 60);
959 frames -= mins * fr * 60;
962 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
965 disk_space_label.set_text (buf);
967 // An attempt to make the disk space label flash red when space has run out.
969 if (frames < fr * 60 * 5) {
970 /* disk_space_box.style ("disk_space_label_empty"); */
972 /* disk_space_box.style ("disk_space_label"); */
978 ARDOUR_UI::update_wall_clock ()
985 tm_now = localtime (&now);
987 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
988 wall_clock_label.set_text (buf);
994 ARDOUR_UI::session_menu (GdkEventButton *ev)
996 session_popup_menu->popup (0, 0);
1001 ARDOUR_UI::redisplay_recent_sessions ()
1003 std::vector<sys::path> session_directories;
1004 RecentSessionsSorter cmp;
1006 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1007 recent_session_model->clear ();
1009 ARDOUR::RecentSessions rs;
1010 ARDOUR::read_recent_sessions (rs);
1013 recent_session_display.set_model (recent_session_model);
1017 // sort them alphabetically
1018 sort (rs.begin(), rs.end(), cmp);
1020 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1021 session_directories.push_back ((*i).second);
1024 for (vector<sys::path>::const_iterator i = session_directories.begin();
1025 i != session_directories.end(); ++i)
1027 std::vector<sys::path> state_file_paths;
1029 // now get available states for this session
1031 get_state_files_in_directory (*i, state_file_paths);
1033 vector<string*>* states;
1034 vector<const gchar*> item;
1035 string fullpath = (*i).to_string();
1037 /* remove any trailing / */
1039 if (fullpath[fullpath.length()-1] == '/') {
1040 fullpath = fullpath.substr (0, fullpath.length()-1);
1043 /* check whether session still exists */
1044 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1045 /* session doesn't exist */
1046 cerr << "skipping non-existent session " << fullpath << endl;
1050 /* now get available states for this session */
1052 if ((states = Session::possible_states (fullpath)) == 0) {
1053 /* no state file? */
1057 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1059 Gtk::TreeModel::Row row = *(recent_session_model->append());
1061 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1062 row[recent_session_columns.fullpath] = fullpath;
1064 if (state_file_names.size() > 1) {
1068 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1069 i2 != state_file_names.end(); ++i2)
1072 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1074 child_row[recent_session_columns.visible_name] = *i2;
1075 child_row[recent_session_columns.fullpath] = fullpath;
1080 recent_session_display.set_model (recent_session_model);
1084 ARDOUR_UI::build_session_selector ()
1086 session_selector_window = new ArdourDialog ("session selector");
1088 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1090 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1091 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1092 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1093 recent_session_model = TreeStore::create (recent_session_columns);
1094 recent_session_display.set_model (recent_session_model);
1095 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1096 recent_session_display.set_headers_visible (false);
1097 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1098 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1100 scroller->add (recent_session_display);
1101 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1103 session_selector_window->set_name ("SessionSelectorWindow");
1104 session_selector_window->set_size_request (200, 400);
1105 session_selector_window->get_vbox()->pack_start (*scroller);
1107 recent_session_display.show();
1109 //session_selector_window->get_vbox()->show();
1113 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1115 session_selector_window->response (RESPONSE_ACCEPT);
1119 ARDOUR_UI::open_recent_session ()
1121 bool can_return = (session != 0);
1123 if (session_selector_window == 0) {
1124 build_session_selector ();
1127 redisplay_recent_sessions ();
1131 session_selector_window->set_position (WIN_POS_MOUSE);
1133 ResponseType r = (ResponseType) session_selector_window->run ();
1136 case RESPONSE_ACCEPT:
1140 session_selector_window->hide();
1147 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1151 session_selector_window->hide();
1153 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1155 if (i == recent_session_model->children().end()) {
1159 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1160 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1162 _session_is_new = false;
1164 if (load_session (path, state) == 0) {
1173 ARDOUR_UI::check_audioengine ()
1176 if (!engine->connected()) {
1177 MessageDialog msg (_("Ardour is not connected to JACK\n"
1178 "You cannot open or close sessions in this condition"));
1190 ARDOUR_UI::open_session ()
1192 if (!check_audioengine()) {
1197 /* popup selector window */
1199 if (open_session_selector == 0) {
1201 /* ardour sessions are folders */
1203 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1204 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1205 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1206 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1208 FileFilter session_filter;
1209 session_filter.add_pattern ("*.ardour");
1210 session_filter.set_name (_("Ardour sessions"));
1211 open_session_selector->add_filter (session_filter);
1212 open_session_selector->set_filter (session_filter);
1215 int response = open_session_selector->run();
1216 open_session_selector->hide ();
1219 case RESPONSE_ACCEPT:
1222 open_session_selector->hide();
1226 open_session_selector->hide();
1227 string session_path = open_session_selector->get_filename();
1231 if (session_path.length() > 0) {
1232 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1233 _session_is_new = isnew;
1234 load_session (path, name);
1241 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1243 list<boost::shared_ptr<MidiTrack> > tracks;
1246 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1253 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1255 if (tracks.size() != how_many) {
1256 if (how_many == 1) {
1257 error << _("could not create a new midi track") << endmsg;
1259 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1263 if ((route = session->new_midi_route ()) == 0) {
1264 error << _("could not create new midi bus") << endmsg;
1270 MessageDialog msg (*editor,
1271 _("There are insufficient JACK ports available\n\
1272 to create a new track or bus.\n\
1273 You should save Ardour, exit and\n\
1274 restart JACK with more ports."));
1281 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1283 list<boost::shared_ptr<AudioTrack> > tracks;
1287 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1293 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1295 if (tracks.size() != how_many) {
1296 if (how_many == 1) {
1297 error << _("could not create a new audio track") << endmsg;
1299 error << string_compose (_("could only create %1 of %2 new audio %3"),
1300 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1306 routes = session->new_audio_route (input_channels, output_channels, how_many);
1308 if (routes.size() != how_many) {
1309 if (how_many == 1) {
1310 error << _("could not create a new audio track") << endmsg;
1312 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1318 if (need_control_room_outs) {
1324 route->set_stereo_control_outs (control_lr_channels);
1325 route->control_outs()->set_stereo_pan (pans, this);
1327 #endif /* CONTROLOUTS */
1331 MessageDialog msg (*editor,
1332 _("There are insufficient JACK ports available\n\
1333 to create a new track or bus.\n\
1334 You should save Ardour, exit and\n\
1335 restart JACK with more ports."));
1342 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1344 nframes_t _preroll = 0;
1347 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1348 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1350 if (new_position > _preroll) {
1351 new_position -= _preroll;
1356 session->request_locate (new_position);
1361 ARDOUR_UI::transport_goto_start ()
1364 session->goto_start();
1367 /* force displayed area in editor to start no matter
1368 what "follow playhead" setting is.
1372 editor->reset_x_origin (session->current_start_frame());
1378 ARDOUR_UI::transport_goto_zero ()
1381 session->request_locate (0);
1384 /* force displayed area in editor to start no matter
1385 what "follow playhead" setting is.
1389 editor->reset_x_origin (0);
1395 ARDOUR_UI::transport_goto_wallclock ()
1397 if (session && editor) {
1404 localtime_r (&now, &tmnow);
1406 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1407 frames += tmnow.tm_min * (60 * session->frame_rate());
1408 frames += tmnow.tm_sec * session->frame_rate();
1410 session->request_locate (frames);
1412 /* force displayed area in editor to start no matter
1413 what "follow playhead" setting is.
1417 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1423 ARDOUR_UI::transport_goto_end ()
1426 nframes_t frame = session->current_end_frame();
1427 session->request_locate (frame);
1429 /* force displayed area in editor to start no matter
1430 what "follow playhead" setting is.
1434 editor->reset_x_origin (frame);
1440 ARDOUR_UI::transport_stop ()
1446 if (session->is_auditioning()) {
1447 session->cancel_audition ();
1451 if (session->get_play_loop ()) {
1452 session->request_play_loop (false);
1455 session->request_stop ();
1459 ARDOUR_UI::transport_stop_and_forget_capture ()
1462 session->request_stop (true);
1467 ARDOUR_UI::remove_last_capture()
1470 editor->remove_last_capture();
1475 ARDOUR_UI::transport_record (bool roll)
1479 switch (session->record_status()) {
1480 case Session::Disabled:
1481 if (session->ntracks() == 0) {
1482 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1486 session->maybe_enable_record ();
1491 case Session::Recording:
1493 session->request_stop();
1495 session->disable_record (false, true);
1499 case Session::Enabled:
1500 session->disable_record (false, true);
1503 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1507 ARDOUR_UI::transport_roll ()
1515 rolling = session->transport_rolling ();
1517 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1519 if (session->get_play_loop()) {
1520 session->request_play_loop (false);
1521 auto_loop_button.set_visual_state (1);
1522 roll_button.set_visual_state (1);
1523 } else if (session->get_play_range ()) {
1524 session->request_play_range (false);
1525 play_selection_button.set_visual_state (0);
1526 } else if (rolling) {
1527 session->request_locate (session->last_transport_start(), true);
1530 session->request_transport_speed (1.0f);
1534 ARDOUR_UI::transport_loop()
1537 if (session->get_play_loop()) {
1538 if (session->transport_rolling()) {
1539 Location * looploc = session->locations()->auto_loop_location();
1541 session->request_locate (looploc->start(), true);
1546 session->request_play_loop (true);
1552 ARDOUR_UI::transport_play_selection ()
1558 if (!session->get_play_range()) {
1559 session->request_stop ();
1562 editor->play_selection ();
1566 ARDOUR_UI::transport_rewind (int option)
1568 float current_transport_speed;
1571 current_transport_speed = session->transport_speed();
1573 if (current_transport_speed >= 0.0f) {
1576 session->request_transport_speed (-1.0f);
1579 session->request_transport_speed (-4.0f);
1582 session->request_transport_speed (-0.5f);
1587 session->request_transport_speed (current_transport_speed * 1.5f);
1593 ARDOUR_UI::transport_forward (int option)
1595 float current_transport_speed;
1598 current_transport_speed = session->transport_speed();
1600 if (current_transport_speed <= 0.0f) {
1603 session->request_transport_speed (1.0f);
1606 session->request_transport_speed (4.0f);
1609 session->request_transport_speed (0.5f);
1614 session->request_transport_speed (current_transport_speed * 1.5f);
1620 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1626 boost::shared_ptr<Route> r;
1628 if ((r = session->route_by_remote_id (dstream)) != 0) {
1632 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1633 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1642 ARDOUR_UI::queue_transport_change ()
1644 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1648 ARDOUR_UI::map_transport_state ()
1650 float sp = session->transport_speed();
1653 transport_rolling ();
1654 } else if (sp < 0.0f) {
1655 transport_rewinding ();
1656 } else if (sp > 0.0f) {
1657 transport_forwarding ();
1659 transport_stopped ();
1664 ARDOUR_UI::engine_stopped ()
1666 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1667 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1668 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1672 ARDOUR_UI::engine_running ()
1674 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1675 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1676 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1678 Glib::RefPtr<Action> action;
1679 const char* action_name = 0;
1681 switch (engine->frames_per_cycle()) {
1683 action_name = X_("JACKLatency32");
1686 action_name = X_("JACKLatency64");
1689 action_name = X_("JACKLatency128");
1692 action_name = X_("JACKLatency512");
1695 action_name = X_("JACKLatency1024");
1698 action_name = X_("JACKLatency2048");
1701 action_name = X_("JACKLatency4096");
1704 action_name = X_("JACKLatency8192");
1707 /* XXX can we do anything useful ? */
1713 action = ActionManager::get_action (X_("JACK"), action_name);
1716 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1717 ract->set_active ();
1723 ARDOUR_UI::engine_halted ()
1725 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1727 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1728 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1730 update_sample_rate (0);
1732 MessageDialog msg (*editor,
1734 JACK has either been shutdown or it\n\
1735 disconnected Ardour because Ardour\n\
1736 was not fast enough. Try to restart\n\
1737 JACK, reconnect and save the session."));
1743 ARDOUR_UI::do_engine_start ()
1751 error << _("Unable to start the session running")
1761 ARDOUR_UI::setup_theme ()
1763 theme_manager->setup_theme();
1767 ARDOUR_UI::update_clocks ()
1769 if (!editor || !editor->dragging_playhead()) {
1770 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1775 ARDOUR_UI::start_clocking ()
1777 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1781 ARDOUR_UI::stop_clocking ()
1783 clock_signal_connection.disconnect ();
1787 ARDOUR_UI::toggle_clocking ()
1790 if (clock_button.get_active()) {
1799 ARDOUR_UI::_blink (void *arg)
1802 ((ARDOUR_UI *) arg)->blink ();
1809 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1813 ARDOUR_UI::start_blinking ()
1815 /* Start the blink signal. Everybody with a blinking widget
1816 uses Blink to drive the widget's state.
1819 if (blink_timeout_tag < 0) {
1821 blink_timeout_tag = g_timeout_add (240, _blink, this);
1826 ARDOUR_UI::stop_blinking ()
1828 if (blink_timeout_tag >= 0) {
1829 g_source_remove (blink_timeout_tag);
1830 blink_timeout_tag = -1;
1835 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1840 vector<string> connections;
1843 if (io.n_inputs().n_total() == 0) {
1848 /* XXX we're not handling multiple ports yet. */
1850 if (io.input(0)->get_connections(connections) == 0) {
1853 buf = connections.front();
1858 if (io.n_outputs().n_total() == 0) {
1863 /* XXX we're not handling multiple ports yet. */
1865 if (io.output(0)->get_connections(connections) == 0) {
1868 buf = connections.front();
1873 /** Ask the user for the name of a new shapshot and then take it.
1876 ARDOUR_UI::snapshot_session ()
1878 ArdourPrompter prompter (true);
1882 struct tm local_time;
1885 localtime_r (&n, &local_time);
1886 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1888 prompter.set_name ("Prompter");
1889 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1890 prompter.set_prompt (_("Name of New Snapshot"));
1891 prompter.set_initial_text (timebuf);
1893 switch (prompter.run()) {
1894 case RESPONSE_ACCEPT:
1895 prompter.get_result (snapname);
1896 if (snapname.length()){
1897 save_state (snapname);
1907 ARDOUR_UI::save_state (const string & name)
1909 (void) save_state_canfail (name);
1913 ARDOUR_UI::save_state_canfail (string name)
1918 if (name.length() == 0) {
1919 name = session->snap_name();
1922 if ((ret = session->save_state (name)) != 0) {
1926 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1931 ARDOUR_UI::primary_clock_value_changed ()
1934 session->request_locate (primary_clock.current_time ());
1939 ARDOUR_UI::big_clock_value_changed ()
1942 session->request_locate (big_clock.current_time ());
1947 ARDOUR_UI::secondary_clock_value_changed ()
1950 session->request_locate (secondary_clock.current_time ());
1955 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1961 switch (session->record_status()) {
1962 case Session::Enabled:
1964 rec_button.set_visual_state (2);
1966 rec_button.set_visual_state (0);
1970 case Session::Recording:
1971 rec_button.set_visual_state (1);
1975 rec_button.set_visual_state (0);
1981 ARDOUR_UI::save_template ()
1984 ArdourPrompter prompter (true);
1987 if (!check_audioengine()) {
1991 prompter.set_name (X_("Prompter"));
1992 prompter.set_prompt (_("Name for mix template:"));
1993 prompter.set_initial_text(session->name() + _("-template"));
1994 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1996 switch (prompter.run()) {
1997 case RESPONSE_ACCEPT:
1998 prompter.get_result (name);
2000 if (name.length()) {
2001 session->save_template (name);
2011 ARDOUR_UI::edit_metadata ()
2013 SessionMetadataEditor dialog;
2014 dialog.set_session (session);
2015 editor->ensure_float (dialog);
2020 ARDOUR_UI::import_metadata ()
2022 SessionMetadataImporter dialog;
2023 dialog.set_session (session);
2024 editor->ensure_float (dialog);
2029 ARDOUR_UI::fontconfig_dialog ()
2032 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2033 may not and it can take a while to build it. Warn them.
2036 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2038 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2039 MessageDialog msg (*_startup,
2040 _("Welcome to Ardour.\n\n"
2041 "The program will take a bit longer to start up\n"
2042 "while the system fonts are checked.\n\n"
2043 "This will only be done once, and you will\n"
2044 "not see this message again\n"),
2057 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2059 existing_session = false;
2061 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2062 session_path = cmdline_path;
2063 existing_session = true;
2064 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2065 session_path = Glib::path_get_dirname (string (cmdline_path));
2066 existing_session = true;
2068 /* it doesn't exist, assume the best */
2069 session_path = Glib::path_get_dirname (string (cmdline_path));
2072 session_name = basename_nosuffix (string (cmdline_path));
2076 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2078 /* when this is called, the backend audio system must be running */
2080 /* the main idea here is to deal with the fact that a cmdline argument for the session
2081 can be interpreted in different ways - it could be a directory or a file, and before
2082 we load, we need to know both the session directory and the snapshot (statefile) within it
2083 that we are supposed to use.
2086 if (session_name.length() == 0 || session_path.length() == 0) {
2090 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2092 Glib::ustring predicted_session_file;
2094 predicted_session_file = session_path;
2095 predicted_session_file += '/';
2096 predicted_session_file += session_name;
2097 predicted_session_file += ARDOUR::statefile_suffix;
2099 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2100 existing_session = true;
2103 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2105 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2106 /* existing .ardour file */
2107 existing_session = true;
2111 existing_session = false;
2114 /* lets just try to load it */
2116 if (create_engine ()) {
2117 backend_audio_error (false, _startup);
2121 return load_session (session_path, session_name);
2125 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2127 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2129 MessageDialog msg (str,
2131 Gtk::MESSAGE_WARNING,
2132 Gtk::BUTTONS_YES_NO,
2136 msg.set_name (X_("CleanupDialog"));
2137 msg.set_wmclass (X_("existing_session"), "Ardour");
2138 msg.set_position (Gtk::WIN_POS_MOUSE);
2141 switch (msg.run()) {
2150 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2155 AutoConnectOption iconnect;
2156 AutoConnectOption oconnect;
2160 if (Profile->get_sae()) {
2164 iconnect = AutoConnectPhysical;
2165 oconnect = AutoConnectMaster;
2166 nphysin = 0; // use all available
2167 nphysout = 0; // use all available
2171 /* get settings from advanced section of NSD */
2173 if (_startup->create_control_bus()) {
2174 cchns = (uint32_t) _startup->control_channel_count();
2179 if (_startup->create_master_bus()) {
2180 mchns = (uint32_t) _startup->master_channel_count();
2185 if (_startup->connect_inputs()) {
2186 iconnect = AutoConnectPhysical;
2188 iconnect = AutoConnectOption (0);
2191 /// @todo some minor tweaks.
2193 if (_startup->connect_outs_to_master()) {
2194 oconnect = AutoConnectMaster;
2195 } else if (_startup->connect_outs_to_physical()) {
2196 oconnect = AutoConnectPhysical;
2198 oconnect = AutoConnectOption (0);
2201 nphysin = (uint32_t) _startup->input_limit_count();
2202 nphysout = (uint32_t) _startup->output_limit_count();
2205 if (build_session (session_path,
2213 engine->frame_rate() * 60 * 5)) {
2222 ARDOUR_UI::end_loading_messages ()
2228 ARDOUR_UI::loading_message (const std::string& msg)
2231 // splash->message (msg);
2236 ARDOUR_UI::get_session_parameters (bool should_be_new)
2238 Glib::ustring session_name;
2239 Glib::ustring session_path;
2240 Glib::ustring template_name;
2242 bool likely_new = false;
2246 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2248 /* if they named a specific statefile, use it, otherwise they are
2249 just giving a session folder, and we want to use it as is
2250 to find the session.
2253 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2254 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2256 session_path = ARDOUR_COMMAND_LINE::session_name;
2259 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2263 run_startup (should_be_new);
2265 /* if we run the startup dialog again, offer more than just "new session" */
2267 should_be_new = false;
2269 session_name = _startup->session_name (likely_new);
2271 /* this shouldn't happen, but we catch it just in case it does */
2273 if (session_name.empty()) {
2276 if (_startup->use_session_template()) {
2277 template_name = _startup->session_template_name();
2278 _session_is_new = true;
2282 if (session_name[0] == '/' ||
2283 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2284 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2286 session_path = Glib::path_get_dirname (session_name);
2287 session_name = Glib::path_get_basename (session_name);
2291 session_path = _startup->session_folder();
2295 if (create_engine ()) {
2299 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2303 ustring existing = Glib::build_filename (session_path, session_name);
2305 if (!ask_about_loading_existing_session (existing)) {
2306 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2311 _session_is_new = false;
2316 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2318 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2322 _session_is_new = true;
2325 if (likely_new && template_name.empty()) {
2327 ret = build_session_from_nsd (session_path, session_name);
2331 ret = load_session (session_path, session_name, template_name);
2339 ARDOUR_UI::close_session()
2341 if (!check_audioengine()) {
2345 unload_session (true);
2347 get_session_parameters (false);
2351 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2353 Session *new_session;
2357 session_loaded = false;
2359 if (!check_audioengine()) {
2363 unload_status = unload_session ();
2365 if (unload_status < 0) {
2367 } else if (unload_status > 0) {
2372 /* if it already exists, we must have write access */
2374 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2375 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2376 "This prevents the session from being loaded."));
2382 loading_message (_("Please wait while Ardour loads your session"));
2385 new_session = new Session (*engine, path, snap_name, mix_template);
2388 /* this one is special */
2390 catch (AudioEngine::PortRegistrationFailure& err) {
2392 MessageDialog msg (err.what(),
2395 Gtk::BUTTONS_CLOSE);
2397 msg.set_title (_("Port Registration Error"));
2398 msg.set_secondary_text (_("Click the Close button to try again."));
2399 msg.set_position (Gtk::WIN_POS_CENTER);
2403 int response = msg.run ();
2408 case RESPONSE_CANCEL:
2418 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2421 Gtk::BUTTONS_CLOSE);
2423 msg.set_title (_("Loading Error"));
2424 msg.set_secondary_text (_("Click the Close button to try again."));
2425 msg.set_position (Gtk::WIN_POS_CENTER);
2429 int response = msg.run ();
2434 case RESPONSE_CANCEL:
2442 connect_to_session (new_session);
2444 Config->set_current_owner (ConfigVariableBase::Interface);
2446 session_loaded = true;
2448 goto_editor_window ();
2451 session->set_clean ();
2462 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2463 uint32_t control_channels,
2464 uint32_t master_channels,
2465 AutoConnectOption input_connect,
2466 AutoConnectOption output_connect,
2469 nframes_t initial_length)
2471 Session *new_session;
2474 if (!check_audioengine()) {
2478 session_loaded = false;
2480 x = unload_session ();
2488 _session_is_new = true;
2491 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2492 control_channels, master_channels, nphysin, nphysout, initial_length);
2497 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2503 connect_to_session (new_session);
2505 session_loaded = true;
2507 new_session->save_state(new_session->name());
2516 editor->show_window ();
2527 ARDOUR_UI::show_about ()
2531 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2538 ARDOUR_UI::hide_about ()
2541 about->get_window()->set_cursor ();
2547 ARDOUR_UI::about_signal_response(int response)
2553 ARDOUR_UI::show_splash ()
2557 splash = new Splash;
2565 splash->queue_draw ();
2566 splash->get_window()->process_updates (true);
2571 ARDOUR_UI::hide_splash ()
2579 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2583 removed = rep.paths.size();
2586 MessageDialog msgd (*editor,
2587 _("No audio files were ready for cleanup"),
2590 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2591 msgd.set_secondary_text (_("If this seems suprising, \n\
2592 check for any existing snapshots.\n\
2593 These may still include regions that\n\
2594 require some unused files to continue to exist."));
2600 ArdourDialog results (_("ardour: cleanup"), true, false);
2602 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2603 CleanupResultsModelColumns() {
2607 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2608 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2612 CleanupResultsModelColumns results_columns;
2613 Glib::RefPtr<Gtk::ListStore> results_model;
2614 Gtk::TreeView results_display;
2616 results_model = ListStore::create (results_columns);
2617 results_display.set_model (results_model);
2618 results_display.append_column (list_title, results_columns.visible_name);
2620 results_display.set_name ("CleanupResultsList");
2621 results_display.set_headers_visible (true);
2622 results_display.set_headers_clickable (false);
2623 results_display.set_reorderable (false);
2625 Gtk::ScrolledWindow list_scroller;
2628 Gtk::HBox dhbox; // the hbox for the image and text
2629 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2630 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2632 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2634 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2636 if (rep.space < 1048576.0f) {
2638 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2640 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2644 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2646 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2650 dhbox.pack_start (*dimage, true, false, 5);
2651 dhbox.pack_start (txt, true, false, 5);
2653 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2654 TreeModel::Row row = *(results_model->append());
2655 row[results_columns.visible_name] = *i;
2656 row[results_columns.fullpath] = *i;
2659 list_scroller.add (results_display);
2660 list_scroller.set_size_request (-1, 150);
2661 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2663 dvbox.pack_start (dhbox, true, false, 5);
2664 dvbox.pack_start (list_scroller, true, false, 5);
2665 ddhbox.pack_start (dvbox, true, false, 5);
2667 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2668 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2669 results.set_default_response (RESPONSE_CLOSE);
2670 results.set_position (Gtk::WIN_POS_MOUSE);
2672 results_display.show();
2673 list_scroller.show();
2680 //results.get_vbox()->show();
2681 results.set_resizable (false);
2688 ARDOUR_UI::cleanup ()
2691 /* shouldn't happen: menu item is insensitive */
2696 MessageDialog checker (_("Are you sure you want to cleanup?"),
2698 Gtk::MESSAGE_QUESTION,
2699 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2701 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2702 ALL undo/redo information will be lost if you cleanup.\n\
2703 After cleanup, unused audio files will be moved to a \
2704 \"dead sounds\" location."));
2706 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2707 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2708 checker.set_default_response (RESPONSE_CANCEL);
2710 checker.set_name (_("CleanupDialog"));
2711 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2712 checker.set_position (Gtk::WIN_POS_MOUSE);
2714 switch (checker.run()) {
2715 case RESPONSE_ACCEPT:
2721 Session::cleanup_report rep;
2723 editor->prepare_for_cleanup ();
2725 /* do not allow flush until a session is reloaded */
2727 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2729 act->set_sensitive (false);
2732 if (session->cleanup_sources (rep)) {
2733 editor->finish_cleanup ();
2737 editor->finish_cleanup ();
2740 display_cleanup_results (rep,
2743 The following %1 %2 not in use and \n\
2744 have been moved to:\n\
2746 Flushing the wastebasket will \n\
2747 release an additional\n\
2748 %4 %5bytes of disk space.\n"
2754 ARDOUR_UI::flush_trash ()
2757 /* shouldn't happen: menu item is insensitive */
2761 Session::cleanup_report rep;
2763 if (session->cleanup_trash_sources (rep)) {
2767 display_cleanup_results (rep,
2769 _("The following %1 %2 deleted from\n\
2771 releasing %4 %5bytes of disk space"));
2775 ARDOUR_UI::add_route (Gtk::Window* float_window)
2783 if (add_route_dialog == 0) {
2784 add_route_dialog = new AddRouteDialog;
2786 add_route_dialog->set_transient_for (*float_window);
2790 if (add_route_dialog->is_visible()) {
2791 /* we're already doing this */
2795 ResponseType r = (ResponseType) add_route_dialog->run ();
2797 add_route_dialog->hide();
2800 case RESPONSE_ACCEPT:
2807 if ((count = add_route_dialog->count()) <= 0) {
2811 string template_path = add_route_dialog->track_template();
2813 if (!template_path.empty()) {
2814 session->new_route_from_template (count, template_path);
2818 uint32_t input_chan = add_route_dialog->channels ();
2819 uint32_t output_chan;
2820 string name_template = add_route_dialog->name_template ();
2821 bool track = add_route_dialog->track ();
2823 AutoConnectOption oac = Config->get_output_auto_connect();
2825 if (oac & AutoConnectMaster) {
2826 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2828 output_chan = input_chan;
2831 /* XXX do something with name template */
2833 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2835 session_add_midi_track(count);
2837 MessageDialog msg (*editor,
2838 _("Sorry, MIDI Busses are not supported at this time."));
2840 //session_add_midi_bus();
2844 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2846 session_add_audio_bus (input_chan, output_chan, count);
2852 ARDOUR_UI::mixer_settings () const
2857 node = session->instant_xml(X_("Mixer"));
2859 node = Config->instant_xml(X_("Mixer"));
2863 node = new XMLNode (X_("Mixer"));
2870 ARDOUR_UI::editor_settings () const
2875 node = session->instant_xml(X_("Editor"));
2877 node = Config->instant_xml(X_("Editor"));
2881 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2882 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2887 node = new XMLNode (X_("Editor"));
2894 ARDOUR_UI::keyboard_settings () const
2898 node = Config->extra_xml(X_("Keyboard"));
2901 node = new XMLNode (X_("Keyboard"));
2907 ARDOUR_UI::create_xrun_marker(nframes_t where)
2909 editor->mouse_add_new_marker (where, false, true);
2913 ARDOUR_UI::halt_on_xrun_message ()
2915 MessageDialog msg (*editor,
2916 _("Recording was stopped because your system could not keep up."));
2921 ARDOUR_UI::xrun_handler(nframes_t where)
2927 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2929 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2930 create_xrun_marker(where);
2933 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2934 halt_on_xrun_message ();
2939 ARDOUR_UI::disk_overrun_handler ()
2941 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2943 if (!have_disk_speed_dialog_displayed) {
2944 have_disk_speed_dialog_displayed = true;
2945 MessageDialog* msg = new MessageDialog (*editor, _("\
2946 The disk system on your computer\n\
2947 was not able to keep up with Ardour.\n\
2949 Specifically, it failed to write data to disk\n\
2950 quickly enough to keep up with recording.\n"));
2951 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2957 ARDOUR_UI::disk_underrun_handler ()
2959 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2961 if (!have_disk_speed_dialog_displayed) {
2962 have_disk_speed_dialog_displayed = true;
2963 MessageDialog* msg = new MessageDialog (*editor,
2964 _("The disk system on your computer\n\
2965 was not able to keep up with Ardour.\n\
2967 Specifically, it failed to read data from disk\n\
2968 quickly enough to keep up with playback.\n"));
2969 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2975 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2977 have_disk_speed_dialog_displayed = false;
2982 ARDOUR_UI::session_dialog (std::string msg)
2984 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
2989 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
2991 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3000 ARDOUR_UI::pending_state_dialog ()
3002 HBox* hbox = new HBox();
3003 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3004 ArdourDialog dialog (_("Crash Recovery"), true);
3006 This session appears to have been in\n\
3007 middle of recording when ardour or\n\
3008 the computer was shutdown.\n\
3010 Ardour can recover any captured audio for\n\
3011 you, or it can ignore it. Please decide\n\
3012 what you would like to do.\n"));
3013 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3014 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3015 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3016 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3017 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3018 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3019 dialog.set_default_response (RESPONSE_ACCEPT);
3020 dialog.set_position (WIN_POS_CENTER);
3025 switch (dialog.run ()) {
3026 case RESPONSE_ACCEPT:
3034 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3036 HBox* hbox = new HBox();
3037 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3038 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3039 Label message (string_compose (_("\
3040 This session was created with a sample rate of %1 Hz\n\
3042 The audioengine is currently running at %2 Hz\n"), desired, actual));
3044 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3045 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3046 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3047 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3048 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3049 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3050 dialog.set_default_response (RESPONSE_ACCEPT);
3051 dialog.set_position (WIN_POS_CENTER);
3056 switch (dialog.run ()) {
3057 case RESPONSE_ACCEPT:
3066 ARDOUR_UI::disconnect_from_jack ()
3069 if( engine->disconnect_from_jack ()) {
3070 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3074 update_sample_rate (0);
3079 ARDOUR_UI::reconnect_to_jack ()
3082 if (engine->reconnect_to_jack ()) {
3083 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3087 update_sample_rate (0);
3092 ARDOUR_UI::use_config ()
3094 Glib::RefPtr<Action> act;
3096 switch (Config->get_native_file_data_format ()) {
3098 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3101 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3104 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3109 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3110 ract->set_active ();
3113 switch (Config->get_native_file_header_format ()) {
3115 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3118 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3121 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3124 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3127 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3130 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3133 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3138 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3139 ract->set_active ();
3142 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3144 set_transport_controllable_state (*node);
3149 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3151 if (Config->get_primary_clock_delta_edit_cursor()) {
3152 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3154 primary_clock.set (pos, 0, true);
3157 if (Config->get_secondary_clock_delta_edit_cursor()) {
3158 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3160 secondary_clock.set (pos);
3163 if (big_clock_window) {
3164 big_clock.set (pos);
3169 ARDOUR_UI::record_state_changed ()
3171 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3173 if (!session || !big_clock_window) {
3174 /* why bother - the clock isn't visible */
3178 switch (session->record_status()) {
3179 case Session::Recording:
3180 big_clock.set_widget_name ("BigClockRecording");
3183 big_clock.set_widget_name ("BigClockNonRecording");
3189 ARDOUR_UI::first_idle ()
3192 session->allow_auto_play (true);
3196 editor->first_idle();
3199 Keyboard::set_can_save_keybindings (true);
3204 ARDOUR_UI::store_clock_modes ()
3206 XMLNode* node = new XMLNode(X_("ClockModes"));
3208 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3209 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3212 session->add_extra_xml (*node);
3213 session->set_dirty ();
3218 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3219 : Controllable (name), ui (u), type(tp)
3225 ARDOUR_UI::TransportControllable::set_value (float val)
3227 if (type == ShuttleControl) {
3234 fract = -((0.5f - val)/0.5f);
3236 fract = ((val - 0.5f)/0.5f);
3240 ui.set_shuttle_fract (fract);
3245 /* do nothing: these are radio-style actions */
3249 const char *action = 0;
3253 action = X_("Roll");
3256 action = X_("Stop");
3259 action = X_("Goto Start");
3262 action = X_("Goto End");
3265 action = X_("Loop");
3268 action = X_("Play Selection");
3271 action = X_("Record");
3281 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3289 ARDOUR_UI::TransportControllable::get_value (void) const
3308 case ShuttleControl:
3318 ARDOUR_UI::TransportControllable::set_id (const string& str)
3324 ARDOUR_UI::setup_profile ()
3326 if (gdk_screen_width() < 1200) {
3327 Profile->set_small_screen ();
3331 if (getenv ("ARDOUR_SAE")) {
3332 Profile->set_sae ();
3333 Profile->set_single_package ();