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.
32 #include <sys/resource.h>
34 #include <gtkmm/messagedialog.h>
35 #include <gtkmm/accelmap.h>
37 #include <pbd/error.h>
38 #include <pbd/basename.h>
39 #include <pbd/compose.h>
40 #include <pbd/pathscanner.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/stacktrace.h>
44 #include <gtkmm2ext/gtk_ui.h>
45 #include <gtkmm2ext/utils.h>
46 #include <gtkmm2ext/click_box.h>
47 #include <gtkmm2ext/fastmeter.h>
48 #include <gtkmm2ext/stop_signal.h>
49 #include <gtkmm2ext/popup.h>
50 #include <gtkmm2ext/window_title.h>
52 #include <midi++/port.h>
53 #include <midi++/mmc.h>
55 #include <ardour/ardour.h>
56 #include <ardour/profile.h>
57 #include <ardour/session_route.h>
58 #include <ardour/port.h>
59 #include <ardour/audioengine.h>
60 #include <ardour/playlist.h>
61 #include <ardour/utils.h>
62 #include <ardour/plugin.h>
63 #include <ardour/audio_diskstream.h>
64 #include <ardour/audiofilesource.h>
65 #include <ardour/recent_sessions.h>
66 #include <ardour/port.h>
67 #include <ardour/audio_track.h>
69 typedef uint64_t microseconds_t;
72 #include "ardour_ui.h"
73 #include "public_editor.h"
74 #include "audio_clock.h"
79 #include "add_route_dialog.h"
80 #include "new_session_dialog.h"
85 #include "gui_thread.h"
86 #include "theme_manager.h"
87 #include "engine_dialog.h"
88 #include "gain_meter.h"
89 #include "route_time_axis.h"
93 using namespace ARDOUR;
95 using namespace Gtkmm2ext;
99 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
100 UIConfiguration *ARDOUR_UI::ui_config = 0;
102 sigc::signal<void,bool> ARDOUR_UI::Blink;
103 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
104 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
105 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
107 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
109 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
111 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
112 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
113 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
114 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
118 preroll_button (_("pre\nroll")),
119 postroll_button (_("post\nroll")),
123 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
127 roll_controllable ("transport roll", *this, TransportControllable::Roll),
128 stop_controllable ("transport stop", *this, TransportControllable::Stop),
129 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
130 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
131 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
132 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
133 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
134 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
135 shuttle_controller_binding_proxy (shuttle_controllable),
137 roll_button (&roll_controllable),
138 stop_button (&stop_controllable),
139 goto_start_button (&goto_start_controllable),
140 goto_end_button (&goto_end_controllable),
141 auto_loop_button (&auto_loop_controllable),
142 play_selection_button (&play_selection_controllable),
143 rec_button (&rec_controllable),
145 shuttle_units_button (_("% ")),
147 punch_in_button (_("Punch In")),
148 punch_out_button (_("Punch Out")),
149 auto_return_button (_("Auto Return")),
150 auto_play_button (_("Auto Play")),
151 auto_input_button (_("Auto Input")),
152 click_button (_("Click")),
153 time_master_button (_("time\nmaster")),
155 auditioning_alert_button (_("AUDITION")),
156 solo_alert_button (_("SOLO")),
158 error_log_button (_("Errors"))
160 using namespace Gtk::Menu_Helpers;
165 _auto_display_errors = false;
171 if (ARDOUR_COMMAND_LINE::session_name.length()) {
172 /* only show this if we're not going to post the new session dialog */
176 if (theArdourUI == 0) {
180 ui_config = new UIConfiguration();
181 theme_manager = new ThemeManager();
187 _session_is_new = false;
188 big_clock_window = 0;
189 session_selector_window = 0;
190 new_session_dialog = 0;
191 last_key_press_time = 0;
192 connection_editor = 0;
193 add_route_dialog = 0;
198 open_session_selector = 0;
199 have_configure_timeout = false;
200 have_disk_speed_dialog_displayed = false;
201 _will_create_new_session_automatically = false;
202 session_loaded = false;
203 last_speed_displayed = -1.0f;
204 ignore_dual_punch = false;
205 _mixer_on_top = false;
207 roll_button.unset_flags (Gtk::CAN_FOCUS);
208 stop_button.unset_flags (Gtk::CAN_FOCUS);
209 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
210 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
211 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
212 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
213 rec_button.unset_flags (Gtk::CAN_FOCUS);
215 last_configure_time= 0;
217 shuttle_grabbed = false;
219 shuttle_max_speed = 8.0f;
221 shuttle_style_menu = 0;
222 shuttle_unit_menu = 0;
224 // We do not have jack linked in yet so;
226 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
228 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
229 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
231 ARDOUR::Plugin::PresetFileExists.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler));
233 /* handle dialog requests */
235 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
237 /* handle pending state with a dialog */
239 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
241 /* handle sr mismatch with a dialog */
243 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
245 /* lets get this party started */
248 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
249 throw failed_constructor ();
252 setup_gtk_ardour_enums ();
253 Config->set_current_owner (ConfigVariableBase::Interface);
256 GainMeter::setup_slider_pix ();
257 RouteTimeAxisView::setup_slider_pix ();
259 } catch (failed_constructor& err) {
260 error << _("could not initialize Ardour.") << endmsg;
265 /* we like keyboards */
267 keyboard = new Keyboard;
271 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
272 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
278 ARDOUR_UI::create_engine ()
280 // this gets called every time by new_session()
286 loading_message (_("Starting audio engine"));
289 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
296 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
297 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
298 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
299 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
307 ARDOUR_UI::post_engine ()
309 /* Things to be done once we create the AudioEngine
312 check_memory_locking();
314 ActionManager::init ();
317 if (setup_windows ()) {
318 throw failed_constructor ();
321 /* this is the first point at which all the keybindings are available */
323 if (ARDOUR_COMMAND_LINE::show_key_actions) {
324 vector<string> names;
325 vector<string> paths;
327 vector<AccelKey> bindings;
329 ActionManager::get_all_actions (names, paths, keys, bindings);
331 vector<string>::iterator n;
332 vector<string>::iterator k;
333 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
334 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
340 blink_timeout_tag = -1;
342 /* the global configuration object is now valid */
346 /* this being a GUI and all, we want peakfiles */
348 AudioFileSource::set_build_peakfiles (true);
349 AudioFileSource::set_build_missing_peakfiles (true);
351 /* set default clock modes */
353 if (Profile->get_sae()) {
354 primary_clock.set_mode (AudioClock::BBT);
355 secondary_clock.set_mode (AudioClock::MinSec);
357 primary_clock.set_mode (AudioClock::SMPTE);
358 secondary_clock.set_mode (AudioClock::BBT);
361 /* start the time-of-day-clock */
364 /* OS X provides an always visible wallclock, so don't be stupid */
365 update_wall_clock ();
366 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
369 update_disk_space ();
371 update_sample_rate (engine->frame_rate());
373 platform_specific ();
375 /* now start and maybe save state */
377 if (do_engine_start () == 0) {
378 if (session && _session_is_new) {
379 /* we need to retain initial visual
380 settings for a new session
382 session->save_state ("");
387 ARDOUR_UI::~ARDOUR_UI ()
389 save_ardour_state ();
403 if (add_route_dialog) {
404 delete add_route_dialog;
407 if (new_session_dialog) {
408 delete new_session_dialog;
413 ARDOUR_UI::pop_back_splash ()
415 if (Splash::instance()) {
416 // Splash::instance()->pop_back();
417 Splash::instance()->hide ();
422 ARDOUR_UI::configure_timeout ()
424 if (last_configure_time == 0) {
425 /* no configure events yet */
429 /* force a gap of 0.5 seconds since the last configure event
432 if (get_microseconds() - last_configure_time < 500000) {
435 have_configure_timeout = false;
436 save_ardour_state ();
442 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
444 if (have_configure_timeout) {
445 last_configure_time = get_microseconds();
447 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
448 have_configure_timeout = true;
455 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
457 const XMLProperty* prop;
459 if ((prop = node.property ("roll")) != 0) {
460 roll_controllable.set_id (prop->value());
462 if ((prop = node.property ("stop")) != 0) {
463 stop_controllable.set_id (prop->value());
465 if ((prop = node.property ("goto_start")) != 0) {
466 goto_start_controllable.set_id (prop->value());
468 if ((prop = node.property ("goto_end")) != 0) {
469 goto_end_controllable.set_id (prop->value());
471 if ((prop = node.property ("auto_loop")) != 0) {
472 auto_loop_controllable.set_id (prop->value());
474 if ((prop = node.property ("play_selection")) != 0) {
475 play_selection_controllable.set_id (prop->value());
477 if ((prop = node.property ("rec")) != 0) {
478 rec_controllable.set_id (prop->value());
480 if ((prop = node.property ("shuttle")) != 0) {
481 shuttle_controllable.set_id (prop->value());
486 ARDOUR_UI::get_transport_controllable_state ()
488 XMLNode* node = new XMLNode(X_("TransportControllables"));
491 roll_controllable.id().print (buf, sizeof (buf));
492 node->add_property (X_("roll"), buf);
493 stop_controllable.id().print (buf, sizeof (buf));
494 node->add_property (X_("stop"), buf);
495 goto_start_controllable.id().print (buf, sizeof (buf));
496 node->add_property (X_("goto_start"), buf);
497 goto_end_controllable.id().print (buf, sizeof (buf));
498 node->add_property (X_("goto_end"), buf);
499 auto_loop_controllable.id().print (buf, sizeof (buf));
500 node->add_property (X_("auto_loop"), buf);
501 play_selection_controllable.id().print (buf, sizeof (buf));
502 node->add_property (X_("play_selection"), buf);
503 rec_controllable.id().print (buf, sizeof (buf));
504 node->add_property (X_("rec"), buf);
505 shuttle_controllable.id().print (buf, sizeof (buf));
506 node->add_property (X_("shuttle"), buf);
512 ARDOUR_UI::save_ardour_state ()
514 if (!keyboard || !mixer || !editor) {
518 /* XXX this is all a bit dubious. add_extra_xml() uses
519 a different lifetime model from add_instant_xml().
522 XMLNode* node = new XMLNode (keyboard->get_state());
523 Config->add_extra_xml (*node);
524 Config->add_extra_xml (get_transport_controllable_state());
525 if (new_session_dialog) {
526 if (new_session_dialog->engine_control.was_used()) {
527 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
530 Config->save_state();
531 ui_config->save_state ();
533 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
534 XMLNode mnode(mixer->get_state());
537 session->add_instant_xml (enode, session->path());
538 session->add_instant_xml (mnode, session->path());
540 Config->add_instant_xml (enode, get_user_ardour_path());
541 Config->add_instant_xml (mnode, get_user_ardour_path());
544 Keyboard::save_keybindings ();
548 ARDOUR_UI::autosave_session ()
550 if (g_main_depth() > 1) {
551 /* inside a recursive main loop,
552 give up because we may not be able to
558 if (!Config->get_periodic_safety_backups())
562 session->maybe_write_autosave();
569 ARDOUR_UI::update_autosave ()
571 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
573 if (session && session->dirty()) {
574 if (_autosave_connection.connected()) {
575 _autosave_connection.disconnect();
578 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
579 Config->get_periodic_safety_backup_interval() * 1000);
582 if (_autosave_connection.connected()) {
583 _autosave_connection.disconnect();
589 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
593 title = _("Ardour could not start JACK");
595 title = _("Ardour could not connect to JACK.");
598 MessageDialog win (title,
604 win.set_secondary_text(_("There are several possible reasons:\n\
606 1) You requested audio parameters that are not supported..\n\
607 2) JACK is running as another user.\n\
609 Please consider the possibilities, and perhaps try different parameters."));
611 win.set_secondary_text(_("There are several possible reasons:\n\
613 1) JACK is not running.\n\
614 2) JACK is running as another user, perhaps root.\n\
615 3) There is already another client called \"ardour\".\n\
617 Please consider the possibilities, and perhaps (re)start JACK."));
621 win.set_transient_for (*toplevel);
625 win.add_button (Stock::OK, RESPONSE_CLOSE);
627 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
630 win.set_default_response (RESPONSE_CLOSE);
633 win.set_position (Gtk::WIN_POS_CENTER);
636 /* we just don't care about the result, but we want to block */
642 ARDOUR_UI::startup ()
646 new_session_dialog = new NewSessionDialog();
648 bool backend_audio_is_running = EngineControl::engine_running();
649 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
652 new_session_dialog->engine_control.set_state (*audio_setup);
655 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
659 BootMessage (_("Ardour is ready for use"));
664 ARDOUR_UI::no_memory_warning ()
666 XMLNode node (X_("no-memory-warning"));
667 Config->add_instant_xml (node, get_user_ardour_path());
671 ARDOUR_UI::check_memory_locking ()
674 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
678 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
680 if (engine->is_realtime() && memory_warning_node == 0) {
682 struct rlimit limits;
684 long pages, page_size;
686 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
689 ram = (int64_t) pages * (int64_t) page_size;
692 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
696 if (limits.rlim_cur != RLIM_INFINITY) {
698 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
701 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
702 "This might cause Ardour to run out of memory before your system "
703 "runs out of memory. \n\n"
704 "You can view the memory limit with 'ulimit -l', "
705 "and it is normally controlled by /etc/security/limits.conf"));
707 VBox* vbox = msg.get_vbox();
709 CheckButton cb (_("Do not show this window again"));
711 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
713 hbox.pack_start (cb, true, false);
714 vbox->pack_start (hbox);
732 if (session->transport_rolling()) {
733 session->request_stop ();
737 if (session->dirty()) {
738 switch (ask_about_saving_session(_("quit"))) {
743 /* use the default name */
744 if (save_state_canfail ("")) {
745 /* failed - don't quit */
746 MessageDialog msg (*editor,
748 Ardour was unable to save your session.\n\n\
749 If you still wish to quit, please use the\n\n\
750 \"Just quit\" option."));
761 session->set_deletion_in_progress ();
764 ArdourDialog::close_all_dialogs ();
766 save_ardour_state ();
771 ARDOUR_UI::ask_about_saving_session (const string & what)
773 ArdourDialog window (_("ardour: save session?"));
774 Gtk::HBox dhbox; // the hbox for the image and text
775 Gtk::Label prompt_label;
776 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
780 msg = string_compose(_("Don't %1"), what);
781 window.add_button (msg, RESPONSE_REJECT);
782 msg = string_compose(_("Just %1"), what);
783 window.add_button (msg, RESPONSE_APPLY);
784 msg = string_compose(_("Save and %1"), what);
785 window.add_button (msg, RESPONSE_ACCEPT);
787 window.set_default_response (RESPONSE_ACCEPT);
789 Gtk::Button noquit_button (msg);
790 noquit_button.set_name ("EditorGTKButton");
795 if (session->snap_name() == session->name()) {
798 type = _("snapshot");
800 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?"),
801 type, session->snap_name());
803 prompt_label.set_text (prompt);
804 prompt_label.set_name (X_("PrompterLabel"));
805 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
807 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
809 dhbox.set_homogeneous (false);
810 dhbox.pack_start (*dimage, false, false, 5);
811 dhbox.pack_start (prompt_label, true, false, 5);
812 window.get_vbox()->pack_start (dhbox);
814 window.set_name (_("Prompter"));
815 window.set_position (Gtk::WIN_POS_MOUSE);
816 window.set_modal (true);
817 window.set_resizable (false);
820 window.set_keep_above (true);
823 ResponseType r = (ResponseType) window.run();
828 case RESPONSE_ACCEPT: // save and get out of here
830 case RESPONSE_APPLY: // get out of here
840 ARDOUR_UI::every_second ()
843 update_buffer_load ();
844 update_disk_space ();
849 ARDOUR_UI::every_point_one_seconds ()
851 update_speed_display ();
852 RapidScreenUpdate(); /* EMIT_SIGNAL */
857 ARDOUR_UI::every_point_zero_one_seconds ()
859 // august 2007: actual update frequency: 40Hz, not 100Hz
861 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
866 ARDOUR_UI::update_sample_rate (nframes_t ignored)
870 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
872 if (!engine->connected()) {
874 snprintf (buf, sizeof (buf), _("disconnected"));
878 nframes_t rate = engine->frame_rate();
880 if (fmod (rate, 1000.0) != 0.0) {
881 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
882 (float) rate/1000.0f,
883 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
885 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
887 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
891 sample_rate_label.set_text (buf);
895 ARDOUR_UI::update_cpu_load ()
898 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
899 cpu_load_label.set_text (buf);
903 ARDOUR_UI::update_buffer_load ()
909 c = session->capture_load ();
910 p = session->playback_load ();
912 push_buffer_stats (c, p);
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();
932 ARDOUR_UI::update_disk_space()
938 nframes_t frames = session->available_capture_duration();
941 if (frames == max_frames) {
942 strcpy (buf, _("Disk: 24hrs+"));
947 nframes_t fr = session->frame_rate();
949 rec_enabled_streams = 0;
950 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
952 if (rec_enabled_streams) {
953 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);
969 ARDOUR_UI::update_wall_clock ()
976 tm_now = localtime (&now);
978 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
979 wall_clock_label.set_text (buf);
985 ARDOUR_UI::session_menu (GdkEventButton *ev)
987 session_popup_menu->popup (0, 0);
992 ARDOUR_UI::redisplay_recent_sessions ()
994 vector<string *> *sessions;
995 vector<string *>::iterator i;
996 RecentSessionsSorter cmp;
998 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
999 recent_session_model->clear ();
1002 ARDOUR::read_recent_sessions (rs);
1005 recent_session_display.set_model (recent_session_model);
1009 /* sort them alphabetically */
1010 sort (rs.begin(), rs.end(), cmp);
1011 sessions = new vector<string*>;
1013 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1014 sessions->push_back (new string ((*i).second));
1017 for (i = sessions->begin(); i != sessions->end(); ++i) {
1019 vector<string*>* states;
1020 vector<const gchar*> item;
1021 string fullpath = *(*i);
1023 /* remove any trailing / */
1025 if (fullpath[fullpath.length()-1] == '/') {
1026 fullpath = fullpath.substr (0, fullpath.length()-1);
1029 /* check whether session still exists */
1030 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1031 /* session doesn't exist */
1032 cerr << "skipping non-existent session " << fullpath << endl;
1036 /* now get available states for this session */
1038 if ((states = Session::possible_states (fullpath)) == 0) {
1039 /* no state file? */
1043 TreeModel::Row row = *(recent_session_model->append());
1045 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1046 row[recent_session_columns.fullpath] = fullpath;
1048 if (states->size() > 1) {
1050 /* add the children */
1052 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1054 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1056 child_row[recent_session_columns.visible_name] = **i2;
1057 child_row[recent_session_columns.fullpath] = fullpath;
1066 recent_session_display.set_model (recent_session_model);
1071 ARDOUR_UI::build_session_selector ()
1073 session_selector_window = new ArdourDialog ("session selector");
1075 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1077 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1078 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1079 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1080 recent_session_model = TreeStore::create (recent_session_columns);
1081 recent_session_display.set_model (recent_session_model);
1082 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1083 recent_session_display.set_headers_visible (false);
1084 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1085 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1087 scroller->add (recent_session_display);
1088 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1090 session_selector_window->set_name ("SessionSelectorWindow");
1091 session_selector_window->set_size_request (200, 400);
1092 session_selector_window->get_vbox()->pack_start (*scroller);
1093 session_selector_window->show_all_children();
1097 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1099 session_selector_window->response (RESPONSE_ACCEPT);
1103 ARDOUR_UI::open_recent_session ()
1105 bool can_return = (session != 0);
1107 if (session_selector_window == 0) {
1108 build_session_selector ();
1111 redisplay_recent_sessions ();
1115 session_selector_window->set_position (WIN_POS_MOUSE);
1117 ResponseType r = (ResponseType) session_selector_window->run ();
1120 case RESPONSE_ACCEPT:
1124 session_selector_window->hide();
1131 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1135 session_selector_window->hide();
1137 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1139 if (i == recent_session_model->children().end()) {
1143 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1144 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1146 _session_is_new = false;
1148 if (load_session (path, state) == 0) {
1157 ARDOUR_UI::check_audioengine ()
1160 if (!engine->connected()) {
1161 MessageDialog msg (_("Ardour is not connected to JACK\n"
1162 "You cannot open or close sessions in this condition"));
1164 msg.set_position (WIN_POS_CENTER);
1175 ARDOUR_UI::open_session ()
1177 if (!check_audioengine()) {
1181 /* popup selector window */
1183 if (open_session_selector == 0) {
1185 /* ardour sessions are folders */
1187 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1188 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1189 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1190 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1192 FileFilter session_filter;
1193 session_filter.add_pattern ("*.ardour");
1194 session_filter.set_name (_("Ardour sessions"));
1195 open_session_selector->add_filter (session_filter);
1196 open_session_selector->set_filter (session_filter);
1199 int response = open_session_selector->run();
1200 open_session_selector->hide ();
1203 case RESPONSE_ACCEPT:
1206 open_session_selector->hide();
1210 open_session_selector->hide();
1211 string session_path = open_session_selector->get_filename();
1215 if (session_path.length() > 0) {
1216 if (Session::find_session (session_path, path, name, isnew) == 0) {
1217 _session_is_new = isnew;
1218 load_session (path, name);
1225 ARDOUR_UI::session_add_midi_track ()
1227 cerr << _("Patience is a virtue.\n");
1231 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1233 list<boost::shared_ptr<AudioTrack> > tracks;
1234 Session::RouteList routes;
1237 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1243 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1245 if (tracks.size() != how_many) {
1246 if (how_many == 1) {
1247 error << _("could not create a new audio track") << endmsg;
1249 error << string_compose (_("could only create %1 of %2 new audio %3"),
1250 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1256 routes = session->new_audio_route (input_channels, output_channels, how_many);
1258 if (routes.size() != how_many) {
1259 if (how_many == 1) {
1260 error << _("could not create a new audio track") << endmsg;
1262 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1268 if (need_control_room_outs) {
1274 route->set_stereo_control_outs (control_lr_channels);
1275 route->control_outs()->set_stereo_pan (pans, this);
1277 #endif /* CONTROLOUTS */
1281 MessageDialog msg (*editor,
1282 _("There are insufficient JACK ports available\n\
1283 to create a new track or bus.\n\
1284 You should save Ardour, exit and\n\
1285 restart JACK with more ports."));
1292 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1294 nframes_t _preroll = 0;
1297 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1298 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1300 if (new_position > _preroll) {
1301 new_position -= _preroll;
1306 session->request_locate (new_position);
1311 ARDOUR_UI::transport_goto_start ()
1314 session->goto_start();
1317 /* force displayed area in editor to start no matter
1318 what "follow playhead" setting is.
1322 editor->reset_x_origin (session->current_start_frame());
1328 ARDOUR_UI::transport_goto_zero ()
1331 session->request_locate (0);
1334 /* force displayed area in editor to start no matter
1335 what "follow playhead" setting is.
1339 editor->reset_x_origin (0);
1345 ARDOUR_UI::transport_goto_wallclock ()
1347 if (session && editor) {
1354 localtime_r (&now, &tmnow);
1356 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1357 frames += tmnow.tm_min * (60 * session->frame_rate());
1358 frames += tmnow.tm_sec * session->frame_rate();
1360 session->request_locate (frames);
1362 /* force displayed area in editor to start no matter
1363 what "follow playhead" setting is.
1367 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1373 ARDOUR_UI::transport_goto_end ()
1376 nframes_t frame = session->current_end_frame();
1377 session->request_locate (frame);
1379 /* force displayed area in editor to start no matter
1380 what "follow playhead" setting is.
1384 editor->reset_x_origin (frame);
1390 ARDOUR_UI::transport_stop ()
1396 if (session->is_auditioning()) {
1397 session->cancel_audition ();
1401 if (session->get_play_loop ()) {
1402 session->request_play_loop (false);
1405 session->request_stop ();
1409 ARDOUR_UI::transport_stop_and_forget_capture ()
1412 session->request_stop (true);
1417 ARDOUR_UI::remove_last_capture()
1420 editor->remove_last_capture();
1425 ARDOUR_UI::transport_record (bool roll)
1429 switch (session->record_status()) {
1430 case Session::Disabled:
1431 if (session->ntracks() == 0) {
1432 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1436 session->maybe_enable_record ();
1441 case Session::Recording:
1443 session->request_stop();
1445 session->disable_record (false, true);
1449 case Session::Enabled:
1450 session->disable_record (false, true);
1453 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1457 ARDOUR_UI::transport_roll ()
1465 rolling = session->transport_rolling ();
1467 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1469 if (session->get_play_loop()) {
1470 session->request_play_loop (false);
1471 auto_loop_button.set_visual_state (1);
1472 roll_button.set_visual_state (1);
1473 } else if (session->get_play_range ()) {
1474 session->request_play_range (false);
1475 play_selection_button.set_visual_state (0);
1476 } else if (rolling) {
1477 session->request_locate (session->last_transport_start(), true);
1480 session->request_transport_speed (1.0f);
1484 ARDOUR_UI::transport_loop()
1487 if (session->get_play_loop()) {
1488 if (session->transport_rolling()) {
1489 Location * looploc = session->locations()->auto_loop_location();
1491 session->request_locate (looploc->start(), true);
1496 session->request_play_loop (true);
1502 ARDOUR_UI::transport_play_selection ()
1508 if (!session->get_play_range()) {
1509 session->request_stop ();
1512 editor->play_selection ();
1516 ARDOUR_UI::transport_rewind (int option)
1518 float current_transport_speed;
1521 current_transport_speed = session->transport_speed();
1523 if (current_transport_speed >= 0.0f) {
1526 session->request_transport_speed (-1.0f);
1529 session->request_transport_speed (-4.0f);
1532 session->request_transport_speed (-0.5f);
1537 session->request_transport_speed (current_transport_speed * 1.5f);
1543 ARDOUR_UI::transport_forward (int option)
1545 float current_transport_speed;
1548 current_transport_speed = session->transport_speed();
1550 if (current_transport_speed <= 0.0f) {
1553 session->request_transport_speed (1.0f);
1556 session->request_transport_speed (4.0f);
1559 session->request_transport_speed (0.5f);
1564 session->request_transport_speed (current_transport_speed * 1.5f);
1570 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1576 boost::shared_ptr<Route> r;
1578 if ((r = session->route_by_remote_id (dstream)) != 0) {
1582 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1583 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1592 ARDOUR_UI::queue_transport_change ()
1594 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1598 ARDOUR_UI::map_transport_state ()
1600 float sp = session->transport_speed();
1603 transport_rolling ();
1604 } else if (sp < 0.0f) {
1605 transport_rewinding ();
1606 } else if (sp > 0.0f) {
1607 transport_forwarding ();
1609 transport_stopped ();
1614 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1616 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1617 (int) adj.get_value()].c_str());
1621 ARDOUR_UI::engine_stopped ()
1623 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1624 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1625 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1629 ARDOUR_UI::engine_running ()
1631 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1632 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1633 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1635 Glib::RefPtr<Action> action;
1636 const char* action_name = 0;
1638 switch (engine->frames_per_cycle()) {
1640 action_name = X_("JACKLatency32");
1643 action_name = X_("JACKLatency64");
1646 action_name = X_("JACKLatency128");
1649 action_name = X_("JACKLatency512");
1652 action_name = X_("JACKLatency1024");
1655 action_name = X_("JACKLatency2048");
1658 action_name = X_("JACKLatency4096");
1661 action_name = X_("JACKLatency8192");
1664 /* XXX can we do anything useful ? */
1670 action = ActionManager::get_action (X_("JACK"), action_name);
1673 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1674 ract->set_active ();
1680 ARDOUR_UI::engine_halted ()
1682 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1684 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1685 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1687 update_sample_rate (0);
1689 MessageDialog msg (*editor,
1691 JACK has either been shutdown or it\n\
1692 disconnected Ardour because Ardour\n\
1693 was not fast enough. Try to restart\n\
1694 JACK, reconnect and save the session."));
1700 ARDOUR_UI::do_engine_start ()
1708 error << _("Unable to start the session running")
1718 ARDOUR_UI::setup_theme ()
1720 theme_manager->setup_theme();
1724 ARDOUR_UI::update_clocks ()
1726 if (!editor || !editor->dragging_playhead()) {
1727 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1732 ARDOUR_UI::start_clocking ()
1734 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1738 ARDOUR_UI::stop_clocking ()
1740 clock_signal_connection.disconnect ();
1744 ARDOUR_UI::toggle_clocking ()
1747 if (clock_button.get_active()) {
1756 ARDOUR_UI::_blink (void *arg)
1759 ((ARDOUR_UI *) arg)->blink ();
1766 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1770 ARDOUR_UI::start_blinking ()
1772 /* Start the blink signal. Everybody with a blinking widget
1773 uses Blink to drive the widget's state.
1776 if (blink_timeout_tag < 0) {
1778 blink_timeout_tag = g_timeout_add (240, _blink, this);
1783 ARDOUR_UI::stop_blinking ()
1785 if (blink_timeout_tag >= 0) {
1786 g_source_remove (blink_timeout_tag);
1787 blink_timeout_tag = -1;
1792 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1798 if (io.n_inputs() == 0) {
1803 /* XXX we're not handling multiple ports yet. */
1805 const char **connections = io.input(0)->get_connections();
1807 if (connections == 0 || connections[0] == '\0') {
1810 buf = connections[0];
1817 if (io.n_outputs() == 0) {
1822 /* XXX we're not handling multiple ports yet. */
1824 const char **connections = io.output(0)->get_connections();
1826 if (connections == 0 || connections[0] == '\0') {
1829 buf = connections[0];
1836 /** Ask the user for the name of a new shapshot and then take it.
1839 ARDOUR_UI::snapshot_session ()
1841 ArdourPrompter prompter (true);
1845 struct tm local_time;
1848 localtime_r (&n, &local_time);
1849 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1851 prompter.set_name ("Prompter");
1852 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1853 prompter.set_title (_("Take Snapshot"));
1854 prompter.set_prompt (_("Name of New Snapshot"));
1855 prompter.set_initial_text (timebuf);
1858 switch (prompter.run()) {
1859 case RESPONSE_ACCEPT:
1860 prompter.get_result (snapname);
1861 if (snapname.length()){
1862 if (snapname.find ('/') != string::npos) {
1863 MessageDialog msg (_("To ensure compatibility with various systems\n"
1864 "snapshot names may not contain a '/' character"));
1868 if (snapname.find ('\\') != string::npos) {
1869 MessageDialog msg (_("To ensure compatibility with various systems\n"
1870 "snapshot names may not contain a '\\' character"));
1874 save_state (snapname);
1884 ARDOUR_UI::save_state (const string & name)
1886 (void) save_state_canfail (name);
1890 ARDOUR_UI::save_state_canfail (string name)
1895 if (name.length() == 0) {
1896 name = session->snap_name();
1899 if ((ret = session->save_state (name)) != 0) {
1903 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1908 ARDOUR_UI::primary_clock_value_changed ()
1911 session->request_locate (primary_clock.current_time ());
1916 ARDOUR_UI::big_clock_value_changed ()
1919 session->request_locate (big_clock.current_time ());
1924 ARDOUR_UI::secondary_clock_value_changed ()
1927 session->request_locate (secondary_clock.current_time ());
1932 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1938 switch (session->record_status()) {
1939 case Session::Enabled:
1941 rec_button.set_visual_state (2);
1943 rec_button.set_visual_state (0);
1947 case Session::Recording:
1948 rec_button.set_visual_state (1);
1952 rec_button.set_visual_state (0);
1958 ARDOUR_UI::save_template ()
1960 ArdourPrompter prompter (true);
1963 if (!check_audioengine()) {
1967 prompter.set_name (X_("Prompter"));
1968 prompter.set_title (_("Save Mix Template"));
1969 prompter.set_prompt (_("Name for mix template:"));
1970 prompter.set_initial_text(session->name() + _("-template"));
1971 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1973 switch (prompter.run()) {
1974 case RESPONSE_ACCEPT:
1975 prompter.get_result (name);
1977 if (name.length()) {
1978 session->save_template (name);
1988 ARDOUR_UI::fontconfig_dialog ()
1991 /* this issue seems to have gone away with changes to font handling in GTK/Quartz
1994 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1995 may not and it can take a while to build it. Warn them.
1998 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2000 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2001 MessageDialog msg (*new_session_dialog,
2002 _("Welcome to Ardour.\n\n"
2003 "The program will take a bit longer to start up\n"
2004 "while the system fonts are checked.\n\n"
2005 "This will only be done once, and you will\n"
2006 "not see this message again\n"),
2020 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2022 existing_session = false;
2024 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2025 session_path = cmdline_path;
2026 existing_session = true;
2027 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2028 session_path = Glib::path_get_dirname (string (cmdline_path));
2029 existing_session = true;
2031 /* it doesn't exist, assume the best */
2032 session_path = Glib::path_get_dirname (string (cmdline_path));
2035 session_name = basename_nosuffix (string (cmdline_path));
2039 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2041 /* when this is called, the backend audio system must be running */
2043 /* the main idea here is to deal with the fact that a cmdline argument for the session
2044 can be interpreted in different ways - it could be a directory or a file, and before
2045 we load, we need to know both the session directory and the snapshot (statefile) within it
2046 that we are supposed to use.
2049 if (session_name.length() == 0 || session_path.length() == 0) {
2053 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2055 Glib::ustring predicted_session_file;
2057 predicted_session_file = session_path;
2058 predicted_session_file += '/';
2059 predicted_session_file += session_name;
2060 predicted_session_file += Session::statefile_suffix();
2062 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2063 existing_session = true;
2066 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2068 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2069 /* existing .ardour file */
2070 existing_session = true;
2074 existing_session = false;
2077 /* lets just try to load it */
2079 if (create_engine ()) {
2080 backend_audio_error (false, new_session_dialog);
2084 return load_session (session_path, session_name);
2088 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2090 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2092 MessageDialog msg (str,
2094 Gtk::MESSAGE_WARNING,
2095 Gtk::BUTTONS_YES_NO,
2099 msg.set_name (X_("CleanupDialog"));
2100 msg.set_title (_("Cleanup Unused Sources"));
2101 msg.set_wmclass (X_("existing_session"), "Ardour");
2102 msg.set_position (Gtk::WIN_POS_MOUSE);
2105 switch (msg.run()) {
2114 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2119 AutoConnectOption iconnect;
2120 AutoConnectOption oconnect;
2124 if (Profile->get_sae()) {
2128 iconnect = AutoConnectPhysical;
2129 oconnect = AutoConnectMaster;
2130 nphysin = 0; // use all available
2131 nphysout = 0; // use all available
2135 /* get settings from advanced section of NSD */
2137 if (new_session_dialog->create_control_bus()) {
2138 cchns = (uint32_t) new_session_dialog->control_channel_count();
2143 if (new_session_dialog->create_master_bus()) {
2144 mchns = (uint32_t) new_session_dialog->master_channel_count();
2149 if (new_session_dialog->connect_inputs()) {
2150 iconnect = AutoConnectPhysical;
2152 iconnect = AutoConnectOption (0);
2155 /// @todo some minor tweaks.
2157 if (new_session_dialog->connect_outs_to_master()) {
2158 oconnect = AutoConnectMaster;
2159 } else if (new_session_dialog->connect_outs_to_physical()) {
2160 oconnect = AutoConnectPhysical;
2162 oconnect = AutoConnectOption (0);
2165 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2166 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2169 if (build_session (session_path,
2177 engine->frame_rate() * 60 * 5)) {
2186 ARDOUR_UI::end_loading_messages ()
2192 ARDOUR_UI::loading_message (const std::string& msg)
2195 splash->message (msg);
2200 ARDOUR_UI::idle_load (const Glib::ustring& path)
2203 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2204 /* /path/to/foo => /path/to/foo, foo */
2205 load_session (path, basename_nosuffix (path));
2207 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2208 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2212 ARDOUR_COMMAND_LINE::session_name = path;
2214 if (new_session_dialog) {
2217 /* make it break out of Dialog::run() and
2221 new_session_dialog->response (1);
2227 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2229 bool existing_session = false;
2230 Glib::ustring session_name;
2231 Glib::ustring session_path;
2232 Glib::ustring template_name;
2236 response = Gtk::RESPONSE_NONE;
2238 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2240 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2242 /* don't ever reuse this */
2244 ARDOUR_COMMAND_LINE::session_name = string();
2246 if (existing_session && backend_audio_is_running) {
2248 /* just load the thing already */
2250 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2255 /* make the NSD use whatever information we have */
2257 new_session_dialog->set_session_name (session_name);
2258 new_session_dialog->set_session_folder (session_path);
2261 /* loading failed, or we need the NSD for something */
2263 new_session_dialog->set_modal (false);
2264 new_session_dialog->set_position (WIN_POS_CENTER);
2265 new_session_dialog->set_current_page (0);
2266 new_session_dialog->set_existing_session (existing_session);
2267 new_session_dialog->reset_recent();
2270 new_session_dialog->set_have_engine (backend_audio_is_running);
2271 new_session_dialog->present ();
2272 response = new_session_dialog->run ();
2274 _session_is_new = false;
2276 /* handle possible negative responses */
2280 /* sent by idle_load, meaning restart the whole process again */
2281 new_session_dialog->hide();
2282 new_session_dialog->reset();
2286 case Gtk::RESPONSE_CANCEL:
2287 case Gtk::RESPONSE_DELETE_EVENT:
2289 if (engine && engine->running()) {
2290 engine->stop (true);
2294 new_session_dialog->hide ();
2297 case Gtk::RESPONSE_NONE:
2298 /* "Clear" was pressed */
2302 fontconfig_dialog();
2304 if (!backend_audio_is_running) {
2305 int ret = new_session_dialog->engine_control.setup_engine ();
2308 } else if (ret > 0) {
2309 response = Gtk::RESPONSE_REJECT;
2313 /* hide the NSD while we start up the engine */
2315 new_session_dialog->hide ();
2319 if (create_engine ()) {
2321 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2324 new_session_dialog->set_existing_session (false);
2325 new_session_dialog->set_current_page (0); // new engine page
2326 new_session_dialog->engine_control.unset_interface_chosen ();
2328 response = Gtk::RESPONSE_NONE;
2332 backend_audio_is_running = true;
2334 if (response == Gtk::RESPONSE_OK) {
2336 session_name = new_session_dialog->session_name();
2338 if (session_name.empty()) {
2339 response = Gtk::RESPONSE_NONE;
2343 /* if the user mistakenly typed path information into the session filename entry,
2344 convert what they typed into a path & a name
2347 if (session_name[0] == '/' ||
2348 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2349 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2351 session_path = Glib::path_get_dirname (session_name);
2352 session_name = Glib::path_get_basename (session_name);
2356 session_path = new_session_dialog->session_folder();
2360 template_name = Glib::ustring();
2361 switch (new_session_dialog->which_page()) {
2363 case NewSessionDialog::OpenPage:
2367 case NewSessionDialog::EnginePage:
2368 if (new_session_dialog->engine_control.interface_chosen() && !session_path.empty()) {
2375 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2377 should_be_new = true;
2379 if (session_name.find ('/') != Glib::ustring::npos) {
2380 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2381 "session names may not contain a '/' character"));
2383 response = RESPONSE_NONE;
2387 if (session_name.find ('\\') != Glib::ustring::npos) {
2388 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2389 "session names may not contain a '\\' character"));
2391 response = RESPONSE_NONE;
2395 //XXX This is needed because session constructor wants a
2396 //non-existant path. hopefully this will be fixed at some point.
2398 session_path = Glib::build_filename (session_path, session_name);
2400 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2402 new_session_dialog->hide ();
2404 if (ask_about_loading_existing_session (session_path)) {
2407 response = RESPONSE_NONE;
2412 _session_is_new = true;
2414 if (new_session_dialog->use_session_template()) {
2416 template_name = new_session_dialog->session_template_name();
2420 if (build_session_from_nsd (session_path, session_name)) {
2421 response = RESPONSE_NONE;
2433 new_session_dialog->hide ();
2435 if (load_session (session_path, session_name, template_name)) {
2437 response = Gtk::RESPONSE_NONE;
2441 if (response == Gtk::RESPONSE_NONE) {
2442 new_session_dialog->set_existing_session (false);
2443 new_session_dialog->reset ();
2447 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2451 new_session_dialog->hide();
2452 new_session_dialog->reset();
2453 goto_editor_window ();
2458 ARDOUR_UI::close_session ()
2460 if (!check_audioengine()) {
2464 if (unload_session (true)) {
2468 get_session_parameters (true, false);
2472 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2474 Session *new_session;
2478 session_loaded = false;
2480 if (!check_audioengine()) {
2484 unload_status = unload_session ();
2486 if (unload_status < 0) {
2488 } else if (unload_status > 0) {
2493 loading_message (_("Please wait while Ardour loads your session"));
2496 new_session = new Session (*engine, path, snap_name, mix_template);
2499 /* this one is special */
2501 catch (AudioEngine::PortRegistrationFailure& err) {
2503 MessageDialog msg (err.what(),
2506 Gtk::BUTTONS_CLOSE);
2508 msg.set_title (_("Port Registration Error"));
2509 msg.set_secondary_text (_("Click the Close button to try again."));
2510 msg.set_position (Gtk::WIN_POS_CENTER);
2514 int response = msg.run ();
2519 case RESPONSE_CANCEL:
2527 /* this exception is also special */
2529 catch (Session::SRMismatchRejected& err) {
2530 goto out; /* just go back and reload something else, etc. */
2535 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2538 Gtk::BUTTONS_CLOSE);
2540 msg.set_title (_("Loading Error"));
2541 msg.set_secondary_text (_("Click the Close button to try again."));
2542 msg.set_position (Gtk::WIN_POS_CENTER);
2546 int response = msg.run ();
2551 case RESPONSE_CANCEL:
2559 connect_to_session (new_session);
2561 Config->set_current_owner (ConfigVariableBase::Interface);
2563 session_loaded = true;
2565 goto_editor_window ();
2568 session->set_clean ();
2579 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2580 uint32_t control_channels,
2581 uint32_t master_channels,
2582 AutoConnectOption input_connect,
2583 AutoConnectOption output_connect,
2586 nframes_t initial_length)
2588 Session *new_session;
2591 if (!check_audioengine()) {
2595 session_loaded = false;
2597 x = unload_session ();
2605 _session_is_new = true;
2608 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2609 control_channels, master_channels, nphysin, nphysout, initial_length);
2614 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2620 connect_to_session (new_session);
2622 session_loaded = true;
2624 new_session->save_state(new_session->name());
2633 editor->show_window ();
2644 ARDOUR_UI::show_about ()
2648 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2651 about->set_transient_for(*editor);
2657 ARDOUR_UI::launch_chat ()
2660 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2662 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2667 ARDOUR_UI::hide_about ()
2670 about->get_window()->set_cursor ();
2676 ARDOUR_UI::about_signal_response(int response)
2682 ARDOUR_UI::show_splash ()
2686 splash = new Splash;
2694 splash->queue_draw ();
2695 splash->get_window()->process_updates (true);
2700 ARDOUR_UI::hide_splash ()
2708 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2709 const string& plural_msg, const string& singular_msg)
2713 removed = rep.paths.size();
2716 MessageDialog msgd (*editor,
2717 _("No audio files were ready for cleanup"),
2720 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2721 msgd.set_secondary_text (_("If this seems suprising, \n\
2722 check for any existing snapshots.\n\
2723 These may still include regions that\n\
2724 require some unused files to continue to exist."));
2730 ArdourDialog results (_("ardour: cleanup"), true, false);
2732 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2733 CleanupResultsModelColumns() {
2737 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2738 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2742 CleanupResultsModelColumns results_columns;
2743 Glib::RefPtr<Gtk::ListStore> results_model;
2744 Gtk::TreeView results_display;
2746 results_model = ListStore::create (results_columns);
2747 results_display.set_model (results_model);
2748 results_display.append_column (list_title, results_columns.visible_name);
2750 results_display.set_name ("CleanupResultsList");
2751 results_display.set_headers_visible (true);
2752 results_display.set_headers_clickable (false);
2753 results_display.set_reorderable (false);
2755 Gtk::ScrolledWindow list_scroller;
2758 Gtk::HBox dhbox; // the hbox for the image and text
2759 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2760 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2762 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2766 %1 - number of files removed
2767 %2 - location of "dead_sounds"
2768 %3 - size of files affected
2769 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2772 const char* bprefix;
2773 float space_adjusted;
2775 if (rep.space < 1000000.0f) {
2776 bprefix = X_("kilo");
2777 space_adjusted = truncf((float)rep.space / 1000.0f);
2778 } else if (rep.space < (1000000.0f * 1000)) {
2779 bprefix = X_("mega");
2780 space_adjusted = truncf((float)rep.space / (1000000.0f));
2782 bprefix = X_("giga");
2783 space_adjusted = truncf((float)rep.space / (1000000.0f * 1000));
2787 txt.set_text (string_compose (plural_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2789 txt.set_text (string_compose (singular_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2792 dhbox.pack_start (*dimage, true, false, 5);
2793 dhbox.pack_start (txt, true, false, 5);
2795 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2796 TreeModel::Row row = *(results_model->append());
2797 row[results_columns.visible_name] = *i;
2798 row[results_columns.fullpath] = *i;
2801 list_scroller.add (results_display);
2802 list_scroller.set_size_request (-1, 150);
2803 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2805 dvbox.pack_start (dhbox, true, false, 5);
2806 dvbox.pack_start (list_scroller, true, false, 5);
2807 ddhbox.pack_start (dvbox, true, false, 5);
2809 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2810 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2811 results.set_default_response (RESPONSE_CLOSE);
2812 results.set_position (Gtk::WIN_POS_MOUSE);
2813 results.show_all_children ();
2814 results.set_resizable (false);
2821 ARDOUR_UI::cleanup ()
2824 /* shouldn't happen: menu item is insensitive */
2829 MessageDialog checker (_("Are you sure you want to cleanup?"),
2831 Gtk::MESSAGE_QUESTION,
2832 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2834 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2835 ALL undo/redo information will be lost if you cleanup.\n\
2836 After cleanup, unused audio files will be moved to a \
2837 \"dead sounds\" location."));
2839 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2840 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2841 checker.set_default_response (RESPONSE_CANCEL);
2843 checker.set_name (_("CleanupDialog"));
2844 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2845 checker.set_position (Gtk::WIN_POS_MOUSE);
2847 switch (checker.run()) {
2848 case RESPONSE_ACCEPT:
2854 Session::cleanup_report rep;
2856 editor->prepare_for_cleanup ();
2858 /* do not allow flush until a session is reloaded */
2860 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2862 act->set_sensitive (false);
2865 if (session->cleanup_sources (rep)) {
2866 editor->finish_cleanup ();
2870 editor->finish_cleanup ();
2873 display_cleanup_results (rep,
2876 The following %1 files were not in use and \n\
2877 have been moved to:\n\
2879 Flushing the wastebasket will \n\
2880 release an additional\n\
2881 %3 %4bytes of disk space.\n"),
2883 The following file was not in use and \n \
2884 has been moved to:\n \
2886 Flushing the wastebasket will \n\
2887 release an additional\n\
2888 %3 %4bytes of disk space.\n"
2894 ARDOUR_UI::flush_trash ()
2897 /* shouldn't happen: menu item is insensitive */
2901 Session::cleanup_report rep;
2903 if (session->cleanup_trash_sources (rep)) {
2907 display_cleanup_results (rep,
2909 _("The following %1 files were deleted from\n\
2911 releasing %3 %4bytes of disk space"),
2912 _("The following file was deleted from\n\
2914 releasing %3 %4bytes of disk space"));
2918 ARDOUR_UI::add_route (Gtk::Window* float_window)
2926 if (add_route_dialog == 0) {
2927 add_route_dialog = new AddRouteDialog;
2929 add_route_dialog->set_transient_for (*float_window);
2933 if (add_route_dialog->is_visible()) {
2934 /* we're already doing this */
2938 ResponseType r = (ResponseType) add_route_dialog->run ();
2940 add_route_dialog->hide();
2943 case RESPONSE_ACCEPT:
2950 if ((count = add_route_dialog->count()) <= 0) {
2954 string template_path = add_route_dialog->track_template();
2956 if (!template_path.empty()) {
2957 session->new_route_from_template (count, template_path);
2961 uint32_t input_chan = add_route_dialog->channels ();
2962 uint32_t output_chan;
2963 string name_template = add_route_dialog->name_template ();
2964 bool track = add_route_dialog->track ();
2966 AutoConnectOption oac = Config->get_output_auto_connect();
2968 if (oac & AutoConnectMaster) {
2969 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2971 output_chan = input_chan;
2974 /* XXX do something with name template */
2977 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2979 session_add_audio_bus (input_chan, output_chan, count);
2984 ARDOUR_UI::mixer_settings () const
2989 node = session->instant_xml(X_("Mixer"), session->path());
2991 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2995 node = new XMLNode (X_("Mixer"));
3002 ARDOUR_UI::editor_settings () const
3007 node = session->instant_xml(X_("Editor"), session->path());
3009 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
3013 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3014 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3019 node = new XMLNode (X_("Editor"));
3025 ARDOUR_UI::keyboard_settings () const
3029 node = Config->extra_xml(X_("Keyboard"));
3032 node = new XMLNode (X_("Keyboard"));
3038 ARDOUR_UI::create_xrun_marker(nframes_t where)
3040 editor->mouse_add_new_marker (where, false, true);
3044 ARDOUR_UI::halt_on_xrun_message ()
3046 MessageDialog msg (*editor,
3047 _("Recording was stopped because your system could not keep up."));
3052 ARDOUR_UI::xrun_handler(nframes_t where)
3058 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3060 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3061 create_xrun_marker(where);
3064 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3065 halt_on_xrun_message ();
3070 ARDOUR_UI::preset_file_exists_handler ()
3072 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3075 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3079 HBox* hbox = new HBox();
3080 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3081 Gtk::Dialog dialog (_("Preset Exists"), true, false);
3083 A preset with this name already exists for this plugin.\n\
3085 What you would like to do?\n"));
3086 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3087 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3088 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3089 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3090 dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3091 dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3092 dialog.set_default_response (RESPONSE_ACCEPT);
3093 dialog.set_position (WIN_POS_MOUSE);
3094 dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3100 switch (dialog.run ()) {
3101 case RESPONSE_ACCEPT:
3109 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3114 while (disk_buffer_stats.size() > 60) {
3115 disk_buffer_stats.pop_front ();
3118 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3122 ARDOUR_UI::write_buffer_stats ()
3127 char path[PATH_MAX+1]; int fd;
3129 strcpy (path, "ardourBufferingXXXXXX");
3131 if ((fd = mkstemp (path )) < 0) {
3132 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3140 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3144 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3145 localtime_r (&(*i).when, &tm);
3146 strftime (buf, sizeof (buf), "%T", &tm);
3147 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3150 disk_buffer_stats.clear ();
3154 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3159 ARDOUR_UI::disk_overrun_handler ()
3162 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3164 write_buffer_stats ();
3166 if (!have_disk_speed_dialog_displayed) {
3167 have_disk_speed_dialog_displayed = true;
3168 MessageDialog* msg = new MessageDialog (*editor, _("\
3169 The disk system on your computer\n\
3170 was not able to keep up with Ardour.\n\
3172 Specifically, it failed to write data to disk\n\
3173 quickly enough to keep up with recording.\n"));
3174 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3180 ARDOUR_UI::disk_underrun_handler ()
3183 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3185 write_buffer_stats ();
3187 if (!have_disk_speed_dialog_displayed) {
3188 have_disk_speed_dialog_displayed = true;
3189 MessageDialog* msg = new MessageDialog (*editor,
3190 _("The disk system on your computer\n\
3191 was not able to keep up with Ardour.\n\
3193 Specifically, it failed to read data from disk\n\
3194 quickly enough to keep up with playback.\n"));
3195 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3201 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3203 have_disk_speed_dialog_displayed = false;
3208 ARDOUR_UI::session_dialog (std::string msg)
3210 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3215 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3217 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3226 ARDOUR_UI::pending_state_dialog ()
3228 HBox* hbox = new HBox();
3229 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3230 ArdourDialog dialog (_("Crash Recovery"), true);
3232 This session appears to have been in\n\
3233 middle of recording when ardour or\n\
3234 the computer was shutdown.\n\
3236 Ardour can recover any captured audio for\n\
3237 you, or it can ignore it. Please decide\n\
3238 what you would like to do.\n"));
3239 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3240 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3241 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3242 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3243 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3244 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3245 dialog.set_default_response (RESPONSE_ACCEPT);
3246 dialog.set_position (WIN_POS_CENTER);
3253 switch (dialog.run ()) {
3254 case RESPONSE_ACCEPT:
3262 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3264 HBox* hbox = new HBox();
3265 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3266 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3267 Label message (string_compose (_("\
3268 This session was created with a sample rate of %1 Hz\n\
3270 The audioengine is currently running at %2 Hz\n"), desired, actual));
3272 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3273 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3274 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3275 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3276 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3277 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3278 dialog.set_default_response (RESPONSE_ACCEPT);
3279 dialog.set_position (WIN_POS_CENTER);
3284 switch (dialog.run ()) {
3285 case RESPONSE_ACCEPT:
3294 ARDOUR_UI::disconnect_from_jack ()
3297 if( engine->disconnect_from_jack ()) {
3298 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3302 update_sample_rate (0);
3307 ARDOUR_UI::reconnect_to_jack ()
3310 if (engine->reconnect_to_jack ()) {
3311 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3315 update_sample_rate (0);
3320 ARDOUR_UI::use_config ()
3322 Glib::RefPtr<Action> act;
3324 switch (Config->get_native_file_data_format ()) {
3326 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3329 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3332 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3337 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3338 ract->set_active ();
3341 switch (Config->get_native_file_header_format ()) {
3343 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3346 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3349 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3352 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3355 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3358 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3361 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3366 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3367 ract->set_active ();
3370 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3372 set_transport_controllable_state (*node);
3377 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3379 if (Config->get_primary_clock_delta_edit_cursor()) {
3380 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3382 primary_clock.set (pos, 0, true);
3385 if (Config->get_secondary_clock_delta_edit_cursor()) {
3386 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3388 secondary_clock.set (pos);
3391 if (big_clock_window) {
3392 big_clock.set (pos);
3397 ARDOUR_UI::record_state_changed ()
3399 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3401 if (!session || !big_clock_window) {
3402 /* why bother - the clock isn't visible */
3406 switch (session->record_status()) {
3407 case Session::Recording:
3408 big_clock.set_widget_name ("BigClockRecording");
3411 big_clock.set_widget_name ("BigClockNonRecording");
3417 ARDOUR_UI::first_idle ()
3420 session->allow_auto_play (true);
3424 editor->first_idle();
3427 Keyboard::set_can_save_keybindings (true);
3432 ARDOUR_UI::store_clock_modes ()
3434 XMLNode* node = new XMLNode(X_("ClockModes"));
3436 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3437 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3440 session->add_extra_xml (*node);
3441 session->set_dirty ();
3446 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3447 : Controllable (name), ui (u), type(tp)
3453 ARDOUR_UI::TransportControllable::set_value (float val)
3455 if (type == ShuttleControl) {
3462 fract = -((0.5f - val)/0.5f);
3464 fract = ((val - 0.5f)/0.5f);
3468 ui.set_shuttle_fract (fract);
3473 /* do nothing: these are radio-style actions */
3477 const char *action = 0;
3481 action = X_("Roll");
3484 action = X_("Stop");
3487 action = X_("Goto Start");
3490 action = X_("Goto End");
3493 action = X_("Loop");
3496 action = X_("Play Selection");
3499 action = X_("Record");
3509 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3517 ARDOUR_UI::TransportControllable::get_value (void) const
3536 case ShuttleControl:
3546 ARDOUR_UI::TransportControllable::set_id (const string& str)
3552 ARDOUR_UI::setup_profile ()
3554 if (gdk_screen_width() < 1200) {
3555 Profile->set_small_screen ();
3558 if (getenv ("ARDOUR_SAE")) {
3559 Profile->set_sae ();
3560 Profile->set_single_package ();