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
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
39 #include <pbd/basename.h>
40 #include <pbd/compose.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/memento_command.h>
44 #include <pbd/file_utils.h>
46 #include <gtkmm2ext/gtk_ui.h>
47 #include <gtkmm2ext/utils.h>
48 #include <gtkmm2ext/click_box.h>
49 #include <gtkmm2ext/fastmeter.h>
50 #include <gtkmm2ext/stop_signal.h>
51 #include <gtkmm2ext/popup.h>
52 #include <gtkmm2ext/window_title.h>
54 #include <midi++/manager.h>
56 #include <ardour/ardour.h>
57 #include <ardour/profile.h>
58 #include <ardour/session_directory.h>
59 #include <ardour/session_route.h>
60 #include <ardour/session_state_utils.h>
61 #include <ardour/session_utils.h>
62 #include <ardour/port.h>
63 #include <ardour/audioengine.h>
64 #include <ardour/playlist.h>
65 #include <ardour/utils.h>
66 #include <ardour/audio_diskstream.h>
67 #include <ardour/audiofilesource.h>
68 #include <ardour/recent_sessions.h>
69 #include <ardour/port.h>
70 #include <ardour/audio_track.h>
71 #include <ardour/midi_track.h>
72 #include <ardour/filesystem_paths.h>
73 #include <ardour/filename_extensions.h>
76 #include "ardour_ui.h"
77 #include "public_editor.h"
78 #include "audio_clock.h"
83 #include "add_route_dialog.h"
84 #include "new_session_dialog.h"
88 #include "gui_thread.h"
89 #include "theme_manager.h"
90 #include "bundle_manager.h"
94 using namespace ARDOUR;
96 using namespace Gtkmm2ext;
100 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
101 UIConfiguration *ARDOUR_UI::ui_config = 0;
103 sigc::signal<void,bool> ARDOUR_UI::Blink;
104 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
105 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
106 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
108 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
110 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
112 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
113 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
114 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
115 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
119 adjuster_table (3, 3),
123 preroll_button (_("pre\nroll")),
124 postroll_button (_("post\nroll")),
128 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
132 roll_controllable ("transport roll", *this, TransportControllable::Roll),
133 stop_controllable ("transport stop", *this, TransportControllable::Stop),
134 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
135 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
136 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
137 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
138 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
139 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
140 shuttle_controller_binding_proxy (shuttle_controllable),
142 roll_button (roll_controllable),
143 stop_button (stop_controllable),
144 goto_start_button (goto_start_controllable),
145 goto_end_button (goto_end_controllable),
146 auto_loop_button (auto_loop_controllable),
147 play_selection_button (play_selection_controllable),
148 rec_button (rec_controllable),
150 shuttle_units_button (_("% ")),
152 punch_in_button (_("Punch In")),
153 punch_out_button (_("Punch Out")),
154 auto_return_button (_("Auto Return")),
155 auto_play_button (_("Auto Play")),
156 auto_input_button (_("Auto Input")),
157 click_button (_("Click")),
158 time_master_button (_("time\nmaster")),
160 auditioning_alert_button (_("AUDITION")),
161 solo_alert_button (_("SOLO")),
162 midi_panic_button (_("Panic")),
164 error_log_button (_("Errors"))
167 using namespace Gtk::Menu_Helpers;
173 _auto_display_errors = false;
179 if (ARDOUR_COMMAND_LINE::session_name.length()) {
180 /* only show this if we're not going to post the new session dialog */
184 if (theArdourUI == 0) {
188 ui_config = new UIConfiguration();
189 theme_manager = new ThemeManager();
195 _session_is_new = false;
196 big_clock_window = 0;
197 session_selector_window = 0;
198 last_key_press_time = 0;
199 connection_editor = 0;
200 _will_create_new_session_automatically = false;
201 new_session_dialog = 0;
202 add_route_dialog = 0;
206 open_session_selector = 0;
207 have_configure_timeout = false;
208 have_disk_speed_dialog_displayed = false;
209 session_loaded = false;
210 last_speed_displayed = -1.0f;
211 ignore_dual_punch = false;
213 last_configure_time.tv_sec = 0;
214 last_configure_time.tv_usec = 0;
216 shuttle_grabbed = false;
218 shuttle_max_speed = 8.0f;
220 shuttle_style_menu = 0;
221 shuttle_unit_menu = 0;
223 gettimeofday (&last_peak_grab, 0);
224 gettimeofday (&last_shuttle_request, 0);
226 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
227 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
229 /* handle dialog requests */
231 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
233 /* handle pending state with a dialog */
235 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
237 /* handle sr mismatch with a dialog */
239 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
241 /* lets get this party started */
244 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
245 throw failed_constructor ();
248 setup_gtk_ardour_enums ();
249 Config->set_current_owner (ConfigVariableBase::Interface);
252 } catch (failed_constructor& err) {
253 error << _("could not initialize Ardour.") << endmsg;
258 /* we like keyboards */
260 keyboard = new Keyboard;
264 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
265 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
271 ARDOUR_UI::create_engine ()
273 // this gets called every time by new_session()
279 loading_message (_("Starting audio engine"));
282 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
289 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
290 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
291 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
292 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
300 ARDOUR_UI::post_engine ()
302 extern int setup_midi ();
304 /* Things to be done once we create the AudioEngine
307 MIDI::Manager::instance()->set_api_data (engine->jack());
310 ActionManager::init ();
313 if (setup_windows ()) {
314 throw failed_constructor ();
317 check_memory_locking();
319 /* this is the first point at which all the keybindings are available */
321 if (ARDOUR_COMMAND_LINE::show_key_actions) {
322 vector<string> names;
323 vector<string> paths;
325 vector<AccelKey> bindings;
327 ActionManager::get_all_actions (names, paths, keys, bindings);
329 vector<string>::iterator n;
330 vector<string>::iterator k;
331 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
332 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
338 blink_timeout_tag = -1;
340 /* the global configuration object is now valid */
344 /* this being a GUI and all, we want peakfiles */
346 AudioFileSource::set_build_peakfiles (true);
347 AudioFileSource::set_build_missing_peakfiles (true);
349 /* set default clock modes */
351 if (Profile->get_sae()) {
352 primary_clock.set_mode (AudioClock::MinSec);
354 primary_clock.set_mode (AudioClock::SMPTE);
356 secondary_clock.set_mode (AudioClock::BBT);
358 /* start the time-of-day-clock */
361 /* OS X provides an always visible wallclock, so don't be stupid */
362 update_wall_clock ();
363 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
366 update_disk_space ();
368 update_sample_rate (engine->frame_rate());
370 /* now start and maybe save state */
372 if (do_engine_start () == 0) {
373 if (session && _session_is_new) {
374 /* we need to retain initial visual
375 settings for a new session
377 session->save_state ("");
382 ARDOUR_UI::~ARDOUR_UI ()
384 save_ardour_state ();
398 if (add_route_dialog) {
399 delete add_route_dialog;
403 if (new_session_dialog) {
404 delete new_session_dialog;
409 ARDOUR_UI::pop_back_splash ()
411 if (Splash::instance()) {
412 // Splash::instance()->pop_back();
413 Splash::instance()->hide ();
418 ARDOUR_UI::configure_timeout ()
423 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
424 /* no configure events yet */
428 gettimeofday (&now, 0);
429 timersub (&now, &last_configure_time, &diff);
431 /* force a gap of 0.5 seconds since the last configure event
434 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
437 have_configure_timeout = false;
438 save_ardour_state ();
444 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
446 if (have_configure_timeout) {
447 gettimeofday (&last_configure_time, 0);
449 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
450 have_configure_timeout = true;
457 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
459 const XMLProperty* prop;
461 if ((prop = node.property ("roll")) != 0) {
462 roll_controllable.set_id (prop->value());
464 if ((prop = node.property ("stop")) != 0) {
465 stop_controllable.set_id (prop->value());
467 if ((prop = node.property ("goto_start")) != 0) {
468 goto_start_controllable.set_id (prop->value());
470 if ((prop = node.property ("goto_end")) != 0) {
471 goto_end_controllable.set_id (prop->value());
473 if ((prop = node.property ("auto_loop")) != 0) {
474 auto_loop_controllable.set_id (prop->value());
476 if ((prop = node.property ("play_selection")) != 0) {
477 play_selection_controllable.set_id (prop->value());
479 if ((prop = node.property ("rec")) != 0) {
480 rec_controllable.set_id (prop->value());
482 if ((prop = node.property ("shuttle")) != 0) {
483 shuttle_controllable.set_id (prop->value());
488 ARDOUR_UI::get_transport_controllable_state ()
490 XMLNode* node = new XMLNode(X_("TransportControllables"));
493 roll_controllable.id().print (buf, sizeof (buf));
494 node->add_property (X_("roll"), buf);
495 stop_controllable.id().print (buf, sizeof (buf));
496 node->add_property (X_("stop"), buf);
497 goto_start_controllable.id().print (buf, sizeof (buf));
498 node->add_property (X_("goto_start"), buf);
499 goto_end_controllable.id().print (buf, sizeof (buf));
500 node->add_property (X_("goto_end"), buf);
501 auto_loop_controllable.id().print (buf, sizeof (buf));
502 node->add_property (X_("auto_loop"), buf);
503 play_selection_controllable.id().print (buf, sizeof (buf));
504 node->add_property (X_("play_selection"), buf);
505 rec_controllable.id().print (buf, sizeof (buf));
506 node->add_property (X_("rec"), buf);
507 shuttle_controllable.id().print (buf, sizeof (buf));
508 node->add_property (X_("shuttle"), buf);
514 ARDOUR_UI::save_ardour_state ()
516 if (!keyboard || !mixer || !editor) {
520 /* XXX this is all a bit dubious. add_extra_xml() uses
521 a different lifetime model from add_instant_xml().
524 XMLNode* node = new XMLNode (keyboard->get_state());
525 Config->add_extra_xml (*node);
526 Config->add_extra_xml (get_transport_controllable_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 (!Config->get_periodic_safety_backups())
551 session->maybe_write_autosave();
558 ARDOUR_UI::update_autosave ()
560 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
562 if (session->dirty()) {
563 if (_autosave_connection.connected()) {
564 _autosave_connection.disconnect();
567 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
568 Config->get_periodic_safety_backup_interval() * 1000);
571 if (_autosave_connection.connected()) {
572 _autosave_connection.disconnect();
578 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
582 title = _("Ardour could not start JACK");
584 title = _("Ardour could not connect to JACK.");
587 MessageDialog win (title,
593 win.set_secondary_text(_("There are several possible reasons:\n\
595 1) You requested audio parameters that are not supported..\n\
596 2) JACK is running as another user.\n\
598 Please consider the possibilities, and perhaps try different parameters."));
600 win.set_secondary_text(_("There are several possible reasons:\n\
602 1) JACK is not running.\n\
603 2) JACK is running as another user, perhaps root.\n\
604 3) There is already another client called \"ardour\".\n\
606 Please consider the possibilities, and perhaps (re)start JACK."));
610 win.set_transient_for (*toplevel);
614 win.add_button (Stock::OK, RESPONSE_CLOSE);
616 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
619 win.set_default_response (RESPONSE_CLOSE);
622 win.set_position (Gtk::WIN_POS_CENTER);
625 /* we just don't care about the result, but we want to block */
631 ARDOUR_UI::startup ()
635 new_session_dialog = new NewSessionDialog();
637 bool backend_audio_is_running = EngineControl::engine_running();
638 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
641 new_session_dialog->engine_control.set_state (*audio_setup);
644 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
648 BootMessage (_("Ardour is ready for use"));
653 ARDOUR_UI::no_memory_warning ()
655 XMLNode node (X_("no-memory-warning"));
656 Config->add_instant_xml (node);
660 ARDOUR_UI::check_memory_locking ()
663 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
667 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
669 if (engine->is_realtime() && memory_warning_node == 0) {
671 struct rlimit limits;
673 long pages, page_size;
675 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
678 ram = (int64_t) pages * (int64_t) page_size;
681 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
685 if (limits.rlim_cur != RLIM_INFINITY) {
687 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
690 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
691 "This might cause Ardour to run out of memory before your system "
692 "runs out of memory. \n\n"
693 "You can view the memory limit with 'ulimit -l', "
694 "and it is normally controlled by /etc/security/limits.conf"));
696 VBox* vbox = msg.get_vbox();
698 CheckButton cb (_("Do not show this window again"));
700 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
702 hbox.pack_start (cb, true, false);
703 vbox->pack_start (hbox);
710 editor->ensure_float (msg);
724 if (session->transport_rolling()) {
725 session->request_stop ();
729 if (session->dirty()) {
730 switch (ask_about_saving_session(_("quit"))) {
735 /* use the default name */
736 if (save_state_canfail ("")) {
737 /* failed - don't quit */
738 MessageDialog msg (*editor,
740 Ardour was unable to save your session.\n\n\
741 If you still wish to quit, please use the\n\n\
742 \"Just quit\" option."));
753 session->set_deletion_in_progress ();
757 Config->save_state();
758 ARDOUR_UI::config()->save_state();
763 ARDOUR_UI::ask_about_saving_session (const string & what)
765 ArdourDialog window (_("ardour: save session?"));
766 Gtk::HBox dhbox; // the hbox for the image and text
767 Gtk::Label prompt_label;
768 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
772 msg = string_compose(_("Don't %1"), what);
773 window.add_button (msg, RESPONSE_REJECT);
774 msg = string_compose(_("Just %1"), what);
775 window.add_button (msg, RESPONSE_APPLY);
776 msg = string_compose(_("Save and %1"), what);
777 window.add_button (msg, RESPONSE_ACCEPT);
779 window.set_default_response (RESPONSE_ACCEPT);
781 Gtk::Button noquit_button (msg);
782 noquit_button.set_name ("EditorGTKButton");
787 if (session->snap_name() == session->name()) {
790 type = _("snapshot");
792 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?"),
793 type, session->snap_name());
795 prompt_label.set_text (prompt);
796 prompt_label.set_name (X_("PrompterLabel"));
797 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
799 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
801 dhbox.set_homogeneous (false);
802 dhbox.pack_start (*dimage, false, false, 5);
803 dhbox.pack_start (prompt_label, true, false, 5);
804 window.get_vbox()->pack_start (dhbox);
806 window.set_name (_("Prompter"));
807 window.set_position (Gtk::WIN_POS_MOUSE);
808 window.set_modal (true);
809 window.set_resizable (false);
816 save_the_session = 0;
818 window.set_keep_above (true);
821 ResponseType r = (ResponseType) window.run();
826 case RESPONSE_ACCEPT: // save and get out of here
828 case RESPONSE_APPLY: // get out of here
838 ARDOUR_UI::every_second ()
841 update_buffer_load ();
842 update_disk_space ();
847 ARDOUR_UI::every_point_one_seconds ()
849 update_speed_display ();
850 RapidScreenUpdate(); /* EMIT_SIGNAL */
855 ARDOUR_UI::every_point_zero_one_seconds ()
857 // august 2007: actual update frequency: 40Hz, not 100Hz
859 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
864 ARDOUR_UI::update_sample_rate (nframes_t ignored)
868 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
870 if (!engine->connected()) {
872 snprintf (buf, sizeof (buf), _("disconnected"));
876 nframes_t rate = engine->frame_rate();
878 if (fmod (rate, 1000.0) != 0.0) {
879 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
880 (float) rate/1000.0f,
881 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
883 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
889 sample_rate_label.set_text (buf);
893 ARDOUR_UI::update_cpu_load ()
896 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
897 cpu_load_label.set_text (buf);
901 ARDOUR_UI::update_buffer_load ()
906 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
907 session->playback_load(), session->capture_load());
908 buffer_load_label.set_text (buf);
910 buffer_load_label.set_text ("");
915 ARDOUR_UI::count_recenabled_streams (Route& route)
917 Track* track = dynamic_cast<Track*>(&route);
918 if (track && track->diskstream()->record_enabled()) {
919 rec_enabled_streams += track->n_inputs().n_total();
924 ARDOUR_UI::update_disk_space()
930 nframes_t frames = session->available_capture_duration();
933 if (frames == max_frames) {
934 strcpy (buf, _("Disk: 24hrs+"));
939 nframes_t fr = session->frame_rate();
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;
948 hrs = frames / (fr * 3600);
949 frames -= hrs * fr * 3600;
950 mins = frames / (fr * 60);
951 frames -= mins * fr * 60;
954 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
957 disk_space_label.set_text (buf);
961 ARDOUR_UI::update_wall_clock ()
968 tm_now = localtime (&now);
970 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
971 wall_clock_label.set_text (buf);
977 ARDOUR_UI::session_menu (GdkEventButton *ev)
979 session_popup_menu->popup (0, 0);
984 ARDOUR_UI::redisplay_recent_sessions ()
986 std::vector<sys::path> session_directories;
987 RecentSessionsSorter cmp;
989 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
990 recent_session_model->clear ();
992 ARDOUR::RecentSessions rs;
993 ARDOUR::read_recent_sessions (rs);
996 recent_session_display.set_model (recent_session_model);
1000 // sort them alphabetically
1001 sort (rs.begin(), rs.end(), cmp);
1003 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1004 session_directories.push_back ((*i).second);
1007 for (vector<sys::path>::const_iterator i = session_directories.begin();
1008 i != session_directories.end(); ++i)
1010 std::vector<sys::path> state_file_paths;
1012 // now get available states for this session
1014 get_state_files_in_directory (*i, state_file_paths);
1016 vector<string*>* states;
1017 vector<const gchar*> item;
1018 string fullpath = (*i).to_string();
1020 /* remove any trailing / */
1022 if (fullpath[fullpath.length()-1] == '/') {
1023 fullpath = fullpath.substr (0, fullpath.length()-1);
1026 /* check whether session still exists */
1027 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1028 /* session doesn't exist */
1029 cerr << "skipping non-existent session " << fullpath << endl;
1033 /* now get available states for this session */
1035 if ((states = Session::possible_states (fullpath)) == 0) {
1036 /* no state file? */
1040 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1042 Gtk::TreeModel::Row row = *(recent_session_model->append());
1044 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1045 row[recent_session_columns.fullpath] = fullpath;
1047 if (state_file_names.size() > 1) {
1051 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1052 i2 != state_file_names.end(); ++i2)
1055 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1057 child_row[recent_session_columns.visible_name] = *i2;
1058 child_row[recent_session_columns.fullpath] = fullpath;
1063 recent_session_display.set_model (recent_session_model);
1067 ARDOUR_UI::build_session_selector ()
1069 session_selector_window = new ArdourDialog ("session selector");
1071 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1073 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1074 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1075 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1076 recent_session_model = TreeStore::create (recent_session_columns);
1077 recent_session_display.set_model (recent_session_model);
1078 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1079 recent_session_display.set_headers_visible (false);
1080 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1081 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1083 scroller->add (recent_session_display);
1084 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1086 session_selector_window->set_name ("SessionSelectorWindow");
1087 session_selector_window->set_size_request (200, 400);
1088 session_selector_window->get_vbox()->pack_start (*scroller);
1090 recent_session_display.show();
1092 //session_selector_window->get_vbox()->show();
1096 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1098 session_selector_window->response (RESPONSE_ACCEPT);
1102 ARDOUR_UI::open_recent_session ()
1104 bool can_return = (session != 0);
1106 if (session_selector_window == 0) {
1107 build_session_selector ();
1110 redisplay_recent_sessions ();
1114 session_selector_window->set_position (WIN_POS_MOUSE);
1116 ResponseType r = (ResponseType) session_selector_window->run ();
1119 case RESPONSE_ACCEPT:
1123 session_selector_window->hide();
1130 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1134 session_selector_window->hide();
1136 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1138 if (i == recent_session_model->children().end()) {
1142 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1143 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1145 _session_is_new = false;
1147 if (load_session (path, state) == 0) {
1156 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1158 struct stat statbuf;
1160 if (stat (info.filename.c_str(), &statbuf) != 0) {
1164 if (!S_ISDIR(statbuf.st_mode)) {
1170 string session_file = info.filename;
1171 session_file += '/';
1172 session_file += Glib::path_get_basename (info.filename);
1173 session_file += ".ardour";
1175 if (stat (session_file.c_str(), &statbuf) != 0) {
1179 return S_ISREG (statbuf.st_mode);
1183 ARDOUR_UI::check_audioengine ()
1186 if (!engine->connected()) {
1187 MessageDialog msg (_("Ardour is not connected to JACK\n"
1188 "You cannot open or close sessions in this condition"));
1200 ARDOUR_UI::open_session ()
1202 if (!check_audioengine()) {
1207 /* popup selector window */
1209 if (open_session_selector == 0) {
1211 /* ardour sessions are folders */
1213 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1214 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1215 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1216 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1218 FileFilter session_filter;
1219 session_filter.add_pattern ("*.ardour");
1220 session_filter.set_name (_("Ardour sessions"));
1221 open_session_selector->add_filter (session_filter);
1222 open_session_selector->set_filter (session_filter);
1225 int response = open_session_selector->run();
1226 open_session_selector->hide ();
1229 case RESPONSE_ACCEPT:
1232 open_session_selector->hide();
1236 open_session_selector->hide();
1237 string session_path = open_session_selector->get_filename();
1241 if (session_path.length() > 0) {
1242 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1243 _session_is_new = isnew;
1244 load_session (path, name);
1251 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1253 list<boost::shared_ptr<MidiTrack> > tracks;
1256 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1263 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1265 if (tracks.size() != how_many) {
1266 if (how_many == 1) {
1267 error << _("could not create a new midi track") << endmsg;
1269 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1273 if ((route = session->new_midi_route ()) == 0) {
1274 error << _("could not create new midi bus") << endmsg;
1280 MessageDialog msg (*editor,
1281 _("There are insufficient JACK ports available\n\
1282 to create a new track or bus.\n\
1283 You should save Ardour, exit and\n\
1284 restart JACK with more ports."));
1291 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1293 list<boost::shared_ptr<AudioTrack> > tracks;
1294 Session::RouteList routes;
1297 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1303 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1305 if (tracks.size() != how_many) {
1306 if (how_many == 1) {
1307 error << _("could not create a new audio track") << endmsg;
1309 error << string_compose (_("could only create %1 of %2 new audio %3"),
1310 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1316 routes = session->new_audio_route (input_channels, output_channels, how_many);
1318 if (routes.size() != how_many) {
1319 if (how_many == 1) {
1320 error << _("could not create a new audio track") << endmsg;
1322 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1328 if (need_control_room_outs) {
1334 route->set_stereo_control_outs (control_lr_channels);
1335 route->control_outs()->set_stereo_pan (pans, this);
1337 #endif /* CONTROLOUTS */
1341 MessageDialog msg (*editor,
1342 _("There are insufficient JACK ports available\n\
1343 to create a new track or bus.\n\
1344 You should save Ardour, exit and\n\
1345 restart JACK with more ports."));
1352 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1354 nframes_t _preroll = 0;
1357 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1358 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1360 if (new_position > _preroll) {
1361 new_position -= _preroll;
1366 session->request_locate (new_position);
1371 ARDOUR_UI::transport_goto_start ()
1374 session->goto_start();
1377 /* force displayed area in editor to start no matter
1378 what "follow playhead" setting is.
1382 editor->reset_x_origin (session->current_start_frame());
1388 ARDOUR_UI::transport_goto_zero ()
1391 session->request_locate (0);
1394 /* force displayed area in editor to start no matter
1395 what "follow playhead" setting is.
1399 editor->reset_x_origin (0);
1405 ARDOUR_UI::transport_goto_end ()
1408 nframes_t frame = session->current_end_frame();
1409 session->request_locate (frame);
1411 /* force displayed area in editor to start no matter
1412 what "follow playhead" setting is.
1416 editor->reset_x_origin (frame);
1422 ARDOUR_UI::transport_stop ()
1428 if (session->is_auditioning()) {
1429 session->cancel_audition ();
1433 if (session->get_play_loop ()) {
1434 session->request_play_loop (false);
1437 session->request_stop ();
1441 ARDOUR_UI::transport_stop_and_forget_capture ()
1444 session->request_stop (true);
1449 ARDOUR_UI::remove_last_capture()
1452 editor->remove_last_capture();
1457 ARDOUR_UI::transport_record (bool roll)
1461 switch (session->record_status()) {
1462 case Session::Disabled:
1463 if (session->ntracks() == 0) {
1464 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1468 session->maybe_enable_record ();
1473 case Session::Recording:
1475 session->request_stop();
1477 session->disable_record (false, true);
1481 case Session::Enabled:
1482 session->disable_record (false, true);
1485 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1489 ARDOUR_UI::transport_roll ()
1497 rolling = session->transport_rolling ();
1499 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1501 if (session->get_play_loop()) {
1502 session->request_play_loop (false);
1503 auto_loop_button.set_visual_state (1);
1504 roll_button.set_visual_state (1);
1505 } else if (session->get_play_range ()) {
1506 session->request_play_range (false);
1507 play_selection_button.set_visual_state (0);
1508 } else if (rolling) {
1509 session->request_locate (session->last_transport_start(), true);
1512 session->request_transport_speed (1.0f);
1516 ARDOUR_UI::transport_loop()
1519 if (session->get_play_loop()) {
1520 if (session->transport_rolling()) {
1521 Location * looploc = session->locations()->auto_loop_location();
1523 session->request_locate (looploc->start(), true);
1528 session->request_play_loop (true);
1534 ARDOUR_UI::transport_play_selection ()
1540 if (!session->get_play_range()) {
1541 session->request_stop ();
1544 editor->play_selection ();
1548 ARDOUR_UI::transport_rewind (int option)
1550 float current_transport_speed;
1553 current_transport_speed = session->transport_speed();
1555 if (current_transport_speed >= 0.0f) {
1558 session->request_transport_speed (-1.0f);
1561 session->request_transport_speed (-4.0f);
1564 session->request_transport_speed (-0.5f);
1569 session->request_transport_speed (current_transport_speed * 1.5f);
1575 ARDOUR_UI::transport_forward (int option)
1577 float current_transport_speed;
1580 current_transport_speed = session->transport_speed();
1582 if (current_transport_speed <= 0.0f) {
1585 session->request_transport_speed (1.0f);
1588 session->request_transport_speed (4.0f);
1591 session->request_transport_speed (0.5f);
1596 session->request_transport_speed (current_transport_speed * 1.5f);
1602 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1608 boost::shared_ptr<Route> r;
1610 if ((r = session->route_by_remote_id (dstream)) != 0) {
1614 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1615 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1624 ARDOUR_UI::queue_transport_change ()
1626 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1630 ARDOUR_UI::map_transport_state ()
1632 float sp = session->transport_speed();
1635 transport_rolling ();
1636 } else if (sp < 0.0f) {
1637 transport_rewinding ();
1638 } else if (sp > 0.0f) {
1639 transport_forwarding ();
1641 transport_stopped ();
1646 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1648 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1649 (int) adj.get_value()].c_str());
1653 ARDOUR_UI::engine_stopped ()
1655 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1656 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1657 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1661 ARDOUR_UI::engine_running ()
1663 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1664 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1665 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1667 Glib::RefPtr<Action> action;
1668 const char* action_name = 0;
1670 switch (engine->frames_per_cycle()) {
1672 action_name = X_("JACKLatency32");
1675 action_name = X_("JACKLatency64");
1678 action_name = X_("JACKLatency128");
1681 action_name = X_("JACKLatency512");
1684 action_name = X_("JACKLatency1024");
1687 action_name = X_("JACKLatency2048");
1690 action_name = X_("JACKLatency4096");
1693 action_name = X_("JACKLatency8192");
1696 /* XXX can we do anything useful ? */
1702 action = ActionManager::get_action (X_("JACK"), action_name);
1705 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1706 ract->set_active ();
1712 ARDOUR_UI::engine_halted ()
1714 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1716 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1717 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1719 update_sample_rate (0);
1721 MessageDialog msg (*editor,
1723 JACK has either been shutdown or it\n\
1724 disconnected Ardour because Ardour\n\
1725 was not fast enough. You can save the\n\
1726 session and/or try to reconnect to JACK ."));
1732 ARDOUR_UI::do_engine_start ()
1740 error << _("Unable to start the session running")
1750 ARDOUR_UI::setup_theme ()
1752 theme_manager->setup_theme();
1756 ARDOUR_UI::update_clocks ()
1758 if (!editor || !editor->dragging_playhead()) {
1759 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1764 ARDOUR_UI::start_clocking ()
1766 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1770 ARDOUR_UI::stop_clocking ()
1772 clock_signal_connection.disconnect ();
1776 ARDOUR_UI::toggle_clocking ()
1779 if (clock_button.get_active()) {
1788 ARDOUR_UI::_blink (void *arg)
1791 ((ARDOUR_UI *) arg)->blink ();
1798 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1802 ARDOUR_UI::start_blinking ()
1804 /* Start the blink signal. Everybody with a blinking widget
1805 uses Blink to drive the widget's state.
1808 if (blink_timeout_tag < 0) {
1810 blink_timeout_tag = g_timeout_add (240, _blink, this);
1815 ARDOUR_UI::stop_blinking ()
1817 if (blink_timeout_tag >= 0) {
1818 g_source_remove (blink_timeout_tag);
1819 blink_timeout_tag = -1;
1824 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1829 vector<string> connections;
1832 if (io.n_inputs().n_total() == 0) {
1837 /* XXX we're not handling multiple ports yet. */
1839 if (io.input(0)->get_connections(connections) == 0) {
1842 buf = connections.front();
1847 if (io.n_outputs().n_total() == 0) {
1852 /* XXX we're not handling multiple ports yet. */
1854 if (io.output(0)->get_connections(connections) == 0) {
1857 buf = connections.front();
1862 /** Ask the user for the name of a new shapshot and then take it.
1865 ARDOUR_UI::snapshot_session ()
1867 ArdourPrompter prompter (true);
1871 struct tm local_time;
1874 localtime_r (&n, &local_time);
1875 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1877 prompter.set_name ("Prompter");
1878 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1879 prompter.set_prompt (_("Name of New Snapshot"));
1880 prompter.set_initial_text (timebuf);
1882 switch (prompter.run()) {
1883 case RESPONSE_ACCEPT:
1884 prompter.get_result (snapname);
1885 if (snapname.length()){
1886 save_state (snapname);
1896 ARDOUR_UI::save_state (const string & name)
1898 (void) save_state_canfail (name);
1902 ARDOUR_UI::save_state_canfail (string name)
1907 if (name.length() == 0) {
1908 name = session->snap_name();
1911 if ((ret = session->save_state (name)) != 0) {
1915 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1920 ARDOUR_UI::restore_state (string name)
1923 if (name.length() == 0) {
1924 name = session->name();
1926 session->restore_state (name);
1931 ARDOUR_UI::primary_clock_value_changed ()
1934 session->request_locate (primary_clock.current_time ());
1939 ARDOUR_UI::big_clock_value_changed ()
1942 session->request_locate (big_clock.current_time ());
1947 ARDOUR_UI::secondary_clock_value_changed ()
1950 session->request_locate (secondary_clock.current_time ());
1955 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1957 if (session && dstream && dstream->record_enabled()) {
1959 Session::RecordState rs;
1961 rs = session->record_status ();
1964 case Session::Disabled:
1965 case Session::Enabled:
1966 if (w->get_state() != STATE_SELECTED) {
1967 w->set_state (STATE_SELECTED);
1971 case Session::Recording:
1972 if (w->get_state() != STATE_ACTIVE) {
1973 w->set_state (STATE_ACTIVE);
1979 if (w->get_state() != STATE_NORMAL) {
1980 w->set_state (STATE_NORMAL);
1986 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1992 switch (session->record_status()) {
1993 case Session::Enabled:
1995 rec_button.set_visual_state (2);
1997 rec_button.set_visual_state (0);
2001 case Session::Recording:
2002 rec_button.set_visual_state (1);
2006 rec_button.set_visual_state (0);
2012 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2020 ARDOUR_UI::save_template ()
2023 ArdourPrompter prompter (true);
2026 if (!check_audioengine()) {
2030 prompter.set_name (X_("Prompter"));
2031 prompter.set_prompt (_("Name for mix template:"));
2032 prompter.set_initial_text(session->name() + _("-template"));
2033 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2035 switch (prompter.run()) {
2036 case RESPONSE_ACCEPT:
2037 prompter.get_result (name);
2039 if (name.length()) {
2040 session->save_template (name);
2050 ARDOUR_UI::fontconfig_dialog ()
2053 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2054 may not and it can take a while to build it. Warn them.
2057 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2059 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2060 MessageDialog msg (*new_session_dialog,
2061 _("Welcome to Ardour.\n\n"
2062 "The program will take a bit longer to start up\n"
2063 "while the system fonts are checked.\n\n"
2064 "This will only be done once, and you will\n"
2065 "not see this message again\n"),
2078 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2080 existing_session = false;
2082 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2083 session_path = cmdline_path;
2084 existing_session = true;
2085 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2086 session_path = Glib::path_get_dirname (string (cmdline_path));
2087 existing_session = true;
2089 /* it doesn't exist, assume the best */
2090 session_path = Glib::path_get_dirname (string (cmdline_path));
2093 session_name = basename_nosuffix (string (cmdline_path));
2097 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2099 /* when this is called, the backend audio system must be running */
2101 /* the main idea here is to deal with the fact that a cmdline argument for the session
2102 can be interpreted in different ways - it could be a directory or a file, and before
2103 we load, we need to know both the session directory and the snapshot (statefile) within it
2104 that we are supposed to use.
2107 if (session_name.length() == 0 || session_path.length() == 0) {
2111 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2113 Glib::ustring predicted_session_file;
2115 predicted_session_file = session_path;
2116 predicted_session_file += '/';
2117 predicted_session_file += session_name;
2118 predicted_session_file += ARDOUR::statefile_suffix;
2120 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2121 existing_session = true;
2124 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2126 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2127 /* existing .ardour file */
2128 existing_session = true;
2132 existing_session = false;
2135 /* lets just try to load it */
2137 if (create_engine ()) {
2138 backend_audio_error (false, new_session_dialog);
2142 return load_session (session_path, session_name);
2146 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2148 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2150 MessageDialog msg (str,
2152 Gtk::MESSAGE_WARNING,
2153 Gtk::BUTTONS_YES_NO,
2157 msg.set_name (X_("CleanupDialog"));
2158 msg.set_wmclass (X_("existing_session"), "Ardour");
2159 msg.set_position (Gtk::WIN_POS_MOUSE);
2162 switch (msg.run()) {
2171 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2176 AutoConnectOption iconnect;
2177 AutoConnectOption oconnect;
2181 if (Profile->get_sae()) {
2185 iconnect = AutoConnectPhysical;
2186 oconnect = AutoConnectMaster;
2187 nphysin = 0; // use all available
2188 nphysout = 0; // use all available
2192 /* get settings from advanced section of NSD */
2194 if (new_session_dialog->create_control_bus()) {
2195 cchns = (uint32_t) new_session_dialog->control_channel_count();
2200 if (new_session_dialog->create_master_bus()) {
2201 mchns = (uint32_t) new_session_dialog->master_channel_count();
2206 if (new_session_dialog->connect_inputs()) {
2207 iconnect = AutoConnectPhysical;
2209 iconnect = AutoConnectOption (0);
2212 /// @todo some minor tweaks.
2214 if (new_session_dialog->connect_outs_to_master()) {
2215 oconnect = AutoConnectMaster;
2216 } else if (new_session_dialog->connect_outs_to_physical()) {
2217 oconnect = AutoConnectPhysical;
2219 oconnect = AutoConnectOption (0);
2222 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2223 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2226 if (build_session (session_path,
2234 engine->frame_rate() * 60 * 5)) {
2243 ARDOUR_UI::end_loading_messages ()
2249 ARDOUR_UI::loading_message (const std::string& msg)
2252 splash->message (msg);
2257 ARDOUR_UI::idle_load (const Glib::ustring& path)
2260 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2261 /* /path/to/foo => /path/to/foo, foo */
2262 load_session (path, basename_nosuffix (path));
2264 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2265 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2268 ARDOUR_COMMAND_LINE::session_name = path;
2269 if (new_session_dialog) {
2270 /* make it break out of Dialog::run() and
2273 new_session_dialog->response (1);
2279 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2281 bool existing_session = false;
2282 Glib::ustring session_name;
2283 Glib::ustring session_path;
2284 Glib::ustring template_name;
2288 response = Gtk::RESPONSE_NONE;
2290 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2292 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2294 /* don't ever reuse this */
2296 ARDOUR_COMMAND_LINE::session_name = string();
2298 if (existing_session && backend_audio_is_running) {
2300 /* just load the thing already */
2302 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2307 /* make the NSD use whatever information we have */
2309 new_session_dialog->set_session_name (session_name);
2310 new_session_dialog->set_session_folder (session_path);
2313 /* loading failed, or we need the NSD for something */
2315 new_session_dialog->set_modal (false);
2316 new_session_dialog->set_position (WIN_POS_CENTER);
2317 new_session_dialog->set_current_page (0);
2318 new_session_dialog->set_existing_session (existing_session);
2319 new_session_dialog->reset_recent();
2322 new_session_dialog->set_have_engine (backend_audio_is_running);
2323 new_session_dialog->present ();
2324 end_loading_messages ();
2325 response = new_session_dialog->run ();
2327 _session_is_new = false;
2329 /* handle possible negative responses */
2333 /* sent by idle_load, meaning restart the whole process again */
2334 new_session_dialog->hide();
2335 new_session_dialog->reset();
2339 case Gtk::RESPONSE_CANCEL:
2340 case Gtk::RESPONSE_DELETE_EVENT:
2344 new_session_dialog->hide ();
2347 case Gtk::RESPONSE_NONE:
2348 /* "Clear" was pressed */
2352 fontconfig_dialog();
2354 if (!backend_audio_is_running) {
2355 if (new_session_dialog->engine_control.setup_engine ()) {
2356 new_session_dialog->hide ();
2361 if (create_engine ()) {
2363 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2366 new_session_dialog->set_existing_session (false);
2367 new_session_dialog->set_current_page (2);
2369 response = Gtk::RESPONSE_NONE;
2373 backend_audio_is_running = true;
2375 if (response == Gtk::RESPONSE_OK) {
2377 session_name = new_session_dialog->session_name();
2379 if (session_name.empty()) {
2380 response = Gtk::RESPONSE_NONE;
2384 /* if the user mistakenly typed path information into the session filename entry,
2385 convert what they typed into a path & a name
2388 if (session_name[0] == '/' ||
2389 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2390 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2392 session_path = Glib::path_get_dirname (session_name);
2393 session_name = Glib::path_get_basename (session_name);
2397 session_path = new_session_dialog->session_folder();
2400 template_name = Glib::ustring();
2401 switch (new_session_dialog->which_page()) {
2403 case NewSessionDialog::OpenPage:
2404 case NewSessionDialog::EnginePage:
2408 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2410 should_be_new = true;
2412 //XXX This is needed because session constructor wants a
2413 //non-existant path. hopefully this will be fixed at some point.
2415 session_path = Glib::build_filename (session_path, session_name);
2417 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2419 if (ask_about_loading_existing_session (session_path)) {
2422 response = RESPONSE_NONE;
2427 _session_is_new = true;
2429 if (new_session_dialog->use_session_template()) {
2431 template_name = new_session_dialog->session_template_name();
2435 if (build_session_from_nsd (session_path, session_name)) {
2436 response = RESPONSE_NONE;
2448 new_session_dialog->hide ();
2450 if (load_session (session_path, session_name, template_name)) {
2452 response = Gtk::RESPONSE_NONE;
2456 if (response == Gtk::RESPONSE_NONE) {
2457 new_session_dialog->set_existing_session (false);
2458 new_session_dialog->reset ();
2462 } while (response == Gtk::RESPONSE_NONE);
2466 new_session_dialog->hide();
2467 new_session_dialog->reset();
2468 goto_editor_window ();
2473 ARDOUR_UI::close_session()
2475 if (!check_audioengine()) {
2479 unload_session (true);
2481 get_session_parameters (true, false);
2485 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2487 Session *new_session;
2491 session_loaded = false;
2493 if (!check_audioengine()) {
2497 unload_status = unload_session ();
2499 if (unload_status < 0) {
2501 } else if (unload_status > 0) {
2506 /* if it already exists, we must have write access */
2508 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2509 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2510 "This prevents the session from being loaded."));
2516 loading_message (_("Please wait while Ardour loads your session"));
2519 new_session = new Session (*engine, path, snap_name, mix_template);
2522 /* this one is special */
2524 catch (AudioEngine::PortRegistrationFailure& err) {
2526 MessageDialog msg (err.what(),
2529 Gtk::BUTTONS_OK_CANCEL);
2531 msg.set_title (_("Loading Error"));
2532 msg.set_secondary_text (_("Click the OK button to try again."));
2533 msg.set_position (Gtk::WIN_POS_CENTER);
2537 int response = msg.run ();
2542 case RESPONSE_CANCEL:
2552 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2555 Gtk::BUTTONS_OK_CANCEL);
2557 msg.set_title (_("Loading Error"));
2558 msg.set_secondary_text (_("Click the OK button to try again."));
2559 msg.set_position (Gtk::WIN_POS_CENTER);
2563 int response = msg.run ();
2568 case RESPONSE_CANCEL:
2576 connect_to_session (new_session);
2578 Config->set_current_owner (ConfigVariableBase::Interface);
2580 session_loaded = true;
2582 goto_editor_window ();
2585 session->set_clean ();
2596 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2597 uint32_t control_channels,
2598 uint32_t master_channels,
2599 AutoConnectOption input_connect,
2600 AutoConnectOption output_connect,
2603 nframes_t initial_length)
2605 Session *new_session;
2608 if (!check_audioengine()) {
2612 session_loaded = false;
2614 x = unload_session ();
2622 _session_is_new = true;
2625 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2626 control_channels, master_channels, nphysin, nphysout, initial_length);
2631 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2637 connect_to_session (new_session);
2639 session_loaded = true;
2647 editor->show_window ();
2658 ARDOUR_UI::show_about ()
2662 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2669 ARDOUR_UI::hide_about ()
2672 about->get_window()->set_cursor ();
2678 ARDOUR_UI::about_signal_response(int response)
2684 ARDOUR_UI::show_splash ()
2688 splash = new Splash;
2696 splash->queue_draw ();
2697 splash->get_window()->process_updates (true);
2702 ARDOUR_UI::hide_splash ()
2710 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2714 removed = rep.paths.size();
2717 MessageDialog msgd (*editor,
2718 _("No audio files were ready for cleanup"),
2721 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2722 msgd.set_secondary_text (_("If this seems suprising, \n\
2723 check for any existing snapshots.\n\
2724 These may still include regions that\n\
2725 require some unused files to continue to exist."));
2731 ArdourDialog results (_("ardour: cleanup"), true, false);
2733 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2734 CleanupResultsModelColumns() {
2738 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2739 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2743 CleanupResultsModelColumns results_columns;
2744 Glib::RefPtr<Gtk::ListStore> results_model;
2745 Gtk::TreeView results_display;
2747 results_model = ListStore::create (results_columns);
2748 results_display.set_model (results_model);
2749 results_display.append_column (list_title, results_columns.visible_name);
2751 results_display.set_name ("CleanupResultsList");
2752 results_display.set_headers_visible (true);
2753 results_display.set_headers_clickable (false);
2754 results_display.set_reorderable (false);
2756 Gtk::ScrolledWindow list_scroller;
2759 Gtk::HBox dhbox; // the hbox for the image and text
2760 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2761 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2763 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2765 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2767 if (rep.space < 1048576.0f) {
2769 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2771 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2775 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2777 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2781 dhbox.pack_start (*dimage, true, false, 5);
2782 dhbox.pack_start (txt, true, false, 5);
2784 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2785 TreeModel::Row row = *(results_model->append());
2786 row[results_columns.visible_name] = *i;
2787 row[results_columns.fullpath] = *i;
2790 list_scroller.add (results_display);
2791 list_scroller.set_size_request (-1, 150);
2792 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2794 dvbox.pack_start (dhbox, true, false, 5);
2795 dvbox.pack_start (list_scroller, true, false, 5);
2796 ddhbox.pack_start (dvbox, true, false, 5);
2798 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2799 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2800 results.set_default_response (RESPONSE_CLOSE);
2801 results.set_position (Gtk::WIN_POS_MOUSE);
2803 results_display.show();
2804 list_scroller.show();
2811 //results.get_vbox()->show();
2812 results.set_resizable (false);
2819 ARDOUR_UI::cleanup ()
2822 /* shouldn't happen: menu item is insensitive */
2827 MessageDialog checker (_("Are you sure you want to cleanup?"),
2829 Gtk::MESSAGE_QUESTION,
2830 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2832 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2833 ALL undo/redo information will be lost if you cleanup.\n\
2834 After cleanup, unused audio files will be moved to a \
2835 \"dead sounds\" location."));
2837 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2838 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2839 checker.set_default_response (RESPONSE_CANCEL);
2841 checker.set_name (_("CleanupDialog"));
2842 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2843 checker.set_position (Gtk::WIN_POS_MOUSE);
2845 switch (checker.run()) {
2846 case RESPONSE_ACCEPT:
2852 Session::cleanup_report rep;
2854 editor->prepare_for_cleanup ();
2856 /* do not allow flush until a session is reloaded */
2858 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2860 act->set_sensitive (false);
2863 if (session->cleanup_sources (rep)) {
2868 display_cleanup_results (rep,
2871 The following %1 %2 not in use and \n\
2872 have been moved to:\n\
2874 Flushing the wastebasket will \n\
2875 release an additional\n\
2876 %4 %5bytes of disk space.\n"
2884 ARDOUR_UI::flush_trash ()
2887 /* shouldn't happen: menu item is insensitive */
2891 Session::cleanup_report rep;
2893 if (session->cleanup_trash_sources (rep)) {
2897 display_cleanup_results (rep,
2899 _("The following %1 %2 deleted from\n\
2901 releasing %4 %5bytes of disk space"));
2905 ARDOUR_UI::add_route (Gtk::Window* float_window)
2913 if (add_route_dialog == 0) {
2914 add_route_dialog = new AddRouteDialog;
2916 add_route_dialog->set_transient_for (*float_window);
2920 if (add_route_dialog->is_visible()) {
2921 /* we're already doing this */
2925 ResponseType r = (ResponseType) add_route_dialog->run ();
2927 add_route_dialog->hide();
2930 case RESPONSE_ACCEPT:
2937 if ((count = add_route_dialog->count()) <= 0) {
2941 uint32_t input_chan = add_route_dialog->channels ();
2942 uint32_t output_chan;
2943 string name_template = add_route_dialog->name_template ();
2944 bool track = add_route_dialog->track ();
2946 AutoConnectOption oac = Config->get_output_auto_connect();
2948 if (oac & AutoConnectMaster) {
2949 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2951 output_chan = input_chan;
2954 /* XXX do something with name template */
2956 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2958 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2960 session_add_midi_track(count);
2962 MessageDialog msg (*editor,
2963 _("Sorry, MIDI Busses are not supported at this time."));
2965 //session_add_midi_bus();
2969 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2971 session_add_audio_bus (input_chan, output_chan, count);
2977 ARDOUR_UI::mixer_settings () const
2982 node = session->instant_xml(X_("Mixer"));
2984 node = Config->instant_xml(X_("Mixer"));
2988 node = new XMLNode (X_("Mixer"));
2995 ARDOUR_UI::editor_settings () const
3000 node = session->instant_xml(X_("Editor"));
3002 node = Config->instant_xml(X_("Editor"));
3006 node = new XMLNode (X_("Editor"));
3012 ARDOUR_UI::keyboard_settings () const
3016 node = Config->extra_xml(X_("Keyboard"));
3019 node = new XMLNode (X_("Keyboard"));
3025 ARDOUR_UI::create_xrun_marker(nframes_t where)
3027 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where));
3028 editor->mouse_add_new_marker (where, false, true);
3032 ARDOUR_UI::halt_on_xrun_message ()
3034 MessageDialog msg (*editor,
3035 _("Recording was stopped because your system could not keep up."));
3040 ARDOUR_UI::xrun_handler(nframes_t where)
3042 if (Config->get_create_xrun_marker() && session->actively_recording()) {
3043 create_xrun_marker(where);
3046 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3047 halt_on_xrun_message ();
3052 ARDOUR_UI::disk_overrun_handler ()
3054 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3056 if (!have_disk_speed_dialog_displayed) {
3057 have_disk_speed_dialog_displayed = true;
3058 MessageDialog* msg = new MessageDialog (*editor, _("\
3059 The disk system on your computer\n\
3060 was not able to keep up with Ardour.\n\
3062 Specifically, it failed to write data to disk\n\
3063 quickly enough to keep up with recording.\n"));
3064 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3070 ARDOUR_UI::disk_underrun_handler ()
3072 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3074 if (!have_disk_speed_dialog_displayed) {
3075 have_disk_speed_dialog_displayed = true;
3076 MessageDialog* msg = new MessageDialog (*editor,
3077 _("The disk system on your computer\n\
3078 was not able to keep up with Ardour.\n\
3080 Specifically, it failed to read data from disk\n\
3081 quickly enough to keep up with playback.\n"));
3082 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3088 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3090 have_disk_speed_dialog_displayed = false;
3095 ARDOUR_UI::session_dialog (std::string msg)
3097 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3102 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3104 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3113 ARDOUR_UI::pending_state_dialog ()
3115 HBox* hbox = new HBox();
3116 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3117 ArdourDialog dialog (_("Crash Recovery"), true);
3119 This session appears to have been in\n\
3120 middle of recording when ardour or\n\
3121 the computer was shutdown.\n\
3123 Ardour can recover any captured audio for\n\
3124 you, or it can ignore it. Please decide\n\
3125 what you would like to do.\n"));
3126 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3127 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3128 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3129 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3130 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3131 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3132 dialog.set_default_response (RESPONSE_ACCEPT);
3133 dialog.set_position (WIN_POS_CENTER);
3138 switch (dialog.run ()) {
3139 case RESPONSE_ACCEPT:
3147 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3149 HBox* hbox = new HBox();
3150 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3151 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3152 Label message (string_compose (_("\
3153 This session was created with a sample rate of %1 Hz\n\
3155 The audioengine is currently running at %2 Hz\n"), desired, actual));
3157 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3158 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3159 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3160 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3161 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3162 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3163 dialog.set_default_response (RESPONSE_ACCEPT);
3164 dialog.set_position (WIN_POS_CENTER);
3169 switch (dialog.run ()) {
3170 case RESPONSE_ACCEPT:
3179 ARDOUR_UI::disconnect_from_jack ()
3182 if( engine->disconnect_from_jack ()) {
3183 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3187 update_sample_rate (0);
3192 ARDOUR_UI::reconnect_to_jack ()
3195 if (engine->reconnect_to_jack ()) {
3196 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3200 update_sample_rate (0);
3205 ARDOUR_UI::use_config ()
3207 Glib::RefPtr<Action> act;
3209 switch (Config->get_native_file_data_format ()) {
3211 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3214 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3217 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3222 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3223 ract->set_active ();
3226 switch (Config->get_native_file_header_format ()) {
3228 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3231 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3234 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3237 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3240 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3243 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3246 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3251 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3252 ract->set_active ();
3255 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3257 set_transport_controllable_state (*node);
3262 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3264 if (Config->get_primary_clock_delta_edit_cursor()) {
3265 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3267 primary_clock.set (pos, 0, true);
3270 if (Config->get_secondary_clock_delta_edit_cursor()) {
3271 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3273 secondary_clock.set (pos);
3276 if (big_clock_window) {
3277 big_clock.set (pos);
3282 ARDOUR_UI::record_state_changed ()
3284 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3286 if (!session || !big_clock_window) {
3287 /* why bother - the clock isn't visible */
3291 switch (session->record_status()) {
3292 case Session::Recording:
3293 big_clock.set_widget_name ("BigClockRecording");
3296 big_clock.set_widget_name ("BigClockNonRecording");
3302 ARDOUR_UI::first_idle ()
3305 session->allow_auto_play (true);
3309 editor->first_idle();
3312 Keyboard::set_can_save_keybindings (true);
3317 ARDOUR_UI::store_clock_modes ()
3319 XMLNode* node = new XMLNode(X_("ClockModes"));
3321 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3322 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3325 session->add_extra_xml (*node);
3326 session->set_dirty ();
3331 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3332 : Controllable (name), ui (u), type(tp)
3338 ARDOUR_UI::TransportControllable::set_value (float val)
3340 if (type == ShuttleControl) {
3347 fract = -((0.5f - val)/0.5f);
3349 fract = ((val - 0.5f)/0.5f);
3353 ui.set_shuttle_fract (fract);
3358 /* do nothing: these are radio-style actions */
3362 const char *action = 0;
3366 action = X_("Roll");
3369 action = X_("Stop");
3372 action = X_("Goto Start");
3375 action = X_("Goto End");
3378 action = X_("Loop");
3381 action = X_("Play Selection");
3384 action = X_("Record");
3394 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3402 ARDOUR_UI::TransportControllable::get_value (void) const
3421 case ShuttleControl:
3431 ARDOUR_UI::TransportControllable::set_id (const string& str)
3437 ARDOUR_UI::setup_profile ()
3439 if (gdk_screen_width() < 1200) {
3440 Profile->set_small_screen ();
3444 if (getenv ("ARDOUR_SAE")) {
3445 Profile->set_sae ();
3446 Profile->set_single_package ();