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 Config->save_state();
525 ui_config->save_state ();
527 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
528 XMLNode mnode(mixer->get_state());
531 session->add_instant_xml (enode);
532 session->add_instant_xml (mnode);
534 Config->add_instant_xml (enode);
535 Config->add_instant_xml (mnode);
538 Keyboard::save_keybindings ();
542 ARDOUR_UI::autosave_session ()
544 if (g_main_depth() > 1) {
545 /* inside a recursive main loop,
546 give up because we may not be able to
552 if (!Config->get_periodic_safety_backups()) {
557 session->maybe_write_autosave();
564 ARDOUR_UI::update_autosave ()
566 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
568 if (session->dirty()) {
569 if (_autosave_connection.connected()) {
570 _autosave_connection.disconnect();
573 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
574 Config->get_periodic_safety_backup_interval() * 1000);
577 if (_autosave_connection.connected()) {
578 _autosave_connection.disconnect();
584 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
588 title = _("Ardour could not start JACK");
590 title = _("Ardour could not connect to JACK.");
593 MessageDialog win (title,
599 win.set_secondary_text(_("There are several possible reasons:\n\
601 1) You requested audio parameters that are not supported..\n\
602 2) JACK is running as another user.\n\
604 Please consider the possibilities, and perhaps try different parameters."));
606 win.set_secondary_text(_("There are several possible reasons:\n\
608 1) JACK is not running.\n\
609 2) JACK is running as another user, perhaps root.\n\
610 3) There is already another client called \"ardour\".\n\
612 Please consider the possibilities, and perhaps (re)start JACK."));
616 win.set_transient_for (*toplevel);
620 win.add_button (Stock::OK, RESPONSE_CLOSE);
622 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
625 win.set_default_response (RESPONSE_CLOSE);
628 win.set_position (Gtk::WIN_POS_CENTER);
631 /* we just don't care about the result, but we want to block */
637 ARDOUR_UI::startup ()
641 new_session_dialog = new NewSessionDialog();
643 bool backend_audio_is_running = EngineControl::engine_running();
644 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
647 new_session_dialog->engine_control.set_state (*audio_setup);
650 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
654 BootMessage (_("Ardour is ready for use"));
659 ARDOUR_UI::no_memory_warning ()
661 XMLNode node (X_("no-memory-warning"));
662 Config->add_instant_xml (node);
666 ARDOUR_UI::check_memory_locking ()
669 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
673 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
675 if (engine->is_realtime() && memory_warning_node == 0) {
677 struct rlimit limits;
679 long pages, page_size;
681 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
684 ram = (int64_t) pages * (int64_t) page_size;
687 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
691 if (limits.rlim_cur != RLIM_INFINITY) {
693 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
696 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
697 "This might cause Ardour to run out of memory before your system "
698 "runs out of memory. \n\n"
699 "You can view the memory limit with 'ulimit -l', "
700 "and it is normally controlled by /etc/security/limits.conf"));
702 VBox* vbox = msg.get_vbox();
704 CheckButton cb (_("Do not show this window again"));
706 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
708 hbox.pack_start (cb, true, false);
709 vbox->pack_start (hbox);
716 editor->ensure_float (msg);
730 if (session->transport_rolling()) {
731 session->request_stop ();
735 if (session->dirty()) {
736 switch (ask_about_saving_session(_("quit"))) {
741 /* use the default name */
742 if (save_state_canfail ("")) {
743 /* failed - don't quit */
744 MessageDialog msg (*editor,
746 Ardour was unable to save your session.\n\n\
747 If you still wish to quit, please use the\n\n\
748 \"Just quit\" option."));
759 session->set_deletion_in_progress ();
763 Config->save_state();
764 ARDOUR_UI::config()->save_state();
769 ARDOUR_UI::ask_about_saving_session (const string & what)
771 ArdourDialog window (_("ardour: save session?"));
772 Gtk::HBox dhbox; // the hbox for the image and text
773 Gtk::Label prompt_label;
774 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
778 msg = string_compose(_("Don't %1"), what);
779 window.add_button (msg, RESPONSE_REJECT);
780 msg = string_compose(_("Just %1"), what);
781 window.add_button (msg, RESPONSE_APPLY);
782 msg = string_compose(_("Save and %1"), what);
783 window.add_button (msg, RESPONSE_ACCEPT);
785 window.set_default_response (RESPONSE_ACCEPT);
787 Gtk::Button noquit_button (msg);
788 noquit_button.set_name ("EditorGTKButton");
793 if (session->snap_name() == session->name()) {
796 type = _("snapshot");
798 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?"),
799 type, session->snap_name());
801 prompt_label.set_text (prompt);
802 prompt_label.set_name (X_("PrompterLabel"));
803 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
805 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
806 dhbox.set_homogeneous (false);
807 dhbox.pack_start (*dimage, false, false, 5);
808 dhbox.pack_start (prompt_label, true, false, 5);
809 window.get_vbox()->pack_start (dhbox);
811 window.set_name (_("Prompter"));
812 window.set_position (Gtk::WIN_POS_MOUSE);
813 window.set_modal (true);
814 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 ()
908 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
909 session->playback_load(), session->capture_load());
910 buffer_load_label.set_text (buf);
912 buffer_load_label.set_text ("");
917 ARDOUR_UI::count_recenabled_streams (Route& route)
919 Track* track = dynamic_cast<Track*>(&route);
920 if (track && track->diskstream()->record_enabled()) {
921 rec_enabled_streams += track->n_inputs().n_total();
926 ARDOUR_UI::update_disk_space()
932 nframes_t frames = session->available_capture_duration();
934 nframes_t fr = session->frame_rate();
936 if (frames == max_frames) {
937 strcpy (buf, _("Disk: 24hrs+"));
939 rec_enabled_streams = 0;
940 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
942 if (rec_enabled_streams) {
943 frames /= rec_enabled_streams;
950 hrs = frames / (fr * 3600);
951 frames -= hrs * fr * 3600;
952 mins = frames / (fr * 60);
953 frames -= mins * fr * 60;
956 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
959 disk_space_label.set_text (buf);
961 // An attempt to make the disk space label flash red when space has run out.
963 if (frames < fr * 60 * 5) {
964 /* disk_space_box.style ("disk_space_label_empty"); */
966 /* disk_space_box.style ("disk_space_label"); */
972 ARDOUR_UI::update_wall_clock ()
979 tm_now = localtime (&now);
981 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
982 wall_clock_label.set_text (buf);
988 ARDOUR_UI::session_menu (GdkEventButton *ev)
990 session_popup_menu->popup (0, 0);
995 ARDOUR_UI::redisplay_recent_sessions ()
997 std::vector<sys::path> session_directories;
998 RecentSessionsSorter cmp;
1000 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1001 recent_session_model->clear ();
1003 ARDOUR::RecentSessions rs;
1004 ARDOUR::read_recent_sessions (rs);
1007 recent_session_display.set_model (recent_session_model);
1011 // sort them alphabetically
1012 sort (rs.begin(), rs.end(), cmp);
1014 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1015 session_directories.push_back ((*i).second);
1018 for (vector<sys::path>::const_iterator i = session_directories.begin();
1019 i != session_directories.end(); ++i)
1021 std::vector<sys::path> state_file_paths;
1023 // now get available states for this session
1025 get_state_files_in_directory (*i, state_file_paths);
1027 vector<string*>* states;
1028 vector<const gchar*> item;
1029 string fullpath = (*i).to_string();
1031 /* remove any trailing / */
1033 if (fullpath[fullpath.length()-1] == '/') {
1034 fullpath = fullpath.substr (0, fullpath.length()-1);
1037 /* check whether session still exists */
1038 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1039 /* session doesn't exist */
1040 cerr << "skipping non-existent session " << fullpath << endl;
1044 /* now get available states for this session */
1046 if ((states = Session::possible_states (fullpath)) == 0) {
1047 /* no state file? */
1051 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1053 Gtk::TreeModel::Row row = *(recent_session_model->append());
1055 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1056 row[recent_session_columns.fullpath] = fullpath;
1058 if (state_file_names.size() > 1) {
1062 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1063 i2 != state_file_names.end(); ++i2)
1066 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1068 child_row[recent_session_columns.visible_name] = *i2;
1069 child_row[recent_session_columns.fullpath] = fullpath;
1074 recent_session_display.set_model (recent_session_model);
1078 ARDOUR_UI::build_session_selector ()
1080 session_selector_window = new ArdourDialog ("session selector");
1082 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1084 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1085 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1086 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1087 recent_session_model = TreeStore::create (recent_session_columns);
1088 recent_session_display.set_model (recent_session_model);
1089 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1090 recent_session_display.set_headers_visible (false);
1091 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1092 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1094 scroller->add (recent_session_display);
1095 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1097 session_selector_window->set_name ("SessionSelectorWindow");
1098 session_selector_window->set_size_request (200, 400);
1099 session_selector_window->get_vbox()->pack_start (*scroller);
1101 recent_session_display.show();
1103 //session_selector_window->get_vbox()->show();
1107 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1109 session_selector_window->response (RESPONSE_ACCEPT);
1113 ARDOUR_UI::open_recent_session ()
1115 bool can_return = (session != 0);
1117 if (session_selector_window == 0) {
1118 build_session_selector ();
1121 redisplay_recent_sessions ();
1125 session_selector_window->set_position (WIN_POS_MOUSE);
1127 ResponseType r = (ResponseType) session_selector_window->run ();
1130 case RESPONSE_ACCEPT:
1134 session_selector_window->hide();
1141 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1145 session_selector_window->hide();
1147 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1149 if (i == recent_session_model->children().end()) {
1153 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1154 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1156 _session_is_new = false;
1158 if (load_session (path, state) == 0) {
1167 ARDOUR_UI::check_audioengine ()
1170 if (!engine->connected()) {
1171 MessageDialog msg (_("Ardour is not connected to JACK\n"
1172 "You cannot open or close sessions in this condition"));
1184 ARDOUR_UI::open_session ()
1186 if (!check_audioengine()) {
1191 /* popup selector window */
1193 if (open_session_selector == 0) {
1195 /* ardour sessions are folders */
1197 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1198 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1199 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1200 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1202 FileFilter session_filter;
1203 session_filter.add_pattern ("*.ardour");
1204 session_filter.set_name (_("Ardour sessions"));
1205 open_session_selector->add_filter (session_filter);
1206 open_session_selector->set_filter (session_filter);
1209 int response = open_session_selector->run();
1210 open_session_selector->hide ();
1213 case RESPONSE_ACCEPT:
1216 open_session_selector->hide();
1220 open_session_selector->hide();
1221 string session_path = open_session_selector->get_filename();
1225 if (session_path.length() > 0) {
1226 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1227 _session_is_new = isnew;
1228 load_session (path, name);
1235 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1237 list<boost::shared_ptr<MidiTrack> > tracks;
1240 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1247 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1249 if (tracks.size() != how_many) {
1250 if (how_many == 1) {
1251 error << _("could not create a new midi track") << endmsg;
1253 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1257 if ((route = session->new_midi_route ()) == 0) {
1258 error << _("could not create new midi bus") << endmsg;
1264 MessageDialog msg (*editor,
1265 _("There are insufficient JACK ports available\n\
1266 to create a new track or bus.\n\
1267 You should save Ardour, exit and\n\
1268 restart JACK with more ports."));
1275 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1277 list<boost::shared_ptr<AudioTrack> > tracks;
1278 Session::RouteList routes;
1281 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1287 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1289 if (tracks.size() != how_many) {
1290 if (how_many == 1) {
1291 error << _("could not create a new audio track") << endmsg;
1293 error << string_compose (_("could only create %1 of %2 new audio %3"),
1294 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1300 routes = session->new_audio_route (input_channels, output_channels, how_many);
1302 if (routes.size() != how_many) {
1303 if (how_many == 1) {
1304 error << _("could not create a new audio track") << endmsg;
1306 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1312 if (need_control_room_outs) {
1318 route->set_stereo_control_outs (control_lr_channels);
1319 route->control_outs()->set_stereo_pan (pans, this);
1321 #endif /* CONTROLOUTS */
1325 MessageDialog msg (*editor,
1326 _("There are insufficient JACK ports available\n\
1327 to create a new track or bus.\n\
1328 You should save Ardour, exit and\n\
1329 restart JACK with more ports."));
1336 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1338 nframes_t _preroll = 0;
1341 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1342 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1344 if (new_position > _preroll) {
1345 new_position -= _preroll;
1350 session->request_locate (new_position);
1355 ARDOUR_UI::transport_goto_start ()
1358 session->goto_start();
1361 /* force displayed area in editor to start no matter
1362 what "follow playhead" setting is.
1366 editor->reset_x_origin (session->current_start_frame());
1372 ARDOUR_UI::transport_goto_zero ()
1375 session->request_locate (0);
1378 /* force displayed area in editor to start no matter
1379 what "follow playhead" setting is.
1383 editor->reset_x_origin (0);
1389 ARDOUR_UI::transport_goto_wallclock ()
1391 if (session && editor) {
1398 localtime_r (&now, &tmnow);
1400 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1401 frames += tmnow.tm_min * (60 * session->frame_rate());
1402 frames += tmnow.tm_sec * session->frame_rate();
1404 session->request_locate (frames);
1406 /* force displayed area in editor to start no matter
1407 what "follow playhead" setting is.
1411 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1417 ARDOUR_UI::transport_goto_end ()
1420 nframes_t frame = session->current_end_frame();
1421 session->request_locate (frame);
1423 /* force displayed area in editor to start no matter
1424 what "follow playhead" setting is.
1428 editor->reset_x_origin (frame);
1434 ARDOUR_UI::transport_stop ()
1440 if (session->is_auditioning()) {
1441 session->cancel_audition ();
1445 if (session->get_play_loop ()) {
1446 session->request_play_loop (false);
1449 session->request_stop ();
1453 ARDOUR_UI::transport_stop_and_forget_capture ()
1456 session->request_stop (true);
1461 ARDOUR_UI::remove_last_capture()
1464 editor->remove_last_capture();
1469 ARDOUR_UI::transport_record (bool roll)
1473 switch (session->record_status()) {
1474 case Session::Disabled:
1475 if (session->ntracks() == 0) {
1476 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1480 session->maybe_enable_record ();
1485 case Session::Recording:
1487 session->request_stop();
1489 session->disable_record (false, true);
1493 case Session::Enabled:
1494 session->disable_record (false, true);
1497 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1501 ARDOUR_UI::transport_roll ()
1509 rolling = session->transport_rolling ();
1511 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1513 if (session->get_play_loop()) {
1514 session->request_play_loop (false);
1515 auto_loop_button.set_visual_state (1);
1516 roll_button.set_visual_state (1);
1517 } else if (session->get_play_range ()) {
1518 session->request_play_range (false);
1519 play_selection_button.set_visual_state (0);
1520 } else if (rolling) {
1521 session->request_locate (session->last_transport_start(), true);
1524 session->request_transport_speed (1.0f);
1528 ARDOUR_UI::transport_loop()
1531 if (session->get_play_loop()) {
1532 if (session->transport_rolling()) {
1533 Location * looploc = session->locations()->auto_loop_location();
1535 session->request_locate (looploc->start(), true);
1540 session->request_play_loop (true);
1546 ARDOUR_UI::transport_play_selection ()
1552 if (!session->get_play_range()) {
1553 session->request_stop ();
1556 editor->play_selection ();
1560 ARDOUR_UI::transport_rewind (int option)
1562 float current_transport_speed;
1565 current_transport_speed = session->transport_speed();
1567 if (current_transport_speed >= 0.0f) {
1570 session->request_transport_speed (-1.0f);
1573 session->request_transport_speed (-4.0f);
1576 session->request_transport_speed (-0.5f);
1581 session->request_transport_speed (current_transport_speed * 1.5f);
1587 ARDOUR_UI::transport_forward (int option)
1589 float current_transport_speed;
1592 current_transport_speed = session->transport_speed();
1594 if (current_transport_speed <= 0.0f) {
1597 session->request_transport_speed (1.0f);
1600 session->request_transport_speed (4.0f);
1603 session->request_transport_speed (0.5f);
1608 session->request_transport_speed (current_transport_speed * 1.5f);
1614 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1620 boost::shared_ptr<Route> r;
1622 if ((r = session->route_by_remote_id (dstream)) != 0) {
1626 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1627 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1636 ARDOUR_UI::queue_transport_change ()
1638 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1642 ARDOUR_UI::map_transport_state ()
1644 float sp = session->transport_speed();
1647 transport_rolling ();
1648 } else if (sp < 0.0f) {
1649 transport_rewinding ();
1650 } else if (sp > 0.0f) {
1651 transport_forwarding ();
1653 transport_stopped ();
1658 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1660 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1661 (int) adj.get_value()].c_str());
1665 ARDOUR_UI::engine_stopped ()
1667 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1668 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1669 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1673 ARDOUR_UI::engine_running ()
1675 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1676 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1677 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1679 Glib::RefPtr<Action> action;
1680 const char* action_name = 0;
1682 switch (engine->frames_per_cycle()) {
1684 action_name = X_("JACKLatency32");
1687 action_name = X_("JACKLatency64");
1690 action_name = X_("JACKLatency128");
1693 action_name = X_("JACKLatency512");
1696 action_name = X_("JACKLatency1024");
1699 action_name = X_("JACKLatency2048");
1702 action_name = X_("JACKLatency4096");
1705 action_name = X_("JACKLatency8192");
1708 /* XXX can we do anything useful ? */
1714 action = ActionManager::get_action (X_("JACK"), action_name);
1717 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1718 ract->set_active ();
1724 ARDOUR_UI::engine_halted ()
1726 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1728 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1729 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1731 update_sample_rate (0);
1733 MessageDialog msg (*editor,
1735 JACK has either been shutdown or it\n\
1736 disconnected Ardour because Ardour\n\
1737 was not fast enough. You can save the\n\
1738 session and/or try to reconnect to JACK ."));
1744 ARDOUR_UI::do_engine_start ()
1752 error << _("Unable to start the session running")
1762 ARDOUR_UI::setup_theme ()
1764 theme_manager->setup_theme();
1768 ARDOUR_UI::update_clocks ()
1770 if (!editor || !editor->dragging_playhead()) {
1771 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1776 ARDOUR_UI::start_clocking ()
1778 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1782 ARDOUR_UI::stop_clocking ()
1784 clock_signal_connection.disconnect ();
1788 ARDOUR_UI::toggle_clocking ()
1791 if (clock_button.get_active()) {
1800 ARDOUR_UI::_blink (void *arg)
1803 ((ARDOUR_UI *) arg)->blink ();
1810 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1814 ARDOUR_UI::start_blinking ()
1816 /* Start the blink signal. Everybody with a blinking widget
1817 uses Blink to drive the widget's state.
1820 if (blink_timeout_tag < 0) {
1822 blink_timeout_tag = g_timeout_add (240, _blink, this);
1827 ARDOUR_UI::stop_blinking ()
1829 if (blink_timeout_tag >= 0) {
1830 g_source_remove (blink_timeout_tag);
1831 blink_timeout_tag = -1;
1836 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1841 vector<string> connections;
1844 if (io.n_inputs().n_total() == 0) {
1849 /* XXX we're not handling multiple ports yet. */
1851 if (io.input(0)->get_connections(connections) == 0) {
1854 buf = connections.front();
1859 if (io.n_outputs().n_total() == 0) {
1864 /* XXX we're not handling multiple ports yet. */
1866 if (io.output(0)->get_connections(connections) == 0) {
1869 buf = connections.front();
1874 /** Ask the user for the name of a new shapshot and then take it.
1877 ARDOUR_UI::snapshot_session ()
1879 ArdourPrompter prompter (true);
1883 struct tm local_time;
1886 localtime_r (&n, &local_time);
1887 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1889 prompter.set_name ("Prompter");
1890 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1891 prompter.set_prompt (_("Name of New Snapshot"));
1892 prompter.set_initial_text (timebuf);
1894 switch (prompter.run()) {
1895 case RESPONSE_ACCEPT:
1896 prompter.get_result (snapname);
1897 if (snapname.length()){
1898 save_state (snapname);
1908 ARDOUR_UI::save_state (const string & name)
1910 (void) save_state_canfail (name);
1914 ARDOUR_UI::save_state_canfail (string name)
1919 if (name.length() == 0) {
1920 name = session->snap_name();
1923 if ((ret = session->save_state (name)) != 0) {
1927 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1932 ARDOUR_UI::primary_clock_value_changed ()
1935 session->request_locate (primary_clock.current_time ());
1940 ARDOUR_UI::big_clock_value_changed ()
1943 session->request_locate (big_clock.current_time ());
1948 ARDOUR_UI::secondary_clock_value_changed ()
1951 session->request_locate (secondary_clock.current_time ());
1956 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1962 switch (session->record_status()) {
1963 case Session::Enabled:
1965 rec_button.set_visual_state (2);
1967 rec_button.set_visual_state (0);
1971 case Session::Recording:
1972 rec_button.set_visual_state (1);
1976 rec_button.set_visual_state (0);
1982 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1990 ARDOUR_UI::save_template ()
1993 ArdourPrompter prompter (true);
1996 if (!check_audioengine()) {
2000 prompter.set_name (X_("Prompter"));
2001 prompter.set_prompt (_("Name for mix template:"));
2002 prompter.set_initial_text(session->name() + _("-template"));
2003 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2005 switch (prompter.run()) {
2006 case RESPONSE_ACCEPT:
2007 prompter.get_result (name);
2009 if (name.length()) {
2010 session->save_template (name);
2020 ARDOUR_UI::edit_metadata ()
2022 SessionMetadataEditor dialog;
2023 dialog.set_session (session);
2024 editor->ensure_float (dialog);
2029 ARDOUR_UI::import_metadata ()
2031 SessionMetadataImporter dialog;
2032 dialog.set_session (session);
2033 editor->ensure_float (dialog);
2038 ARDOUR_UI::fontconfig_dialog ()
2041 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2042 may not and it can take a while to build it. Warn them.
2045 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2047 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2048 MessageDialog msg (*new_session_dialog,
2049 _("Welcome to Ardour.\n\n"
2050 "The program will take a bit longer to start up\n"
2051 "while the system fonts are checked.\n\n"
2052 "This will only be done once, and you will\n"
2053 "not see this message again\n"),
2066 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2068 existing_session = false;
2070 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2071 session_path = cmdline_path;
2072 existing_session = true;
2073 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2074 session_path = Glib::path_get_dirname (string (cmdline_path));
2075 existing_session = true;
2077 /* it doesn't exist, assume the best */
2078 session_path = Glib::path_get_dirname (string (cmdline_path));
2081 session_name = basename_nosuffix (string (cmdline_path));
2085 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2087 /* when this is called, the backend audio system must be running */
2089 /* the main idea here is to deal with the fact that a cmdline argument for the session
2090 can be interpreted in different ways - it could be a directory or a file, and before
2091 we load, we need to know both the session directory and the snapshot (statefile) within it
2092 that we are supposed to use.
2095 if (session_name.length() == 0 || session_path.length() == 0) {
2099 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2101 Glib::ustring predicted_session_file;
2103 predicted_session_file = session_path;
2104 predicted_session_file += '/';
2105 predicted_session_file += session_name;
2106 predicted_session_file += ARDOUR::statefile_suffix;
2108 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2109 existing_session = true;
2112 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2114 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2115 /* existing .ardour file */
2116 existing_session = true;
2120 existing_session = false;
2123 /* lets just try to load it */
2125 if (create_engine ()) {
2126 backend_audio_error (false, new_session_dialog);
2130 return load_session (session_path, session_name);
2134 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2136 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2138 MessageDialog msg (str,
2140 Gtk::MESSAGE_WARNING,
2141 Gtk::BUTTONS_YES_NO,
2145 msg.set_name (X_("CleanupDialog"));
2146 msg.set_wmclass (X_("existing_session"), "Ardour");
2147 msg.set_position (Gtk::WIN_POS_MOUSE);
2150 switch (msg.run()) {
2159 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2164 AutoConnectOption iconnect;
2165 AutoConnectOption oconnect;
2169 if (Profile->get_sae()) {
2173 iconnect = AutoConnectPhysical;
2174 oconnect = AutoConnectMaster;
2175 nphysin = 0; // use all available
2176 nphysout = 0; // use all available
2180 /* get settings from advanced section of NSD */
2182 if (new_session_dialog->create_control_bus()) {
2183 cchns = (uint32_t) new_session_dialog->control_channel_count();
2188 if (new_session_dialog->create_master_bus()) {
2189 mchns = (uint32_t) new_session_dialog->master_channel_count();
2194 if (new_session_dialog->connect_inputs()) {
2195 iconnect = AutoConnectPhysical;
2197 iconnect = AutoConnectOption (0);
2200 /// @todo some minor tweaks.
2202 if (new_session_dialog->connect_outs_to_master()) {
2203 oconnect = AutoConnectMaster;
2204 } else if (new_session_dialog->connect_outs_to_physical()) {
2205 oconnect = AutoConnectPhysical;
2207 oconnect = AutoConnectOption (0);
2210 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2211 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2214 if (build_session (session_path,
2222 engine->frame_rate() * 60 * 5)) {
2231 ARDOUR_UI::end_loading_messages ()
2237 ARDOUR_UI::loading_message (const std::string& msg)
2240 splash->message (msg);
2245 ARDOUR_UI::idle_load (const Glib::ustring& path)
2248 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2249 /* /path/to/foo => /path/to/foo, foo */
2250 load_session (path, basename_nosuffix (path));
2252 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2253 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2256 ARDOUR_COMMAND_LINE::session_name = path;
2257 if (new_session_dialog) {
2258 /* make it break out of Dialog::run() and
2261 new_session_dialog->response (1);
2267 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2269 bool existing_session = false;
2270 Glib::ustring session_name;
2271 Glib::ustring session_path;
2272 Glib::ustring template_name;
2276 response = Gtk::RESPONSE_NONE;
2278 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2280 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2282 /* don't ever reuse this */
2284 ARDOUR_COMMAND_LINE::session_name = string();
2286 if (existing_session && backend_audio_is_running) {
2288 /* just load the thing already */
2290 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2295 /* make the NSD use whatever information we have */
2297 new_session_dialog->set_session_name (session_name);
2298 new_session_dialog->set_session_folder (session_path);
2301 /* loading failed, or we need the NSD for something */
2303 new_session_dialog->set_modal (false);
2304 new_session_dialog->set_position (WIN_POS_CENTER);
2305 new_session_dialog->set_current_page (0);
2306 new_session_dialog->set_existing_session (existing_session);
2307 new_session_dialog->reset_recent();
2310 new_session_dialog->set_have_engine (backend_audio_is_running);
2311 new_session_dialog->present ();
2312 end_loading_messages ();
2313 response = new_session_dialog->run ();
2315 _session_is_new = false;
2317 /* handle possible negative responses */
2321 /* sent by idle_load, meaning restart the whole process again */
2322 new_session_dialog->hide();
2323 new_session_dialog->reset();
2327 case Gtk::RESPONSE_CANCEL:
2328 case Gtk::RESPONSE_DELETE_EVENT:
2332 new_session_dialog->hide ();
2335 case Gtk::RESPONSE_NONE:
2336 /* "Clear" was pressed */
2340 fontconfig_dialog();
2342 if (!backend_audio_is_running) {
2343 int ret = new_session_dialog->engine_control.setup_engine ();
2346 } else if (ret > 0) {
2347 response = Gtk::RESPONSE_REJECT;
2352 if (create_engine ()) {
2354 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2357 new_session_dialog->set_existing_session (false);
2358 new_session_dialog->set_current_page (2);
2360 response = Gtk::RESPONSE_NONE;
2364 backend_audio_is_running = true;
2366 if (response == Gtk::RESPONSE_OK) {
2368 session_name = new_session_dialog->session_name();
2370 if (session_name.empty()) {
2371 response = Gtk::RESPONSE_NONE;
2375 /* if the user mistakenly typed path information into the session filename entry,
2376 convert what they typed into a path & a name
2379 if (session_name[0] == '/' ||
2380 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2381 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2383 session_path = Glib::path_get_dirname (session_name);
2384 session_name = Glib::path_get_basename (session_name);
2388 session_path = new_session_dialog->session_folder();
2391 template_name = Glib::ustring();
2392 switch (new_session_dialog->which_page()) {
2394 case NewSessionDialog::OpenPage:
2395 case NewSessionDialog::EnginePage:
2399 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2401 should_be_new = true;
2403 //XXX This is needed because session constructor wants a
2404 //non-existant path. hopefully this will be fixed at some point.
2406 session_path = Glib::build_filename (session_path, session_name);
2408 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2410 if (ask_about_loading_existing_session (session_path)) {
2413 response = RESPONSE_NONE;
2418 _session_is_new = true;
2420 if (new_session_dialog->use_session_template()) {
2422 template_name = new_session_dialog->session_template_name();
2426 if (build_session_from_nsd (session_path, session_name)) {
2427 response = RESPONSE_NONE;
2439 new_session_dialog->hide ();
2441 if (load_session (session_path, session_name, template_name)) {
2443 response = Gtk::RESPONSE_NONE;
2447 if (response == Gtk::RESPONSE_NONE) {
2448 new_session_dialog->set_existing_session (false);
2449 new_session_dialog->reset ();
2453 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2457 new_session_dialog->hide();
2458 new_session_dialog->reset();
2459 goto_editor_window ();
2464 ARDOUR_UI::close_session()
2466 if (!check_audioengine()) {
2470 unload_session (true);
2472 get_session_parameters (true, false);
2476 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2478 Session *new_session;
2482 session_loaded = false;
2484 if (!check_audioengine()) {
2488 unload_status = unload_session ();
2490 if (unload_status < 0) {
2492 } else if (unload_status > 0) {
2497 /* if it already exists, we must have write access */
2499 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2500 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2501 "This prevents the session from being loaded."));
2507 loading_message (_("Please wait while Ardour loads your session"));
2510 new_session = new Session (*engine, path, snap_name, mix_template);
2513 /* this one is special */
2515 catch (AudioEngine::PortRegistrationFailure& err) {
2517 MessageDialog msg (err.what(),
2520 Gtk::BUTTONS_OK_CANCEL);
2522 msg.set_title (_("Loading Error"));
2523 msg.set_secondary_text (_("Click the OK button to try again."));
2524 msg.set_position (Gtk::WIN_POS_CENTER);
2528 int response = msg.run ();
2533 case RESPONSE_CANCEL:
2543 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2546 Gtk::BUTTONS_OK_CANCEL);
2548 msg.set_title (_("Loading Error"));
2549 msg.set_secondary_text (_("Click the OK button to try again."));
2550 msg.set_position (Gtk::WIN_POS_CENTER);
2554 int response = msg.run ();
2559 case RESPONSE_CANCEL:
2567 connect_to_session (new_session);
2569 Config->set_current_owner (ConfigVariableBase::Interface);
2571 session_loaded = true;
2573 goto_editor_window ();
2576 session->set_clean ();
2587 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2588 uint32_t control_channels,
2589 uint32_t master_channels,
2590 AutoConnectOption input_connect,
2591 AutoConnectOption output_connect,
2594 nframes_t initial_length)
2596 Session *new_session;
2599 if (!check_audioengine()) {
2603 session_loaded = false;
2605 x = unload_session ();
2613 _session_is_new = true;
2616 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2617 control_channels, master_channels, nphysin, nphysout, initial_length);
2622 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2628 connect_to_session (new_session);
2630 session_loaded = true;
2638 editor->show_window ();
2649 ARDOUR_UI::show_about ()
2653 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2660 ARDOUR_UI::hide_about ()
2663 about->get_window()->set_cursor ();
2669 ARDOUR_UI::about_signal_response(int response)
2675 ARDOUR_UI::show_splash ()
2679 splash = new Splash;
2687 splash->queue_draw ();
2688 splash->get_window()->process_updates (true);
2693 ARDOUR_UI::hide_splash ()
2701 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2705 removed = rep.paths.size();
2708 MessageDialog msgd (*editor,
2709 _("No audio files were ready for cleanup"),
2712 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2713 msgd.set_secondary_text (_("If this seems suprising, \n\
2714 check for any existing snapshots.\n\
2715 These may still include regions that\n\
2716 require some unused files to continue to exist."));
2722 ArdourDialog results (_("ardour: cleanup"), true, false);
2724 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2725 CleanupResultsModelColumns() {
2729 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2730 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2734 CleanupResultsModelColumns results_columns;
2735 Glib::RefPtr<Gtk::ListStore> results_model;
2736 Gtk::TreeView results_display;
2738 results_model = ListStore::create (results_columns);
2739 results_display.set_model (results_model);
2740 results_display.append_column (list_title, results_columns.visible_name);
2742 results_display.set_name ("CleanupResultsList");
2743 results_display.set_headers_visible (true);
2744 results_display.set_headers_clickable (false);
2745 results_display.set_reorderable (false);
2747 Gtk::ScrolledWindow list_scroller;
2750 Gtk::HBox dhbox; // the hbox for the image and text
2751 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2752 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2754 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2756 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2758 if (rep.space < 1048576.0f) {
2760 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2762 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2766 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2768 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2772 dhbox.pack_start (*dimage, true, false, 5);
2773 dhbox.pack_start (txt, true, false, 5);
2775 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2776 TreeModel::Row row = *(results_model->append());
2777 row[results_columns.visible_name] = *i;
2778 row[results_columns.fullpath] = *i;
2781 list_scroller.add (results_display);
2782 list_scroller.set_size_request (-1, 150);
2783 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2785 dvbox.pack_start (dhbox, true, false, 5);
2786 dvbox.pack_start (list_scroller, true, false, 5);
2787 ddhbox.pack_start (dvbox, true, false, 5);
2789 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2790 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2791 results.set_default_response (RESPONSE_CLOSE);
2792 results.set_position (Gtk::WIN_POS_MOUSE);
2794 results_display.show();
2795 list_scroller.show();
2802 //results.get_vbox()->show();
2803 results.set_resizable (false);
2810 ARDOUR_UI::cleanup ()
2813 /* shouldn't happen: menu item is insensitive */
2818 MessageDialog checker (_("Are you sure you want to cleanup?"),
2820 Gtk::MESSAGE_QUESTION,
2821 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2823 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2824 ALL undo/redo information will be lost if you cleanup.\n\
2825 After cleanup, unused audio files will be moved to a \
2826 \"dead sounds\" location."));
2828 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2829 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2830 checker.set_default_response (RESPONSE_CANCEL);
2832 checker.set_name (_("CleanupDialog"));
2833 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2834 checker.set_position (Gtk::WIN_POS_MOUSE);
2836 switch (checker.run()) {
2837 case RESPONSE_ACCEPT:
2843 Session::cleanup_report rep;
2845 editor->prepare_for_cleanup ();
2847 /* do not allow flush until a session is reloaded */
2849 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2851 act->set_sensitive (false);
2854 if (session->cleanup_sources (rep)) {
2855 editor->finish_cleanup ();
2859 editor->finish_cleanup ();
2862 display_cleanup_results (rep,
2865 The following %1 %2 not in use and \n\
2866 have been moved to:\n\
2868 Flushing the wastebasket will \n\
2869 release an additional\n\
2870 %4 %5bytes of disk space.\n"
2876 ARDOUR_UI::flush_trash ()
2879 /* shouldn't happen: menu item is insensitive */
2883 Session::cleanup_report rep;
2885 if (session->cleanup_trash_sources (rep)) {
2889 display_cleanup_results (rep,
2891 _("The following %1 %2 deleted from\n\
2893 releasing %4 %5bytes of disk space"));
2897 ARDOUR_UI::add_route (Gtk::Window* float_window)
2905 if (add_route_dialog == 0) {
2906 add_route_dialog = new AddRouteDialog;
2908 add_route_dialog->set_transient_for (*float_window);
2912 if (add_route_dialog->is_visible()) {
2913 /* we're already doing this */
2917 ResponseType r = (ResponseType) add_route_dialog->run ();
2919 add_route_dialog->hide();
2922 case RESPONSE_ACCEPT:
2929 if ((count = add_route_dialog->count()) <= 0) {
2933 uint32_t input_chan = add_route_dialog->channels ();
2934 uint32_t output_chan;
2935 string name_template = add_route_dialog->name_template ();
2936 bool track = add_route_dialog->track ();
2938 AutoConnectOption oac = Config->get_output_auto_connect();
2940 if (oac & AutoConnectMaster) {
2941 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2943 output_chan = input_chan;
2946 /* XXX do something with name template */
2948 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2950 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2952 session_add_midi_track(count);
2954 MessageDialog msg (*editor,
2955 _("Sorry, MIDI Busses are not supported at this time."));
2957 //session_add_midi_bus();
2961 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2963 session_add_audio_bus (input_chan, output_chan, count);
2969 ARDOUR_UI::mixer_settings () const
2974 node = session->instant_xml(X_("Mixer"));
2976 node = Config->instant_xml(X_("Mixer"));
2980 node = new XMLNode (X_("Mixer"));
2987 ARDOUR_UI::editor_settings () const
2992 node = session->instant_xml(X_("Editor"));
2994 node = Config->instant_xml(X_("Editor"));
2998 node = new XMLNode (X_("Editor"));
3004 ARDOUR_UI::keyboard_settings () const
3008 node = Config->extra_xml(X_("Keyboard"));
3011 node = new XMLNode (X_("Keyboard"));
3017 ARDOUR_UI::create_xrun_marker(nframes_t where)
3019 editor->mouse_add_new_marker (where, false, true);
3023 ARDOUR_UI::halt_on_xrun_message ()
3025 MessageDialog msg (*editor,
3026 _("Recording was stopped because your system could not keep up."));
3031 ARDOUR_UI::xrun_handler(nframes_t where)
3033 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3035 if (Config->get_create_xrun_marker() && session->actively_recording()) {
3036 create_xrun_marker(where);
3039 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3040 halt_on_xrun_message ();
3045 ARDOUR_UI::disk_overrun_handler ()
3047 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3049 if (!have_disk_speed_dialog_displayed) {
3050 have_disk_speed_dialog_displayed = true;
3051 MessageDialog* msg = new MessageDialog (*editor, _("\
3052 The disk system on your computer\n\
3053 was not able to keep up with Ardour.\n\
3055 Specifically, it failed to write data to disk\n\
3056 quickly enough to keep up with recording.\n"));
3057 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3063 ARDOUR_UI::disk_underrun_handler ()
3065 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3067 if (!have_disk_speed_dialog_displayed) {
3068 have_disk_speed_dialog_displayed = true;
3069 MessageDialog* msg = new MessageDialog (*editor,
3070 _("The disk system on your computer\n\
3071 was not able to keep up with Ardour.\n\
3073 Specifically, it failed to read data from disk\n\
3074 quickly enough to keep up with playback.\n"));
3075 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3081 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3083 have_disk_speed_dialog_displayed = false;
3088 ARDOUR_UI::session_dialog (std::string msg)
3090 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3095 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3097 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3106 ARDOUR_UI::pending_state_dialog ()
3108 HBox* hbox = new HBox();
3109 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3110 ArdourDialog dialog (_("Crash Recovery"), true);
3112 This session appears to have been in\n\
3113 middle of recording when ardour or\n\
3114 the computer was shutdown.\n\
3116 Ardour can recover any captured audio for\n\
3117 you, or it can ignore it. Please decide\n\
3118 what you would like to do.\n"));
3119 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3120 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3121 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3122 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3123 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3124 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3125 dialog.set_default_response (RESPONSE_ACCEPT);
3126 dialog.set_position (WIN_POS_CENTER);
3131 switch (dialog.run ()) {
3132 case RESPONSE_ACCEPT:
3140 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3142 HBox* hbox = new HBox();
3143 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3144 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3145 Label message (string_compose (_("\
3146 This session was created with a sample rate of %1 Hz\n\
3148 The audioengine is currently running at %2 Hz\n"), desired, actual));
3150 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3151 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3152 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3153 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3154 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3155 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3156 dialog.set_default_response (RESPONSE_ACCEPT);
3157 dialog.set_position (WIN_POS_CENTER);
3162 switch (dialog.run ()) {
3163 case RESPONSE_ACCEPT:
3172 ARDOUR_UI::disconnect_from_jack ()
3175 if( engine->disconnect_from_jack ()) {
3176 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3180 update_sample_rate (0);
3185 ARDOUR_UI::reconnect_to_jack ()
3188 if (engine->reconnect_to_jack ()) {
3189 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3193 update_sample_rate (0);
3198 ARDOUR_UI::use_config ()
3200 Glib::RefPtr<Action> act;
3202 switch (Config->get_native_file_data_format ()) {
3204 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3207 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3210 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3215 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3216 ract->set_active ();
3219 switch (Config->get_native_file_header_format ()) {
3221 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3224 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3227 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3230 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3233 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3236 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3239 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3244 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3245 ract->set_active ();
3248 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3250 set_transport_controllable_state (*node);
3255 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3257 if (Config->get_primary_clock_delta_edit_cursor()) {
3258 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3260 primary_clock.set (pos, 0, true);
3263 if (Config->get_secondary_clock_delta_edit_cursor()) {
3264 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3266 secondary_clock.set (pos);
3269 if (big_clock_window) {
3270 big_clock.set (pos);
3275 ARDOUR_UI::record_state_changed ()
3277 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3279 if (!session || !big_clock_window) {
3280 /* why bother - the clock isn't visible */
3284 switch (session->record_status()) {
3285 case Session::Recording:
3286 big_clock.set_widget_name ("BigClockRecording");
3289 big_clock.set_widget_name ("BigClockNonRecording");
3295 ARDOUR_UI::first_idle ()
3298 session->allow_auto_play (true);
3302 editor->first_idle();
3305 Keyboard::set_can_save_keybindings (true);
3310 ARDOUR_UI::store_clock_modes ()
3312 XMLNode* node = new XMLNode(X_("ClockModes"));
3314 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3315 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3318 session->add_extra_xml (*node);
3319 session->set_dirty ();
3324 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3325 : Controllable (name), ui (u), type(tp)
3331 ARDOUR_UI::TransportControllable::set_value (float val)
3333 if (type == ShuttleControl) {
3340 fract = -((0.5f - val)/0.5f);
3342 fract = ((val - 0.5f)/0.5f);
3346 ui.set_shuttle_fract (fract);
3351 /* do nothing: these are radio-style actions */
3355 const char *action = 0;
3359 action = X_("Roll");
3362 action = X_("Stop");
3365 action = X_("Goto Start");
3368 action = X_("Goto End");
3371 action = X_("Loop");
3374 action = X_("Play Selection");
3377 action = X_("Record");
3387 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3395 ARDOUR_UI::TransportControllable::get_value (void) const
3414 case ShuttleControl:
3424 ARDOUR_UI::TransportControllable::set_id (const string& str)
3430 ARDOUR_UI::setup_profile ()
3432 if (gdk_screen_width() < 1200) {
3433 Profile->set_small_screen ();
3437 if (getenv ("ARDOUR_SAE")) {
3438 Profile->set_sae ();
3439 Profile->set_single_package ();