2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define __STDC_FORMAT_MACROS 1
34 #include <sys/resource.h>
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
55 #include "midi++/manager.h"
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
76 typedef uint64_t microseconds_t;
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
86 #include "add_route_dialog.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
97 #include "engine_dialog.h"
101 using namespace ARDOUR;
103 using namespace Gtkmm2ext;
105 using namespace sigc;
107 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
108 UIConfiguration *ARDOUR_UI::ui_config = 0;
110 sigc::signal<void,bool> ARDOUR_UI::Blink;
111 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
112 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
113 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
117 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
119 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
120 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
121 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
122 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
126 preroll_button (_("pre\nroll")),
127 postroll_button (_("post\nroll")),
131 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
135 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
136 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
137 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
138 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
139 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
140 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
141 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
142 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
143 shuttle_controller_binding_proxy (shuttle_controllable),
145 roll_button (roll_controllable),
146 stop_button (stop_controllable),
147 goto_start_button (goto_start_controllable),
148 goto_end_button (goto_end_controllable),
149 auto_loop_button (auto_loop_controllable),
150 play_selection_button (play_selection_controllable),
151 rec_button (rec_controllable),
153 shuttle_units_button (_("% ")),
155 punch_in_button (_("Punch In")),
156 punch_out_button (_("Punch Out")),
157 auto_return_button (_("Auto Return")),
158 auto_play_button (_("Auto Play")),
159 auto_input_button (_("Auto Input")),
160 click_button (_("Click")),
161 time_master_button (_("time\nmaster")),
163 auditioning_alert_button (_("AUDITION")),
164 solo_alert_button (_("SOLO")),
166 error_log_button (_("Errors"))
169 using namespace Gtk::Menu_Helpers;
175 _auto_display_errors = false;
182 if (theArdourUI == 0) {
186 ui_config = new UIConfiguration();
187 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 _will_create_new_session_automatically = false;
199 add_route_dialog = 0;
201 rc_option_editor = 0;
202 session_option_editor = 0;
204 open_session_selector = 0;
205 have_configure_timeout = false;
206 have_disk_speed_dialog_displayed = false;
207 session_loaded = false;
208 last_speed_displayed = -1.0f;
209 ignore_dual_punch = false;
210 _mixer_on_top = false;
212 roll_button.unset_flags (Gtk::CAN_FOCUS);
213 stop_button.unset_flags (Gtk::CAN_FOCUS);
214 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
215 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
216 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
217 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
218 rec_button.unset_flags (Gtk::CAN_FOCUS);
220 last_configure_time= 0;
222 shuttle_grabbed = false;
224 shuttle_max_speed = 8.0f;
226 shuttle_style_menu = 0;
227 shuttle_unit_menu = 0;
229 // We do not have jack linked in yet so;
231 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
233 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
234 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
236 /* handle dialog requests */
238 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
240 /* handle pending state with a dialog */
242 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
244 /* handle sr mismatch with a dialog */
246 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
248 /* lets get this party started */
251 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
252 throw failed_constructor ();
255 setup_gtk_ardour_enums ();
258 GainMeter::setup_slider_pix ();
259 RouteTimeAxisView::setup_slider_pix ();
261 } catch (failed_constructor& err) {
262 error << _("could not initialize Ardour.") << endmsg;
267 /* we like keyboards */
269 keyboard = new Keyboard;
273 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
274 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
280 ARDOUR_UI::run_startup (bool should_be_new)
283 _startup = new ArdourStartup ();
286 _startup->set_new_only (should_be_new);
287 _startup->present ();
291 /* we don't return here until the startup assistant is finished */
297 ARDOUR_UI::create_engine ()
299 // this gets called every time by new_session()
305 loading_message (_("Starting audio engine"));
308 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
315 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
316 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
317 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
318 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
326 ARDOUR_UI::post_engine ()
328 /* Things to be done once we create the AudioEngine
331 MIDI::Manager::instance()->set_api_data (engine->jack());
334 ActionManager::init ();
337 if (setup_windows ()) {
338 throw failed_constructor ();
341 check_memory_locking();
343 /* this is the first point at which all the keybindings are available */
345 if (ARDOUR_COMMAND_LINE::show_key_actions) {
346 vector<string> names;
347 vector<string> paths;
349 vector<AccelKey> bindings;
351 ActionManager::get_all_actions (names, paths, keys, bindings);
353 vector<string>::iterator n;
354 vector<string>::iterator k;
355 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
356 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
362 blink_timeout_tag = -1;
364 /* this being a GUI and all, we want peakfiles */
366 AudioFileSource::set_build_peakfiles (true);
367 AudioFileSource::set_build_missing_peakfiles (true);
369 /* set default clock modes */
371 if (Profile->get_sae()) {
372 primary_clock.set_mode (AudioClock::BBT);
373 secondary_clock.set_mode (AudioClock::MinSec);
375 primary_clock.set_mode (AudioClock::SMPTE);
376 secondary_clock.set_mode (AudioClock::BBT);
379 /* start the time-of-day-clock */
382 /* OS X provides an always visible wallclock, so don't be stupid */
383 update_wall_clock ();
384 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
387 update_disk_space ();
389 update_sample_rate (engine->frame_rate());
391 /* now start and maybe save state */
393 if (do_engine_start () == 0) {
394 if (session && _session_is_new) {
395 /* we need to retain initial visual
396 settings for a new session
398 session->save_state ("");
403 ARDOUR_UI::~ARDOUR_UI ()
405 save_ardour_state ();
410 delete add_route_dialog;
414 ARDOUR_UI::pop_back_splash ()
416 if (Splash::instance()) {
417 // Splash::instance()->pop_back();
418 Splash::instance()->hide ();
423 ARDOUR_UI::configure_timeout ()
425 if (last_configure_time == 0) {
426 /* no configure events yet */
430 /* force a gap of 0.5 seconds since the last configure event
433 if (get_microseconds() - last_configure_time < 500000) {
436 have_configure_timeout = false;
437 save_ardour_state ();
443 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
445 if (have_configure_timeout) {
446 last_configure_time = get_microseconds();
448 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
449 have_configure_timeout = true;
456 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
458 const XMLProperty* prop;
460 if ((prop = node.property ("roll")) != 0) {
461 roll_controllable->set_id (prop->value());
463 if ((prop = node.property ("stop")) != 0) {
464 stop_controllable->set_id (prop->value());
466 if ((prop = node.property ("goto-start")) != 0) {
467 goto_start_controllable->set_id (prop->value());
469 if ((prop = node.property ("goto-end")) != 0) {
470 goto_end_controllable->set_id (prop->value());
472 if ((prop = node.property ("auto-loop")) != 0) {
473 auto_loop_controllable->set_id (prop->value());
475 if ((prop = node.property ("play-selection")) != 0) {
476 play_selection_controllable->set_id (prop->value());
478 if ((prop = node.property ("rec")) != 0) {
479 rec_controllable->set_id (prop->value());
481 if ((prop = node.property ("shuttle")) != 0) {
482 shuttle_controllable->set_id (prop->value());
487 ARDOUR_UI::get_transport_controllable_state ()
489 XMLNode* node = new XMLNode(X_("TransportControllables"));
492 roll_controllable->id().print (buf, sizeof (buf));
493 node->add_property (X_("roll"), buf);
494 stop_controllable->id().print (buf, sizeof (buf));
495 node->add_property (X_("stop"), buf);
496 goto_start_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("goto_start"), buf);
498 goto_end_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("goto_end"), buf);
500 auto_loop_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("auto_loop"), buf);
502 play_selection_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("play_selection"), buf);
504 rec_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("rec"), buf);
506 shuttle_controllable->id().print (buf, sizeof (buf));
507 node->add_property (X_("shuttle"), buf);
513 ARDOUR_UI::save_ardour_state ()
515 if (!keyboard || !mixer || !editor) {
519 /* XXX this is all a bit dubious. add_extra_xml() uses
520 a different lifetime model from add_instant_xml().
523 XMLNode* node = new XMLNode (keyboard->get_state());
524 Config->add_extra_xml (*node);
525 Config->add_extra_xml (get_transport_controllable_state());
526 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
527 Config->add_extra_xml (_startup->engine_control()->get_state());
529 Config->save_state();
530 ui_config->save_state ();
532 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
533 XMLNode mnode(mixer->get_state());
536 session->add_instant_xml (enode);
537 session->add_instant_xml (mnode);
539 Config->add_instant_xml (enode);
540 Config->add_instant_xml (mnode);
543 Keyboard::save_keybindings ();
547 ARDOUR_UI::autosave_session ()
549 if (g_main_depth() > 1) {
550 /* inside a recursive main loop,
551 give up because we may not be able to
557 if (!Config->get_periodic_safety_backups()) {
562 session->maybe_write_autosave();
569 ARDOUR_UI::update_autosave ()
571 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
573 if (session->dirty()) {
574 if (_autosave_connection.connected()) {
575 _autosave_connection.disconnect();
578 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
579 Config->get_periodic_safety_backup_interval() * 1000);
582 if (_autosave_connection.connected()) {
583 _autosave_connection.disconnect();
589 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
593 title = _("Ardour could not start JACK");
595 title = _("Ardour could not connect to JACK.");
598 MessageDialog win (title,
604 win.set_secondary_text(_("There are several possible reasons:\n\
606 1) You requested audio parameters that are not supported..\n\
607 2) JACK is running as another user.\n\
609 Please consider the possibilities, and perhaps try different parameters."));
611 win.set_secondary_text(_("There are several possible reasons:\n\
613 1) JACK is not running.\n\
614 2) JACK is running as another user, perhaps root.\n\
615 3) There is already another client called \"ardour\".\n\
617 Please consider the possibilities, and perhaps (re)start JACK."));
621 win.set_transient_for (*toplevel);
625 win.add_button (Stock::OK, RESPONSE_CLOSE);
627 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
630 win.set_default_response (RESPONSE_CLOSE);
633 win.set_position (Gtk::WIN_POS_CENTER);
636 /* we just don't care about the result, but we want to block */
642 ARDOUR_UI::startup ()
644 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
646 if (audio_setup && _startup && _startup->engine_control()) {
647 _startup->engine_control()->set_state (*audio_setup);
650 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
656 goto_editor_window ();
658 BootMessage (_("Ardour is ready for use"));
663 ARDOUR_UI::no_memory_warning ()
665 XMLNode node (X_("no-memory-warning"));
666 Config->add_instant_xml (node);
670 ARDOUR_UI::check_memory_locking ()
673 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
677 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
679 if (engine->is_realtime() && memory_warning_node == 0) {
681 struct rlimit limits;
683 long pages, page_size;
685 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
688 ram = (int64_t) pages * (int64_t) page_size;
691 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
695 if (limits.rlim_cur != RLIM_INFINITY) {
697 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
700 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
701 "This might cause Ardour to run out of memory before your system "
702 "runs out of memory. \n\n"
703 "You can view the memory limit with 'ulimit -l', "
704 "and it is normally controlled by /etc/security/limits.conf"));
706 VBox* vbox = msg.get_vbox();
708 CheckButton cb (_("Do not show this window again"));
710 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
712 hbox.pack_start (cb, true, false);
713 vbox->pack_start (hbox);
720 editor->ensure_float (msg);
734 if (session->transport_rolling()) {
735 session->request_stop ();
739 if (session->dirty()) {
740 switch (ask_about_saving_session(_("quit"))) {
745 /* use the default name */
746 if (save_state_canfail ("")) {
747 /* failed - don't quit */
748 MessageDialog msg (*editor,
750 Ardour was unable to save your session.\n\n\
751 If you still wish to quit, please use the\n\n\
752 \"Just quit\" option."));
763 session->set_deletion_in_progress ();
766 ArdourDialog::close_all_dialogs ();
768 save_ardour_state ();
773 ARDOUR_UI::ask_about_saving_session (const string & what)
775 ArdourDialog window (_("ardour: save session?"));
776 Gtk::HBox dhbox; // the hbox for the image and text
777 Gtk::Label prompt_label;
778 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
782 msg = string_compose(_("Don't %1"), what);
783 window.add_button (msg, RESPONSE_REJECT);
784 msg = string_compose(_("Just %1"), what);
785 window.add_button (msg, RESPONSE_APPLY);
786 msg = string_compose(_("Save and %1"), what);
787 window.add_button (msg, RESPONSE_ACCEPT);
789 window.set_default_response (RESPONSE_ACCEPT);
791 Gtk::Button noquit_button (msg);
792 noquit_button.set_name ("EditorGTKButton");
797 if (session->snap_name() == session->name()) {
800 type = _("snapshot");
802 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?"),
803 type, session->snap_name());
805 prompt_label.set_text (prompt);
806 prompt_label.set_name (X_("PrompterLabel"));
807 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
809 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
810 dhbox.set_homogeneous (false);
811 dhbox.pack_start (*dimage, false, false, 5);
812 dhbox.pack_start (prompt_label, true, false, 5);
813 window.get_vbox()->pack_start (dhbox);
815 window.set_name (_("Prompter"));
816 window.set_position (Gtk::WIN_POS_MOUSE);
817 window.set_modal (true);
818 window.set_resizable (false);
824 window.set_keep_above (true);
827 ResponseType r = (ResponseType) window.run();
832 case RESPONSE_ACCEPT: // save and get out of here
834 case RESPONSE_APPLY: // get out of here
844 ARDOUR_UI::every_second ()
847 update_buffer_load ();
848 update_disk_space ();
853 ARDOUR_UI::every_point_one_seconds ()
855 update_speed_display ();
856 RapidScreenUpdate(); /* EMIT_SIGNAL */
861 ARDOUR_UI::every_point_zero_one_seconds ()
863 // august 2007: actual update frequency: 40Hz, not 100Hz
865 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
870 ARDOUR_UI::update_sample_rate (nframes_t ignored)
874 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
876 if (!engine->connected()) {
878 snprintf (buf, sizeof (buf), _("disconnected"));
882 nframes_t rate = engine->frame_rate();
884 if (fmod (rate, 1000.0) != 0.0) {
885 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
886 (float) rate/1000.0f,
887 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
889 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
891 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
895 sample_rate_label.set_text (buf);
899 ARDOUR_UI::update_cpu_load ()
902 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
903 cpu_load_label.set_text (buf);
907 ARDOUR_UI::update_buffer_load ()
913 c = session->capture_load ();
914 p = session->playback_load ();
916 push_buffer_stats (c, p);
918 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
919 session->playback_load(), session->capture_load());
920 buffer_load_label.set_text (buf);
922 buffer_load_label.set_text ("");
927 ARDOUR_UI::count_recenabled_streams (Route& route)
929 Track* track = dynamic_cast<Track*>(&route);
930 if (track && track->diskstream()->record_enabled()) {
931 rec_enabled_streams += track->n_inputs().n_total();
936 ARDOUR_UI::update_disk_space()
942 nframes_t frames = session->available_capture_duration();
944 nframes_t fr = session->frame_rate();
946 if (frames == max_frames) {
947 strcpy (buf, _("Disk: 24hrs+"));
949 rec_enabled_streams = 0;
950 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
952 if (rec_enabled_streams) {
953 frames /= rec_enabled_streams;
960 hrs = frames / (fr * 3600);
961 frames -= hrs * fr * 3600;
962 mins = frames / (fr * 60);
963 frames -= mins * fr * 60;
966 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
969 disk_space_label.set_text (buf);
971 // An attempt to make the disk space label flash red when space has run out.
973 if (frames < fr * 60 * 5) {
974 /* disk_space_box.style ("disk_space_label_empty"); */
976 /* disk_space_box.style ("disk_space_label"); */
982 ARDOUR_UI::update_wall_clock ()
989 tm_now = localtime (&now);
991 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
992 wall_clock_label.set_text (buf);
998 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1000 session_popup_menu->popup (0, 0);
1005 ARDOUR_UI::redisplay_recent_sessions ()
1007 std::vector<sys::path> session_directories;
1008 RecentSessionsSorter cmp;
1010 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1011 recent_session_model->clear ();
1013 ARDOUR::RecentSessions rs;
1014 ARDOUR::read_recent_sessions (rs);
1017 recent_session_display.set_model (recent_session_model);
1021 // sort them alphabetically
1022 sort (rs.begin(), rs.end(), cmp);
1024 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1025 session_directories.push_back ((*i).second);
1028 for (vector<sys::path>::const_iterator i = session_directories.begin();
1029 i != session_directories.end(); ++i)
1031 std::vector<sys::path> state_file_paths;
1033 // now get available states for this session
1035 get_state_files_in_directory (*i, state_file_paths);
1037 vector<string*>* states;
1038 vector<const gchar*> item;
1039 string fullpath = (*i).to_string();
1041 /* remove any trailing / */
1043 if (fullpath[fullpath.length()-1] == '/') {
1044 fullpath = fullpath.substr (0, fullpath.length()-1);
1047 /* check whether session still exists */
1048 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1049 /* session doesn't exist */
1050 cerr << "skipping non-existent session " << fullpath << endl;
1054 /* now get available states for this session */
1056 if ((states = Session::possible_states (fullpath)) == 0) {
1057 /* no state file? */
1061 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1063 Gtk::TreeModel::Row row = *(recent_session_model->append());
1065 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1066 row[recent_session_columns.fullpath] = fullpath;
1068 if (state_file_names.size() > 1) {
1072 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1073 i2 != state_file_names.end(); ++i2)
1076 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1078 child_row[recent_session_columns.visible_name] = *i2;
1079 child_row[recent_session_columns.fullpath] = fullpath;
1084 recent_session_display.set_model (recent_session_model);
1088 ARDOUR_UI::build_session_selector ()
1090 session_selector_window = new ArdourDialog ("session selector");
1092 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1094 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1095 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1096 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1097 recent_session_model = TreeStore::create (recent_session_columns);
1098 recent_session_display.set_model (recent_session_model);
1099 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1100 recent_session_display.set_headers_visible (false);
1101 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1102 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1104 scroller->add (recent_session_display);
1105 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1107 session_selector_window->set_name ("SessionSelectorWindow");
1108 session_selector_window->set_size_request (200, 400);
1109 session_selector_window->get_vbox()->pack_start (*scroller);
1111 recent_session_display.show();
1113 //session_selector_window->get_vbox()->show();
1117 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1119 session_selector_window->response (RESPONSE_ACCEPT);
1123 ARDOUR_UI::open_recent_session ()
1125 bool can_return = (session != 0);
1127 if (session_selector_window == 0) {
1128 build_session_selector ();
1131 redisplay_recent_sessions ();
1135 session_selector_window->set_position (WIN_POS_MOUSE);
1137 ResponseType r = (ResponseType) session_selector_window->run ();
1140 case RESPONSE_ACCEPT:
1144 session_selector_window->hide();
1151 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1155 session_selector_window->hide();
1157 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1159 if (i == recent_session_model->children().end()) {
1163 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1164 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1166 _session_is_new = false;
1168 if (load_session (path, state) == 0) {
1177 ARDOUR_UI::check_audioengine ()
1180 if (!engine->connected()) {
1181 MessageDialog msg (_("Ardour is not connected to JACK\n"
1182 "You cannot open or close sessions in this condition"));
1194 ARDOUR_UI::open_session ()
1196 if (!check_audioengine()) {
1201 /* popup selector window */
1203 if (open_session_selector == 0) {
1205 /* ardour sessions are folders */
1207 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1208 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1209 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1210 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1212 FileFilter session_filter;
1213 session_filter.add_pattern ("*.ardour");
1214 session_filter.set_name (_("Ardour sessions"));
1215 open_session_selector->add_filter (session_filter);
1216 open_session_selector->set_filter (session_filter);
1219 int response = open_session_selector->run();
1220 open_session_selector->hide ();
1223 case RESPONSE_ACCEPT:
1226 open_session_selector->hide();
1230 open_session_selector->hide();
1231 string session_path = open_session_selector->get_filename();
1235 if (session_path.length() > 0) {
1236 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1237 _session_is_new = isnew;
1238 load_session (path, name);
1245 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1247 list<boost::shared_ptr<MidiTrack> > tracks;
1250 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1257 tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1259 if (tracks.size() != how_many) {
1260 if (how_many == 1) {
1261 error << _("could not create a new midi track") << endmsg;
1263 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1267 if ((route = session->new_midi_route ()) == 0) {
1268 error << _("could not create new midi bus") << endmsg;
1274 MessageDialog msg (*editor,
1275 _("There are insufficient JACK ports available\n\
1276 to create a new track or bus.\n\
1277 You should save Ardour, exit and\n\
1278 restart JACK with more ports."));
1285 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1287 list<boost::shared_ptr<AudioTrack> > tracks;
1291 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1297 tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1299 if (tracks.size() != how_many) {
1300 if (how_many == 1) {
1301 error << _("could not create a new audio track") << endmsg;
1303 error << string_compose (_("could only create %1 of %2 new audio %3"),
1304 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1310 routes = session->new_audio_route (input_channels, output_channels, route_group, how_many);
1312 if (routes.size() != how_many) {
1313 if (how_many == 1) {
1314 error << _("could not create a new audio track") << endmsg;
1316 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1322 if (need_control_room_outs) {
1328 route->set_stereo_control_outs (control_lr_channels);
1329 route->control_outs()->set_stereo_pan (pans, this);
1331 #endif /* CONTROLOUTS */
1335 MessageDialog msg (*editor,
1336 _("There are insufficient JACK ports available\n\
1337 to create a new track or bus.\n\
1338 You should save Ardour, exit and\n\
1339 restart JACK with more ports."));
1346 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1348 nframes_t _preroll = 0;
1351 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1352 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1354 if (new_position > _preroll) {
1355 new_position -= _preroll;
1360 session->request_locate (new_position);
1365 ARDOUR_UI::transport_goto_start ()
1368 session->goto_start();
1371 /* force displayed area in editor to start no matter
1372 what "follow playhead" setting is.
1376 editor->reset_x_origin (session->current_start_frame());
1382 ARDOUR_UI::transport_goto_zero ()
1385 session->request_locate (0);
1388 /* force displayed area in editor to start no matter
1389 what "follow playhead" setting is.
1393 editor->reset_x_origin (0);
1399 ARDOUR_UI::transport_goto_wallclock ()
1401 if (session && editor) {
1408 localtime_r (&now, &tmnow);
1410 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1411 frames += tmnow.tm_min * (60 * session->frame_rate());
1412 frames += tmnow.tm_sec * session->frame_rate();
1414 session->request_locate (frames);
1416 /* force displayed area in editor to start no matter
1417 what "follow playhead" setting is.
1421 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1427 ARDOUR_UI::transport_goto_end ()
1430 nframes_t frame = session->current_end_frame();
1431 session->request_locate (frame);
1433 /* force displayed area in editor to start no matter
1434 what "follow playhead" setting is.
1438 editor->reset_x_origin (frame);
1444 ARDOUR_UI::transport_stop ()
1450 if (session->is_auditioning()) {
1451 session->cancel_audition ();
1455 if (session->get_play_loop ()) {
1456 session->request_play_loop (false);
1459 session->request_stop ();
1463 ARDOUR_UI::transport_stop_and_forget_capture ()
1466 session->request_stop (true);
1471 ARDOUR_UI::remove_last_capture()
1474 editor->remove_last_capture();
1479 ARDOUR_UI::transport_record (bool roll)
1483 switch (session->record_status()) {
1484 case Session::Disabled:
1485 if (session->ntracks() == 0) {
1486 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1490 session->maybe_enable_record ();
1495 case Session::Recording:
1497 session->request_stop();
1499 session->disable_record (false, true);
1503 case Session::Enabled:
1504 session->disable_record (false, true);
1507 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1511 ARDOUR_UI::transport_roll ()
1519 rolling = session->transport_rolling ();
1521 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1523 if (session->get_play_loop()) {
1524 session->request_play_loop (false);
1525 auto_loop_button.set_visual_state (1);
1526 roll_button.set_visual_state (1);
1527 } else if (session->get_play_range ()) {
1528 session->request_play_range (false);
1529 play_selection_button.set_visual_state (0);
1530 } else if (rolling) {
1531 session->request_locate (session->last_transport_start(), true);
1534 session->request_transport_speed (1.0f);
1538 ARDOUR_UI::transport_loop()
1541 if (session->get_play_loop()) {
1542 if (session->transport_rolling()) {
1543 Location * looploc = session->locations()->auto_loop_location();
1545 session->request_locate (looploc->start(), true);
1550 session->request_play_loop (true);
1556 ARDOUR_UI::transport_play_selection ()
1562 if (!session->get_play_range()) {
1563 session->request_stop ();
1566 editor->play_selection ();
1570 ARDOUR_UI::transport_rewind (int option)
1572 float current_transport_speed;
1575 current_transport_speed = session->transport_speed();
1577 if (current_transport_speed >= 0.0f) {
1580 session->request_transport_speed (-1.0f);
1583 session->request_transport_speed (-4.0f);
1586 session->request_transport_speed (-0.5f);
1591 session->request_transport_speed (current_transport_speed * 1.5f);
1597 ARDOUR_UI::transport_forward (int option)
1599 float current_transport_speed;
1602 current_transport_speed = session->transport_speed();
1604 if (current_transport_speed <= 0.0f) {
1607 session->request_transport_speed (1.0f);
1610 session->request_transport_speed (4.0f);
1613 session->request_transport_speed (0.5f);
1618 session->request_transport_speed (current_transport_speed * 1.5f);
1624 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1630 boost::shared_ptr<Route> r;
1632 if ((r = session->route_by_remote_id (dstream)) != 0) {
1636 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1637 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1646 ARDOUR_UI::queue_transport_change ()
1648 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1652 ARDOUR_UI::map_transport_state ()
1654 float sp = session->transport_speed();
1657 transport_rolling ();
1658 } else if (sp < 0.0f) {
1659 transport_rewinding ();
1660 } else if (sp > 0.0f) {
1661 transport_forwarding ();
1663 transport_stopped ();
1668 ARDOUR_UI::engine_stopped ()
1670 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1671 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1672 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1676 ARDOUR_UI::engine_running ()
1678 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1679 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1680 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1682 Glib::RefPtr<Action> action;
1683 const char* action_name = 0;
1685 switch (engine->frames_per_cycle()) {
1687 action_name = X_("JACKLatency32");
1690 action_name = X_("JACKLatency64");
1693 action_name = X_("JACKLatency128");
1696 action_name = X_("JACKLatency512");
1699 action_name = X_("JACKLatency1024");
1702 action_name = X_("JACKLatency2048");
1705 action_name = X_("JACKLatency4096");
1708 action_name = X_("JACKLatency8192");
1711 /* XXX can we do anything useful ? */
1717 action = ActionManager::get_action (X_("JACK"), action_name);
1720 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1721 ract->set_active ();
1727 ARDOUR_UI::engine_halted ()
1729 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1731 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1732 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1734 update_sample_rate (0);
1736 MessageDialog msg (*editor,
1738 JACK has either been shutdown or it\n\
1739 disconnected Ardour because Ardour\n\
1740 was not fast enough. Try to restart\n\
1741 JACK, reconnect and save the session."));
1747 ARDOUR_UI::do_engine_start ()
1755 error << _("Unable to start the session running")
1765 ARDOUR_UI::setup_theme ()
1767 theme_manager->setup_theme();
1771 ARDOUR_UI::update_clocks ()
1773 if (!editor || !editor->dragging_playhead()) {
1774 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1779 ARDOUR_UI::start_clocking ()
1781 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1785 ARDOUR_UI::stop_clocking ()
1787 clock_signal_connection.disconnect ();
1791 ARDOUR_UI::toggle_clocking ()
1794 if (clock_button.get_active()) {
1803 ARDOUR_UI::_blink (void *arg)
1806 ((ARDOUR_UI *) arg)->blink ();
1813 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1817 ARDOUR_UI::start_blinking ()
1819 /* Start the blink signal. Everybody with a blinking widget
1820 uses Blink to drive the widget's state.
1823 if (blink_timeout_tag < 0) {
1825 blink_timeout_tag = g_timeout_add (240, _blink, this);
1830 ARDOUR_UI::stop_blinking ()
1832 if (blink_timeout_tag >= 0) {
1833 g_source_remove (blink_timeout_tag);
1834 blink_timeout_tag = -1;
1839 /** Ask the user for the name of a new shapshot and then take it.
1842 ARDOUR_UI::snapshot_session ()
1844 ArdourPrompter prompter (true);
1848 struct tm local_time;
1851 localtime_r (&n, &local_time);
1852 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1854 prompter.set_name ("Prompter");
1855 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1856 prompter.set_prompt (_("Name of New Snapshot"));
1857 prompter.set_initial_text (timebuf);
1859 switch (prompter.run()) {
1860 case RESPONSE_ACCEPT:
1862 prompter.get_result (snapname);
1864 bool do_save = (snapname.length() != 0);
1866 vector<sys::path> p;
1867 get_state_files_in_directory (session->session_directory().root_path(), p);
1868 vector<string> n = get_file_names_no_extension (p);
1869 if (find (n.begin(), n.end(), snapname) != n.end()) {
1871 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1872 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1873 confirm.get_vbox()->pack_start (m, true, true);
1874 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1875 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1876 confirm.show_all ();
1877 switch (confirm.run()) {
1878 case RESPONSE_CANCEL:
1884 save_state (snapname);
1895 ARDOUR_UI::save_state (const string & name)
1897 (void) save_state_canfail (name);
1901 ARDOUR_UI::save_state_canfail (string name)
1906 if (name.length() == 0) {
1907 name = session->snap_name();
1910 if ((ret = session->save_state (name)) != 0) {
1914 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1919 ARDOUR_UI::primary_clock_value_changed ()
1922 session->request_locate (primary_clock.current_time ());
1927 ARDOUR_UI::big_clock_value_changed ()
1930 session->request_locate (big_clock.current_time ());
1935 ARDOUR_UI::secondary_clock_value_changed ()
1938 session->request_locate (secondary_clock.current_time ());
1943 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1949 Session::RecordState const r = session->record_status ();
1950 bool const h = session->have_rec_enabled_diskstream ();
1952 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1954 rec_button.set_visual_state (2);
1956 rec_button.set_visual_state (0);
1958 } else if (r == Session::Recording && h) {
1959 rec_button.set_visual_state (1);
1961 rec_button.set_visual_state (0);
1966 ARDOUR_UI::save_template ()
1969 ArdourPrompter prompter (true);
1972 if (!check_audioengine()) {
1976 prompter.set_name (X_("Prompter"));
1977 prompter.set_prompt (_("Name for mix template:"));
1978 prompter.set_initial_text(session->name() + _("-template"));
1979 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1981 switch (prompter.run()) {
1982 case RESPONSE_ACCEPT:
1983 prompter.get_result (name);
1985 if (name.length()) {
1986 session->save_template (name);
1996 ARDOUR_UI::edit_metadata ()
1998 SessionMetadataEditor dialog;
1999 dialog.set_session (session);
2000 editor->ensure_float (dialog);
2005 ARDOUR_UI::import_metadata ()
2007 SessionMetadataImporter dialog;
2008 dialog.set_session (session);
2009 editor->ensure_float (dialog);
2014 ARDOUR_UI::fontconfig_dialog ()
2017 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2018 may not and it can take a while to build it. Warn them.
2021 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2023 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2024 MessageDialog msg (*_startup,
2025 _("Welcome to Ardour.\n\n"
2026 "The program will take a bit longer to start up\n"
2027 "while the system fonts are checked.\n\n"
2028 "This will only be done once, and you will\n"
2029 "not see this message again\n"),
2042 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2044 existing_session = false;
2046 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2047 session_path = cmdline_path;
2048 existing_session = true;
2049 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2050 session_path = Glib::path_get_dirname (string (cmdline_path));
2051 existing_session = true;
2053 /* it doesn't exist, assume the best */
2054 session_path = Glib::path_get_dirname (string (cmdline_path));
2057 session_name = basename_nosuffix (string (cmdline_path));
2061 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2063 /* when this is called, the backend audio system must be running */
2065 /* the main idea here is to deal with the fact that a cmdline argument for the session
2066 can be interpreted in different ways - it could be a directory or a file, and before
2067 we load, we need to know both the session directory and the snapshot (statefile) within it
2068 that we are supposed to use.
2071 if (session_name.length() == 0 || session_path.length() == 0) {
2075 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2077 Glib::ustring predicted_session_file;
2079 predicted_session_file = session_path;
2080 predicted_session_file += '/';
2081 predicted_session_file += session_name;
2082 predicted_session_file += ARDOUR::statefile_suffix;
2084 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2085 existing_session = true;
2088 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2090 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2091 /* existing .ardour file */
2092 existing_session = true;
2096 existing_session = false;
2099 /* lets just try to load it */
2101 if (create_engine ()) {
2102 backend_audio_error (false, _startup);
2106 return load_session (session_path, session_name);
2110 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2112 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2114 MessageDialog msg (str,
2116 Gtk::MESSAGE_WARNING,
2117 Gtk::BUTTONS_YES_NO,
2121 msg.set_name (X_("CleanupDialog"));
2122 msg.set_wmclass (X_("existing_session"), "Ardour");
2123 msg.set_position (Gtk::WIN_POS_MOUSE);
2126 switch (msg.run()) {
2135 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2140 AutoConnectOption iconnect;
2141 AutoConnectOption oconnect;
2145 if (Profile->get_sae()) {
2149 iconnect = AutoConnectPhysical;
2150 oconnect = AutoConnectMaster;
2151 nphysin = 0; // use all available
2152 nphysout = 0; // use all available
2156 /* get settings from advanced section of NSD */
2158 if (_startup->create_control_bus()) {
2159 cchns = (uint32_t) _startup->control_channel_count();
2164 if (_startup->create_master_bus()) {
2165 mchns = (uint32_t) _startup->master_channel_count();
2170 if (_startup->connect_inputs()) {
2171 iconnect = AutoConnectPhysical;
2173 iconnect = AutoConnectOption (0);
2176 /// @todo some minor tweaks.
2178 if (_startup->connect_outs_to_master()) {
2179 oconnect = AutoConnectMaster;
2180 } else if (_startup->connect_outs_to_physical()) {
2181 oconnect = AutoConnectPhysical;
2183 oconnect = AutoConnectOption (0);
2186 nphysin = (uint32_t) _startup->input_limit_count();
2187 nphysout = (uint32_t) _startup->output_limit_count();
2190 if (build_session (session_path,
2198 engine->frame_rate() * 60 * 5)) {
2207 ARDOUR_UI::end_loading_messages ()
2213 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2216 // splash->message (msg);
2221 ARDOUR_UI::get_session_parameters (bool should_be_new)
2223 Glib::ustring session_name;
2224 Glib::ustring session_path;
2225 Glib::ustring template_name;
2227 bool likely_new = false;
2231 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2233 /* if they named a specific statefile, use it, otherwise they are
2234 just giving a session folder, and we want to use it as is
2235 to find the session.
2238 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2239 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2241 session_path = ARDOUR_COMMAND_LINE::session_name;
2244 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2248 run_startup (should_be_new);
2250 /* if we run the startup dialog again, offer more than just "new session" */
2252 should_be_new = false;
2254 session_name = _startup->session_name (likely_new);
2256 /* this shouldn't happen, but we catch it just in case it does */
2258 if (session_name.empty()) {
2261 if (_startup->use_session_template()) {
2262 template_name = _startup->session_template_name();
2263 _session_is_new = true;
2267 if (session_name[0] == '/' ||
2268 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2269 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2271 session_path = Glib::path_get_dirname (session_name);
2272 session_name = Glib::path_get_basename (session_name);
2276 session_path = _startup->session_folder();
2280 if (create_engine ()) {
2284 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2288 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2290 if (!ask_about_loading_existing_session (existing)) {
2291 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2296 _session_is_new = false;
2301 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2303 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2307 _session_is_new = true;
2310 if (likely_new && template_name.empty()) {
2312 ret = build_session_from_nsd (session_path, session_name);
2316 ret = load_session (session_path, session_name, template_name);
2324 ARDOUR_UI::close_session()
2326 if (!check_audioengine()) {
2330 unload_session (true);
2332 get_session_parameters (false);
2336 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2338 Session *new_session;
2342 session_loaded = false;
2344 if (!check_audioengine()) {
2348 unload_status = unload_session ();
2350 if (unload_status < 0) {
2352 } else if (unload_status > 0) {
2357 /* if it already exists, we must have write access */
2359 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2360 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2361 "This prevents the session from being loaded."));
2367 loading_message (_("Please wait while Ardour loads your session"));
2370 new_session = new Session (*engine, path, snap_name, mix_template);
2373 /* this one is special */
2375 catch (AudioEngine::PortRegistrationFailure& err) {
2377 MessageDialog msg (err.what(),
2380 Gtk::BUTTONS_CLOSE);
2382 msg.set_title (_("Port Registration Error"));
2383 msg.set_secondary_text (_("Click the Close button to try again."));
2384 msg.set_position (Gtk::WIN_POS_CENTER);
2388 int response = msg.run ();
2393 case RESPONSE_CANCEL:
2403 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2406 Gtk::BUTTONS_CLOSE);
2408 msg.set_title (_("Loading Error"));
2409 msg.set_secondary_text (_("Click the Close button to try again."));
2410 msg.set_position (Gtk::WIN_POS_CENTER);
2414 int response = msg.run ();
2419 case RESPONSE_CANCEL:
2427 connect_to_session (new_session);
2429 session_loaded = true;
2431 goto_editor_window ();
2434 session->set_clean ();
2445 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2446 uint32_t control_channels,
2447 uint32_t master_channels,
2448 AutoConnectOption input_connect,
2449 AutoConnectOption output_connect,
2452 nframes_t initial_length)
2454 Session *new_session;
2457 if (!check_audioengine()) {
2461 session_loaded = false;
2463 x = unload_session ();
2471 _session_is_new = true;
2474 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2475 control_channels, master_channels, nphysin, nphysout, initial_length);
2480 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2486 connect_to_session (new_session);
2488 session_loaded = true;
2490 new_session->save_state(new_session->name());
2499 editor->show_window ();
2510 ARDOUR_UI::show_about ()
2514 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2521 ARDOUR_UI::hide_about ()
2524 about->get_window()->set_cursor ();
2530 ARDOUR_UI::about_signal_response (int /*response*/)
2536 ARDOUR_UI::show_splash ()
2540 splash = new Splash;
2548 splash->queue_draw ();
2549 splash->get_window()->process_updates (true);
2554 ARDOUR_UI::hide_splash ()
2562 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2563 const string& plural_msg, const string& singular_msg)
2567 removed = rep.paths.size();
2570 MessageDialog msgd (*editor,
2571 _("No audio files were ready for cleanup"),
2574 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2575 msgd.set_secondary_text (_("If this seems suprising, \n\
2576 check for any existing snapshots.\n\
2577 These may still include regions that\n\
2578 require some unused files to continue to exist."));
2584 ArdourDialog results (_("ardour: cleanup"), true, false);
2586 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2587 CleanupResultsModelColumns() {
2591 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2592 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2596 CleanupResultsModelColumns results_columns;
2597 Glib::RefPtr<Gtk::ListStore> results_model;
2598 Gtk::TreeView results_display;
2600 results_model = ListStore::create (results_columns);
2601 results_display.set_model (results_model);
2602 results_display.append_column (list_title, results_columns.visible_name);
2604 results_display.set_name ("CleanupResultsList");
2605 results_display.set_headers_visible (true);
2606 results_display.set_headers_clickable (false);
2607 results_display.set_reorderable (false);
2609 Gtk::ScrolledWindow list_scroller;
2612 Gtk::HBox dhbox; // the hbox for the image and text
2613 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2614 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2616 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2618 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2624 %1 - number of files removed
2625 %2 - location of "dead_sounds"
2626 %3 - size of files affected
2627 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2630 const char* bprefix;
2632 if (rep.space < 1048576.0f) {
2633 bprefix = X_("kilo");
2634 } else if (rep.space < 1048576.0f * 1000) {
2635 bprefix = X_("mega");
2637 bprefix = X_("giga");
2641 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2643 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2646 dhbox.pack_start (*dimage, true, false, 5);
2647 dhbox.pack_start (txt, true, false, 5);
2649 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2650 TreeModel::Row row = *(results_model->append());
2651 row[results_columns.visible_name] = *i;
2652 row[results_columns.fullpath] = *i;
2655 list_scroller.add (results_display);
2656 list_scroller.set_size_request (-1, 150);
2657 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2659 dvbox.pack_start (dhbox, true, false, 5);
2660 dvbox.pack_start (list_scroller, true, false, 5);
2661 ddhbox.pack_start (dvbox, true, false, 5);
2663 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2664 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2665 results.set_default_response (RESPONSE_CLOSE);
2666 results.set_position (Gtk::WIN_POS_MOUSE);
2668 results_display.show();
2669 list_scroller.show();
2676 //results.get_vbox()->show();
2677 results.set_resizable (false);
2684 ARDOUR_UI::cleanup ()
2687 /* shouldn't happen: menu item is insensitive */
2692 MessageDialog checker (_("Are you sure you want to cleanup?"),
2694 Gtk::MESSAGE_QUESTION,
2695 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2697 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2698 ALL undo/redo information will be lost if you cleanup.\n\
2699 After cleanup, unused audio files will be moved to a \
2700 \"dead sounds\" location."));
2702 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2703 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2704 checker.set_default_response (RESPONSE_CANCEL);
2706 checker.set_name (_("CleanupDialog"));
2707 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2708 checker.set_position (Gtk::WIN_POS_MOUSE);
2710 switch (checker.run()) {
2711 case RESPONSE_ACCEPT:
2717 Session::cleanup_report rep;
2719 editor->prepare_for_cleanup ();
2721 /* do not allow flush until a session is reloaded */
2723 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2725 act->set_sensitive (false);
2728 if (session->cleanup_sources (rep)) {
2729 editor->finish_cleanup ();
2733 editor->finish_cleanup ();
2736 display_cleanup_results (rep,
2739 The following %1 files were not in use and \n\
2740 have been moved to:\n\
2742 Flushing the wastebasket will \n\
2743 release an additional\n\
2744 %3 %4bytes of disk space.\n"),
2746 The following file was not in use and \n \
2747 has been moved to:\n \
2749 Flushing the wastebasket will \n\
2750 release an additional\n\
2751 %3 %4bytes of disk space.\n"
2757 ARDOUR_UI::flush_trash ()
2760 /* shouldn't happen: menu item is insensitive */
2764 Session::cleanup_report rep;
2766 if (session->cleanup_trash_sources (rep)) {
2770 display_cleanup_results (rep,
2772 _("The following %1 files were deleted from\n\
2774 releasing %3 %4bytes of disk space"),
2775 _("The following file was deleted from\n\
2777 releasing %3 %4bytes of disk space"));
2781 ARDOUR_UI::add_route (Gtk::Window* float_window)
2789 if (add_route_dialog == 0) {
2790 add_route_dialog = new AddRouteDialog (*session);
2792 add_route_dialog->set_transient_for (*float_window);
2796 if (add_route_dialog->is_visible()) {
2797 /* we're already doing this */
2801 ResponseType r = (ResponseType) add_route_dialog->run ();
2803 add_route_dialog->hide();
2806 case RESPONSE_ACCEPT:
2813 if ((count = add_route_dialog->count()) <= 0) {
2817 string template_path = add_route_dialog->track_template();
2819 if (!template_path.empty()) {
2820 session->new_route_from_template (count, template_path);
2824 uint32_t input_chan = add_route_dialog->channels ();
2825 uint32_t output_chan;
2826 string name_template = add_route_dialog->name_template ();
2827 bool track = add_route_dialog->track ();
2828 RouteGroup* route_group = add_route_dialog->route_group ();
2830 AutoConnectOption oac = Config->get_output_auto_connect();
2832 if (oac & AutoConnectMaster) {
2833 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2835 output_chan = input_chan;
2838 /* XXX do something with name template */
2840 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2842 session_add_midi_track (route_group, count);
2844 MessageDialog msg (*editor,
2845 _("Sorry, MIDI Busses are not supported at this time."));
2847 //session_add_midi_bus();
2851 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
2853 session_add_audio_bus (input_chan, output_chan, route_group, count);
2859 ARDOUR_UI::mixer_settings () const
2864 node = session->instant_xml(X_("Mixer"));
2866 node = Config->instant_xml(X_("Mixer"));
2870 node = new XMLNode (X_("Mixer"));
2877 ARDOUR_UI::editor_settings () const
2882 node = session->instant_xml(X_("Editor"));
2884 node = Config->instant_xml(X_("Editor"));
2888 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2889 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2894 node = new XMLNode (X_("Editor"));
2901 ARDOUR_UI::keyboard_settings () const
2905 node = Config->extra_xml(X_("Keyboard"));
2908 node = new XMLNode (X_("Keyboard"));
2914 ARDOUR_UI::create_xrun_marker(nframes_t where)
2916 editor->mouse_add_new_marker (where, false, true);
2920 ARDOUR_UI::halt_on_xrun_message ()
2922 MessageDialog msg (*editor,
2923 _("Recording was stopped because your system could not keep up."));
2928 ARDOUR_UI::xrun_handler(nframes_t where)
2934 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2936 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2937 create_xrun_marker(where);
2940 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2941 halt_on_xrun_message ();
2946 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2951 while (disk_buffer_stats.size() > 60) {
2952 disk_buffer_stats.pop_front ();
2955 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2959 ARDOUR_UI::write_buffer_stats ()
2965 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2966 int fd = mkstemp (tmplt);
2968 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
2972 FILE* fout = fdopen (fd, "w");
2974 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
2978 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
2979 std::ostringstream ss;
2980 localtime_r (&(*i).when, &tm);
2981 strftime (buf, sizeof (buf), "%T", &tm);
2982 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
2985 disk_buffer_stats.clear ();
2990 cerr << "Ardour buffering statistics can be found in: " << path << endl;
2996 ARDOUR_UI::disk_overrun_handler ()
2998 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3000 write_buffer_stats ();
3002 if (!have_disk_speed_dialog_displayed) {
3003 have_disk_speed_dialog_displayed = true;
3004 MessageDialog* msg = new MessageDialog (*editor, _("\
3005 The disk system on your computer\n\
3006 was not able to keep up with Ardour.\n\
3008 Specifically, it failed to write data to disk\n\
3009 quickly enough to keep up with recording.\n"));
3010 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3016 ARDOUR_UI::disk_underrun_handler ()
3018 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3020 write_buffer_stats ();
3022 if (!have_disk_speed_dialog_displayed) {
3023 have_disk_speed_dialog_displayed = true;
3024 MessageDialog* msg = new MessageDialog (*editor,
3025 _("The disk system on your computer\n\
3026 was not able to keep up with Ardour.\n\
3028 Specifically, it failed to read data from disk\n\
3029 quickly enough to keep up with playback.\n"));
3030 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3036 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3038 have_disk_speed_dialog_displayed = false;
3043 ARDOUR_UI::session_dialog (std::string msg)
3045 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3050 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3052 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3061 ARDOUR_UI::pending_state_dialog ()
3063 HBox* hbox = new HBox();
3064 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3065 ArdourDialog dialog (_("Crash Recovery"), true);
3067 This session appears to have been in\n\
3068 middle of recording when ardour or\n\
3069 the computer was shutdown.\n\
3071 Ardour can recover any captured audio for\n\
3072 you, or it can ignore it. Please decide\n\
3073 what you would like to do.\n"));
3074 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3075 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3076 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3077 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3078 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3079 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3080 dialog.set_default_response (RESPONSE_ACCEPT);
3081 dialog.set_position (WIN_POS_CENTER);
3086 switch (dialog.run ()) {
3087 case RESPONSE_ACCEPT:
3095 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3097 HBox* hbox = new HBox();
3098 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3099 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3100 Label message (string_compose (_("\
3101 This session was created with a sample rate of %1 Hz\n\
3103 The audioengine is currently running at %2 Hz\n"), desired, actual));
3105 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3106 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3107 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3108 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3109 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3110 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3111 dialog.set_default_response (RESPONSE_ACCEPT);
3112 dialog.set_position (WIN_POS_CENTER);
3117 switch (dialog.run ()) {
3118 case RESPONSE_ACCEPT:
3127 ARDOUR_UI::disconnect_from_jack ()
3130 if( engine->disconnect_from_jack ()) {
3131 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3135 update_sample_rate (0);
3140 ARDOUR_UI::reconnect_to_jack ()
3143 if (engine->reconnect_to_jack ()) {
3144 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3148 update_sample_rate (0);
3153 ARDOUR_UI::use_config ()
3156 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3158 set_transport_controllable_state (*node);
3163 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3165 if (Config->get_primary_clock_delta_edit_cursor()) {
3166 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3168 primary_clock.set (pos, 0, true);
3171 if (Config->get_secondary_clock_delta_edit_cursor()) {
3172 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3174 secondary_clock.set (pos);
3177 if (big_clock_window) {
3178 big_clock.set (pos);
3183 ARDOUR_UI::record_state_changed ()
3185 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3187 if (!session || !big_clock_window) {
3188 /* why bother - the clock isn't visible */
3192 Session::RecordState const r = session->record_status ();
3193 bool const h = session->have_rec_enabled_diskstream ();
3195 if (r == Session::Recording && h) {
3196 big_clock.set_widget_name ("BigClockRecording");
3198 big_clock.set_widget_name ("BigClockNonRecording");
3203 ARDOUR_UI::first_idle ()
3206 session->allow_auto_play (true);
3210 editor->first_idle();
3213 Keyboard::set_can_save_keybindings (true);
3218 ARDOUR_UI::store_clock_modes ()
3220 XMLNode* node = new XMLNode(X_("ClockModes"));
3222 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3223 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3226 session->add_extra_xml (*node);
3227 session->set_dirty ();
3232 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3233 : Controllable (name), ui (u), type(tp)
3239 ARDOUR_UI::TransportControllable::set_value (float val)
3241 if (type == ShuttleControl) {
3248 fract = -((0.5f - val)/0.5f);
3250 fract = ((val - 0.5f)/0.5f);
3254 ui.set_shuttle_fract (fract);
3259 /* do nothing: these are radio-style actions */
3263 const char *action = 0;
3267 action = X_("Roll");
3270 action = X_("Stop");
3273 action = X_("Goto Start");
3276 action = X_("Goto End");
3279 action = X_("Loop");
3282 action = X_("Play Selection");
3285 action = X_("Record");
3295 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3303 ARDOUR_UI::TransportControllable::get_value (void) const
3322 case ShuttleControl:
3332 ARDOUR_UI::TransportControllable::set_id (const string& str)
3338 ARDOUR_UI::setup_profile ()
3340 if (gdk_screen_width() < 1200) {
3341 Profile->set_small_screen ();
3345 if (getenv ("ARDOUR_SAE")) {
3346 Profile->set_sae ();
3347 Profile->set_single_package ();