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")),
163 error_log_button (_("Errors"))
166 using namespace Gtk::Menu_Helpers;
172 _auto_display_errors = false;
178 if (ARDOUR_COMMAND_LINE::session_name.length()) {
179 /* only show this if we're not going to post the new session dialog */
183 if (theArdourUI == 0) {
187 ui_config = new UIConfiguration();
188 theme_manager = new ThemeManager();
194 _session_is_new = false;
195 big_clock_window = 0;
196 session_selector_window = 0;
197 last_key_press_time = 0;
198 connection_editor = 0;
199 _will_create_new_session_automatically = false;
200 new_session_dialog = 0;
201 add_route_dialog = 0;
205 open_session_selector = 0;
206 have_configure_timeout = false;
207 have_disk_speed_dialog_displayed = false;
208 session_loaded = false;
209 last_speed_displayed = -1.0f;
210 ignore_dual_punch = false;
212 last_configure_time.tv_sec = 0;
213 last_configure_time.tv_usec = 0;
215 shuttle_grabbed = false;
217 shuttle_max_speed = 8.0f;
219 shuttle_style_menu = 0;
220 shuttle_unit_menu = 0;
222 gettimeofday (&last_peak_grab, 0);
223 gettimeofday (&last_shuttle_request, 0);
225 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
226 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
228 /* handle pending state with a dialog */
230 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
232 /* handle sr mismatch with a dialog */
234 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
236 /* lets get this party started */
239 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
240 throw failed_constructor ();
243 setup_gtk_ardour_enums ();
244 Config->set_current_owner (ConfigVariableBase::Interface);
247 } catch (failed_constructor& err) {
248 error << _("could not initialize Ardour.") << endmsg;
253 /* we like keyboards */
255 keyboard = new Keyboard;
259 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
260 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
266 ARDOUR_UI::create_engine ()
268 // this gets called every time by new_session()
274 loading_message (_("Starting audio engine"));
277 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
284 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
285 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
286 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
287 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
295 ARDOUR_UI::post_engine ()
297 extern int setup_midi ();
299 /* Things to be done once we create the AudioEngine
302 MIDI::Manager::instance()->set_api_data (engine->jack());
305 ActionManager::init ();
308 if (setup_windows ()) {
309 throw failed_constructor ();
312 check_memory_locking();
314 /* this is the first point at which all the keybindings are available */
316 if (ARDOUR_COMMAND_LINE::show_key_actions) {
317 vector<string> names;
318 vector<string> paths;
320 vector<AccelKey> bindings;
322 ActionManager::get_all_actions (names, paths, keys, bindings);
324 vector<string>::iterator n;
325 vector<string>::iterator k;
326 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
327 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
333 blink_timeout_tag = -1;
335 /* the global configuration object is now valid */
339 /* this being a GUI and all, we want peakfiles */
341 AudioFileSource::set_build_peakfiles (true);
342 AudioFileSource::set_build_missing_peakfiles (true);
344 /* set default clock modes */
346 if (Profile->get_sae()) {
347 primary_clock.set_mode (AudioClock::MinSec);
349 primary_clock.set_mode (AudioClock::SMPTE);
351 secondary_clock.set_mode (AudioClock::BBT);
353 /* start the time-of-day-clock */
356 /* OS X provides an always visible wallclock, so don't be stupid */
357 update_wall_clock ();
358 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
361 update_disk_space ();
363 update_sample_rate (engine->frame_rate());
365 /* now start and maybe save state */
367 if (do_engine_start () == 0) {
368 if (session && _session_is_new) {
369 /* we need to retain initial visual
370 settings for a new session
372 session->save_state ("");
377 ARDOUR_UI::~ARDOUR_UI ()
379 save_ardour_state ();
393 if (add_route_dialog) {
394 delete add_route_dialog;
398 if (new_session_dialog) {
399 delete new_session_dialog;
404 ARDOUR_UI::pop_back_splash ()
406 if (Splash::instance()) {
407 // Splash::instance()->pop_back();
408 Splash::instance()->hide ();
413 ARDOUR_UI::configure_timeout ()
418 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
419 /* no configure events yet */
423 gettimeofday (&now, 0);
424 timersub (&now, &last_configure_time, &diff);
426 /* force a gap of 0.5 seconds since the last configure event
429 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
432 have_configure_timeout = false;
433 save_ardour_state ();
439 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
441 if (have_configure_timeout) {
442 gettimeofday (&last_configure_time, 0);
444 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
445 have_configure_timeout = true;
452 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
454 const XMLProperty* prop;
456 if ((prop = node.property ("roll")) != 0) {
457 roll_controllable.set_id (prop->value());
459 if ((prop = node.property ("stop")) != 0) {
460 stop_controllable.set_id (prop->value());
462 if ((prop = node.property ("goto_start")) != 0) {
463 goto_start_controllable.set_id (prop->value());
465 if ((prop = node.property ("goto_end")) != 0) {
466 goto_end_controllable.set_id (prop->value());
468 if ((prop = node.property ("auto_loop")) != 0) {
469 auto_loop_controllable.set_id (prop->value());
471 if ((prop = node.property ("play_selection")) != 0) {
472 play_selection_controllable.set_id (prop->value());
474 if ((prop = node.property ("rec")) != 0) {
475 rec_controllable.set_id (prop->value());
477 if ((prop = node.property ("shuttle")) != 0) {
478 shuttle_controllable.set_id (prop->value());
483 ARDOUR_UI::get_transport_controllable_state ()
485 XMLNode* node = new XMLNode(X_("TransportControllables"));
488 roll_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("roll"), buf);
490 stop_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("stop"), buf);
492 goto_start_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("goto_start"), buf);
494 goto_end_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("goto_end"), buf);
496 auto_loop_controllable.id().print (buf, sizeof (buf));
497 node->add_property (X_("auto_loop"), buf);
498 play_selection_controllable.id().print (buf, sizeof (buf));
499 node->add_property (X_("play_selection"), buf);
500 rec_controllable.id().print (buf, sizeof (buf));
501 node->add_property (X_("rec"), buf);
502 shuttle_controllable.id().print (buf, sizeof (buf));
503 node->add_property (X_("shuttle"), buf);
509 ARDOUR_UI::save_ardour_state ()
511 if (!keyboard || !mixer || !editor) {
515 /* XXX this is all a bit dubious. add_extra_xml() uses
516 a different lifetime model from add_instant_xml().
519 XMLNode* node = new XMLNode (keyboard->get_state());
520 Config->add_extra_xml (*node);
521 Config->add_extra_xml (get_transport_controllable_state());
522 Config->save_state();
523 ui_config->save_state ();
525 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
526 XMLNode mnode(mixer->get_state());
529 session->add_instant_xml (enode);
530 session->add_instant_xml (mnode);
532 Config->add_instant_xml (enode);
533 Config->add_instant_xml (mnode);
536 Keyboard::save_keybindings ();
540 ARDOUR_UI::autosave_session ()
542 if (!Config->get_periodic_safety_backups())
546 session->maybe_write_autosave();
553 ARDOUR_UI::update_autosave ()
555 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
557 if (session->dirty()) {
558 if (_autosave_connection.connected()) {
559 _autosave_connection.disconnect();
562 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
563 Config->get_periodic_safety_backup_interval() * 1000);
566 if (_autosave_connection.connected()) {
567 _autosave_connection.disconnect();
573 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
577 title = _("Ardour could not start JACK");
579 title = _("Ardour could not connect to JACK.");
582 MessageDialog win (title,
588 win.set_secondary_text(_("There are several possible reasons:\n\
590 1) You requested audio parameters that are not supported..\n\
591 2) JACK is running as another user.\n\
593 Please consider the possibilities, and perhaps try different parameters."));
595 win.set_secondary_text(_("There are several possible reasons:\n\
597 1) JACK is not running.\n\
598 2) JACK is running as another user, perhaps root.\n\
599 3) There is already another client called \"ardour\".\n\
601 Please consider the possibilities, and perhaps (re)start JACK."));
605 win.set_transient_for (*toplevel);
609 win.add_button (Stock::OK, RESPONSE_CLOSE);
611 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
614 win.set_default_response (RESPONSE_CLOSE);
617 win.set_position (Gtk::WIN_POS_CENTER);
620 /* we just don't care about the result, but we want to block */
626 ARDOUR_UI::startup ()
630 new_session_dialog = new NewSessionDialog();
632 bool backend_audio_is_running = EngineControl::engine_running();
633 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
636 new_session_dialog->engine_control.set_state (*audio_setup);
639 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
643 BootMessage (_("Ardour is ready for use"));
648 ARDOUR_UI::no_memory_warning ()
650 XMLNode node (X_("no-memory-warning"));
651 Config->add_instant_xml (node);
655 ARDOUR_UI::check_memory_locking ()
658 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
662 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
664 if (engine->is_realtime() && memory_warning_node == 0) {
666 struct rlimit limits;
668 long pages, page_size;
670 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
673 ram = (int64_t) pages * (int64_t) page_size;
676 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
680 if (limits.rlim_cur != RLIM_INFINITY) {
682 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
685 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
686 "This might cause Ardour to run out of memory before your system "
687 "runs out of memory. \n\n"
688 "You can view the memory limit with 'ulimit -l', "
689 "and it is normally controlled by /etc/security/limits.conf"));
691 VBox* vbox = msg.get_vbox();
693 CheckButton cb (_("Do not show this window again"));
695 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
697 hbox.pack_start (cb, true, false);
698 vbox->pack_start (hbox);
705 editor->ensure_float (msg);
719 if (session->transport_rolling()) {
720 session->request_stop ();
724 if (session->dirty()) {
725 switch (ask_about_saving_session(_("quit"))) {
730 /* use the default name */
731 if (save_state_canfail ("")) {
732 /* failed - don't quit */
733 MessageDialog msg (*editor,
735 Ardour was unable to save your session.\n\n\
736 If you still wish to quit, please use the\n\n\
737 \"Just quit\" option."));
748 session->set_deletion_in_progress ();
752 Config->save_state();
753 ARDOUR_UI::config()->save_state();
758 ARDOUR_UI::ask_about_saving_session (const string & what)
760 ArdourDialog window (_("ardour: save session?"));
761 Gtk::HBox dhbox; // the hbox for the image and text
762 Gtk::Label prompt_label;
763 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
767 msg = string_compose(_("Don't %1"), what);
768 window.add_button (msg, RESPONSE_REJECT);
769 msg = string_compose(_("Just %1"), what);
770 window.add_button (msg, RESPONSE_APPLY);
771 msg = string_compose(_("Save and %1"), what);
772 window.add_button (msg, RESPONSE_ACCEPT);
774 window.set_default_response (RESPONSE_ACCEPT);
776 Gtk::Button noquit_button (msg);
777 noquit_button.set_name ("EditorGTKButton");
782 if (session->snap_name() == session->name()) {
785 type = _("snapshot");
787 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?"),
788 type, session->snap_name());
790 prompt_label.set_text (prompt);
791 prompt_label.set_name (X_("PrompterLabel"));
792 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
794 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
796 dhbox.set_homogeneous (false);
797 dhbox.pack_start (*dimage, false, false, 5);
798 dhbox.pack_start (prompt_label, true, false, 5);
799 window.get_vbox()->pack_start (dhbox);
801 window.set_name (_("Prompter"));
802 window.set_position (Gtk::WIN_POS_MOUSE);
803 window.set_modal (true);
804 window.set_resizable (false);
811 save_the_session = 0;
813 window.set_keep_above (true);
816 ResponseType r = (ResponseType) window.run();
821 case RESPONSE_ACCEPT: // save and get out of here
823 case RESPONSE_APPLY: // get out of here
833 ARDOUR_UI::every_second ()
836 update_buffer_load ();
837 update_disk_space ();
842 ARDOUR_UI::every_point_one_seconds ()
844 update_speed_display ();
845 RapidScreenUpdate(); /* EMIT_SIGNAL */
850 ARDOUR_UI::every_point_zero_one_seconds ()
852 // august 2007: actual update frequency: 40Hz, not 100Hz
854 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
859 ARDOUR_UI::update_sample_rate (nframes_t ignored)
863 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
865 if (!engine->connected()) {
867 snprintf (buf, sizeof (buf), _("disconnected"));
871 nframes_t rate = engine->frame_rate();
873 if (fmod (rate, 1000.0) != 0.0) {
874 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
875 (float) rate/1000.0f,
876 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
878 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
880 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
884 sample_rate_label.set_text (buf);
888 ARDOUR_UI::update_cpu_load ()
891 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
892 cpu_load_label.set_text (buf);
896 ARDOUR_UI::update_buffer_load ()
901 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
902 session->playback_load(), session->capture_load());
903 buffer_load_label.set_text (buf);
905 buffer_load_label.set_text ("");
910 ARDOUR_UI::count_recenabled_streams (Route& route)
912 Track* track = dynamic_cast<Track*>(&route);
913 if (track && track->diskstream()->record_enabled()) {
914 rec_enabled_streams += track->n_inputs().n_total();
919 ARDOUR_UI::update_disk_space()
925 nframes_t frames = session->available_capture_duration();
928 if (frames == max_frames) {
929 strcpy (buf, _("Disk: 24hrs+"));
934 nframes_t fr = session->frame_rate();
936 rec_enabled_streams = 0;
937 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
939 if (rec_enabled_streams) {
940 frames /= rec_enabled_streams;
943 hrs = frames / (fr * 3600);
944 frames -= hrs * fr * 3600;
945 mins = frames / (fr * 60);
946 frames -= mins * fr * 60;
949 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
952 disk_space_label.set_text (buf);
956 ARDOUR_UI::update_wall_clock ()
963 tm_now = localtime (&now);
965 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
966 wall_clock_label.set_text (buf);
972 ARDOUR_UI::session_menu (GdkEventButton *ev)
974 session_popup_menu->popup (0, 0);
979 ARDOUR_UI::redisplay_recent_sessions ()
981 std::vector<sys::path> session_directories;
982 RecentSessionsSorter cmp;
984 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
985 recent_session_model->clear ();
987 ARDOUR::RecentSessions rs;
988 ARDOUR::read_recent_sessions (rs);
991 recent_session_display.set_model (recent_session_model);
995 // sort them alphabetically
996 sort (rs.begin(), rs.end(), cmp);
998 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
999 session_directories.push_back ((*i).second);
1002 for (vector<sys::path>::const_iterator i = session_directories.begin();
1003 i != session_directories.end(); ++i)
1005 std::vector<sys::path> state_file_paths;
1007 // now get available states for this session
1009 get_state_files_in_directory (*i, state_file_paths);
1011 vector<string*>* states;
1012 vector<const gchar*> item;
1013 string fullpath = (*i).to_string();
1015 /* remove any trailing / */
1017 if (fullpath[fullpath.length()-1] == '/') {
1018 fullpath = fullpath.substr (0, fullpath.length()-1);
1021 /* check whether session still exists */
1022 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1023 /* session doesn't exist */
1024 cerr << "skipping non-existent session " << fullpath << endl;
1028 /* now get available states for this session */
1030 if ((states = Session::possible_states (fullpath)) == 0) {
1031 /* no state file? */
1035 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1037 Gtk::TreeModel::Row row = *(recent_session_model->append());
1039 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1040 row[recent_session_columns.fullpath] = fullpath;
1042 if (state_file_names.size() > 1) {
1046 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1047 i2 != state_file_names.end(); ++i2)
1050 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1052 child_row[recent_session_columns.visible_name] = *i2;
1053 child_row[recent_session_columns.fullpath] = fullpath;
1058 recent_session_display.set_model (recent_session_model);
1062 ARDOUR_UI::build_session_selector ()
1064 session_selector_window = new ArdourDialog ("session selector");
1066 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1068 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1069 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1070 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1071 recent_session_model = TreeStore::create (recent_session_columns);
1072 recent_session_display.set_model (recent_session_model);
1073 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1074 recent_session_display.set_headers_visible (false);
1075 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1076 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1078 scroller->add (recent_session_display);
1079 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1081 session_selector_window->set_name ("SessionSelectorWindow");
1082 session_selector_window->set_size_request (200, 400);
1083 session_selector_window->get_vbox()->pack_start (*scroller);
1085 recent_session_display.show();
1087 //session_selector_window->get_vbox()->show();
1091 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1093 session_selector_window->response (RESPONSE_ACCEPT);
1097 ARDOUR_UI::open_recent_session ()
1099 bool can_return = (session != 0);
1101 if (session_selector_window == 0) {
1102 build_session_selector ();
1105 redisplay_recent_sessions ();
1109 session_selector_window->set_position (WIN_POS_MOUSE);
1111 ResponseType r = (ResponseType) session_selector_window->run ();
1114 case RESPONSE_ACCEPT:
1118 session_selector_window->hide();
1125 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1129 session_selector_window->hide();
1131 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1133 if (i == recent_session_model->children().end()) {
1137 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1138 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1140 _session_is_new = false;
1142 if (load_session (path, state) == 0) {
1151 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1153 struct stat statbuf;
1155 if (stat (info.filename.c_str(), &statbuf) != 0) {
1159 if (!S_ISDIR(statbuf.st_mode)) {
1165 string session_file = info.filename;
1166 session_file += '/';
1167 session_file += Glib::path_get_basename (info.filename);
1168 session_file += ".ardour";
1170 if (stat (session_file.c_str(), &statbuf) != 0) {
1174 return S_ISREG (statbuf.st_mode);
1178 ARDOUR_UI::check_audioengine ()
1181 if (!engine->connected()) {
1182 MessageDialog msg (_("Ardour is not connected to JACK\n"
1183 "You cannot open or close sessions in this condition"));
1195 ARDOUR_UI::open_session ()
1197 if (!check_audioengine()) {
1202 /* popup selector window */
1204 if (open_session_selector == 0) {
1206 /* ardour sessions are folders */
1208 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1209 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1210 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1211 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1213 FileFilter session_filter;
1214 session_filter.add_pattern ("*.ardour");
1215 session_filter.set_name (_("Ardour sessions"));
1216 open_session_selector->add_filter (session_filter);
1217 open_session_selector->set_filter (session_filter);
1220 int response = open_session_selector->run();
1221 open_session_selector->hide ();
1224 case RESPONSE_ACCEPT:
1227 open_session_selector->hide();
1231 open_session_selector->hide();
1232 string session_path = open_session_selector->get_filename();
1236 if (session_path.length() > 0) {
1237 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1238 _session_is_new = isnew;
1239 load_session (path, name);
1246 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1248 list<boost::shared_ptr<MidiTrack> > tracks;
1251 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1258 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1260 if (tracks.size() != how_many) {
1261 if (how_many == 1) {
1262 error << _("could not create a new midi track") << endmsg;
1264 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1268 if ((route = session->new_midi_route ()) == 0) {
1269 error << _("could not create new midi bus") << endmsg;
1275 MessageDialog msg (*editor,
1276 _("There are insufficient JACK ports available\n\
1277 to create a new track or bus.\n\
1278 You should save Ardour, exit and\n\
1279 restart JACK with more ports."));
1286 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1288 list<boost::shared_ptr<AudioTrack> > tracks;
1289 Session::RouteList routes;
1292 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1298 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1300 if (tracks.size() != how_many) {
1301 if (how_many == 1) {
1302 error << _("could not create a new audio track") << endmsg;
1304 error << string_compose (_("could only create %1 of %2 new audio %3"),
1305 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1311 routes = session->new_audio_route (input_channels, output_channels, how_many);
1313 if (routes.size() != how_many) {
1314 if (how_many == 1) {
1315 error << _("could not create a new audio track") << endmsg;
1317 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1323 if (need_control_room_outs) {
1329 route->set_stereo_control_outs (control_lr_channels);
1330 route->control_outs()->set_stereo_pan (pans, this);
1332 #endif /* CONTROLOUTS */
1336 MessageDialog msg (*editor,
1337 _("There are insufficient JACK ports available\n\
1338 to create a new track or bus.\n\
1339 You should save Ardour, exit and\n\
1340 restart JACK with more ports."));
1347 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1349 nframes_t _preroll = 0;
1352 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1353 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1355 if (new_position > _preroll) {
1356 new_position -= _preroll;
1361 session->request_locate (new_position);
1366 ARDOUR_UI::transport_goto_start ()
1369 session->goto_start();
1372 /* force displayed area in editor to start no matter
1373 what "follow playhead" setting is.
1377 editor->reset_x_origin (session->current_start_frame());
1383 ARDOUR_UI::transport_goto_zero ()
1386 session->request_locate (0);
1389 /* force displayed area in editor to start no matter
1390 what "follow playhead" setting is.
1394 editor->reset_x_origin (0);
1400 ARDOUR_UI::transport_goto_end ()
1403 nframes_t frame = session->current_end_frame();
1404 session->request_locate (frame);
1406 /* force displayed area in editor to start no matter
1407 what "follow playhead" setting is.
1411 editor->reset_x_origin (frame);
1417 ARDOUR_UI::transport_stop ()
1423 if (session->is_auditioning()) {
1424 session->cancel_audition ();
1428 if (session->get_play_loop ()) {
1429 session->request_play_loop (false);
1432 session->request_stop ();
1436 ARDOUR_UI::transport_stop_and_forget_capture ()
1439 session->request_stop (true);
1444 ARDOUR_UI::remove_last_capture()
1447 editor->remove_last_capture();
1452 ARDOUR_UI::transport_record (bool roll)
1455 switch (session->record_status()) {
1456 case Session::Disabled:
1457 if (session->ntracks() == 0) {
1458 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1462 session->maybe_enable_record ();
1467 case Session::Recording:
1469 session->request_stop();
1471 session->disable_record (false, true);
1475 case Session::Enabled:
1476 session->disable_record (false, true);
1482 ARDOUR_UI::transport_roll ()
1490 rolling = session->transport_rolling ();
1492 if (session->get_play_loop()) {
1493 session->request_play_loop (false);
1494 auto_loop_button.set_visual_state (1);
1495 roll_button.set_visual_state (1);
1496 } else if (session->get_play_range ()) {
1497 session->request_play_range (false);
1498 play_selection_button.set_visual_state (0);
1499 } else if (rolling) {
1500 session->request_locate (session->last_transport_start(), true);
1503 session->request_transport_speed (1.0f);
1507 ARDOUR_UI::transport_loop()
1510 if (session->get_play_loop()) {
1511 if (session->transport_rolling()) {
1512 Location * looploc = session->locations()->auto_loop_location();
1514 session->request_locate (looploc->start(), true);
1519 session->request_play_loop (true);
1525 ARDOUR_UI::transport_play_selection ()
1531 if (!session->get_play_range()) {
1532 session->request_stop ();
1535 editor->play_selection ();
1539 ARDOUR_UI::transport_rewind (int option)
1541 float current_transport_speed;
1544 current_transport_speed = session->transport_speed();
1546 if (current_transport_speed >= 0.0f) {
1549 session->request_transport_speed (-1.0f);
1552 session->request_transport_speed (-4.0f);
1555 session->request_transport_speed (-0.5f);
1560 session->request_transport_speed (current_transport_speed * 1.5f);
1566 ARDOUR_UI::transport_forward (int option)
1568 float current_transport_speed;
1571 current_transport_speed = session->transport_speed();
1573 if (current_transport_speed <= 0.0f) {
1576 session->request_transport_speed (1.0f);
1579 session->request_transport_speed (4.0f);
1582 session->request_transport_speed (0.5f);
1587 session->request_transport_speed (current_transport_speed * 1.5f);
1593 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1599 boost::shared_ptr<Route> r;
1601 if ((r = session->route_by_remote_id (dstream)) != 0) {
1605 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1606 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1615 ARDOUR_UI::queue_transport_change ()
1617 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1621 ARDOUR_UI::map_transport_state ()
1623 float sp = session->transport_speed();
1626 transport_rolling ();
1627 } else if (sp < 0.0f) {
1628 transport_rewinding ();
1629 } else if (sp > 0.0f) {
1630 transport_forwarding ();
1632 transport_stopped ();
1637 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1639 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1640 (int) adj.get_value()].c_str());
1644 ARDOUR_UI::engine_stopped ()
1646 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1647 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1648 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1652 ARDOUR_UI::engine_running ()
1654 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1655 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1656 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1658 Glib::RefPtr<Action> action;
1659 const char* action_name = 0;
1661 switch (engine->frames_per_cycle()) {
1663 action_name = X_("JACKLatency32");
1666 action_name = X_("JACKLatency64");
1669 action_name = X_("JACKLatency128");
1672 action_name = X_("JACKLatency512");
1675 action_name = X_("JACKLatency1024");
1678 action_name = X_("JACKLatency2048");
1681 action_name = X_("JACKLatency4096");
1684 action_name = X_("JACKLatency8192");
1687 /* XXX can we do anything useful ? */
1693 action = ActionManager::get_action (X_("JACK"), action_name);
1696 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1697 ract->set_active ();
1703 ARDOUR_UI::engine_halted ()
1705 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1707 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1708 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1710 update_sample_rate (0);
1712 MessageDialog msg (*editor,
1714 JACK has either been shutdown or it\n\
1715 disconnected Ardour because Ardour\n\
1716 was not fast enough. You can save the\n\
1717 session and/or try to reconnect to JACK ."));
1723 ARDOUR_UI::do_engine_start ()
1731 error << _("Unable to start the session running")
1741 ARDOUR_UI::setup_theme ()
1743 theme_manager->setup_theme();
1747 ARDOUR_UI::update_clocks ()
1749 if (!editor || !editor->dragging_playhead()) {
1750 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1755 ARDOUR_UI::start_clocking ()
1757 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1761 ARDOUR_UI::stop_clocking ()
1763 clock_signal_connection.disconnect ();
1767 ARDOUR_UI::toggle_clocking ()
1770 if (clock_button.get_active()) {
1779 ARDOUR_UI::_blink (void *arg)
1782 ((ARDOUR_UI *) arg)->blink ();
1789 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1793 ARDOUR_UI::start_blinking ()
1795 /* Start the blink signal. Everybody with a blinking widget
1796 uses Blink to drive the widget's state.
1799 if (blink_timeout_tag < 0) {
1801 blink_timeout_tag = g_timeout_add (240, _blink, this);
1806 ARDOUR_UI::stop_blinking ()
1808 if (blink_timeout_tag >= 0) {
1809 g_source_remove (blink_timeout_tag);
1810 blink_timeout_tag = -1;
1815 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1820 vector<string> connections;
1823 if (io.n_inputs().n_total() == 0) {
1828 /* XXX we're not handling multiple ports yet. */
1830 if (io.input(0)->get_connections(connections) == 0) {
1833 buf = connections.front();
1838 if (io.n_outputs().n_total() == 0) {
1843 /* XXX we're not handling multiple ports yet. */
1845 if (io.output(0)->get_connections(connections) == 0) {
1848 buf = connections.front();
1853 /** Ask the user for the name of a new shapshot and then take it.
1856 ARDOUR_UI::snapshot_session ()
1858 ArdourPrompter prompter (true);
1862 struct tm local_time;
1865 localtime_r (&n, &local_time);
1866 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1868 prompter.set_name ("Prompter");
1869 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1870 prompter.set_prompt (_("Name of New Snapshot"));
1871 prompter.set_initial_text (timebuf);
1873 switch (prompter.run()) {
1874 case RESPONSE_ACCEPT:
1875 prompter.get_result (snapname);
1876 if (snapname.length()){
1877 save_state (snapname);
1887 ARDOUR_UI::save_state (const string & name)
1889 (void) save_state_canfail (name);
1893 ARDOUR_UI::save_state_canfail (string name)
1898 if (name.length() == 0) {
1899 name = session->snap_name();
1902 if ((ret = session->save_state (name)) != 0) {
1906 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1911 ARDOUR_UI::restore_state (string name)
1914 if (name.length() == 0) {
1915 name = session->name();
1917 session->restore_state (name);
1922 ARDOUR_UI::primary_clock_value_changed ()
1925 session->request_locate (primary_clock.current_time ());
1930 ARDOUR_UI::big_clock_value_changed ()
1933 session->request_locate (big_clock.current_time ());
1938 ARDOUR_UI::secondary_clock_value_changed ()
1941 session->request_locate (secondary_clock.current_time ());
1946 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1948 if (session && dstream && dstream->record_enabled()) {
1950 Session::RecordState rs;
1952 rs = session->record_status ();
1955 case Session::Disabled:
1956 case Session::Enabled:
1957 if (w->get_state() != STATE_SELECTED) {
1958 w->set_state (STATE_SELECTED);
1962 case Session::Recording:
1963 if (w->get_state() != STATE_ACTIVE) {
1964 w->set_state (STATE_ACTIVE);
1970 if (w->get_state() != STATE_NORMAL) {
1971 w->set_state (STATE_NORMAL);
1977 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1983 switch (session->record_status()) {
1984 case Session::Enabled:
1986 rec_button.set_visual_state (2);
1988 rec_button.set_visual_state (0);
1992 case Session::Recording:
1993 rec_button.set_visual_state (1);
1997 rec_button.set_visual_state (0);
2003 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2011 ARDOUR_UI::save_template ()
2014 ArdourPrompter prompter (true);
2017 if (!check_audioengine()) {
2021 prompter.set_name (X_("Prompter"));
2022 prompter.set_prompt (_("Name for mix template:"));
2023 prompter.set_initial_text(session->name() + _("-template"));
2024 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2026 switch (prompter.run()) {
2027 case RESPONSE_ACCEPT:
2028 prompter.get_result (name);
2030 if (name.length()) {
2031 session->save_template (name);
2041 ARDOUR_UI::fontconfig_dialog ()
2044 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2045 may not and it can take a while to build it. Warn them.
2048 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2050 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2051 MessageDialog msg (*new_session_dialog,
2052 _("Welcome to Ardour.\n\n"
2053 "The program will take a bit longer to start up\n"
2054 "while the system fonts are checked.\n\n"
2055 "This will only be done once, and you will\n"
2056 "not see this message again\n"),
2069 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2071 existing_session = false;
2073 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2074 session_path = cmdline_path;
2075 existing_session = true;
2076 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2077 session_path = Glib::path_get_dirname (string (cmdline_path));
2078 existing_session = true;
2080 /* it doesn't exist, assume the best */
2081 session_path = Glib::path_get_dirname (string (cmdline_path));
2084 session_name = basename_nosuffix (string (cmdline_path));
2088 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2090 /* when this is called, the backend audio system must be running */
2092 /* the main idea here is to deal with the fact that a cmdline argument for the session
2093 can be interpreted in different ways - it could be a directory or a file, and before
2094 we load, we need to know both the session directory and the snapshot (statefile) within it
2095 that we are supposed to use.
2098 if (session_name.length() == 0 || session_path.length() == 0) {
2102 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2104 Glib::ustring predicted_session_file;
2106 predicted_session_file = session_path;
2107 predicted_session_file += '/';
2108 predicted_session_file += session_name;
2109 predicted_session_file += ARDOUR::statefile_suffix;
2111 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2112 existing_session = true;
2115 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2117 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2118 /* existing .ardour file */
2119 existing_session = true;
2123 existing_session = false;
2126 /* lets just try to load it */
2128 if (create_engine ()) {
2129 backend_audio_error (false, new_session_dialog);
2133 return load_session (session_path, session_name);
2137 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2139 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2141 MessageDialog msg (str,
2143 Gtk::MESSAGE_WARNING,
2144 Gtk::BUTTONS_YES_NO,
2148 msg.set_name (X_("CleanupDialog"));
2149 msg.set_wmclass (X_("existing_session"), "Ardour");
2150 msg.set_position (Gtk::WIN_POS_MOUSE);
2153 switch (msg.run()) {
2162 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2167 AutoConnectOption iconnect;
2168 AutoConnectOption oconnect;
2172 if (Profile->get_sae()) {
2176 iconnect = AutoConnectPhysical;
2177 oconnect = AutoConnectMaster;
2178 nphysin = 0; // use all available
2179 nphysout = 0; // use all available
2183 /* get settings from advanced section of NSD */
2185 if (new_session_dialog->create_control_bus()) {
2186 cchns = (uint32_t) new_session_dialog->control_channel_count();
2191 if (new_session_dialog->create_master_bus()) {
2192 mchns = (uint32_t) new_session_dialog->master_channel_count();
2197 if (new_session_dialog->connect_inputs()) {
2198 iconnect = AutoConnectPhysical;
2200 iconnect = AutoConnectOption (0);
2203 /// @todo some minor tweaks.
2205 if (new_session_dialog->connect_outs_to_master()) {
2206 oconnect = AutoConnectMaster;
2207 } else if (new_session_dialog->connect_outs_to_physical()) {
2208 oconnect = AutoConnectPhysical;
2210 oconnect = AutoConnectOption (0);
2213 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2214 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2217 if (build_session (session_path,
2225 engine->frame_rate() * 60 * 5)) {
2234 ARDOUR_UI::end_loading_messages ()
2240 ARDOUR_UI::loading_message (const std::string& msg)
2243 splash->message (msg);
2248 ARDOUR_UI::idle_load (const Glib::ustring& path)
2251 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2252 /* /path/to/foo => /path/to/foo, foo */
2253 load_session (path, basename_nosuffix (path));
2255 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2256 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2259 ARDOUR_COMMAND_LINE::session_name = path;
2260 if (new_session_dialog) {
2261 /* make it break out of Dialog::run() and
2264 new_session_dialog->response (1);
2270 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2272 bool existing_session = false;
2273 Glib::ustring session_name;
2274 Glib::ustring session_path;
2275 Glib::ustring template_name;
2279 response = Gtk::RESPONSE_NONE;
2281 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2283 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2285 /* don't ever reuse this */
2287 ARDOUR_COMMAND_LINE::session_name = string();
2289 if (existing_session && backend_audio_is_running) {
2291 /* just load the thing already */
2293 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2298 /* make the NSD use whatever information we have */
2300 new_session_dialog->set_session_name (session_name);
2301 new_session_dialog->set_session_folder (session_path);
2304 /* loading failed, or we need the NSD for something */
2306 new_session_dialog->set_modal (false);
2307 new_session_dialog->set_position (WIN_POS_CENTER);
2308 new_session_dialog->set_current_page (0);
2309 new_session_dialog->set_existing_session (existing_session);
2310 new_session_dialog->reset_recent();
2313 new_session_dialog->set_have_engine (backend_audio_is_running);
2314 new_session_dialog->present ();
2315 end_loading_messages ();
2316 response = new_session_dialog->run ();
2318 _session_is_new = false;
2320 /* handle possible negative responses */
2324 /* sent by idle_load, meaning restart the whole process again */
2325 new_session_dialog->hide();
2326 new_session_dialog->reset();
2330 case Gtk::RESPONSE_CANCEL:
2331 case Gtk::RESPONSE_DELETE_EVENT:
2335 new_session_dialog->hide ();
2338 case Gtk::RESPONSE_NONE:
2339 /* "Clear" was pressed */
2343 fontconfig_dialog();
2345 if (!backend_audio_is_running) {
2346 if (new_session_dialog->engine_control.setup_engine ()) {
2347 new_session_dialog->hide ();
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);
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)) {
2859 display_cleanup_results (rep,
2862 The following %1 %2 not in use and \n\
2863 have been moved to:\n\
2865 Flushing the wastebasket will \n\
2866 release an additional\n\
2867 %4 %5bytes of disk space.\n"
2875 ARDOUR_UI::flush_trash ()
2878 /* shouldn't happen: menu item is insensitive */
2882 Session::cleanup_report rep;
2884 if (session->cleanup_trash_sources (rep)) {
2888 display_cleanup_results (rep,
2890 _("The following %1 %2 deleted from\n\
2892 releasing %4 %5bytes of disk space"));
2896 ARDOUR_UI::add_route (Gtk::Window* float_window)
2904 if (add_route_dialog == 0) {
2905 add_route_dialog = new AddRouteDialog;
2907 add_route_dialog->set_transient_for (*float_window);
2911 if (add_route_dialog->is_visible()) {
2912 /* we're already doing this */
2916 ResponseType r = (ResponseType) add_route_dialog->run ();
2918 add_route_dialog->hide();
2921 case RESPONSE_ACCEPT:
2928 if ((count = add_route_dialog->count()) <= 0) {
2932 uint32_t input_chan = add_route_dialog->channels ();
2933 uint32_t output_chan;
2934 string name_template = add_route_dialog->name_template ();
2935 bool track = add_route_dialog->track ();
2937 AutoConnectOption oac = Config->get_output_auto_connect();
2939 if (oac & AutoConnectMaster) {
2940 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2942 output_chan = input_chan;
2945 /* XXX do something with name template */
2947 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2949 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2951 session_add_midi_track(count);
2953 MessageDialog msg (*editor,
2954 _("Sorry, MIDI Busses are not supported at this time."));
2956 //session_add_midi_bus();
2960 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2962 session_add_audio_bus (input_chan, output_chan, count);
2968 ARDOUR_UI::mixer_settings () const
2973 node = session->instant_xml(X_("Mixer"));
2975 node = Config->instant_xml(X_("Mixer"));
2979 node = new XMLNode (X_("Mixer"));
2986 ARDOUR_UI::editor_settings () const
2991 node = session->instant_xml(X_("Editor"));
2993 node = Config->instant_xml(X_("Editor"));
2997 node = new XMLNode (X_("Editor"));
3003 ARDOUR_UI::keyboard_settings () const
3007 node = Config->extra_xml(X_("Keyboard"));
3010 node = new XMLNode (X_("Keyboard"));
3016 ARDOUR_UI::create_xrun_marker(nframes_t where)
3018 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), 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 if (Config->get_create_xrun_marker() && session->actively_recording()) {
3034 create_xrun_marker(where);
3037 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3038 halt_on_xrun_message ();
3043 ARDOUR_UI::disk_overrun_handler ()
3045 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3047 if (!have_disk_speed_dialog_displayed) {
3048 have_disk_speed_dialog_displayed = true;
3049 MessageDialog* msg = new MessageDialog (*editor, _("\
3050 The disk system on your computer\n\
3051 was not able to keep up with Ardour.\n\
3053 Specifically, it failed to write data to disk\n\
3054 quickly enough to keep up with recording.\n"));
3055 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3061 ARDOUR_UI::disk_underrun_handler ()
3063 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3065 if (!have_disk_speed_dialog_displayed) {
3066 have_disk_speed_dialog_displayed = true;
3067 MessageDialog* msg = new MessageDialog (*editor,
3068 _("The disk system on your computer\n\
3069 was not able to keep up with Ardour.\n\
3071 Specifically, it failed to read data from disk\n\
3072 quickly enough to keep up with playback.\n"));
3073 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3079 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3081 have_disk_speed_dialog_displayed = false;
3086 ARDOUR_UI::pending_state_dialog ()
3088 HBox* hbox = new HBox();
3089 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3090 ArdourDialog dialog (_("Crash Recovery"), true);
3092 This session appears to have been in\n\
3093 middle of recording when ardour or\n\
3094 the computer was shutdown.\n\
3096 Ardour can recover any captured audio for\n\
3097 you, or it can ignore it. Please decide\n\
3098 what you would like to do.\n"));
3099 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3100 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3101 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3102 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3103 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3104 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3105 dialog.set_default_response (RESPONSE_ACCEPT);
3106 dialog.set_position (WIN_POS_CENTER);
3111 switch (dialog.run ()) {
3112 case RESPONSE_ACCEPT:
3120 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3122 HBox* hbox = new HBox();
3123 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3124 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3125 Label message (string_compose (_("\
3126 This session was created with a sample rate of %1 Hz\n\
3128 The audioengine is currently running at %2 Hz\n"), desired, actual));
3130 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3131 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3132 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3133 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3134 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3135 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3136 dialog.set_default_response (RESPONSE_ACCEPT);
3137 dialog.set_position (WIN_POS_CENTER);
3142 switch (dialog.run ()) {
3143 case RESPONSE_ACCEPT:
3152 ARDOUR_UI::disconnect_from_jack ()
3155 if( engine->disconnect_from_jack ()) {
3156 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3160 update_sample_rate (0);
3165 ARDOUR_UI::reconnect_to_jack ()
3168 if (engine->reconnect_to_jack ()) {
3169 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3173 update_sample_rate (0);
3178 ARDOUR_UI::use_config ()
3180 Glib::RefPtr<Action> act;
3182 switch (Config->get_native_file_data_format ()) {
3184 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3187 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3190 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3195 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3196 ract->set_active ();
3199 switch (Config->get_native_file_header_format ()) {
3201 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3204 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3207 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3210 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3213 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3216 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3219 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3224 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3225 ract->set_active ();
3228 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3230 set_transport_controllable_state (*node);
3235 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3237 if (Config->get_primary_clock_delta_edit_cursor()) {
3238 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3240 primary_clock.set (pos, 0, true);
3243 if (Config->get_secondary_clock_delta_edit_cursor()) {
3244 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3246 secondary_clock.set (pos);
3249 if (big_clock_window) {
3250 big_clock.set (pos);
3255 ARDOUR_UI::record_state_changed ()
3257 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3259 if (!session || !big_clock_window) {
3260 /* why bother - the clock isn't visible */
3264 switch (session->record_status()) {
3265 case Session::Recording:
3266 big_clock.set_widget_name ("BigClockRecording");
3269 big_clock.set_widget_name ("BigClockNonRecording");
3275 ARDOUR_UI::first_idle ()
3278 session->allow_auto_play (true);
3282 editor->first_idle();
3285 Keyboard::set_can_save_keybindings (true);
3290 ARDOUR_UI::store_clock_modes ()
3292 XMLNode* node = new XMLNode(X_("ClockModes"));
3294 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3295 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3298 session->add_extra_xml (*node);
3299 session->set_dirty ();
3304 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3305 : Controllable (name), ui (u), type(tp)
3311 ARDOUR_UI::TransportControllable::set_value (float val)
3313 if (type == ShuttleControl) {
3320 fract = -((0.5f - val)/0.5f);
3322 fract = ((val - 0.5f)/0.5f);
3326 ui.set_shuttle_fract (fract);
3331 /* do nothing: these are radio-style actions */
3335 const char *action = 0;
3339 action = X_("Roll");
3342 action = X_("Stop");
3345 action = X_("Goto Start");
3348 action = X_("Goto End");
3351 action = X_("Loop");
3354 action = X_("Play Selection");
3357 action = X_("Record");
3367 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3375 ARDOUR_UI::TransportControllable::get_value (void) const
3394 case ShuttleControl:
3404 ARDOUR_UI::TransportControllable::set_id (const string& str)
3410 ARDOUR_UI::setup_profile ()
3412 if (gdk_screen_width() < 1200) {
3413 Profile->set_small_screen ();
3417 if (getenv ("ARDOUR_SAE")) {
3418 Profile->set_sae ();
3419 Profile->set_single_package ();