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"
87 #include "new_session_dialog.h"
91 #include "gui_thread.h"
92 #include "theme_manager.h"
93 #include "bundle_manager.h"
94 #include "session_metadata_dialog.h"
95 #include "gain_meter.h"
96 #include "route_time_axis.h"
100 using namespace ARDOUR;
102 using namespace Gtkmm2ext;
104 using namespace sigc;
106 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
107 UIConfiguration *ARDOUR_UI::ui_config = 0;
109 sigc::signal<void,bool> ARDOUR_UI::Blink;
110 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
111 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
112 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
114 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
116 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
118 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
119 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
120 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
121 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
125 preroll_button (_("pre\nroll")),
126 postroll_button (_("post\nroll")),
130 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
134 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
135 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
136 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
137 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
138 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
139 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
140 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
141 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
142 shuttle_controller_binding_proxy (shuttle_controllable),
144 roll_button (roll_controllable),
145 stop_button (stop_controllable),
146 goto_start_button (goto_start_controllable),
147 goto_end_button (goto_end_controllable),
148 auto_loop_button (auto_loop_controllable),
149 play_selection_button (play_selection_controllable),
150 rec_button (rec_controllable),
152 shuttle_units_button (_("% ")),
154 punch_in_button (_("Punch In")),
155 punch_out_button (_("Punch Out")),
156 auto_return_button (_("Auto Return")),
157 auto_play_button (_("Auto Play")),
158 auto_input_button (_("Auto Input")),
159 click_button (_("Click")),
160 time_master_button (_("time\nmaster")),
162 auditioning_alert_button (_("AUDITION")),
163 solo_alert_button (_("SOLO")),
165 error_log_button (_("Errors"))
168 using namespace Gtk::Menu_Helpers;
174 _auto_display_errors = false;
180 if (ARDOUR_COMMAND_LINE::session_name.length()) {
181 /* only show this if we're not going to post the new session dialog */
185 if (theArdourUI == 0) {
189 ui_config = new UIConfiguration();
190 theme_manager = new ThemeManager();
197 _session_is_new = false;
198 big_clock_window = 0;
199 session_selector_window = 0;
200 last_key_press_time = 0;
201 connection_editor = 0;
202 _will_create_new_session_automatically = false;
203 new_session_dialog = 0;
204 add_route_dialog = 0;
208 open_session_selector = 0;
209 have_configure_timeout = false;
210 have_disk_speed_dialog_displayed = false;
211 session_loaded = false;
212 last_speed_displayed = -1.0f;
213 ignore_dual_punch = false;
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 /* handle dialog requests */
233 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
235 /* handle pending state with a dialog */
237 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
239 /* handle sr mismatch with a dialog */
241 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
243 /* lets get this party started */
246 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
247 throw failed_constructor ();
250 setup_gtk_ardour_enums ();
251 Config->set_current_owner (ConfigVariableBase::Interface);
254 GainMeter::setup_slider_pix ();
255 RouteTimeAxisView::setup_slider_pix ();
257 } catch (failed_constructor& err) {
258 error << _("could not initialize Ardour.") << endmsg;
263 /* we like keyboards */
265 keyboard = new Keyboard;
269 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
270 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
276 ARDOUR_UI::create_engine ()
278 // this gets called every time by new_session()
284 loading_message (_("Starting audio engine"));
287 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
294 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
295 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
296 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
297 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
305 ARDOUR_UI::post_engine ()
307 /* Things to be done once we create the AudioEngine
310 MIDI::Manager::instance()->set_api_data (engine->jack());
313 ActionManager::init ();
316 if (setup_windows ()) {
317 throw failed_constructor ();
320 check_memory_locking();
322 /* this is the first point at which all the keybindings are available */
324 if (ARDOUR_COMMAND_LINE::show_key_actions) {
325 vector<string> names;
326 vector<string> paths;
328 vector<AccelKey> bindings;
330 ActionManager::get_all_actions (names, paths, keys, bindings);
332 vector<string>::iterator n;
333 vector<string>::iterator k;
334 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
335 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
341 blink_timeout_tag = -1;
343 /* the global configuration object is now valid */
347 /* this being a GUI and all, we want peakfiles */
349 AudioFileSource::set_build_peakfiles (true);
350 AudioFileSource::set_build_missing_peakfiles (true);
352 /* set default clock modes */
354 if (Profile->get_sae()) {
355 primary_clock.set_mode (AudioClock::MinSec);
357 primary_clock.set_mode (AudioClock::SMPTE);
359 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 /* now start and maybe save state */
375 if (do_engine_start () == 0) {
376 if (session && _session_is_new) {
377 /* we need to retain initial visual
378 settings for a new session
380 session->save_state ("");
385 ARDOUR_UI::~ARDOUR_UI ()
387 save_ardour_state ();
401 if (add_route_dialog) {
402 delete add_route_dialog;
406 if (new_session_dialog) {
407 delete new_session_dialog;
412 ARDOUR_UI::pop_back_splash ()
414 if (Splash::instance()) {
415 // Splash::instance()->pop_back();
416 Splash::instance()->hide ();
421 ARDOUR_UI::configure_timeout ()
423 if (last_configure_time == 0) {
424 /* no configure events yet */
428 /* force a gap of 0.5 seconds since the last configure event
431 if (get_microseconds() - last_configure_time < 500000) {
434 have_configure_timeout = false;
435 save_ardour_state ();
441 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
443 if (have_configure_timeout) {
444 last_configure_time = get_microseconds();
446 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
447 have_configure_timeout = true;
454 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
456 const XMLProperty* prop;
458 if ((prop = node.property ("roll")) != 0) {
459 roll_controllable->set_id (prop->value());
461 if ((prop = node.property ("stop")) != 0) {
462 stop_controllable->set_id (prop->value());
464 if ((prop = node.property ("goto-start")) != 0) {
465 goto_start_controllable->set_id (prop->value());
467 if ((prop = node.property ("goto-end")) != 0) {
468 goto_end_controllable->set_id (prop->value());
470 if ((prop = node.property ("auto-loop")) != 0) {
471 auto_loop_controllable->set_id (prop->value());
473 if ((prop = node.property ("play-selection")) != 0) {
474 play_selection_controllable->set_id (prop->value());
476 if ((prop = node.property ("rec")) != 0) {
477 rec_controllable->set_id (prop->value());
479 if ((prop = node.property ("shuttle")) != 0) {
480 shuttle_controllable->set_id (prop->value());
485 ARDOUR_UI::get_transport_controllable_state ()
487 XMLNode* node = new XMLNode(X_("TransportControllables"));
490 roll_controllable->id().print (buf, sizeof (buf));
491 node->add_property (X_("roll"), buf);
492 stop_controllable->id().print (buf, sizeof (buf));
493 node->add_property (X_("stop"), buf);
494 goto_start_controllable->id().print (buf, sizeof (buf));
495 node->add_property (X_("goto_start"), buf);
496 goto_end_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("goto_end"), buf);
498 auto_loop_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("auto_loop"), buf);
500 play_selection_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("play_selection"), buf);
502 rec_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("rec"), buf);
504 shuttle_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("shuttle"), buf);
511 ARDOUR_UI::save_ardour_state ()
513 if (!keyboard || !mixer || !editor) {
517 /* XXX this is all a bit dubious. add_extra_xml() uses
518 a different lifetime model from add_instant_xml().
521 XMLNode* node = new XMLNode (keyboard->get_state());
522 Config->add_extra_xml (*node);
523 Config->add_extra_xml (get_transport_controllable_state());
524 if (new_session_dialog && new_session_dialog->engine_control.was_used()) {
525 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
527 Config->save_state();
528 ui_config->save_state ();
530 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
531 XMLNode mnode(mixer->get_state());
534 session->add_instant_xml (enode);
535 session->add_instant_xml (mnode);
537 Config->add_instant_xml (enode);
538 Config->add_instant_xml (mnode);
541 Keyboard::save_keybindings ();
545 ARDOUR_UI::autosave_session ()
547 if (g_main_depth() > 1) {
548 /* inside a recursive main loop,
549 give up because we may not be able to
555 if (!Config->get_periodic_safety_backups()) {
560 session->maybe_write_autosave();
567 ARDOUR_UI::update_autosave ()
569 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
571 if (session->dirty()) {
572 if (_autosave_connection.connected()) {
573 _autosave_connection.disconnect();
576 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
577 Config->get_periodic_safety_backup_interval() * 1000);
580 if (_autosave_connection.connected()) {
581 _autosave_connection.disconnect();
587 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
591 title = _("Ardour could not start JACK");
593 title = _("Ardour could not connect to JACK.");
596 MessageDialog win (title,
602 win.set_secondary_text(_("There are several possible reasons:\n\
604 1) You requested audio parameters that are not supported..\n\
605 2) JACK is running as another user.\n\
607 Please consider the possibilities, and perhaps try different parameters."));
609 win.set_secondary_text(_("There are several possible reasons:\n\
611 1) JACK is not running.\n\
612 2) JACK is running as another user, perhaps root.\n\
613 3) There is already another client called \"ardour\".\n\
615 Please consider the possibilities, and perhaps (re)start JACK."));
619 win.set_transient_for (*toplevel);
623 win.add_button (Stock::OK, RESPONSE_CLOSE);
625 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
628 win.set_default_response (RESPONSE_CLOSE);
631 win.set_position (Gtk::WIN_POS_CENTER);
634 /* we just don't care about the result, but we want to block */
640 ARDOUR_UI::startup ()
644 new_session_dialog = new NewSessionDialog();
646 bool backend_audio_is_running = EngineControl::engine_running();
647 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
650 new_session_dialog->engine_control.set_state (*audio_setup);
653 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
657 BootMessage (_("Ardour is ready for use"));
662 ARDOUR_UI::no_memory_warning ()
664 XMLNode node (X_("no-memory-warning"));
665 Config->add_instant_xml (node);
669 ARDOUR_UI::check_memory_locking ()
672 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
676 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
678 if (engine->is_realtime() && memory_warning_node == 0) {
680 struct rlimit limits;
682 long pages, page_size;
684 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
687 ram = (int64_t) pages * (int64_t) page_size;
690 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
694 if (limits.rlim_cur != RLIM_INFINITY) {
696 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
699 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
700 "This might cause Ardour to run out of memory before your system "
701 "runs out of memory. \n\n"
702 "You can view the memory limit with 'ulimit -l', "
703 "and it is normally controlled by /etc/security/limits.conf"));
705 VBox* vbox = msg.get_vbox();
707 CheckButton cb (_("Do not show this window again"));
709 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
711 hbox.pack_start (cb, true, false);
712 vbox->pack_start (hbox);
719 editor->ensure_float (msg);
733 if (session->transport_rolling()) {
734 session->request_stop ();
738 if (session->dirty()) {
739 switch (ask_about_saving_session(_("quit"))) {
744 /* use the default name */
745 if (save_state_canfail ("")) {
746 /* failed - don't quit */
747 MessageDialog msg (*editor,
749 Ardour was unable to save your session.\n\n\
750 If you still wish to quit, please use the\n\n\
751 \"Just quit\" option."));
762 session->set_deletion_in_progress ();
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);
808 dhbox.set_homogeneous (false);
809 dhbox.pack_start (*dimage, false, false, 5);
810 dhbox.pack_start (prompt_label, true, false, 5);
811 window.get_vbox()->pack_start (dhbox);
813 window.set_name (_("Prompter"));
814 window.set_position (Gtk::WIN_POS_MOUSE);
815 window.set_modal (true);
816 window.set_resizable (false);
822 window.set_keep_above (true);
825 ResponseType r = (ResponseType) window.run();
830 case RESPONSE_ACCEPT: // save and get out of here
832 case RESPONSE_APPLY: // get out of here
842 ARDOUR_UI::every_second ()
845 update_buffer_load ();
846 update_disk_space ();
851 ARDOUR_UI::every_point_one_seconds ()
853 update_speed_display ();
854 RapidScreenUpdate(); /* EMIT_SIGNAL */
859 ARDOUR_UI::every_point_zero_one_seconds ()
861 // august 2007: actual update frequency: 40Hz, not 100Hz
863 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::update_sample_rate (nframes_t ignored)
872 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
874 if (!engine->connected()) {
876 snprintf (buf, sizeof (buf), _("disconnected"));
880 nframes_t rate = engine->frame_rate();
882 if (fmod (rate, 1000.0) != 0.0) {
883 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
884 (float) rate/1000.0f,
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
887 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
893 sample_rate_label.set_text (buf);
897 ARDOUR_UI::update_cpu_load ()
900 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
901 cpu_load_label.set_text (buf);
905 ARDOUR_UI::update_buffer_load ()
910 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
911 session->playback_load(), session->capture_load());
912 buffer_load_label.set_text (buf);
914 buffer_load_label.set_text ("");
919 ARDOUR_UI::count_recenabled_streams (Route& route)
921 Track* track = dynamic_cast<Track*>(&route);
922 if (track && track->diskstream()->record_enabled()) {
923 rec_enabled_streams += track->n_inputs().n_total();
928 ARDOUR_UI::update_disk_space()
934 nframes_t frames = session->available_capture_duration();
936 nframes_t fr = session->frame_rate();
938 if (frames == max_frames) {
939 strcpy (buf, _("Disk: 24hrs+"));
941 rec_enabled_streams = 0;
942 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
944 if (rec_enabled_streams) {
945 frames /= rec_enabled_streams;
952 hrs = frames / (fr * 3600);
953 frames -= hrs * fr * 3600;
954 mins = frames / (fr * 60);
955 frames -= mins * fr * 60;
958 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
961 disk_space_label.set_text (buf);
963 // An attempt to make the disk space label flash red when space has run out.
965 if (frames < fr * 60 * 5) {
966 /* disk_space_box.style ("disk_space_label_empty"); */
968 /* disk_space_box.style ("disk_space_label"); */
974 ARDOUR_UI::update_wall_clock ()
981 tm_now = localtime (&now);
983 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
984 wall_clock_label.set_text (buf);
990 ARDOUR_UI::session_menu (GdkEventButton *ev)
992 session_popup_menu->popup (0, 0);
997 ARDOUR_UI::redisplay_recent_sessions ()
999 std::vector<sys::path> session_directories;
1000 RecentSessionsSorter cmp;
1002 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1003 recent_session_model->clear ();
1005 ARDOUR::RecentSessions rs;
1006 ARDOUR::read_recent_sessions (rs);
1009 recent_session_display.set_model (recent_session_model);
1013 // sort them alphabetically
1014 sort (rs.begin(), rs.end(), cmp);
1016 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1017 session_directories.push_back ((*i).second);
1020 for (vector<sys::path>::const_iterator i = session_directories.begin();
1021 i != session_directories.end(); ++i)
1023 std::vector<sys::path> state_file_paths;
1025 // now get available states for this session
1027 get_state_files_in_directory (*i, state_file_paths);
1029 vector<string*>* states;
1030 vector<const gchar*> item;
1031 string fullpath = (*i).to_string();
1033 /* remove any trailing / */
1035 if (fullpath[fullpath.length()-1] == '/') {
1036 fullpath = fullpath.substr (0, fullpath.length()-1);
1039 /* check whether session still exists */
1040 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1041 /* session doesn't exist */
1042 cerr << "skipping non-existent session " << fullpath << endl;
1046 /* now get available states for this session */
1048 if ((states = Session::possible_states (fullpath)) == 0) {
1049 /* no state file? */
1053 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1055 Gtk::TreeModel::Row row = *(recent_session_model->append());
1057 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1058 row[recent_session_columns.fullpath] = fullpath;
1060 if (state_file_names.size() > 1) {
1064 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1065 i2 != state_file_names.end(); ++i2)
1068 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1070 child_row[recent_session_columns.visible_name] = *i2;
1071 child_row[recent_session_columns.fullpath] = fullpath;
1076 recent_session_display.set_model (recent_session_model);
1080 ARDOUR_UI::build_session_selector ()
1082 session_selector_window = new ArdourDialog ("session selector");
1084 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1086 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1087 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1088 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1089 recent_session_model = TreeStore::create (recent_session_columns);
1090 recent_session_display.set_model (recent_session_model);
1091 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1092 recent_session_display.set_headers_visible (false);
1093 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1094 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1096 scroller->add (recent_session_display);
1097 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1099 session_selector_window->set_name ("SessionSelectorWindow");
1100 session_selector_window->set_size_request (200, 400);
1101 session_selector_window->get_vbox()->pack_start (*scroller);
1103 recent_session_display.show();
1105 //session_selector_window->get_vbox()->show();
1109 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1111 session_selector_window->response (RESPONSE_ACCEPT);
1115 ARDOUR_UI::open_recent_session ()
1117 bool can_return = (session != 0);
1119 if (session_selector_window == 0) {
1120 build_session_selector ();
1123 redisplay_recent_sessions ();
1127 session_selector_window->set_position (WIN_POS_MOUSE);
1129 ResponseType r = (ResponseType) session_selector_window->run ();
1132 case RESPONSE_ACCEPT:
1136 session_selector_window->hide();
1143 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1147 session_selector_window->hide();
1149 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1151 if (i == recent_session_model->children().end()) {
1155 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1156 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1158 _session_is_new = false;
1160 if (load_session (path, state) == 0) {
1169 ARDOUR_UI::check_audioengine ()
1172 if (!engine->connected()) {
1173 MessageDialog msg (_("Ardour is not connected to JACK\n"
1174 "You cannot open or close sessions in this condition"));
1186 ARDOUR_UI::open_session ()
1188 if (!check_audioengine()) {
1193 /* popup selector window */
1195 if (open_session_selector == 0) {
1197 /* ardour sessions are folders */
1199 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1200 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1201 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1202 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1204 FileFilter session_filter;
1205 session_filter.add_pattern ("*.ardour");
1206 session_filter.set_name (_("Ardour sessions"));
1207 open_session_selector->add_filter (session_filter);
1208 open_session_selector->set_filter (session_filter);
1211 int response = open_session_selector->run();
1212 open_session_selector->hide ();
1215 case RESPONSE_ACCEPT:
1218 open_session_selector->hide();
1222 open_session_selector->hide();
1223 string session_path = open_session_selector->get_filename();
1227 if (session_path.length() > 0) {
1228 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1229 _session_is_new = isnew;
1230 load_session (path, name);
1237 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1239 list<boost::shared_ptr<MidiTrack> > tracks;
1242 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1249 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1251 if (tracks.size() != how_many) {
1252 if (how_many == 1) {
1253 error << _("could not create a new midi track") << endmsg;
1255 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1259 if ((route = session->new_midi_route ()) == 0) {
1260 error << _("could not create new midi bus") << endmsg;
1266 MessageDialog msg (*editor,
1267 _("There are insufficient JACK ports available\n\
1268 to create a new track or bus.\n\
1269 You should save Ardour, exit and\n\
1270 restart JACK with more ports."));
1277 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1279 list<boost::shared_ptr<AudioTrack> > tracks;
1280 Session::RouteList routes;
1283 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1289 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1291 if (tracks.size() != how_many) {
1292 if (how_many == 1) {
1293 error << _("could not create a new audio track") << endmsg;
1295 error << string_compose (_("could only create %1 of %2 new audio %3"),
1296 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1302 routes = session->new_audio_route (input_channels, output_channels, how_many);
1304 if (routes.size() != how_many) {
1305 if (how_many == 1) {
1306 error << _("could not create a new audio track") << endmsg;
1308 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1314 if (need_control_room_outs) {
1320 route->set_stereo_control_outs (control_lr_channels);
1321 route->control_outs()->set_stereo_pan (pans, this);
1323 #endif /* CONTROLOUTS */
1327 MessageDialog msg (*editor,
1328 _("There are insufficient JACK ports available\n\
1329 to create a new track or bus.\n\
1330 You should save Ardour, exit and\n\
1331 restart JACK with more ports."));
1338 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1340 nframes_t _preroll = 0;
1343 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1344 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1346 if (new_position > _preroll) {
1347 new_position -= _preroll;
1352 session->request_locate (new_position);
1357 ARDOUR_UI::transport_goto_start ()
1360 session->goto_start();
1363 /* force displayed area in editor to start no matter
1364 what "follow playhead" setting is.
1368 editor->reset_x_origin (session->current_start_frame());
1374 ARDOUR_UI::transport_goto_zero ()
1377 session->request_locate (0);
1380 /* force displayed area in editor to start no matter
1381 what "follow playhead" setting is.
1385 editor->reset_x_origin (0);
1391 ARDOUR_UI::transport_goto_wallclock ()
1393 if (session && editor) {
1400 localtime_r (&now, &tmnow);
1402 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1403 frames += tmnow.tm_min * (60 * session->frame_rate());
1404 frames += tmnow.tm_sec * session->frame_rate();
1406 session->request_locate (frames);
1408 /* force displayed area in editor to start no matter
1409 what "follow playhead" setting is.
1413 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1419 ARDOUR_UI::transport_goto_end ()
1422 nframes_t frame = session->current_end_frame();
1423 session->request_locate (frame);
1425 /* force displayed area in editor to start no matter
1426 what "follow playhead" setting is.
1430 editor->reset_x_origin (frame);
1436 ARDOUR_UI::transport_stop ()
1442 if (session->is_auditioning()) {
1443 session->cancel_audition ();
1447 if (session->get_play_loop ()) {
1448 session->request_play_loop (false);
1451 session->request_stop ();
1455 ARDOUR_UI::transport_stop_and_forget_capture ()
1458 session->request_stop (true);
1463 ARDOUR_UI::remove_last_capture()
1466 editor->remove_last_capture();
1471 ARDOUR_UI::transport_record (bool roll)
1475 switch (session->record_status()) {
1476 case Session::Disabled:
1477 if (session->ntracks() == 0) {
1478 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1482 session->maybe_enable_record ();
1487 case Session::Recording:
1489 session->request_stop();
1491 session->disable_record (false, true);
1495 case Session::Enabled:
1496 session->disable_record (false, true);
1499 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1503 ARDOUR_UI::transport_roll ()
1511 rolling = session->transport_rolling ();
1513 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1515 if (session->get_play_loop()) {
1516 session->request_play_loop (false);
1517 auto_loop_button.set_visual_state (1);
1518 roll_button.set_visual_state (1);
1519 } else if (session->get_play_range ()) {
1520 session->request_play_range (false);
1521 play_selection_button.set_visual_state (0);
1522 } else if (rolling) {
1523 session->request_locate (session->last_transport_start(), true);
1526 session->request_transport_speed (1.0f);
1530 ARDOUR_UI::transport_loop()
1533 if (session->get_play_loop()) {
1534 if (session->transport_rolling()) {
1535 Location * looploc = session->locations()->auto_loop_location();
1537 session->request_locate (looploc->start(), true);
1542 session->request_play_loop (true);
1548 ARDOUR_UI::transport_play_selection ()
1554 if (!session->get_play_range()) {
1555 session->request_stop ();
1558 editor->play_selection ();
1562 ARDOUR_UI::transport_rewind (int option)
1564 float current_transport_speed;
1567 current_transport_speed = session->transport_speed();
1569 if (current_transport_speed >= 0.0f) {
1572 session->request_transport_speed (-1.0f);
1575 session->request_transport_speed (-4.0f);
1578 session->request_transport_speed (-0.5f);
1583 session->request_transport_speed (current_transport_speed * 1.5f);
1589 ARDOUR_UI::transport_forward (int option)
1591 float current_transport_speed;
1594 current_transport_speed = session->transport_speed();
1596 if (current_transport_speed <= 0.0f) {
1599 session->request_transport_speed (1.0f);
1602 session->request_transport_speed (4.0f);
1605 session->request_transport_speed (0.5f);
1610 session->request_transport_speed (current_transport_speed * 1.5f);
1616 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1622 boost::shared_ptr<Route> r;
1624 if ((r = session->route_by_remote_id (dstream)) != 0) {
1628 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1629 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1638 ARDOUR_UI::queue_transport_change ()
1640 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1644 ARDOUR_UI::map_transport_state ()
1646 float sp = session->transport_speed();
1649 transport_rolling ();
1650 } else if (sp < 0.0f) {
1651 transport_rewinding ();
1652 } else if (sp > 0.0f) {
1653 transport_forwarding ();
1655 transport_stopped ();
1660 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1662 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1663 (int) adj.get_value()].c_str());
1667 ARDOUR_UI::engine_stopped ()
1669 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1670 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1671 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1675 ARDOUR_UI::engine_running ()
1677 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1678 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1679 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1681 Glib::RefPtr<Action> action;
1682 const char* action_name = 0;
1684 switch (engine->frames_per_cycle()) {
1686 action_name = X_("JACKLatency32");
1689 action_name = X_("JACKLatency64");
1692 action_name = X_("JACKLatency128");
1695 action_name = X_("JACKLatency512");
1698 action_name = X_("JACKLatency1024");
1701 action_name = X_("JACKLatency2048");
1704 action_name = X_("JACKLatency4096");
1707 action_name = X_("JACKLatency8192");
1710 /* XXX can we do anything useful ? */
1716 action = ActionManager::get_action (X_("JACK"), action_name);
1719 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1720 ract->set_active ();
1726 ARDOUR_UI::engine_halted ()
1728 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1730 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1731 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1733 update_sample_rate (0);
1735 MessageDialog msg (*editor,
1737 JACK has either been shutdown or it\n\
1738 disconnected Ardour because Ardour\n\
1739 was not fast enough. You can save the\n\
1740 session and/or try to reconnect to JACK ."));
1746 ARDOUR_UI::do_engine_start ()
1754 error << _("Unable to start the session running")
1764 ARDOUR_UI::setup_theme ()
1766 theme_manager->setup_theme();
1770 ARDOUR_UI::update_clocks ()
1772 if (!editor || !editor->dragging_playhead()) {
1773 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1778 ARDOUR_UI::start_clocking ()
1780 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1784 ARDOUR_UI::stop_clocking ()
1786 clock_signal_connection.disconnect ();
1790 ARDOUR_UI::toggle_clocking ()
1793 if (clock_button.get_active()) {
1802 ARDOUR_UI::_blink (void *arg)
1805 ((ARDOUR_UI *) arg)->blink ();
1812 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1816 ARDOUR_UI::start_blinking ()
1818 /* Start the blink signal. Everybody with a blinking widget
1819 uses Blink to drive the widget's state.
1822 if (blink_timeout_tag < 0) {
1824 blink_timeout_tag = g_timeout_add (240, _blink, this);
1829 ARDOUR_UI::stop_blinking ()
1831 if (blink_timeout_tag >= 0) {
1832 g_source_remove (blink_timeout_tag);
1833 blink_timeout_tag = -1;
1838 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1843 vector<string> connections;
1846 if (io.n_inputs().n_total() == 0) {
1851 /* XXX we're not handling multiple ports yet. */
1853 if (io.input(0)->get_connections(connections) == 0) {
1856 buf = connections.front();
1861 if (io.n_outputs().n_total() == 0) {
1866 /* XXX we're not handling multiple ports yet. */
1868 if (io.output(0)->get_connections(connections) == 0) {
1871 buf = connections.front();
1876 /** Ask the user for the name of a new shapshot and then take it.
1879 ARDOUR_UI::snapshot_session ()
1881 ArdourPrompter prompter (true);
1885 struct tm local_time;
1888 localtime_r (&n, &local_time);
1889 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1891 prompter.set_name ("Prompter");
1892 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1893 prompter.set_prompt (_("Name of New Snapshot"));
1894 prompter.set_initial_text (timebuf);
1896 switch (prompter.run()) {
1897 case RESPONSE_ACCEPT:
1898 prompter.get_result (snapname);
1899 if (snapname.length()){
1900 save_state (snapname);
1910 ARDOUR_UI::save_state (const string & name)
1912 (void) save_state_canfail (name);
1916 ARDOUR_UI::save_state_canfail (string name)
1921 if (name.length() == 0) {
1922 name = session->snap_name();
1925 if ((ret = session->save_state (name)) != 0) {
1929 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1934 ARDOUR_UI::primary_clock_value_changed ()
1937 session->request_locate (primary_clock.current_time ());
1942 ARDOUR_UI::big_clock_value_changed ()
1945 session->request_locate (big_clock.current_time ());
1950 ARDOUR_UI::secondary_clock_value_changed ()
1953 session->request_locate (secondary_clock.current_time ());
1958 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1964 switch (session->record_status()) {
1965 case Session::Enabled:
1967 rec_button.set_visual_state (2);
1969 rec_button.set_visual_state (0);
1973 case Session::Recording:
1974 rec_button.set_visual_state (1);
1978 rec_button.set_visual_state (0);
1984 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1992 ARDOUR_UI::save_template ()
1995 ArdourPrompter prompter (true);
1998 if (!check_audioengine()) {
2002 prompter.set_name (X_("Prompter"));
2003 prompter.set_prompt (_("Name for mix template:"));
2004 prompter.set_initial_text(session->name() + _("-template"));
2005 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2007 switch (prompter.run()) {
2008 case RESPONSE_ACCEPT:
2009 prompter.get_result (name);
2011 if (name.length()) {
2012 session->save_template (name);
2022 ARDOUR_UI::edit_metadata ()
2024 SessionMetadataEditor dialog;
2025 dialog.set_session (session);
2026 editor->ensure_float (dialog);
2031 ARDOUR_UI::import_metadata ()
2033 SessionMetadataImporter dialog;
2034 dialog.set_session (session);
2035 editor->ensure_float (dialog);
2040 ARDOUR_UI::fontconfig_dialog ()
2043 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2044 may not and it can take a while to build it. Warn them.
2047 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2049 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2050 MessageDialog msg (*new_session_dialog,
2051 _("Welcome to Ardour.\n\n"
2052 "The program will take a bit longer to start up\n"
2053 "while the system fonts are checked.\n\n"
2054 "This will only be done once, and you will\n"
2055 "not see this message again\n"),
2068 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2070 existing_session = false;
2072 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2073 session_path = cmdline_path;
2074 existing_session = true;
2075 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2076 session_path = Glib::path_get_dirname (string (cmdline_path));
2077 existing_session = true;
2079 /* it doesn't exist, assume the best */
2080 session_path = Glib::path_get_dirname (string (cmdline_path));
2083 session_name = basename_nosuffix (string (cmdline_path));
2087 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2089 /* when this is called, the backend audio system must be running */
2091 /* the main idea here is to deal with the fact that a cmdline argument for the session
2092 can be interpreted in different ways - it could be a directory or a file, and before
2093 we load, we need to know both the session directory and the snapshot (statefile) within it
2094 that we are supposed to use.
2097 if (session_name.length() == 0 || session_path.length() == 0) {
2101 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2103 Glib::ustring predicted_session_file;
2105 predicted_session_file = session_path;
2106 predicted_session_file += '/';
2107 predicted_session_file += session_name;
2108 predicted_session_file += ARDOUR::statefile_suffix;
2110 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2111 existing_session = true;
2114 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2116 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2117 /* existing .ardour file */
2118 existing_session = true;
2122 existing_session = false;
2125 /* lets just try to load it */
2127 if (create_engine ()) {
2128 backend_audio_error (false, new_session_dialog);
2132 return load_session (session_path, session_name);
2136 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2138 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2140 MessageDialog msg (str,
2142 Gtk::MESSAGE_WARNING,
2143 Gtk::BUTTONS_YES_NO,
2147 msg.set_name (X_("CleanupDialog"));
2148 msg.set_wmclass (X_("existing_session"), "Ardour");
2149 msg.set_position (Gtk::WIN_POS_MOUSE);
2152 switch (msg.run()) {
2161 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2166 AutoConnectOption iconnect;
2167 AutoConnectOption oconnect;
2171 if (Profile->get_sae()) {
2175 iconnect = AutoConnectPhysical;
2176 oconnect = AutoConnectMaster;
2177 nphysin = 0; // use all available
2178 nphysout = 0; // use all available
2182 /* get settings from advanced section of NSD */
2184 if (new_session_dialog->create_control_bus()) {
2185 cchns = (uint32_t) new_session_dialog->control_channel_count();
2190 if (new_session_dialog->create_master_bus()) {
2191 mchns = (uint32_t) new_session_dialog->master_channel_count();
2196 if (new_session_dialog->connect_inputs()) {
2197 iconnect = AutoConnectPhysical;
2199 iconnect = AutoConnectOption (0);
2202 /// @todo some minor tweaks.
2204 if (new_session_dialog->connect_outs_to_master()) {
2205 oconnect = AutoConnectMaster;
2206 } else if (new_session_dialog->connect_outs_to_physical()) {
2207 oconnect = AutoConnectPhysical;
2209 oconnect = AutoConnectOption (0);
2212 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2213 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2216 if (build_session (session_path,
2224 engine->frame_rate() * 60 * 5)) {
2233 ARDOUR_UI::end_loading_messages ()
2239 ARDOUR_UI::loading_message (const std::string& msg)
2242 splash->message (msg);
2247 ARDOUR_UI::idle_load (const Glib::ustring& path)
2250 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2251 /* /path/to/foo => /path/to/foo, foo */
2252 load_session (path, basename_nosuffix (path));
2254 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2255 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2258 ARDOUR_COMMAND_LINE::session_name = path;
2259 if (new_session_dialog) {
2260 /* make it break out of Dialog::run() and
2263 new_session_dialog->response (1);
2269 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2271 bool existing_session = false;
2272 Glib::ustring session_name;
2273 Glib::ustring session_path;
2274 Glib::ustring template_name;
2278 response = Gtk::RESPONSE_NONE;
2280 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2282 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2284 /* don't ever reuse this */
2286 ARDOUR_COMMAND_LINE::session_name = string();
2288 if (existing_session && backend_audio_is_running) {
2290 /* just load the thing already */
2292 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2297 /* make the NSD use whatever information we have */
2299 new_session_dialog->set_session_name (session_name);
2300 new_session_dialog->set_session_folder (session_path);
2303 /* loading failed, or we need the NSD for something */
2305 new_session_dialog->set_modal (false);
2306 new_session_dialog->set_position (WIN_POS_CENTER);
2307 new_session_dialog->set_current_page (0);
2308 new_session_dialog->set_existing_session (existing_session);
2309 new_session_dialog->reset_recent();
2312 new_session_dialog->set_have_engine (backend_audio_is_running);
2313 new_session_dialog->present ();
2314 end_loading_messages ();
2315 response = new_session_dialog->run ();
2317 _session_is_new = false;
2319 /* handle possible negative responses */
2323 /* sent by idle_load, meaning restart the whole process again */
2324 new_session_dialog->hide();
2325 new_session_dialog->reset();
2329 case Gtk::RESPONSE_CANCEL:
2330 case Gtk::RESPONSE_DELETE_EVENT:
2334 new_session_dialog->hide ();
2337 case Gtk::RESPONSE_NONE:
2338 /* "Clear" was pressed */
2342 fontconfig_dialog();
2344 if (!backend_audio_is_running) {
2345 int ret = new_session_dialog->engine_control.setup_engine ();
2348 } else if (ret > 0) {
2349 response = Gtk::RESPONSE_REJECT;
2354 if (create_engine ()) {
2356 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2359 new_session_dialog->set_existing_session (false);
2360 new_session_dialog->set_current_page (2);
2362 response = Gtk::RESPONSE_NONE;
2366 backend_audio_is_running = true;
2368 if (response == Gtk::RESPONSE_OK) {
2370 session_name = new_session_dialog->session_name();
2372 if (session_name.empty()) {
2373 response = Gtk::RESPONSE_NONE;
2377 /* if the user mistakenly typed path information into the session filename entry,
2378 convert what they typed into a path & a name
2381 if (session_name[0] == '/' ||
2382 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2383 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2385 session_path = Glib::path_get_dirname (session_name);
2386 session_name = Glib::path_get_basename (session_name);
2390 session_path = new_session_dialog->session_folder();
2393 template_name = Glib::ustring();
2394 switch (new_session_dialog->which_page()) {
2396 case NewSessionDialog::OpenPage:
2397 case NewSessionDialog::EnginePage:
2401 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2403 should_be_new = true;
2405 //XXX This is needed because session constructor wants a
2406 //non-existant path. hopefully this will be fixed at some point.
2408 session_path = Glib::build_filename (session_path, session_name);
2410 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2412 if (ask_about_loading_existing_session (session_path)) {
2415 response = RESPONSE_NONE;
2420 _session_is_new = true;
2422 if (new_session_dialog->use_session_template()) {
2424 template_name = new_session_dialog->session_template_name();
2428 if (build_session_from_nsd (session_path, session_name)) {
2429 response = RESPONSE_NONE;
2441 new_session_dialog->hide ();
2443 if (load_session (session_path, session_name, template_name)) {
2445 response = Gtk::RESPONSE_NONE;
2449 if (response == Gtk::RESPONSE_NONE) {
2450 new_session_dialog->set_existing_session (false);
2451 new_session_dialog->reset ();
2455 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2459 new_session_dialog->hide();
2460 new_session_dialog->reset();
2461 goto_editor_window ();
2466 ARDOUR_UI::close_session()
2468 if (!check_audioengine()) {
2472 unload_session (true);
2474 get_session_parameters (true, false);
2478 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2480 Session *new_session;
2484 session_loaded = false;
2486 if (!check_audioengine()) {
2490 unload_status = unload_session ();
2492 if (unload_status < 0) {
2494 } else if (unload_status > 0) {
2499 /* if it already exists, we must have write access */
2501 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2502 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2503 "This prevents the session from being loaded."));
2509 loading_message (_("Please wait while Ardour loads your session"));
2512 new_session = new Session (*engine, path, snap_name, mix_template);
2515 /* this one is special */
2517 catch (AudioEngine::PortRegistrationFailure& err) {
2519 MessageDialog msg (err.what(),
2522 Gtk::BUTTONS_OK_CANCEL);
2524 msg.set_title (_("Loading Error"));
2525 msg.set_secondary_text (_("Click the OK button to try again."));
2526 msg.set_position (Gtk::WIN_POS_CENTER);
2530 int response = msg.run ();
2535 case RESPONSE_CANCEL:
2545 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2548 Gtk::BUTTONS_OK_CANCEL);
2550 msg.set_title (_("Loading Error"));
2551 msg.set_secondary_text (_("Click the OK button to try again."));
2552 msg.set_position (Gtk::WIN_POS_CENTER);
2556 int response = msg.run ();
2561 case RESPONSE_CANCEL:
2569 connect_to_session (new_session);
2571 Config->set_current_owner (ConfigVariableBase::Interface);
2573 session_loaded = true;
2575 goto_editor_window ();
2578 session->set_clean ();
2589 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2590 uint32_t control_channels,
2591 uint32_t master_channels,
2592 AutoConnectOption input_connect,
2593 AutoConnectOption output_connect,
2596 nframes_t initial_length)
2598 Session *new_session;
2601 if (!check_audioengine()) {
2605 session_loaded = false;
2607 x = unload_session ();
2615 _session_is_new = true;
2618 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2619 control_channels, master_channels, nphysin, nphysout, initial_length);
2624 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2630 connect_to_session (new_session);
2632 session_loaded = true;
2640 editor->show_window ();
2651 ARDOUR_UI::show_about ()
2655 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2662 ARDOUR_UI::hide_about ()
2665 about->get_window()->set_cursor ();
2671 ARDOUR_UI::about_signal_response(int response)
2677 ARDOUR_UI::show_splash ()
2681 splash = new Splash;
2689 splash->queue_draw ();
2690 splash->get_window()->process_updates (true);
2695 ARDOUR_UI::hide_splash ()
2703 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2707 removed = rep.paths.size();
2710 MessageDialog msgd (*editor,
2711 _("No audio files were ready for cleanup"),
2714 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2715 msgd.set_secondary_text (_("If this seems suprising, \n\
2716 check for any existing snapshots.\n\
2717 These may still include regions that\n\
2718 require some unused files to continue to exist."));
2724 ArdourDialog results (_("ardour: cleanup"), true, false);
2726 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2727 CleanupResultsModelColumns() {
2731 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2732 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2736 CleanupResultsModelColumns results_columns;
2737 Glib::RefPtr<Gtk::ListStore> results_model;
2738 Gtk::TreeView results_display;
2740 results_model = ListStore::create (results_columns);
2741 results_display.set_model (results_model);
2742 results_display.append_column (list_title, results_columns.visible_name);
2744 results_display.set_name ("CleanupResultsList");
2745 results_display.set_headers_visible (true);
2746 results_display.set_headers_clickable (false);
2747 results_display.set_reorderable (false);
2749 Gtk::ScrolledWindow list_scroller;
2752 Gtk::HBox dhbox; // the hbox for the image and text
2753 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2754 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2756 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2758 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2760 if (rep.space < 1048576.0f) {
2762 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2764 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2768 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2770 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2774 dhbox.pack_start (*dimage, true, false, 5);
2775 dhbox.pack_start (txt, true, false, 5);
2777 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2778 TreeModel::Row row = *(results_model->append());
2779 row[results_columns.visible_name] = *i;
2780 row[results_columns.fullpath] = *i;
2783 list_scroller.add (results_display);
2784 list_scroller.set_size_request (-1, 150);
2785 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2787 dvbox.pack_start (dhbox, true, false, 5);
2788 dvbox.pack_start (list_scroller, true, false, 5);
2789 ddhbox.pack_start (dvbox, true, false, 5);
2791 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2792 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2793 results.set_default_response (RESPONSE_CLOSE);
2794 results.set_position (Gtk::WIN_POS_MOUSE);
2796 results_display.show();
2797 list_scroller.show();
2804 //results.get_vbox()->show();
2805 results.set_resizable (false);
2812 ARDOUR_UI::cleanup ()
2815 /* shouldn't happen: menu item is insensitive */
2820 MessageDialog checker (_("Are you sure you want to cleanup?"),
2822 Gtk::MESSAGE_QUESTION,
2823 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2825 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2826 ALL undo/redo information will be lost if you cleanup.\n\
2827 After cleanup, unused audio files will be moved to a \
2828 \"dead sounds\" location."));
2830 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2831 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2832 checker.set_default_response (RESPONSE_CANCEL);
2834 checker.set_name (_("CleanupDialog"));
2835 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2836 checker.set_position (Gtk::WIN_POS_MOUSE);
2838 switch (checker.run()) {
2839 case RESPONSE_ACCEPT:
2845 Session::cleanup_report rep;
2847 editor->prepare_for_cleanup ();
2849 /* do not allow flush until a session is reloaded */
2851 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2853 act->set_sensitive (false);
2856 if (session->cleanup_sources (rep)) {
2857 editor->finish_cleanup ();
2861 editor->finish_cleanup ();
2864 display_cleanup_results (rep,
2867 The following %1 %2 not in use and \n\
2868 have been moved to:\n\
2870 Flushing the wastebasket will \n\
2871 release an additional\n\
2872 %4 %5bytes of disk space.\n"
2878 ARDOUR_UI::flush_trash ()
2881 /* shouldn't happen: menu item is insensitive */
2885 Session::cleanup_report rep;
2887 if (session->cleanup_trash_sources (rep)) {
2891 display_cleanup_results (rep,
2893 _("The following %1 %2 deleted from\n\
2895 releasing %4 %5bytes of disk space"));
2899 ARDOUR_UI::add_route (Gtk::Window* float_window)
2907 if (add_route_dialog == 0) {
2908 add_route_dialog = new AddRouteDialog;
2910 add_route_dialog->set_transient_for (*float_window);
2914 if (add_route_dialog->is_visible()) {
2915 /* we're already doing this */
2919 ResponseType r = (ResponseType) add_route_dialog->run ();
2921 add_route_dialog->hide();
2924 case RESPONSE_ACCEPT:
2931 if ((count = add_route_dialog->count()) <= 0) {
2935 uint32_t input_chan = add_route_dialog->channels ();
2936 uint32_t output_chan;
2937 string name_template = add_route_dialog->name_template ();
2938 bool track = add_route_dialog->track ();
2940 AutoConnectOption oac = Config->get_output_auto_connect();
2942 if (oac & AutoConnectMaster) {
2943 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2945 output_chan = input_chan;
2948 /* XXX do something with name template */
2950 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2952 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2954 session_add_midi_track(count);
2956 MessageDialog msg (*editor,
2957 _("Sorry, MIDI Busses are not supported at this time."));
2959 //session_add_midi_bus();
2963 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2965 session_add_audio_bus (input_chan, output_chan, count);
2971 ARDOUR_UI::mixer_settings () const
2976 node = session->instant_xml(X_("Mixer"));
2978 node = Config->instant_xml(X_("Mixer"));
2982 node = new XMLNode (X_("Mixer"));
2989 ARDOUR_UI::editor_settings () const
2994 node = session->instant_xml(X_("Editor"));
2996 node = Config->instant_xml(X_("Editor"));
3000 node = new XMLNode (X_("Editor"));
3006 ARDOUR_UI::keyboard_settings () const
3010 node = Config->extra_xml(X_("Keyboard"));
3013 node = new XMLNode (X_("Keyboard"));
3019 ARDOUR_UI::create_xrun_marker(nframes_t where)
3021 editor->mouse_add_new_marker (where, false, true);
3025 ARDOUR_UI::halt_on_xrun_message ()
3027 MessageDialog msg (*editor,
3028 _("Recording was stopped because your system could not keep up."));
3033 ARDOUR_UI::xrun_handler(nframes_t where)
3035 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3037 if (Config->get_create_xrun_marker() && session->actively_recording()) {
3038 create_xrun_marker(where);
3041 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3042 halt_on_xrun_message ();
3047 ARDOUR_UI::disk_overrun_handler ()
3049 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3051 if (!have_disk_speed_dialog_displayed) {
3052 have_disk_speed_dialog_displayed = true;
3053 MessageDialog* msg = new MessageDialog (*editor, _("\
3054 The disk system on your computer\n\
3055 was not able to keep up with Ardour.\n\
3057 Specifically, it failed to write data to disk\n\
3058 quickly enough to keep up with recording.\n"));
3059 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3065 ARDOUR_UI::disk_underrun_handler ()
3067 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3069 if (!have_disk_speed_dialog_displayed) {
3070 have_disk_speed_dialog_displayed = true;
3071 MessageDialog* msg = new MessageDialog (*editor,
3072 _("The disk system on your computer\n\
3073 was not able to keep up with Ardour.\n\
3075 Specifically, it failed to read data from disk\n\
3076 quickly enough to keep up with playback.\n"));
3077 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3083 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3085 have_disk_speed_dialog_displayed = false;
3090 ARDOUR_UI::session_dialog (std::string msg)
3092 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3097 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3099 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3108 ARDOUR_UI::pending_state_dialog ()
3110 HBox* hbox = new HBox();
3111 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3112 ArdourDialog dialog (_("Crash Recovery"), true);
3114 This session appears to have been in\n\
3115 middle of recording when ardour or\n\
3116 the computer was shutdown.\n\
3118 Ardour can recover any captured audio for\n\
3119 you, or it can ignore it. Please decide\n\
3120 what you would like to do.\n"));
3121 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3122 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3123 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3124 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3125 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3126 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3127 dialog.set_default_response (RESPONSE_ACCEPT);
3128 dialog.set_position (WIN_POS_CENTER);
3133 switch (dialog.run ()) {
3134 case RESPONSE_ACCEPT:
3142 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3144 HBox* hbox = new HBox();
3145 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3146 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3147 Label message (string_compose (_("\
3148 This session was created with a sample rate of %1 Hz\n\
3150 The audioengine is currently running at %2 Hz\n"), desired, actual));
3152 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3153 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3154 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3155 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3156 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3157 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3158 dialog.set_default_response (RESPONSE_ACCEPT);
3159 dialog.set_position (WIN_POS_CENTER);
3164 switch (dialog.run ()) {
3165 case RESPONSE_ACCEPT:
3174 ARDOUR_UI::disconnect_from_jack ()
3177 if( engine->disconnect_from_jack ()) {
3178 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3182 update_sample_rate (0);
3187 ARDOUR_UI::reconnect_to_jack ()
3190 if (engine->reconnect_to_jack ()) {
3191 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3195 update_sample_rate (0);
3200 ARDOUR_UI::use_config ()
3202 Glib::RefPtr<Action> act;
3204 switch (Config->get_native_file_data_format ()) {
3206 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3209 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3212 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3217 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3218 ract->set_active ();
3221 switch (Config->get_native_file_header_format ()) {
3223 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3226 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3229 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3232 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3235 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3238 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3241 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3246 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3247 ract->set_active ();
3250 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3252 set_transport_controllable_state (*node);
3257 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3259 if (Config->get_primary_clock_delta_edit_cursor()) {
3260 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3262 primary_clock.set (pos, 0, true);
3265 if (Config->get_secondary_clock_delta_edit_cursor()) {
3266 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3268 secondary_clock.set (pos);
3271 if (big_clock_window) {
3272 big_clock.set (pos);
3277 ARDOUR_UI::record_state_changed ()
3279 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3281 if (!session || !big_clock_window) {
3282 /* why bother - the clock isn't visible */
3286 switch (session->record_status()) {
3287 case Session::Recording:
3288 big_clock.set_widget_name ("BigClockRecording");
3291 big_clock.set_widget_name ("BigClockNonRecording");
3297 ARDOUR_UI::first_idle ()
3300 session->allow_auto_play (true);
3304 editor->first_idle();
3307 Keyboard::set_can_save_keybindings (true);
3312 ARDOUR_UI::store_clock_modes ()
3314 XMLNode* node = new XMLNode(X_("ClockModes"));
3316 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3317 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3320 session->add_extra_xml (*node);
3321 session->set_dirty ();
3326 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3327 : Controllable (name), ui (u), type(tp)
3333 ARDOUR_UI::TransportControllable::set_value (float val)
3335 if (type == ShuttleControl) {
3342 fract = -((0.5f - val)/0.5f);
3344 fract = ((val - 0.5f)/0.5f);
3348 ui.set_shuttle_fract (fract);
3353 /* do nothing: these are radio-style actions */
3357 const char *action = 0;
3361 action = X_("Roll");
3364 action = X_("Stop");
3367 action = X_("Goto Start");
3370 action = X_("Goto End");
3373 action = X_("Loop");
3376 action = X_("Play Selection");
3379 action = X_("Record");
3389 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3397 ARDOUR_UI::TransportControllable::get_value (void) const
3416 case ShuttleControl:
3426 ARDOUR_UI::TransportControllable::set_id (const string& str)
3432 ARDOUR_UI::setup_profile ()
3434 if (gdk_screen_width() < 1200) {
3435 Profile->set_small_screen ();
3439 if (getenv ("ARDOUR_SAE")) {
3440 Profile->set_sae ();
3441 Profile->set_single_package ();