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;
177 * This was commented out as it wasn't defined
178 * in A3 IIRC. If this is not needed it should
179 * be completely removed.
187 if (theArdourUI == 0) {
191 ui_config = new UIConfiguration();
192 theme_manager = new ThemeManager();
199 _session_is_new = false;
200 big_clock_window = 0;
201 session_selector_window = 0;
202 last_key_press_time = 0;
203 _will_create_new_session_automatically = false;
204 add_route_dialog = 0;
206 rc_option_editor = 0;
207 session_option_editor = 0;
209 open_session_selector = 0;
210 have_configure_timeout = false;
211 have_disk_speed_dialog_displayed = false;
212 session_loaded = false;
213 last_speed_displayed = -1.0f;
214 ignore_dual_punch = false;
215 _mixer_on_top = false;
217 roll_button.unset_flags (Gtk::CAN_FOCUS);
218 stop_button.unset_flags (Gtk::CAN_FOCUS);
219 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
220 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
221 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
222 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
223 rec_button.unset_flags (Gtk::CAN_FOCUS);
225 last_configure_time= 0;
227 shuttle_grabbed = false;
229 shuttle_max_speed = 8.0f;
231 shuttle_style_menu = 0;
232 shuttle_unit_menu = 0;
234 // We do not have jack linked in yet so;
236 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
238 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241 /* handle dialog requests */
243 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
245 /* handle pending state with a dialog */
247 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
249 /* handle sr mismatch with a dialog */
251 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
253 /* lets get this party started */
256 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
257 throw failed_constructor ();
260 setup_gtk_ardour_enums ();
263 GainMeter::setup_slider_pix ();
264 RouteTimeAxisView::setup_slider_pix ();
266 } catch (failed_constructor& err) {
267 error << _("could not initialize Ardour.") << endmsg;
272 /* we like keyboards */
274 keyboard = new Keyboard;
278 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
279 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
285 ARDOUR_UI::run_startup (bool should_be_new)
288 _startup = new ArdourStartup ();
291 _startup->set_new_only (should_be_new);
292 _startup->present ();
296 /* we don't return here until the startup assistant is finished */
302 ARDOUR_UI::create_engine ()
304 // this gets called every time by new_session()
310 loading_message (_("Starting audio engine"));
313 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
320 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
321 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
322 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
323 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
331 ARDOUR_UI::post_engine ()
333 /* Things to be done once we create the AudioEngine
336 MIDI::Manager::instance()->set_api_data (engine->jack());
339 ARDOUR::init_post_engine ();
341 ActionManager::init ();
344 if (setup_windows ()) {
345 throw failed_constructor ();
348 check_memory_locking();
350 /* this is the first point at which all the keybindings are available */
352 if (ARDOUR_COMMAND_LINE::show_key_actions) {
353 vector<string> names;
354 vector<string> paths;
356 vector<AccelKey> bindings;
358 ActionManager::get_all_actions (names, paths, keys, bindings);
360 vector<string>::iterator n;
361 vector<string>::iterator k;
362 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
363 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
369 blink_timeout_tag = -1;
371 /* this being a GUI and all, we want peakfiles */
373 AudioFileSource::set_build_peakfiles (true);
374 AudioFileSource::set_build_missing_peakfiles (true);
376 /* set default clock modes */
378 if (Profile->get_sae()) {
379 primary_clock.set_mode (AudioClock::BBT);
380 secondary_clock.set_mode (AudioClock::MinSec);
382 primary_clock.set_mode (AudioClock::SMPTE);
383 secondary_clock.set_mode (AudioClock::BBT);
386 /* start the time-of-day-clock */
389 /* OS X provides an always visible wallclock, so don't be stupid */
390 update_wall_clock ();
391 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
394 update_disk_space ();
396 update_sample_rate (engine->frame_rate());
398 /* now start and maybe save state */
400 if (do_engine_start () == 0) {
401 if (session && _session_is_new) {
402 /* we need to retain initial visual
403 settings for a new session
405 session->save_state ("");
410 ARDOUR_UI::~ARDOUR_UI ()
412 save_ardour_state ();
417 delete add_route_dialog;
421 ARDOUR_UI::pop_back_splash ()
423 if (Splash::instance()) {
424 // Splash::instance()->pop_back();
425 Splash::instance()->hide ();
430 ARDOUR_UI::configure_timeout ()
432 if (last_configure_time == 0) {
433 /* no configure events yet */
437 /* force a gap of 0.5 seconds since the last configure event
440 if (get_microseconds() - last_configure_time < 500000) {
443 have_configure_timeout = false;
444 save_ardour_state ();
450 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
452 if (have_configure_timeout) {
453 last_configure_time = get_microseconds();
455 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
456 have_configure_timeout = true;
463 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
465 const XMLProperty* prop;
467 if ((prop = node.property ("roll")) != 0) {
468 roll_controllable->set_id (prop->value());
470 if ((prop = node.property ("stop")) != 0) {
471 stop_controllable->set_id (prop->value());
473 if ((prop = node.property ("goto-start")) != 0) {
474 goto_start_controllable->set_id (prop->value());
476 if ((prop = node.property ("goto-end")) != 0) {
477 goto_end_controllable->set_id (prop->value());
479 if ((prop = node.property ("auto-loop")) != 0) {
480 auto_loop_controllable->set_id (prop->value());
482 if ((prop = node.property ("play-selection")) != 0) {
483 play_selection_controllable->set_id (prop->value());
485 if ((prop = node.property ("rec")) != 0) {
486 rec_controllable->set_id (prop->value());
488 if ((prop = node.property ("shuttle")) != 0) {
489 shuttle_controllable->set_id (prop->value());
494 ARDOUR_UI::get_transport_controllable_state ()
496 XMLNode* node = new XMLNode(X_("TransportControllables"));
499 roll_controllable->id().print (buf, sizeof (buf));
500 node->add_property (X_("roll"), buf);
501 stop_controllable->id().print (buf, sizeof (buf));
502 node->add_property (X_("stop"), buf);
503 goto_start_controllable->id().print (buf, sizeof (buf));
504 node->add_property (X_("goto_start"), buf);
505 goto_end_controllable->id().print (buf, sizeof (buf));
506 node->add_property (X_("goto_end"), buf);
507 auto_loop_controllable->id().print (buf, sizeof (buf));
508 node->add_property (X_("auto_loop"), buf);
509 play_selection_controllable->id().print (buf, sizeof (buf));
510 node->add_property (X_("play_selection"), buf);
511 rec_controllable->id().print (buf, sizeof (buf));
512 node->add_property (X_("rec"), buf);
513 shuttle_controllable->id().print (buf, sizeof (buf));
514 node->add_property (X_("shuttle"), buf);
520 ARDOUR_UI::save_ardour_state ()
522 if (!keyboard || !mixer || !editor) {
526 /* XXX this is all a bit dubious. add_extra_xml() uses
527 a different lifetime model from add_instant_xml().
530 XMLNode* node = new XMLNode (keyboard->get_state());
531 Config->add_extra_xml (*node);
532 Config->add_extra_xml (get_transport_controllable_state());
533 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
534 Config->add_extra_xml (_startup->engine_control()->get_state());
536 Config->save_state();
537 ui_config->save_state ();
539 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
540 XMLNode mnode(mixer->get_state());
543 session->add_instant_xml (enode);
544 session->add_instant_xml (mnode);
546 Config->add_instant_xml (enode);
547 Config->add_instant_xml (mnode);
550 Keyboard::save_keybindings ();
554 ARDOUR_UI::autosave_session ()
556 if (g_main_depth() > 1) {
557 /* inside a recursive main loop,
558 give up because we may not be able to
564 if (!Config->get_periodic_safety_backups()) {
569 session->maybe_write_autosave();
576 ARDOUR_UI::update_autosave ()
578 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
580 if (session && session->dirty()) {
581 if (_autosave_connection.connected()) {
582 _autosave_connection.disconnect();
585 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
586 Config->get_periodic_safety_backup_interval() * 1000);
589 if (_autosave_connection.connected()) {
590 _autosave_connection.disconnect();
596 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
600 title = _("Ardour could not start JACK");
602 title = _("Ardour could not connect to JACK.");
605 MessageDialog win (title,
611 win.set_secondary_text(_("There are several possible reasons:\n\
613 1) You requested audio parameters that are not supported..\n\
614 2) JACK is running as another user.\n\
616 Please consider the possibilities, and perhaps try different parameters."));
618 win.set_secondary_text(_("There are several possible reasons:\n\
620 1) JACK is not running.\n\
621 2) JACK is running as another user, perhaps root.\n\
622 3) There is already another client called \"ardour\".\n\
624 Please consider the possibilities, and perhaps (re)start JACK."));
628 win.set_transient_for (*toplevel);
632 win.add_button (Stock::OK, RESPONSE_CLOSE);
634 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
637 win.set_default_response (RESPONSE_CLOSE);
640 win.set_position (Gtk::WIN_POS_CENTER);
643 /* we just don't care about the result, but we want to block */
649 ARDOUR_UI::startup ()
651 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
653 if (audio_setup && _startup && _startup->engine_control()) {
654 _startup->engine_control()->set_state (*audio_setup);
657 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
663 goto_editor_window ();
665 BootMessage (_("Ardour is ready for use"));
670 ARDOUR_UI::no_memory_warning ()
672 XMLNode node (X_("no-memory-warning"));
673 Config->add_instant_xml (node);
677 ARDOUR_UI::check_memory_locking ()
680 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
684 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
686 if (engine->is_realtime() && memory_warning_node == 0) {
688 struct rlimit limits;
690 long pages, page_size;
692 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
695 ram = (int64_t) pages * (int64_t) page_size;
698 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
702 if (limits.rlim_cur != RLIM_INFINITY) {
704 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
707 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
708 "This might cause Ardour to run out of memory before your system "
709 "runs out of memory. \n\n"
710 "You can view the memory limit with 'ulimit -l', "
711 "and it is normally controlled by /etc/security/limits.conf"));
713 VBox* vbox = msg.get_vbox();
715 CheckButton cb (_("Do not show this window again"));
717 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
719 hbox.pack_start (cb, true, false);
720 vbox->pack_start (hbox);
727 editor->ensure_float (msg);
741 if (session->transport_rolling()) {
742 session->request_stop ();
746 if (session->dirty()) {
747 switch (ask_about_saving_session(_("quit"))) {
752 /* use the default name */
753 if (save_state_canfail ("")) {
754 /* failed - don't quit */
755 MessageDialog msg (*editor,
757 Ardour was unable to save your session.\n\n\
758 If you still wish to quit, please use the\n\n\
759 \"Just quit\" option."));
770 session->set_deletion_in_progress ();
773 ArdourDialog::close_all_dialogs ();
775 save_ardour_state ();
780 ARDOUR_UI::ask_about_saving_session (const string & what)
782 ArdourDialog window (_("ardour: save session?"));
783 Gtk::HBox dhbox; // the hbox for the image and text
784 Gtk::Label prompt_label;
785 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
789 msg = string_compose(_("Don't %1"), what);
790 window.add_button (msg, RESPONSE_REJECT);
791 msg = string_compose(_("Just %1"), what);
792 window.add_button (msg, RESPONSE_APPLY);
793 msg = string_compose(_("Save and %1"), what);
794 window.add_button (msg, RESPONSE_ACCEPT);
796 window.set_default_response (RESPONSE_ACCEPT);
798 Gtk::Button noquit_button (msg);
799 noquit_button.set_name ("EditorGTKButton");
804 if (session->snap_name() == session->name()) {
807 type = _("snapshot");
809 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?"),
810 type, session->snap_name());
812 prompt_label.set_text (prompt);
813 prompt_label.set_name (X_("PrompterLabel"));
814 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
816 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
817 dhbox.set_homogeneous (false);
818 dhbox.pack_start (*dimage, false, false, 5);
819 dhbox.pack_start (prompt_label, true, false, 5);
820 window.get_vbox()->pack_start (dhbox);
822 window.set_name (_("Prompter"));
823 window.set_position (Gtk::WIN_POS_MOUSE);
824 window.set_modal (true);
825 window.set_resizable (false);
831 window.set_keep_above (true);
834 ResponseType r = (ResponseType) window.run();
839 case RESPONSE_ACCEPT: // save and get out of here
841 case RESPONSE_APPLY: // get out of here
851 ARDOUR_UI::every_second ()
854 update_buffer_load ();
855 update_disk_space ();
860 ARDOUR_UI::every_point_one_seconds ()
862 update_speed_display ();
863 RapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::every_point_zero_one_seconds ()
870 // august 2007: actual update frequency: 40Hz, not 100Hz
872 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
877 ARDOUR_UI::update_sample_rate (nframes_t ignored)
881 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
883 if (!engine->connected()) {
885 snprintf (buf, sizeof (buf), _("disconnected"));
889 nframes_t rate = engine->frame_rate();
891 if (fmod (rate, 1000.0) != 0.0) {
892 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
893 (float) rate/1000.0f,
894 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
896 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
898 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
902 sample_rate_label.set_text (buf);
906 ARDOUR_UI::update_cpu_load ()
909 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
910 cpu_load_label.set_text (buf);
914 ARDOUR_UI::update_buffer_load ()
920 c = session->capture_load ();
921 p = session->playback_load ();
923 push_buffer_stats (c, p);
925 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
926 session->playback_load(), session->capture_load());
927 buffer_load_label.set_text (buf);
929 buffer_load_label.set_text ("");
934 ARDOUR_UI::count_recenabled_streams (Route& route)
936 Track* track = dynamic_cast<Track*>(&route);
937 if (track && track->diskstream()->record_enabled()) {
938 rec_enabled_streams += track->n_inputs().n_total();
943 ARDOUR_UI::update_disk_space()
949 nframes_t frames = session->available_capture_duration();
951 nframes_t fr = session->frame_rate();
953 if (frames == max_frames) {
954 strcpy (buf, _("Disk: 24hrs+"));
956 rec_enabled_streams = 0;
957 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
959 if (rec_enabled_streams) {
960 frames /= rec_enabled_streams;
967 hrs = frames / (fr * 3600);
968 frames -= hrs * fr * 3600;
969 mins = frames / (fr * 60);
970 frames -= mins * fr * 60;
973 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
976 disk_space_label.set_text (buf);
978 // An attempt to make the disk space label flash red when space has run out.
980 if (frames < fr * 60 * 5) {
981 /* disk_space_box.style ("disk_space_label_empty"); */
983 /* disk_space_box.style ("disk_space_label"); */
989 ARDOUR_UI::update_wall_clock ()
996 tm_now = localtime (&now);
998 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
999 wall_clock_label.set_text (buf);
1005 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1007 session_popup_menu->popup (0, 0);
1012 ARDOUR_UI::redisplay_recent_sessions ()
1014 std::vector<sys::path> session_directories;
1015 RecentSessionsSorter cmp;
1017 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1018 recent_session_model->clear ();
1020 ARDOUR::RecentSessions rs;
1021 ARDOUR::read_recent_sessions (rs);
1024 recent_session_display.set_model (recent_session_model);
1028 // sort them alphabetically
1029 sort (rs.begin(), rs.end(), cmp);
1031 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1032 session_directories.push_back ((*i).second);
1035 for (vector<sys::path>::const_iterator i = session_directories.begin();
1036 i != session_directories.end(); ++i)
1038 std::vector<sys::path> state_file_paths;
1040 // now get available states for this session
1042 get_state_files_in_directory (*i, state_file_paths);
1044 vector<string*>* states;
1045 vector<const gchar*> item;
1046 string fullpath = (*i).to_string();
1048 /* remove any trailing / */
1050 if (fullpath[fullpath.length()-1] == '/') {
1051 fullpath = fullpath.substr (0, fullpath.length()-1);
1054 /* check whether session still exists */
1055 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1056 /* session doesn't exist */
1057 cerr << "skipping non-existent session " << fullpath << endl;
1061 /* now get available states for this session */
1063 if ((states = Session::possible_states (fullpath)) == 0) {
1064 /* no state file? */
1068 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1070 Gtk::TreeModel::Row row = *(recent_session_model->append());
1072 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1073 row[recent_session_columns.fullpath] = fullpath;
1075 if (state_file_names.size() > 1) {
1079 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1080 i2 != state_file_names.end(); ++i2)
1083 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1085 child_row[recent_session_columns.visible_name] = *i2;
1086 child_row[recent_session_columns.fullpath] = fullpath;
1091 recent_session_display.set_model (recent_session_model);
1095 ARDOUR_UI::build_session_selector ()
1097 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1099 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1101 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1102 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1103 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1104 recent_session_model = TreeStore::create (recent_session_columns);
1105 recent_session_display.set_model (recent_session_model);
1106 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1107 recent_session_display.set_headers_visible (false);
1108 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1109 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1111 scroller->add (recent_session_display);
1112 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1114 session_selector_window->set_name ("SessionSelectorWindow");
1115 session_selector_window->set_size_request (200, 400);
1116 session_selector_window->get_vbox()->pack_start (*scroller);
1118 recent_session_display.show();
1120 //session_selector_window->get_vbox()->show();
1124 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1126 session_selector_window->response (RESPONSE_ACCEPT);
1130 ARDOUR_UI::open_recent_session ()
1132 bool can_return = (session != 0);
1134 if (session_selector_window == 0) {
1135 build_session_selector ();
1138 redisplay_recent_sessions ();
1142 session_selector_window->set_position (WIN_POS_MOUSE);
1144 ResponseType r = (ResponseType) session_selector_window->run ();
1147 case RESPONSE_ACCEPT:
1151 session_selector_window->hide();
1158 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1162 session_selector_window->hide();
1164 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1166 if (i == recent_session_model->children().end()) {
1170 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1171 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1173 _session_is_new = false;
1175 if (load_session (path, state) == 0) {
1184 ARDOUR_UI::check_audioengine ()
1187 if (!engine->connected()) {
1188 MessageDialog msg (_("Ardour is not connected to JACK\n"
1189 "You cannot open or close sessions in this condition"));
1201 ARDOUR_UI::open_session ()
1203 if (!check_audioengine()) {
1208 /* popup selector window */
1210 if (open_session_selector == 0) {
1212 /* ardour sessions are folders */
1214 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1215 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1216 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1217 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1219 FileFilter session_filter;
1220 session_filter.add_pattern ("*.ardour");
1221 session_filter.set_name (_("Ardour sessions"));
1222 open_session_selector->add_filter (session_filter);
1223 open_session_selector->set_filter (session_filter);
1226 int response = open_session_selector->run();
1227 open_session_selector->hide ();
1230 case RESPONSE_ACCEPT:
1233 open_session_selector->hide();
1237 open_session_selector->hide();
1238 string session_path = open_session_selector->get_filename();
1242 if (session_path.length() > 0) {
1243 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1244 _session_is_new = isnew;
1245 load_session (path, name);
1252 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1254 list<boost::shared_ptr<MidiTrack> > tracks;
1257 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1264 tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1266 if (tracks.size() != how_many) {
1267 if (how_many == 1) {
1268 error << _("could not create a new midi track") << endmsg;
1270 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1274 if ((route = session->new_midi_route ()) == 0) {
1275 error << _("could not create new midi bus") << endmsg;
1281 MessageDialog msg (*editor,
1282 _("There are insufficient JACK ports available\n\
1283 to create a new track or bus.\n\
1284 You should save Ardour, exit and\n\
1285 restart JACK with more ports."));
1292 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)
1294 list<boost::shared_ptr<AudioTrack> > tracks;
1298 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1304 tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1306 if (tracks.size() != how_many) {
1307 if (how_many == 1) {
1308 error << _("could not create a new audio track") << endmsg;
1310 error << string_compose (_("could only create %1 of %2 new audio %3"),
1311 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1317 routes = session->new_audio_route (input_channels, output_channels, route_group, how_many);
1319 if (routes.size() != how_many) {
1320 if (how_many == 1) {
1321 error << _("could not create a new audio track") << endmsg;
1323 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1329 if (need_control_room_outs) {
1335 route->set_stereo_control_outs (control_lr_channels);
1336 route->control_outs()->set_stereo_pan (pans, this);
1338 #endif /* CONTROLOUTS */
1342 MessageDialog msg (*editor,
1343 _("There are insufficient JACK ports available\n\
1344 to create a new track or bus.\n\
1345 You should save Ardour, exit and\n\
1346 restart JACK with more ports."));
1353 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1355 nframes_t _preroll = 0;
1358 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1359 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1361 if (new_position > _preroll) {
1362 new_position -= _preroll;
1367 session->request_locate (new_position);
1372 ARDOUR_UI::transport_goto_start ()
1375 session->goto_start();
1378 /* force displayed area in editor to start no matter
1379 what "follow playhead" setting is.
1383 editor->reset_x_origin (session->current_start_frame());
1389 ARDOUR_UI::transport_goto_zero ()
1392 session->request_locate (0);
1395 /* force displayed area in editor to start no matter
1396 what "follow playhead" setting is.
1400 editor->reset_x_origin (0);
1406 ARDOUR_UI::transport_goto_wallclock ()
1408 if (session && editor) {
1415 localtime_r (&now, &tmnow);
1417 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1418 frames += tmnow.tm_min * (60 * session->frame_rate());
1419 frames += tmnow.tm_sec * session->frame_rate();
1421 session->request_locate (frames);
1423 /* force displayed area in editor to start no matter
1424 what "follow playhead" setting is.
1428 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1434 ARDOUR_UI::transport_goto_end ()
1437 nframes_t frame = session->current_end_frame();
1438 session->request_locate (frame);
1440 /* force displayed area in editor to start no matter
1441 what "follow playhead" setting is.
1445 editor->reset_x_origin (frame);
1451 ARDOUR_UI::transport_stop ()
1457 if (session->is_auditioning()) {
1458 session->cancel_audition ();
1462 if (session->get_play_loop ()) {
1463 session->request_play_loop (false);
1466 session->request_stop ();
1470 ARDOUR_UI::transport_stop_and_forget_capture ()
1473 session->request_stop (true);
1478 ARDOUR_UI::remove_last_capture()
1481 editor->remove_last_capture();
1486 ARDOUR_UI::transport_record (bool roll)
1490 switch (session->record_status()) {
1491 case Session::Disabled:
1492 if (session->ntracks() == 0) {
1493 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1497 session->maybe_enable_record ();
1502 case Session::Recording:
1504 session->request_stop();
1506 session->disable_record (false, true);
1510 case Session::Enabled:
1511 session->disable_record (false, true);
1514 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1518 ARDOUR_UI::transport_roll ()
1526 rolling = session->transport_rolling ();
1528 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1530 if (session->get_play_loop()) {
1531 session->request_play_loop (false);
1532 auto_loop_button.set_visual_state (1);
1533 roll_button.set_visual_state (1);
1534 } else if (session->get_play_range ()) {
1535 session->request_play_range (false);
1536 play_selection_button.set_visual_state (0);
1537 } else if (rolling) {
1538 session->request_locate (session->last_transport_start(), true);
1541 session->request_transport_speed (1.0f);
1545 ARDOUR_UI::transport_loop()
1548 if (session->get_play_loop()) {
1549 if (session->transport_rolling()) {
1550 Location * looploc = session->locations()->auto_loop_location();
1552 session->request_locate (looploc->start(), true);
1557 session->request_play_loop (true);
1563 ARDOUR_UI::transport_play_selection ()
1569 if (!session->get_play_range()) {
1570 session->request_stop ();
1573 editor->play_selection ();
1577 ARDOUR_UI::transport_rewind (int option)
1579 float current_transport_speed;
1582 current_transport_speed = session->transport_speed();
1584 if (current_transport_speed >= 0.0f) {
1587 session->request_transport_speed (-1.0f);
1590 session->request_transport_speed (-4.0f);
1593 session->request_transport_speed (-0.5f);
1598 session->request_transport_speed (current_transport_speed * 1.5f);
1604 ARDOUR_UI::transport_forward (int option)
1606 float current_transport_speed;
1609 current_transport_speed = session->transport_speed();
1611 if (current_transport_speed <= 0.0f) {
1614 session->request_transport_speed (1.0f);
1617 session->request_transport_speed (4.0f);
1620 session->request_transport_speed (0.5f);
1625 session->request_transport_speed (current_transport_speed * 1.5f);
1631 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1637 boost::shared_ptr<Route> r;
1639 if ((r = session->route_by_remote_id (dstream)) != 0) {
1643 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1644 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1653 ARDOUR_UI::queue_transport_change ()
1655 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1659 ARDOUR_UI::map_transport_state ()
1661 float sp = session->transport_speed();
1664 transport_rolling ();
1665 } else if (sp < 0.0f) {
1666 transport_rewinding ();
1667 } else if (sp > 0.0f) {
1668 transport_forwarding ();
1670 transport_stopped ();
1675 ARDOUR_UI::engine_stopped ()
1677 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1678 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1679 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1683 ARDOUR_UI::engine_running ()
1685 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1686 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1687 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1689 Glib::RefPtr<Action> action;
1690 const char* action_name = 0;
1692 switch (engine->frames_per_cycle()) {
1694 action_name = X_("JACKLatency32");
1697 action_name = X_("JACKLatency64");
1700 action_name = X_("JACKLatency128");
1703 action_name = X_("JACKLatency512");
1706 action_name = X_("JACKLatency1024");
1709 action_name = X_("JACKLatency2048");
1712 action_name = X_("JACKLatency4096");
1715 action_name = X_("JACKLatency8192");
1718 /* XXX can we do anything useful ? */
1724 action = ActionManager::get_action (X_("JACK"), action_name);
1727 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1728 ract->set_active ();
1734 ARDOUR_UI::engine_halted ()
1736 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1738 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1739 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1741 update_sample_rate (0);
1743 MessageDialog msg (*editor,
1745 JACK has either been shutdown or it\n\
1746 disconnected Ardour because Ardour\n\
1747 was not fast enough. Try to restart\n\
1748 JACK, reconnect and save the session."));
1754 ARDOUR_UI::do_engine_start ()
1762 error << _("Unable to start the session running")
1772 ARDOUR_UI::setup_theme ()
1774 theme_manager->setup_theme();
1778 ARDOUR_UI::update_clocks ()
1780 if (!editor || !editor->dragging_playhead()) {
1781 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1786 ARDOUR_UI::start_clocking ()
1788 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1792 ARDOUR_UI::stop_clocking ()
1794 clock_signal_connection.disconnect ();
1798 ARDOUR_UI::toggle_clocking ()
1801 if (clock_button.get_active()) {
1810 ARDOUR_UI::_blink (void *arg)
1813 ((ARDOUR_UI *) arg)->blink ();
1820 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1824 ARDOUR_UI::start_blinking ()
1826 /* Start the blink signal. Everybody with a blinking widget
1827 uses Blink to drive the widget's state.
1830 if (blink_timeout_tag < 0) {
1832 blink_timeout_tag = g_timeout_add (240, _blink, this);
1837 ARDOUR_UI::stop_blinking ()
1839 if (blink_timeout_tag >= 0) {
1840 g_source_remove (blink_timeout_tag);
1841 blink_timeout_tag = -1;
1846 /** Ask the user for the name of a new shapshot and then take it.
1849 ARDOUR_UI::snapshot_session ()
1851 ArdourPrompter prompter (true);
1855 struct tm local_time;
1858 localtime_r (&n, &local_time);
1859 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1861 prompter.set_name ("Prompter");
1862 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1863 prompter.set_title (_("Take Snapshot"));
1864 prompter.set_prompt (_("Name of New Snapshot"));
1865 prompter.set_initial_text (timebuf);
1867 switch (prompter.run()) {
1868 case RESPONSE_ACCEPT:
1870 prompter.get_result (snapname);
1872 bool do_save = (snapname.length() != 0);
1874 vector<sys::path> p;
1875 get_state_files_in_directory (session->session_directory().root_path(), p);
1876 vector<string> n = get_file_names_no_extension (p);
1877 if (find (n.begin(), n.end(), snapname) != n.end()) {
1879 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1880 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1881 confirm.get_vbox()->pack_start (m, true, true);
1882 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1883 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1884 confirm.show_all ();
1885 switch (confirm.run()) {
1886 case RESPONSE_CANCEL:
1892 save_state (snapname);
1903 ARDOUR_UI::save_state (const string & name)
1905 (void) save_state_canfail (name);
1909 ARDOUR_UI::save_state_canfail (string name)
1914 if (name.length() == 0) {
1915 name = session->snap_name();
1918 if ((ret = session->save_state (name)) != 0) {
1922 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1927 ARDOUR_UI::primary_clock_value_changed ()
1930 session->request_locate (primary_clock.current_time ());
1935 ARDOUR_UI::big_clock_value_changed ()
1938 session->request_locate (big_clock.current_time ());
1943 ARDOUR_UI::secondary_clock_value_changed ()
1946 session->request_locate (secondary_clock.current_time ());
1951 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1957 Session::RecordState const r = session->record_status ();
1958 bool const h = session->have_rec_enabled_diskstream ();
1960 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1962 rec_button.set_visual_state (2);
1964 rec_button.set_visual_state (0);
1966 } else if (r == Session::Recording && h) {
1967 rec_button.set_visual_state (1);
1969 rec_button.set_visual_state (0);
1974 ARDOUR_UI::save_template ()
1976 ArdourPrompter prompter (true);
1979 if (!check_audioengine()) {
1983 prompter.set_name (X_("Prompter"));
1984 prompter.set_title (_("Save Mix Template"));
1985 prompter.set_prompt (_("Name for mix template:"));
1986 prompter.set_initial_text(session->name() + _("-template"));
1987 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1989 switch (prompter.run()) {
1990 case RESPONSE_ACCEPT:
1991 prompter.get_result (name);
1993 if (name.length()) {
1994 session->save_template (name);
2004 ARDOUR_UI::edit_metadata ()
2006 SessionMetadataEditor dialog;
2007 dialog.set_session (session);
2008 editor->ensure_float (dialog);
2013 ARDOUR_UI::import_metadata ()
2015 SessionMetadataImporter dialog;
2016 dialog.set_session (session);
2017 editor->ensure_float (dialog);
2022 ARDOUR_UI::fontconfig_dialog ()
2025 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2026 may not and it can take a while to build it. Warn them.
2029 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2031 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2032 MessageDialog msg (*_startup,
2033 _("Welcome to Ardour.\n\n"
2034 "The program will take a bit longer to start up\n"
2035 "while the system fonts are checked.\n\n"
2036 "This will only be done once, and you will\n"
2037 "not see this message again\n"),
2050 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2052 existing_session = false;
2054 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2055 session_path = cmdline_path;
2056 existing_session = true;
2057 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2058 session_path = Glib::path_get_dirname (string (cmdline_path));
2059 existing_session = true;
2061 /* it doesn't exist, assume the best */
2062 session_path = Glib::path_get_dirname (string (cmdline_path));
2065 session_name = basename_nosuffix (string (cmdline_path));
2069 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2071 /* when this is called, the backend audio system must be running */
2073 /* the main idea here is to deal with the fact that a cmdline argument for the session
2074 can be interpreted in different ways - it could be a directory or a file, and before
2075 we load, we need to know both the session directory and the snapshot (statefile) within it
2076 that we are supposed to use.
2079 if (session_name.length() == 0 || session_path.length() == 0) {
2083 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2085 Glib::ustring predicted_session_file;
2087 predicted_session_file = session_path;
2088 predicted_session_file += '/';
2089 predicted_session_file += session_name;
2090 predicted_session_file += ARDOUR::statefile_suffix;
2092 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2093 existing_session = true;
2096 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2098 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2099 /* existing .ardour file */
2100 existing_session = true;
2104 existing_session = false;
2107 /* lets just try to load it */
2109 if (create_engine ()) {
2110 backend_audio_error (false, _startup);
2114 return load_session (session_path, session_name);
2118 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2120 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2122 MessageDialog msg (str,
2124 Gtk::MESSAGE_WARNING,
2125 Gtk::BUTTONS_YES_NO,
2129 msg.set_name (X_("CleanupDialog"));
2130 msg.set_title (_("Cleanup Unused Sources"));
2131 msg.set_wmclass (X_("existing_session"), "Ardour");
2132 msg.set_position (Gtk::WIN_POS_MOUSE);
2135 switch (msg.run()) {
2144 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2149 AutoConnectOption iconnect;
2150 AutoConnectOption oconnect;
2154 if (Profile->get_sae()) {
2158 iconnect = AutoConnectPhysical;
2159 oconnect = AutoConnectMaster;
2160 nphysin = 0; // use all available
2161 nphysout = 0; // use all available
2165 /* get settings from advanced section of NSD */
2167 if (_startup->create_control_bus()) {
2168 cchns = (uint32_t) _startup->control_channel_count();
2173 if (_startup->create_master_bus()) {
2174 mchns = (uint32_t) _startup->master_channel_count();
2179 if (_startup->connect_inputs()) {
2180 iconnect = AutoConnectPhysical;
2182 iconnect = AutoConnectOption (0);
2185 /// @todo some minor tweaks.
2187 if (_startup->connect_outs_to_master()) {
2188 oconnect = AutoConnectMaster;
2189 } else if (_startup->connect_outs_to_physical()) {
2190 oconnect = AutoConnectPhysical;
2192 oconnect = AutoConnectOption (0);
2195 nphysin = (uint32_t) _startup->input_limit_count();
2196 nphysout = (uint32_t) _startup->output_limit_count();
2199 if (build_session (session_path,
2207 engine->frame_rate() * 60 * 5)) {
2216 ARDOUR_UI::idle_load (const Glib::ustring& path)
2219 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2220 /* /path/to/foo => /path/to/foo, foo */
2221 load_session (path, basename_nosuffix (path));
2223 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2224 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2228 ARDOUR_COMMAND_LINE::session_name = path;
2231 * new_session_dialog doens't exist in A3
2232 * Try to remove all references to it to
2233 * see if it will compile. NOTE: this will
2234 * likely cause a runtime issue is my somewhat
2238 //if (new_session_dialog) {
2241 /* make it break out of Dialog::run() and
2245 //new_session_dialog->response (1);
2251 ARDOUR_UI::end_loading_messages ()
2257 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2260 // splash->message (msg);
2265 ARDOUR_UI::get_session_parameters (bool should_be_new)
2267 Glib::ustring session_name;
2268 Glib::ustring session_path;
2269 Glib::ustring template_name;
2271 bool likely_new = false;
2275 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2277 /* if they named a specific statefile, use it, otherwise they are
2278 just giving a session folder, and we want to use it as is
2279 to find the session.
2282 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2283 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2285 session_path = ARDOUR_COMMAND_LINE::session_name;
2288 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2292 run_startup (should_be_new);
2294 /* if we run the startup dialog again, offer more than just "new session" */
2296 should_be_new = false;
2298 session_name = _startup->session_name (likely_new);
2300 /* this shouldn't happen, but we catch it just in case it does */
2302 if (session_name.empty()) {
2305 if (_startup->use_session_template()) {
2306 template_name = _startup->session_template_name();
2307 _session_is_new = true;
2311 if (session_name[0] == '/' ||
2312 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2313 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2315 session_path = Glib::path_get_dirname (session_name);
2316 session_name = Glib::path_get_basename (session_name);
2320 session_path = _startup->session_folder();
2324 if (create_engine ()) {
2328 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2332 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2334 if (!ask_about_loading_existing_session (existing)) {
2335 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2340 _session_is_new = false;
2345 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2347 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2351 _session_is_new = true;
2354 if (likely_new && template_name.empty()) {
2356 ret = build_session_from_nsd (session_path, session_name);
2360 ret = load_session (session_path, session_name, template_name);
2361 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2362 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2372 ARDOUR_UI::close_session()
2374 if (!check_audioengine()) {
2378 unload_session (true);
2380 ARDOUR_COMMAND_LINE::session_name = "";
2381 get_session_parameters (false);
2385 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2387 Session *new_session;
2391 session_loaded = false;
2393 if (!check_audioengine()) {
2397 unload_status = unload_session ();
2399 if (unload_status < 0) {
2401 } else if (unload_status > 0) {
2406 loading_message (_("Please wait while Ardour loads your session"));
2409 new_session = new Session (*engine, path, snap_name, mix_template);
2412 /* this one is special */
2414 catch (AudioEngine::PortRegistrationFailure& err) {
2416 MessageDialog msg (err.what(),
2419 Gtk::BUTTONS_CLOSE);
2421 msg.set_title (_("Port Registration Error"));
2422 msg.set_secondary_text (_("Click the Close button to try again."));
2423 msg.set_position (Gtk::WIN_POS_CENTER);
2427 int response = msg.run ();
2432 case RESPONSE_CANCEL:
2442 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2445 Gtk::BUTTONS_CLOSE);
2447 msg.set_title (_("Loading Error"));
2448 msg.set_secondary_text (_("Click the Close button to try again."));
2449 msg.set_position (Gtk::WIN_POS_CENTER);
2453 int response = msg.run ();
2458 case RESPONSE_CANCEL:
2466 connect_to_session (new_session);
2468 session_loaded = true;
2470 goto_editor_window ();
2473 session->set_clean ();
2484 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2485 uint32_t control_channels,
2486 uint32_t master_channels,
2487 AutoConnectOption input_connect,
2488 AutoConnectOption output_connect,
2491 nframes_t initial_length)
2493 Session *new_session;
2496 if (!check_audioengine()) {
2500 session_loaded = false;
2502 x = unload_session ();
2510 _session_is_new = true;
2513 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2514 control_channels, master_channels, nphysin, nphysout, initial_length);
2519 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2525 connect_to_session (new_session);
2527 session_loaded = true;
2529 new_session->save_state(new_session->name());
2538 editor->show_window ();
2549 ARDOUR_UI::show_about ()
2553 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2560 ARDOUR_UI::hide_about ()
2563 about->get_window()->set_cursor ();
2569 ARDOUR_UI::about_signal_response (int /*response*/)
2575 ARDOUR_UI::show_splash ()
2579 splash = new Splash;
2587 splash->queue_draw ();
2588 splash->get_window()->process_updates (true);
2593 ARDOUR_UI::hide_splash ()
2601 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2602 const string& plural_msg, const string& singular_msg)
2606 removed = rep.paths.size();
2609 MessageDialog msgd (*editor,
2610 _("No audio files were ready for cleanup"),
2613 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2614 msgd.set_secondary_text (_("If this seems suprising, \n\
2615 check for any existing snapshots.\n\
2616 These may still include regions that\n\
2617 require some unused files to continue to exist."));
2623 ArdourDialog results (_("ardour: cleanup"), true, false);
2625 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2626 CleanupResultsModelColumns() {
2630 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2631 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2635 CleanupResultsModelColumns results_columns;
2636 Glib::RefPtr<Gtk::ListStore> results_model;
2637 Gtk::TreeView results_display;
2639 results_model = ListStore::create (results_columns);
2640 results_display.set_model (results_model);
2641 results_display.append_column (list_title, results_columns.visible_name);
2643 results_display.set_name ("CleanupResultsList");
2644 results_display.set_headers_visible (true);
2645 results_display.set_headers_clickable (false);
2646 results_display.set_reorderable (false);
2648 Gtk::ScrolledWindow list_scroller;
2651 Gtk::HBox dhbox; // the hbox for the image and text
2652 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2653 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2655 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2657 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2663 %1 - number of files removed
2664 %2 - location of "dead_sounds"
2665 %3 - size of files affected
2666 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2669 const char* bprefix;
2671 if (rep.space < 1048576.0f) {
2672 bprefix = X_("kilo");
2673 } else if (rep.space < 1048576.0f * 1000) {
2674 bprefix = X_("mega");
2676 bprefix = X_("giga");
2680 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2682 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2685 dhbox.pack_start (*dimage, true, false, 5);
2686 dhbox.pack_start (txt, true, false, 5);
2688 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2689 TreeModel::Row row = *(results_model->append());
2690 row[results_columns.visible_name] = *i;
2691 row[results_columns.fullpath] = *i;
2694 list_scroller.add (results_display);
2695 list_scroller.set_size_request (-1, 150);
2696 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2698 dvbox.pack_start (dhbox, true, false, 5);
2699 dvbox.pack_start (list_scroller, true, false, 5);
2700 ddhbox.pack_start (dvbox, true, false, 5);
2702 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2703 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2704 results.set_default_response (RESPONSE_CLOSE);
2705 results.set_position (Gtk::WIN_POS_MOUSE);
2707 results_display.show();
2708 list_scroller.show();
2715 //results.get_vbox()->show();
2716 results.set_resizable (false);
2723 ARDOUR_UI::cleanup ()
2726 /* shouldn't happen: menu item is insensitive */
2731 MessageDialog checker (_("Are you sure you want to cleanup?"),
2733 Gtk::MESSAGE_QUESTION,
2734 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2736 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2737 ALL undo/redo information will be lost if you cleanup.\n\
2738 After cleanup, unused audio files will be moved to a \
2739 \"dead sounds\" location."));
2741 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2742 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2743 checker.set_default_response (RESPONSE_CANCEL);
2745 checker.set_name (_("CleanupDialog"));
2746 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2747 checker.set_position (Gtk::WIN_POS_MOUSE);
2749 switch (checker.run()) {
2750 case RESPONSE_ACCEPT:
2756 Session::cleanup_report rep;
2758 editor->prepare_for_cleanup ();
2760 /* do not allow flush until a session is reloaded */
2762 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2764 act->set_sensitive (false);
2767 if (session->cleanup_sources (rep)) {
2768 editor->finish_cleanup ();
2772 editor->finish_cleanup ();
2775 display_cleanup_results (rep,
2778 The following %1 files were not in use and \n\
2779 have been moved to:\n\
2781 Flushing the wastebasket will \n\
2782 release an additional\n\
2783 %3 %4bytes of disk space.\n"),
2785 The following file was not in use and \n \
2786 has been moved to:\n \
2788 Flushing the wastebasket will \n\
2789 release an additional\n\
2790 %3 %4bytes of disk space.\n"
2796 ARDOUR_UI::flush_trash ()
2799 /* shouldn't happen: menu item is insensitive */
2803 Session::cleanup_report rep;
2805 if (session->cleanup_trash_sources (rep)) {
2809 display_cleanup_results (rep,
2811 _("The following %1 files were deleted from\n\
2813 releasing %3 %4bytes of disk space"),
2814 _("The following file was deleted from\n\
2816 releasing %3 %4bytes of disk space"));
2820 ARDOUR_UI::add_route (Gtk::Window* float_window)
2828 if (add_route_dialog == 0) {
2829 add_route_dialog = new AddRouteDialog (*session);
2831 add_route_dialog->set_transient_for (*float_window);
2835 if (add_route_dialog->is_visible()) {
2836 /* we're already doing this */
2840 ResponseType r = (ResponseType) add_route_dialog->run ();
2842 add_route_dialog->hide();
2845 case RESPONSE_ACCEPT:
2852 if ((count = add_route_dialog->count()) <= 0) {
2856 string template_path = add_route_dialog->track_template();
2858 if (!template_path.empty()) {
2859 session->new_route_from_template (count, template_path);
2863 uint32_t input_chan = add_route_dialog->channels ();
2864 uint32_t output_chan;
2865 string name_template = add_route_dialog->name_template ();
2866 bool track = add_route_dialog->track ();
2867 RouteGroup* route_group = add_route_dialog->route_group ();
2869 AutoConnectOption oac = Config->get_output_auto_connect();
2871 if (oac & AutoConnectMaster) {
2872 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2874 output_chan = input_chan;
2877 /* XXX do something with name template */
2879 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2881 session_add_midi_track (route_group, count);
2883 MessageDialog msg (*editor,
2884 _("Sorry, MIDI Busses are not supported at this time."));
2886 //session_add_midi_bus();
2890 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
2892 session_add_audio_bus (input_chan, output_chan, route_group, count);
2898 ARDOUR_UI::mixer_settings () const
2903 node = session->instant_xml(X_("Mixer"));
2905 node = Config->instant_xml(X_("Mixer"));
2909 node = new XMLNode (X_("Mixer"));
2916 ARDOUR_UI::editor_settings () const
2921 node = session->instant_xml(X_("Editor"));
2923 node = Config->instant_xml(X_("Editor"));
2927 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2928 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2933 node = new XMLNode (X_("Editor"));
2940 ARDOUR_UI::keyboard_settings () const
2944 node = Config->extra_xml(X_("Keyboard"));
2947 node = new XMLNode (X_("Keyboard"));
2953 ARDOUR_UI::create_xrun_marker(nframes_t where)
2955 editor->mouse_add_new_marker (where, false, true);
2959 ARDOUR_UI::halt_on_xrun_message ()
2961 MessageDialog msg (*editor,
2962 _("Recording was stopped because your system could not keep up."));
2967 ARDOUR_UI::xrun_handler(nframes_t where)
2973 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2975 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2976 create_xrun_marker(where);
2979 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2980 halt_on_xrun_message ();
2985 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2990 while (disk_buffer_stats.size() > 60) {
2991 disk_buffer_stats.pop_front ();
2994 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2998 ARDOUR_UI::write_buffer_stats ()
3003 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
3004 int fd = mkstemp (tmplt);
3006 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3010 FILE* fout = fdopen (fd, "w");
3012 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), tmplt) << endl;
3016 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3017 std::ostringstream ss;
3018 localtime_r (&(*i).when, &tm);
3019 strftime (buf, sizeof (buf), "%T", &tm);
3020 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
3023 disk_buffer_stats.clear ();
3028 cerr << "Ardour buffering statistics can be found in: " << tmplt << endl;
3033 ARDOUR_UI::disk_overrun_handler ()
3035 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3037 write_buffer_stats ();
3039 if (!have_disk_speed_dialog_displayed) {
3040 have_disk_speed_dialog_displayed = true;
3041 MessageDialog* msg = new MessageDialog (*editor, _("\
3042 The disk system on your computer\n\
3043 was not able to keep up with Ardour.\n\
3045 Specifically, it failed to write data to disk\n\
3046 quickly enough to keep up with recording.\n"));
3047 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3053 ARDOUR_UI::disk_underrun_handler ()
3055 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3057 write_buffer_stats ();
3059 if (!have_disk_speed_dialog_displayed) {
3060 have_disk_speed_dialog_displayed = true;
3061 MessageDialog* msg = new MessageDialog (*editor,
3062 _("The disk system on your computer\n\
3063 was not able to keep up with Ardour.\n\
3065 Specifically, it failed to read data from disk\n\
3066 quickly enough to keep up with playback.\n"));
3067 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3073 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3075 have_disk_speed_dialog_displayed = false;
3080 ARDOUR_UI::session_dialog (std::string msg)
3082 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3087 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3089 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3098 ARDOUR_UI::pending_state_dialog ()
3100 HBox* hbox = new HBox();
3101 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3102 ArdourDialog dialog (_("Crash Recovery"), true);
3104 This session appears to have been in\n\
3105 middle of recording when ardour or\n\
3106 the computer was shutdown.\n\
3108 Ardour can recover any captured audio for\n\
3109 you, or it can ignore it. Please decide\n\
3110 what you would like to do.\n"));
3111 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3112 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3113 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3114 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3115 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3116 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3117 dialog.set_default_response (RESPONSE_ACCEPT);
3118 dialog.set_position (WIN_POS_CENTER);
3123 switch (dialog.run ()) {
3124 case RESPONSE_ACCEPT:
3132 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3134 HBox* hbox = new HBox();
3135 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3136 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3137 Label message (string_compose (_("\
3138 This session was created with a sample rate of %1 Hz\n\
3140 The audioengine is currently running at %2 Hz\n"), desired, actual));
3142 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3143 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3144 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3145 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3146 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3147 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3148 dialog.set_default_response (RESPONSE_ACCEPT);
3149 dialog.set_position (WIN_POS_CENTER);
3154 switch (dialog.run ()) {
3155 case RESPONSE_ACCEPT:
3164 ARDOUR_UI::disconnect_from_jack ()
3167 if( engine->disconnect_from_jack ()) {
3168 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3172 update_sample_rate (0);
3177 ARDOUR_UI::reconnect_to_jack ()
3180 if (engine->reconnect_to_jack ()) {
3181 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3185 update_sample_rate (0);
3190 ARDOUR_UI::use_config ()
3193 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3195 set_transport_controllable_state (*node);
3200 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3202 if (Config->get_primary_clock_delta_edit_cursor()) {
3203 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3205 primary_clock.set (pos, 0, true);
3208 if (Config->get_secondary_clock_delta_edit_cursor()) {
3209 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3211 secondary_clock.set (pos);
3214 if (big_clock_window) {
3215 big_clock.set (pos);
3220 ARDOUR_UI::record_state_changed ()
3222 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3224 if (!session || !big_clock_window) {
3225 /* why bother - the clock isn't visible */
3229 Session::RecordState const r = session->record_status ();
3230 bool const h = session->have_rec_enabled_diskstream ();
3232 if (r == Session::Recording && h) {
3233 big_clock.set_widget_name ("BigClockRecording");
3235 big_clock.set_widget_name ("BigClockNonRecording");
3240 ARDOUR_UI::first_idle ()
3243 session->allow_auto_play (true);
3247 editor->first_idle();
3250 Keyboard::set_can_save_keybindings (true);
3255 ARDOUR_UI::store_clock_modes ()
3257 XMLNode* node = new XMLNode(X_("ClockModes"));
3259 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3260 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3263 session->add_extra_xml (*node);
3264 session->set_dirty ();
3269 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3270 : Controllable (name), ui (u), type(tp)
3276 ARDOUR_UI::TransportControllable::set_value (float val)
3278 if (type == ShuttleControl) {
3285 fract = -((0.5f - val)/0.5f);
3287 fract = ((val - 0.5f)/0.5f);
3291 ui.set_shuttle_fract (fract);
3296 /* do nothing: these are radio-style actions */
3300 const char *action = 0;
3304 action = X_("Roll");
3307 action = X_("Stop");
3310 action = X_("Goto Start");
3313 action = X_("Goto End");
3316 action = X_("Loop");
3319 action = X_("Play Selection");
3322 action = X_("Record");
3332 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3340 ARDOUR_UI::TransportControllable::get_value (void) const
3359 case ShuttleControl:
3369 ARDOUR_UI::TransportControllable::set_id (const string& str)
3375 ARDOUR_UI::setup_profile ()
3377 if (gdk_screen_width() < 1200) {
3378 Profile->set_small_screen ();
3382 if (getenv ("ARDOUR_SAE")) {
3383 Profile->set_sae ();
3384 Profile->set_single_package ();