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;
203 open_session_selector = 0;
204 have_configure_timeout = false;
205 have_disk_speed_dialog_displayed = false;
206 session_loaded = false;
207 last_speed_displayed = -1.0f;
208 ignore_dual_punch = false;
209 _mixer_on_top = false;
211 roll_button.unset_flags (Gtk::CAN_FOCUS);
212 stop_button.unset_flags (Gtk::CAN_FOCUS);
213 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
214 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
215 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
216 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
217 rec_button.unset_flags (Gtk::CAN_FOCUS);
219 last_configure_time= 0;
221 shuttle_grabbed = false;
223 shuttle_max_speed = 8.0f;
225 shuttle_style_menu = 0;
226 shuttle_unit_menu = 0;
228 // We do not have jack linked in yet so;
230 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
232 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
233 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
235 /* handle dialog requests */
237 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
239 /* handle pending state with a dialog */
241 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
243 /* handle sr mismatch with a dialog */
245 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
247 /* lets get this party started */
250 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
251 throw failed_constructor ();
254 setup_gtk_ardour_enums ();
257 GainMeter::setup_slider_pix ();
258 RouteTimeAxisView::setup_slider_pix ();
260 } catch (failed_constructor& err) {
261 error << _("could not initialize Ardour.") << endmsg;
266 /* we like keyboards */
268 keyboard = new Keyboard;
272 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
273 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
279 ARDOUR_UI::run_startup (bool should_be_new)
282 _startup = new ArdourStartup ();
285 _startup->set_new_only (should_be_new);
286 _startup->present ();
290 /* we don't return here until the startup assistant is finished */
296 ARDOUR_UI::create_engine ()
298 // this gets called every time by new_session()
304 loading_message (_("Starting audio engine"));
307 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
314 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
315 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
316 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
317 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
325 ARDOUR_UI::post_engine ()
327 /* Things to be done once we create the AudioEngine
330 MIDI::Manager::instance()->set_api_data (engine->jack());
333 ActionManager::init ();
336 if (setup_windows ()) {
337 throw failed_constructor ();
340 check_memory_locking();
342 /* this is the first point at which all the keybindings are available */
344 if (ARDOUR_COMMAND_LINE::show_key_actions) {
345 vector<string> names;
346 vector<string> paths;
348 vector<AccelKey> bindings;
350 ActionManager::get_all_actions (names, paths, keys, bindings);
352 vector<string>::iterator n;
353 vector<string>::iterator k;
354 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
355 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
361 blink_timeout_tag = -1;
363 /* this being a GUI and all, we want peakfiles */
365 AudioFileSource::set_build_peakfiles (true);
366 AudioFileSource::set_build_missing_peakfiles (true);
368 /* set default clock modes */
370 if (Profile->get_sae()) {
371 primary_clock.set_mode (AudioClock::BBT);
372 secondary_clock.set_mode (AudioClock::MinSec);
374 primary_clock.set_mode (AudioClock::SMPTE);
375 secondary_clock.set_mode (AudioClock::BBT);
378 /* start the time-of-day-clock */
381 /* OS X provides an always visible wallclock, so don't be stupid */
382 update_wall_clock ();
383 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
386 update_disk_space ();
388 update_sample_rate (engine->frame_rate());
390 /* now start and maybe save state */
392 if (do_engine_start () == 0) {
393 if (session && _session_is_new) {
394 /* we need to retain initial visual
395 settings for a new session
397 session->save_state ("");
402 ARDOUR_UI::~ARDOUR_UI ()
404 save_ardour_state ();
409 delete add_route_dialog;
413 ARDOUR_UI::pop_back_splash ()
415 if (Splash::instance()) {
416 // Splash::instance()->pop_back();
417 Splash::instance()->hide ();
422 ARDOUR_UI::configure_timeout ()
424 if (last_configure_time == 0) {
425 /* no configure events yet */
429 /* force a gap of 0.5 seconds since the last configure event
432 if (get_microseconds() - last_configure_time < 500000) {
435 have_configure_timeout = false;
436 save_ardour_state ();
442 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
444 if (have_configure_timeout) {
445 last_configure_time = get_microseconds();
447 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
448 have_configure_timeout = true;
455 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
457 const XMLProperty* prop;
459 if ((prop = node.property ("roll")) != 0) {
460 roll_controllable->set_id (prop->value());
462 if ((prop = node.property ("stop")) != 0) {
463 stop_controllable->set_id (prop->value());
465 if ((prop = node.property ("goto-start")) != 0) {
466 goto_start_controllable->set_id (prop->value());
468 if ((prop = node.property ("goto-end")) != 0) {
469 goto_end_controllable->set_id (prop->value());
471 if ((prop = node.property ("auto-loop")) != 0) {
472 auto_loop_controllable->set_id (prop->value());
474 if ((prop = node.property ("play-selection")) != 0) {
475 play_selection_controllable->set_id (prop->value());
477 if ((prop = node.property ("rec")) != 0) {
478 rec_controllable->set_id (prop->value());
480 if ((prop = node.property ("shuttle")) != 0) {
481 shuttle_controllable->set_id (prop->value());
486 ARDOUR_UI::get_transport_controllable_state ()
488 XMLNode* node = new XMLNode(X_("TransportControllables"));
491 roll_controllable->id().print (buf, sizeof (buf));
492 node->add_property (X_("roll"), buf);
493 stop_controllable->id().print (buf, sizeof (buf));
494 node->add_property (X_("stop"), buf);
495 goto_start_controllable->id().print (buf, sizeof (buf));
496 node->add_property (X_("goto_start"), buf);
497 goto_end_controllable->id().print (buf, sizeof (buf));
498 node->add_property (X_("goto_end"), buf);
499 auto_loop_controllable->id().print (buf, sizeof (buf));
500 node->add_property (X_("auto_loop"), buf);
501 play_selection_controllable->id().print (buf, sizeof (buf));
502 node->add_property (X_("play_selection"), buf);
503 rec_controllable->id().print (buf, sizeof (buf));
504 node->add_property (X_("rec"), buf);
505 shuttle_controllable->id().print (buf, sizeof (buf));
506 node->add_property (X_("shuttle"), buf);
512 ARDOUR_UI::save_ardour_state ()
514 if (!keyboard || !mixer || !editor) {
518 /* XXX this is all a bit dubious. add_extra_xml() uses
519 a different lifetime model from add_instant_xml().
522 XMLNode* node = new XMLNode (keyboard->get_state());
523 Config->add_extra_xml (*node);
524 Config->add_extra_xml (get_transport_controllable_state());
525 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
526 Config->add_extra_xml (_startup->engine_control()->get_state());
528 Config->save_state();
529 ui_config->save_state ();
531 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
532 XMLNode mnode(mixer->get_state());
535 session->add_instant_xml (enode);
536 session->add_instant_xml (mnode);
538 Config->add_instant_xml (enode);
539 Config->add_instant_xml (mnode);
542 Keyboard::save_keybindings ();
546 ARDOUR_UI::autosave_session ()
548 if (g_main_depth() > 1) {
549 /* inside a recursive main loop,
550 give up because we may not be able to
556 if (!Config->get_periodic_safety_backups()) {
561 session->maybe_write_autosave();
568 ARDOUR_UI::update_autosave ()
570 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
572 if (session->dirty()) {
573 if (_autosave_connection.connected()) {
574 _autosave_connection.disconnect();
577 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
578 Config->get_periodic_safety_backup_interval() * 1000);
581 if (_autosave_connection.connected()) {
582 _autosave_connection.disconnect();
588 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
592 title = _("Ardour could not start JACK");
594 title = _("Ardour could not connect to JACK.");
597 MessageDialog win (title,
603 win.set_secondary_text(_("There are several possible reasons:\n\
605 1) You requested audio parameters that are not supported..\n\
606 2) JACK is running as another user.\n\
608 Please consider the possibilities, and perhaps try different parameters."));
610 win.set_secondary_text(_("There are several possible reasons:\n\
612 1) JACK is not running.\n\
613 2) JACK is running as another user, perhaps root.\n\
614 3) There is already another client called \"ardour\".\n\
616 Please consider the possibilities, and perhaps (re)start JACK."));
620 win.set_transient_for (*toplevel);
624 win.add_button (Stock::OK, RESPONSE_CLOSE);
626 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
629 win.set_default_response (RESPONSE_CLOSE);
632 win.set_position (Gtk::WIN_POS_CENTER);
635 /* we just don't care about the result, but we want to block */
641 ARDOUR_UI::startup ()
643 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
645 if (audio_setup && _startup && _startup->engine_control()) {
646 _startup->engine_control()->set_state (*audio_setup);
649 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
655 goto_editor_window ();
657 BootMessage (_("Ardour is ready for use"));
662 ARDOUR_UI::no_memory_warning ()
664 XMLNode node (X_("no-memory-warning"));
665 Config->add_instant_xml (node);
669 ARDOUR_UI::check_memory_locking ()
672 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
676 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
678 if (engine->is_realtime() && memory_warning_node == 0) {
680 struct rlimit limits;
682 long pages, page_size;
684 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
687 ram = (int64_t) pages * (int64_t) page_size;
690 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
694 if (limits.rlim_cur != RLIM_INFINITY) {
696 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
699 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
700 "This might cause Ardour to run out of memory before your system "
701 "runs out of memory. \n\n"
702 "You can view the memory limit with 'ulimit -l', "
703 "and it is normally controlled by /etc/security/limits.conf"));
705 VBox* vbox = msg.get_vbox();
707 CheckButton cb (_("Do not show this window again"));
709 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
711 hbox.pack_start (cb, true, false);
712 vbox->pack_start (hbox);
719 editor->ensure_float (msg);
733 if (session->transport_rolling()) {
734 session->request_stop ();
738 if (session->dirty()) {
739 switch (ask_about_saving_session(_("quit"))) {
744 /* use the default name */
745 if (save_state_canfail ("")) {
746 /* failed - don't quit */
747 MessageDialog msg (*editor,
749 Ardour was unable to save your session.\n\n\
750 If you still wish to quit, please use the\n\n\
751 \"Just quit\" option."));
762 session->set_deletion_in_progress ();
765 ArdourDialog::close_all_dialogs ();
767 save_ardour_state ();
772 ARDOUR_UI::ask_about_saving_session (const string & what)
774 ArdourDialog window (_("ardour: save session?"));
775 Gtk::HBox dhbox; // the hbox for the image and text
776 Gtk::Label prompt_label;
777 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
781 msg = string_compose(_("Don't %1"), what);
782 window.add_button (msg, RESPONSE_REJECT);
783 msg = string_compose(_("Just %1"), what);
784 window.add_button (msg, RESPONSE_APPLY);
785 msg = string_compose(_("Save and %1"), what);
786 window.add_button (msg, RESPONSE_ACCEPT);
788 window.set_default_response (RESPONSE_ACCEPT);
790 Gtk::Button noquit_button (msg);
791 noquit_button.set_name ("EditorGTKButton");
796 if (session->snap_name() == session->name()) {
799 type = _("snapshot");
801 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?"),
802 type, session->snap_name());
804 prompt_label.set_text (prompt);
805 prompt_label.set_name (X_("PrompterLabel"));
806 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
808 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
809 dhbox.set_homogeneous (false);
810 dhbox.pack_start (*dimage, false, false, 5);
811 dhbox.pack_start (prompt_label, true, false, 5);
812 window.get_vbox()->pack_start (dhbox);
814 window.set_name (_("Prompter"));
815 window.set_position (Gtk::WIN_POS_MOUSE);
816 window.set_modal (true);
817 window.set_resizable (false);
823 window.set_keep_above (true);
826 ResponseType r = (ResponseType) window.run();
831 case RESPONSE_ACCEPT: // save and get out of here
833 case RESPONSE_APPLY: // get out of here
843 ARDOUR_UI::every_second ()
846 update_buffer_load ();
847 update_disk_space ();
852 ARDOUR_UI::every_point_one_seconds ()
854 update_speed_display ();
855 RapidScreenUpdate(); /* EMIT_SIGNAL */
860 ARDOUR_UI::every_point_zero_one_seconds ()
862 // august 2007: actual update frequency: 40Hz, not 100Hz
864 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
869 ARDOUR_UI::update_sample_rate (nframes_t ignored)
873 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
875 if (!engine->connected()) {
877 snprintf (buf, sizeof (buf), _("disconnected"));
881 nframes_t rate = engine->frame_rate();
883 if (fmod (rate, 1000.0) != 0.0) {
884 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
885 (float) rate/1000.0f,
886 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
888 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
890 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
894 sample_rate_label.set_text (buf);
898 ARDOUR_UI::update_cpu_load ()
901 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
902 cpu_load_label.set_text (buf);
906 ARDOUR_UI::update_buffer_load ()
912 c = session->capture_load ();
913 p = session->playback_load ();
915 push_buffer_stats (c, p);
917 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
918 session->playback_load(), session->capture_load());
919 buffer_load_label.set_text (buf);
921 buffer_load_label.set_text ("");
926 ARDOUR_UI::count_recenabled_streams (Route& route)
928 Track* track = dynamic_cast<Track*>(&route);
929 if (track && track->diskstream()->record_enabled()) {
930 rec_enabled_streams += track->n_inputs().n_total();
935 ARDOUR_UI::update_disk_space()
941 nframes_t frames = session->available_capture_duration();
943 nframes_t fr = session->frame_rate();
945 if (frames == max_frames) {
946 strcpy (buf, _("Disk: 24hrs+"));
948 rec_enabled_streams = 0;
949 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
951 if (rec_enabled_streams) {
952 frames /= rec_enabled_streams;
959 hrs = frames / (fr * 3600);
960 frames -= hrs * fr * 3600;
961 mins = frames / (fr * 60);
962 frames -= mins * fr * 60;
965 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
968 disk_space_label.set_text (buf);
970 // An attempt to make the disk space label flash red when space has run out.
972 if (frames < fr * 60 * 5) {
973 /* disk_space_box.style ("disk_space_label_empty"); */
975 /* disk_space_box.style ("disk_space_label"); */
981 ARDOUR_UI::update_wall_clock ()
988 tm_now = localtime (&now);
990 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
991 wall_clock_label.set_text (buf);
997 ARDOUR_UI::session_menu (GdkEventButton *ev)
999 session_popup_menu->popup (0, 0);
1004 ARDOUR_UI::redisplay_recent_sessions ()
1006 std::vector<sys::path> session_directories;
1007 RecentSessionsSorter cmp;
1009 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1010 recent_session_model->clear ();
1012 ARDOUR::RecentSessions rs;
1013 ARDOUR::read_recent_sessions (rs);
1016 recent_session_display.set_model (recent_session_model);
1020 // sort them alphabetically
1021 sort (rs.begin(), rs.end(), cmp);
1023 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1024 session_directories.push_back ((*i).second);
1027 for (vector<sys::path>::const_iterator i = session_directories.begin();
1028 i != session_directories.end(); ++i)
1030 std::vector<sys::path> state_file_paths;
1032 // now get available states for this session
1034 get_state_files_in_directory (*i, state_file_paths);
1036 vector<string*>* states;
1037 vector<const gchar*> item;
1038 string fullpath = (*i).to_string();
1040 /* remove any trailing / */
1042 if (fullpath[fullpath.length()-1] == '/') {
1043 fullpath = fullpath.substr (0, fullpath.length()-1);
1046 /* check whether session still exists */
1047 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1048 /* session doesn't exist */
1049 cerr << "skipping non-existent session " << fullpath << endl;
1053 /* now get available states for this session */
1055 if ((states = Session::possible_states (fullpath)) == 0) {
1056 /* no state file? */
1060 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1062 Gtk::TreeModel::Row row = *(recent_session_model->append());
1064 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1065 row[recent_session_columns.fullpath] = fullpath;
1067 if (state_file_names.size() > 1) {
1071 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1072 i2 != state_file_names.end(); ++i2)
1075 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1077 child_row[recent_session_columns.visible_name] = *i2;
1078 child_row[recent_session_columns.fullpath] = fullpath;
1083 recent_session_display.set_model (recent_session_model);
1087 ARDOUR_UI::build_session_selector ()
1089 session_selector_window = new ArdourDialog ("session selector");
1091 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1093 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1094 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1095 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1096 recent_session_model = TreeStore::create (recent_session_columns);
1097 recent_session_display.set_model (recent_session_model);
1098 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1099 recent_session_display.set_headers_visible (false);
1100 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1101 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1103 scroller->add (recent_session_display);
1104 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1106 session_selector_window->set_name ("SessionSelectorWindow");
1107 session_selector_window->set_size_request (200, 400);
1108 session_selector_window->get_vbox()->pack_start (*scroller);
1110 recent_session_display.show();
1112 //session_selector_window->get_vbox()->show();
1116 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1118 session_selector_window->response (RESPONSE_ACCEPT);
1122 ARDOUR_UI::open_recent_session ()
1124 bool can_return = (session != 0);
1126 if (session_selector_window == 0) {
1127 build_session_selector ();
1130 redisplay_recent_sessions ();
1134 session_selector_window->set_position (WIN_POS_MOUSE);
1136 ResponseType r = (ResponseType) session_selector_window->run ();
1139 case RESPONSE_ACCEPT:
1143 session_selector_window->hide();
1150 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1154 session_selector_window->hide();
1156 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1158 if (i == recent_session_model->children().end()) {
1162 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1163 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1165 _session_is_new = false;
1167 if (load_session (path, state) == 0) {
1176 ARDOUR_UI::check_audioengine ()
1179 if (!engine->connected()) {
1180 MessageDialog msg (_("Ardour is not connected to JACK\n"
1181 "You cannot open or close sessions in this condition"));
1193 ARDOUR_UI::open_session ()
1195 if (!check_audioengine()) {
1200 /* popup selector window */
1202 if (open_session_selector == 0) {
1204 /* ardour sessions are folders */
1206 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1207 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1208 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1209 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1211 FileFilter session_filter;
1212 session_filter.add_pattern ("*.ardour");
1213 session_filter.set_name (_("Ardour sessions"));
1214 open_session_selector->add_filter (session_filter);
1215 open_session_selector->set_filter (session_filter);
1218 int response = open_session_selector->run();
1219 open_session_selector->hide ();
1222 case RESPONSE_ACCEPT:
1225 open_session_selector->hide();
1229 open_session_selector->hide();
1230 string session_path = open_session_selector->get_filename();
1234 if (session_path.length() > 0) {
1235 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1236 _session_is_new = isnew;
1237 load_session (path, name);
1244 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1246 list<boost::shared_ptr<MidiTrack> > tracks;
1249 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1256 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1258 if (tracks.size() != how_many) {
1259 if (how_many == 1) {
1260 error << _("could not create a new midi track") << endmsg;
1262 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1266 if ((route = session->new_midi_route ()) == 0) {
1267 error << _("could not create new midi bus") << endmsg;
1273 MessageDialog msg (*editor,
1274 _("There are insufficient JACK ports available\n\
1275 to create a new track or bus.\n\
1276 You should save Ardour, exit and\n\
1277 restart JACK with more ports."));
1284 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1286 list<boost::shared_ptr<AudioTrack> > tracks;
1290 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1296 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1298 if (tracks.size() != how_many) {
1299 if (how_many == 1) {
1300 error << _("could not create a new audio track") << endmsg;
1302 error << string_compose (_("could only create %1 of %2 new audio %3"),
1303 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1309 routes = session->new_audio_route (input_channels, output_channels, how_many);
1311 if (routes.size() != how_many) {
1312 if (how_many == 1) {
1313 error << _("could not create a new audio track") << endmsg;
1315 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1321 if (need_control_room_outs) {
1327 route->set_stereo_control_outs (control_lr_channels);
1328 route->control_outs()->set_stereo_pan (pans, this);
1330 #endif /* CONTROLOUTS */
1334 MessageDialog msg (*editor,
1335 _("There are insufficient JACK ports available\n\
1336 to create a new track or bus.\n\
1337 You should save Ardour, exit and\n\
1338 restart JACK with more ports."));
1345 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1347 nframes_t _preroll = 0;
1350 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1351 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1353 if (new_position > _preroll) {
1354 new_position -= _preroll;
1359 session->request_locate (new_position);
1364 ARDOUR_UI::transport_goto_start ()
1367 session->goto_start();
1370 /* force displayed area in editor to start no matter
1371 what "follow playhead" setting is.
1375 editor->reset_x_origin (session->current_start_frame());
1381 ARDOUR_UI::transport_goto_zero ()
1384 session->request_locate (0);
1387 /* force displayed area in editor to start no matter
1388 what "follow playhead" setting is.
1392 editor->reset_x_origin (0);
1398 ARDOUR_UI::transport_goto_wallclock ()
1400 if (session && editor) {
1407 localtime_r (&now, &tmnow);
1409 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1410 frames += tmnow.tm_min * (60 * session->frame_rate());
1411 frames += tmnow.tm_sec * session->frame_rate();
1413 session->request_locate (frames);
1415 /* force displayed area in editor to start no matter
1416 what "follow playhead" setting is.
1420 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1426 ARDOUR_UI::transport_goto_end ()
1429 nframes_t frame = session->current_end_frame();
1430 session->request_locate (frame);
1432 /* force displayed area in editor to start no matter
1433 what "follow playhead" setting is.
1437 editor->reset_x_origin (frame);
1443 ARDOUR_UI::transport_stop ()
1449 if (session->is_auditioning()) {
1450 session->cancel_audition ();
1454 if (session->get_play_loop ()) {
1455 session->request_play_loop (false);
1458 session->request_stop ();
1462 ARDOUR_UI::transport_stop_and_forget_capture ()
1465 session->request_stop (true);
1470 ARDOUR_UI::remove_last_capture()
1473 editor->remove_last_capture();
1478 ARDOUR_UI::transport_record (bool roll)
1482 switch (session->record_status()) {
1483 case Session::Disabled:
1484 if (session->ntracks() == 0) {
1485 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1489 session->maybe_enable_record ();
1494 case Session::Recording:
1496 session->request_stop();
1498 session->disable_record (false, true);
1502 case Session::Enabled:
1503 session->disable_record (false, true);
1506 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1510 ARDOUR_UI::transport_roll ()
1518 rolling = session->transport_rolling ();
1520 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1522 if (session->get_play_loop()) {
1523 session->request_play_loop (false);
1524 auto_loop_button.set_visual_state (1);
1525 roll_button.set_visual_state (1);
1526 } else if (session->get_play_range ()) {
1527 session->request_play_range (false);
1528 play_selection_button.set_visual_state (0);
1529 } else if (rolling) {
1530 session->request_locate (session->last_transport_start(), true);
1533 session->request_transport_speed (1.0f);
1537 ARDOUR_UI::transport_loop()
1540 if (session->get_play_loop()) {
1541 if (session->transport_rolling()) {
1542 Location * looploc = session->locations()->auto_loop_location();
1544 session->request_locate (looploc->start(), true);
1549 session->request_play_loop (true);
1555 ARDOUR_UI::transport_play_selection ()
1561 if (!session->get_play_range()) {
1562 session->request_stop ();
1565 editor->play_selection ();
1569 ARDOUR_UI::transport_rewind (int option)
1571 float current_transport_speed;
1574 current_transport_speed = session->transport_speed();
1576 if (current_transport_speed >= 0.0f) {
1579 session->request_transport_speed (-1.0f);
1582 session->request_transport_speed (-4.0f);
1585 session->request_transport_speed (-0.5f);
1590 session->request_transport_speed (current_transport_speed * 1.5f);
1596 ARDOUR_UI::transport_forward (int option)
1598 float current_transport_speed;
1601 current_transport_speed = session->transport_speed();
1603 if (current_transport_speed <= 0.0f) {
1606 session->request_transport_speed (1.0f);
1609 session->request_transport_speed (4.0f);
1612 session->request_transport_speed (0.5f);
1617 session->request_transport_speed (current_transport_speed * 1.5f);
1623 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1629 boost::shared_ptr<Route> r;
1631 if ((r = session->route_by_remote_id (dstream)) != 0) {
1635 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1636 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1645 ARDOUR_UI::queue_transport_change ()
1647 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1651 ARDOUR_UI::map_transport_state ()
1653 float sp = session->transport_speed();
1656 transport_rolling ();
1657 } else if (sp < 0.0f) {
1658 transport_rewinding ();
1659 } else if (sp > 0.0f) {
1660 transport_forwarding ();
1662 transport_stopped ();
1667 ARDOUR_UI::engine_stopped ()
1669 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1670 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1671 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1675 ARDOUR_UI::engine_running ()
1677 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1678 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1679 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1681 Glib::RefPtr<Action> action;
1682 const char* action_name = 0;
1684 switch (engine->frames_per_cycle()) {
1686 action_name = X_("JACKLatency32");
1689 action_name = X_("JACKLatency64");
1692 action_name = X_("JACKLatency128");
1695 action_name = X_("JACKLatency512");
1698 action_name = X_("JACKLatency1024");
1701 action_name = X_("JACKLatency2048");
1704 action_name = X_("JACKLatency4096");
1707 action_name = X_("JACKLatency8192");
1710 /* XXX can we do anything useful ? */
1716 action = ActionManager::get_action (X_("JACK"), action_name);
1719 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1720 ract->set_active ();
1726 ARDOUR_UI::engine_halted ()
1728 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1730 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1731 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1733 update_sample_rate (0);
1735 MessageDialog msg (*editor,
1737 JACK has either been shutdown or it\n\
1738 disconnected Ardour because Ardour\n\
1739 was not fast enough. Try to restart\n\
1740 JACK, reconnect and save the session."));
1746 ARDOUR_UI::do_engine_start ()
1754 error << _("Unable to start the session running")
1764 ARDOUR_UI::setup_theme ()
1766 theme_manager->setup_theme();
1770 ARDOUR_UI::update_clocks ()
1772 if (!editor || !editor->dragging_playhead()) {
1773 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1778 ARDOUR_UI::start_clocking ()
1780 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1784 ARDOUR_UI::stop_clocking ()
1786 clock_signal_connection.disconnect ();
1790 ARDOUR_UI::toggle_clocking ()
1793 if (clock_button.get_active()) {
1802 ARDOUR_UI::_blink (void *arg)
1805 ((ARDOUR_UI *) arg)->blink ();
1812 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1816 ARDOUR_UI::start_blinking ()
1818 /* Start the blink signal. Everybody with a blinking widget
1819 uses Blink to drive the widget's state.
1822 if (blink_timeout_tag < 0) {
1824 blink_timeout_tag = g_timeout_add (240, _blink, this);
1829 ARDOUR_UI::stop_blinking ()
1831 if (blink_timeout_tag >= 0) {
1832 g_source_remove (blink_timeout_tag);
1833 blink_timeout_tag = -1;
1838 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1843 vector<string> connections;
1846 if (io.n_inputs().n_total() == 0) {
1851 /* XXX we're not handling multiple ports yet. */
1853 if (io.input(0)->get_connections(connections) == 0) {
1856 buf = connections.front();
1861 if (io.n_outputs().n_total() == 0) {
1866 /* XXX we're not handling multiple ports yet. */
1868 if (io.output(0)->get_connections(connections) == 0) {
1871 buf = connections.front();
1876 /** Ask the user for the name of a new shapshot and then take it.
1879 ARDOUR_UI::snapshot_session ()
1881 ArdourPrompter prompter (true);
1885 struct tm local_time;
1888 localtime_r (&n, &local_time);
1889 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1891 prompter.set_name ("Prompter");
1892 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1893 prompter.set_prompt (_("Name of New Snapshot"));
1894 prompter.set_initial_text (timebuf);
1896 switch (prompter.run()) {
1897 case RESPONSE_ACCEPT:
1899 prompter.get_result (snapname);
1901 bool do_save = (snapname.length() != 0);
1903 vector<sys::path> p;
1904 get_state_files_in_directory (session->session_directory().root_path(), p);
1905 vector<string> n = get_file_names_no_extension (p);
1906 if (find (n.begin(), n.end(), snapname) != n.end()) {
1908 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1909 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1910 confirm.get_vbox()->pack_start (m, true, true);
1911 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1912 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1913 confirm.show_all ();
1914 switch (confirm.run()) {
1915 case RESPONSE_CANCEL:
1921 save_state (snapname);
1932 ARDOUR_UI::save_state (const string & name)
1934 (void) save_state_canfail (name);
1938 ARDOUR_UI::save_state_canfail (string name)
1943 if (name.length() == 0) {
1944 name = session->snap_name();
1947 if ((ret = session->save_state (name)) != 0) {
1951 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1956 ARDOUR_UI::primary_clock_value_changed ()
1959 session->request_locate (primary_clock.current_time ());
1964 ARDOUR_UI::big_clock_value_changed ()
1967 session->request_locate (big_clock.current_time ());
1972 ARDOUR_UI::secondary_clock_value_changed ()
1975 session->request_locate (secondary_clock.current_time ());
1980 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1986 Session::RecordState const r = session->record_status ();
1987 bool const h = session->have_rec_enabled_diskstream ();
1989 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1991 rec_button.set_visual_state (2);
1993 rec_button.set_visual_state (0);
1995 } else if (r == Session::Recording && h) {
1996 rec_button.set_visual_state (1);
1998 rec_button.set_visual_state (0);
2003 ARDOUR_UI::save_template ()
2006 ArdourPrompter prompter (true);
2009 if (!check_audioengine()) {
2013 prompter.set_name (X_("Prompter"));
2014 prompter.set_prompt (_("Name for mix template:"));
2015 prompter.set_initial_text(session->name() + _("-template"));
2016 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2018 switch (prompter.run()) {
2019 case RESPONSE_ACCEPT:
2020 prompter.get_result (name);
2022 if (name.length()) {
2023 session->save_template (name);
2033 ARDOUR_UI::edit_metadata ()
2035 SessionMetadataEditor dialog;
2036 dialog.set_session (session);
2037 editor->ensure_float (dialog);
2042 ARDOUR_UI::import_metadata ()
2044 SessionMetadataImporter dialog;
2045 dialog.set_session (session);
2046 editor->ensure_float (dialog);
2051 ARDOUR_UI::fontconfig_dialog ()
2054 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2055 may not and it can take a while to build it. Warn them.
2058 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2060 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2061 MessageDialog msg (*_startup,
2062 _("Welcome to Ardour.\n\n"
2063 "The program will take a bit longer to start up\n"
2064 "while the system fonts are checked.\n\n"
2065 "This will only be done once, and you will\n"
2066 "not see this message again\n"),
2079 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2081 existing_session = false;
2083 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2084 session_path = cmdline_path;
2085 existing_session = true;
2086 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2087 session_path = Glib::path_get_dirname (string (cmdline_path));
2088 existing_session = true;
2090 /* it doesn't exist, assume the best */
2091 session_path = Glib::path_get_dirname (string (cmdline_path));
2094 session_name = basename_nosuffix (string (cmdline_path));
2098 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2100 /* when this is called, the backend audio system must be running */
2102 /* the main idea here is to deal with the fact that a cmdline argument for the session
2103 can be interpreted in different ways - it could be a directory or a file, and before
2104 we load, we need to know both the session directory and the snapshot (statefile) within it
2105 that we are supposed to use.
2108 if (session_name.length() == 0 || session_path.length() == 0) {
2112 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2114 Glib::ustring predicted_session_file;
2116 predicted_session_file = session_path;
2117 predicted_session_file += '/';
2118 predicted_session_file += session_name;
2119 predicted_session_file += ARDOUR::statefile_suffix;
2121 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2122 existing_session = true;
2125 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2127 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2128 /* existing .ardour file */
2129 existing_session = true;
2133 existing_session = false;
2136 /* lets just try to load it */
2138 if (create_engine ()) {
2139 backend_audio_error (false, _startup);
2143 return load_session (session_path, session_name);
2147 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2149 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2151 MessageDialog msg (str,
2153 Gtk::MESSAGE_WARNING,
2154 Gtk::BUTTONS_YES_NO,
2158 msg.set_name (X_("CleanupDialog"));
2159 msg.set_wmclass (X_("existing_session"), "Ardour");
2160 msg.set_position (Gtk::WIN_POS_MOUSE);
2163 switch (msg.run()) {
2172 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2177 AutoConnectOption iconnect;
2178 AutoConnectOption oconnect;
2182 if (Profile->get_sae()) {
2186 iconnect = AutoConnectPhysical;
2187 oconnect = AutoConnectMaster;
2188 nphysin = 0; // use all available
2189 nphysout = 0; // use all available
2193 /* get settings from advanced section of NSD */
2195 if (_startup->create_control_bus()) {
2196 cchns = (uint32_t) _startup->control_channel_count();
2201 if (_startup->create_master_bus()) {
2202 mchns = (uint32_t) _startup->master_channel_count();
2207 if (_startup->connect_inputs()) {
2208 iconnect = AutoConnectPhysical;
2210 iconnect = AutoConnectOption (0);
2213 /// @todo some minor tweaks.
2215 if (_startup->connect_outs_to_master()) {
2216 oconnect = AutoConnectMaster;
2217 } else if (_startup->connect_outs_to_physical()) {
2218 oconnect = AutoConnectPhysical;
2220 oconnect = AutoConnectOption (0);
2223 nphysin = (uint32_t) _startup->input_limit_count();
2224 nphysout = (uint32_t) _startup->output_limit_count();
2227 if (build_session (session_path,
2235 engine->frame_rate() * 60 * 5)) {
2244 ARDOUR_UI::end_loading_messages ()
2250 ARDOUR_UI::loading_message (const std::string& msg)
2253 // splash->message (msg);
2258 ARDOUR_UI::get_session_parameters (bool should_be_new)
2260 Glib::ustring session_name;
2261 Glib::ustring session_path;
2262 Glib::ustring template_name;
2264 bool likely_new = false;
2268 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2270 /* if they named a specific statefile, use it, otherwise they are
2271 just giving a session folder, and we want to use it as is
2272 to find the session.
2275 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2276 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2278 session_path = ARDOUR_COMMAND_LINE::session_name;
2281 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2285 run_startup (should_be_new);
2287 /* if we run the startup dialog again, offer more than just "new session" */
2289 should_be_new = false;
2291 session_name = _startup->session_name (likely_new);
2293 /* this shouldn't happen, but we catch it just in case it does */
2295 if (session_name.empty()) {
2298 if (_startup->use_session_template()) {
2299 template_name = _startup->session_template_name();
2300 _session_is_new = true;
2304 if (session_name[0] == '/' ||
2305 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2306 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2308 session_path = Glib::path_get_dirname (session_name);
2309 session_name = Glib::path_get_basename (session_name);
2313 session_path = _startup->session_folder();
2317 if (create_engine ()) {
2321 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2325 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2327 if (!ask_about_loading_existing_session (existing)) {
2328 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2333 _session_is_new = false;
2338 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2340 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2344 _session_is_new = true;
2347 if (likely_new && template_name.empty()) {
2349 ret = build_session_from_nsd (session_path, session_name);
2353 ret = load_session (session_path, session_name, template_name);
2361 ARDOUR_UI::close_session()
2363 if (!check_audioengine()) {
2367 unload_session (true);
2369 get_session_parameters (false);
2373 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2375 Session *new_session;
2379 session_loaded = false;
2381 if (!check_audioengine()) {
2385 unload_status = unload_session ();
2387 if (unload_status < 0) {
2389 } else if (unload_status > 0) {
2394 /* if it already exists, we must have write access */
2396 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2397 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2398 "This prevents the session from being loaded."));
2404 loading_message (_("Please wait while Ardour loads your session"));
2407 new_session = new Session (*engine, path, snap_name, mix_template);
2410 /* this one is special */
2412 catch (AudioEngine::PortRegistrationFailure& err) {
2414 MessageDialog msg (err.what(),
2417 Gtk::BUTTONS_CLOSE);
2419 msg.set_title (_("Port Registration Error"));
2420 msg.set_secondary_text (_("Click the Close button to try again."));
2421 msg.set_position (Gtk::WIN_POS_CENTER);
2425 int response = msg.run ();
2430 case RESPONSE_CANCEL:
2440 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2443 Gtk::BUTTONS_CLOSE);
2445 msg.set_title (_("Loading Error"));
2446 msg.set_secondary_text (_("Click the Close button to try again."));
2447 msg.set_position (Gtk::WIN_POS_CENTER);
2451 int response = msg.run ();
2456 case RESPONSE_CANCEL:
2464 connect_to_session (new_session);
2466 session_loaded = true;
2468 goto_editor_window ();
2471 session->set_clean ();
2482 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2483 uint32_t control_channels,
2484 uint32_t master_channels,
2485 AutoConnectOption input_connect,
2486 AutoConnectOption output_connect,
2489 nframes_t initial_length)
2491 Session *new_session;
2494 if (!check_audioengine()) {
2498 session_loaded = false;
2500 x = unload_session ();
2508 _session_is_new = true;
2511 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2512 control_channels, master_channels, nphysin, nphysout, initial_length);
2517 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2523 connect_to_session (new_session);
2525 session_loaded = true;
2527 new_session->save_state(new_session->name());
2536 editor->show_window ();
2547 ARDOUR_UI::show_about ()
2551 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2558 ARDOUR_UI::hide_about ()
2561 about->get_window()->set_cursor ();
2567 ARDOUR_UI::about_signal_response(int response)
2573 ARDOUR_UI::show_splash ()
2577 splash = new Splash;
2585 splash->queue_draw ();
2586 splash->get_window()->process_updates (true);
2591 ARDOUR_UI::hide_splash ()
2599 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2603 removed = rep.paths.size();
2606 MessageDialog msgd (*editor,
2607 _("No audio files were ready for cleanup"),
2610 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2611 msgd.set_secondary_text (_("If this seems suprising, \n\
2612 check for any existing snapshots.\n\
2613 These may still include regions that\n\
2614 require some unused files to continue to exist."));
2620 ArdourDialog results (_("ardour: cleanup"), true, false);
2622 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2623 CleanupResultsModelColumns() {
2627 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2628 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2632 CleanupResultsModelColumns results_columns;
2633 Glib::RefPtr<Gtk::ListStore> results_model;
2634 Gtk::TreeView results_display;
2636 results_model = ListStore::create (results_columns);
2637 results_display.set_model (results_model);
2638 results_display.append_column (list_title, results_columns.visible_name);
2640 results_display.set_name ("CleanupResultsList");
2641 results_display.set_headers_visible (true);
2642 results_display.set_headers_clickable (false);
2643 results_display.set_reorderable (false);
2645 Gtk::ScrolledWindow list_scroller;
2648 Gtk::HBox dhbox; // the hbox for the image and text
2649 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2650 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2652 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2654 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2656 if (rep.space < 1048576.0f) {
2658 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2660 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2664 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2666 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2670 dhbox.pack_start (*dimage, true, false, 5);
2671 dhbox.pack_start (txt, true, false, 5);
2673 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2674 TreeModel::Row row = *(results_model->append());
2675 row[results_columns.visible_name] = *i;
2676 row[results_columns.fullpath] = *i;
2679 list_scroller.add (results_display);
2680 list_scroller.set_size_request (-1, 150);
2681 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2683 dvbox.pack_start (dhbox, true, false, 5);
2684 dvbox.pack_start (list_scroller, true, false, 5);
2685 ddhbox.pack_start (dvbox, true, false, 5);
2687 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2688 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2689 results.set_default_response (RESPONSE_CLOSE);
2690 results.set_position (Gtk::WIN_POS_MOUSE);
2692 results_display.show();
2693 list_scroller.show();
2700 //results.get_vbox()->show();
2701 results.set_resizable (false);
2708 ARDOUR_UI::cleanup ()
2711 /* shouldn't happen: menu item is insensitive */
2716 MessageDialog checker (_("Are you sure you want to cleanup?"),
2718 Gtk::MESSAGE_QUESTION,
2719 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2721 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2722 ALL undo/redo information will be lost if you cleanup.\n\
2723 After cleanup, unused audio files will be moved to a \
2724 \"dead sounds\" location."));
2726 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2727 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2728 checker.set_default_response (RESPONSE_CANCEL);
2730 checker.set_name (_("CleanupDialog"));
2731 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2732 checker.set_position (Gtk::WIN_POS_MOUSE);
2734 switch (checker.run()) {
2735 case RESPONSE_ACCEPT:
2741 Session::cleanup_report rep;
2743 editor->prepare_for_cleanup ();
2745 /* do not allow flush until a session is reloaded */
2747 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2749 act->set_sensitive (false);
2752 if (session->cleanup_sources (rep)) {
2753 editor->finish_cleanup ();
2757 editor->finish_cleanup ();
2760 display_cleanup_results (rep,
2763 The following %1 %2 not in use and \n\
2764 have been moved to:\n\
2766 Flushing the wastebasket will \n\
2767 release an additional\n\
2768 %4 %5bytes of disk space.\n"
2774 ARDOUR_UI::flush_trash ()
2777 /* shouldn't happen: menu item is insensitive */
2781 Session::cleanup_report rep;
2783 if (session->cleanup_trash_sources (rep)) {
2787 display_cleanup_results (rep,
2789 _("The following %1 %2 deleted from\n\
2791 releasing %4 %5bytes of disk space"));
2795 ARDOUR_UI::add_route (Gtk::Window* float_window)
2803 if (add_route_dialog == 0) {
2804 add_route_dialog = new AddRouteDialog;
2806 add_route_dialog->set_transient_for (*float_window);
2810 if (add_route_dialog->is_visible()) {
2811 /* we're already doing this */
2815 ResponseType r = (ResponseType) add_route_dialog->run ();
2817 add_route_dialog->hide();
2820 case RESPONSE_ACCEPT:
2827 if ((count = add_route_dialog->count()) <= 0) {
2831 string template_path = add_route_dialog->track_template();
2833 if (!template_path.empty()) {
2834 session->new_route_from_template (count, template_path);
2838 uint32_t input_chan = add_route_dialog->channels ();
2839 uint32_t output_chan;
2840 string name_template = add_route_dialog->name_template ();
2841 bool track = add_route_dialog->track ();
2843 AutoConnectOption oac = Config->get_output_auto_connect();
2845 if (oac & AutoConnectMaster) {
2846 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2848 output_chan = input_chan;
2851 /* XXX do something with name template */
2853 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2855 session_add_midi_track(count);
2857 MessageDialog msg (*editor,
2858 _("Sorry, MIDI Busses are not supported at this time."));
2860 //session_add_midi_bus();
2864 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2866 session_add_audio_bus (input_chan, output_chan, count);
2872 ARDOUR_UI::mixer_settings () const
2877 node = session->instant_xml(X_("Mixer"));
2879 node = Config->instant_xml(X_("Mixer"));
2883 node = new XMLNode (X_("Mixer"));
2890 ARDOUR_UI::editor_settings () const
2895 node = session->instant_xml(X_("Editor"));
2897 node = Config->instant_xml(X_("Editor"));
2901 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2902 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2907 node = new XMLNode (X_("Editor"));
2914 ARDOUR_UI::keyboard_settings () const
2918 node = Config->extra_xml(X_("Keyboard"));
2921 node = new XMLNode (X_("Keyboard"));
2927 ARDOUR_UI::create_xrun_marker(nframes_t where)
2929 editor->mouse_add_new_marker (where, false, true);
2933 ARDOUR_UI::halt_on_xrun_message ()
2935 MessageDialog msg (*editor,
2936 _("Recording was stopped because your system could not keep up."));
2941 ARDOUR_UI::xrun_handler(nframes_t where)
2947 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2949 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2950 create_xrun_marker(where);
2953 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2954 halt_on_xrun_message ();
2959 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2964 while (disk_buffer_stats.size() > 60) {
2965 disk_buffer_stats.pop_front ();
2968 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2972 ARDOUR_UI::write_buffer_stats ()
2978 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2979 int fd = mkstemp (tmplt);
2981 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
2985 FILE* fout = fdopen (fd, "w");
2987 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
2991 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
2992 std::ostringstream ss;
2993 localtime_r (&(*i).when, &tm);
2994 strftime (buf, sizeof (buf), "%T", &tm);
2995 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
2998 disk_buffer_stats.clear ();
3003 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3009 ARDOUR_UI::disk_overrun_handler ()
3011 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3013 write_buffer_stats ();
3015 if (!have_disk_speed_dialog_displayed) {
3016 have_disk_speed_dialog_displayed = true;
3017 MessageDialog* msg = new MessageDialog (*editor, _("\
3018 The disk system on your computer\n\
3019 was not able to keep up with Ardour.\n\
3021 Specifically, it failed to write data to disk\n\
3022 quickly enough to keep up with recording.\n"));
3023 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3029 ARDOUR_UI::disk_underrun_handler ()
3031 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3033 write_buffer_stats ();
3035 if (!have_disk_speed_dialog_displayed) {
3036 have_disk_speed_dialog_displayed = true;
3037 MessageDialog* msg = new MessageDialog (*editor,
3038 _("The disk system on your computer\n\
3039 was not able to keep up with Ardour.\n\
3041 Specifically, it failed to read data from disk\n\
3042 quickly enough to keep up with playback.\n"));
3043 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3049 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3051 have_disk_speed_dialog_displayed = false;
3056 ARDOUR_UI::session_dialog (std::string msg)
3058 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3063 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3065 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3074 ARDOUR_UI::pending_state_dialog ()
3076 HBox* hbox = new HBox();
3077 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3078 ArdourDialog dialog (_("Crash Recovery"), true);
3080 This session appears to have been in\n\
3081 middle of recording when ardour or\n\
3082 the computer was shutdown.\n\
3084 Ardour can recover any captured audio for\n\
3085 you, or it can ignore it. Please decide\n\
3086 what you would like to do.\n"));
3087 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3088 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3089 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3090 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3091 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3092 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3093 dialog.set_default_response (RESPONSE_ACCEPT);
3094 dialog.set_position (WIN_POS_CENTER);
3099 switch (dialog.run ()) {
3100 case RESPONSE_ACCEPT:
3108 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3110 HBox* hbox = new HBox();
3111 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3112 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3113 Label message (string_compose (_("\
3114 This session was created with a sample rate of %1 Hz\n\
3116 The audioengine is currently running at %2 Hz\n"), desired, actual));
3118 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3119 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3120 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3121 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3122 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3123 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3124 dialog.set_default_response (RESPONSE_ACCEPT);
3125 dialog.set_position (WIN_POS_CENTER);
3130 switch (dialog.run ()) {
3131 case RESPONSE_ACCEPT:
3140 ARDOUR_UI::disconnect_from_jack ()
3143 if( engine->disconnect_from_jack ()) {
3144 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3148 update_sample_rate (0);
3153 ARDOUR_UI::reconnect_to_jack ()
3156 if (engine->reconnect_to_jack ()) {
3157 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3161 update_sample_rate (0);
3166 ARDOUR_UI::use_config ()
3168 Glib::RefPtr<Action> act;
3172 switch (session->config.get_native_file_data_format ()) {
3174 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3177 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3180 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3185 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3186 ract->set_active ();
3189 switch (session->config.get_native_file_header_format ()) {
3191 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3194 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3197 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3200 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3203 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3206 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3209 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3214 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3215 ract->set_active ();
3218 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3220 set_transport_controllable_state (*node);
3225 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3227 if (Config->get_primary_clock_delta_edit_cursor()) {
3228 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3230 primary_clock.set (pos, 0, true);
3233 if (Config->get_secondary_clock_delta_edit_cursor()) {
3234 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3236 secondary_clock.set (pos);
3239 if (big_clock_window) {
3240 big_clock.set (pos);
3245 ARDOUR_UI::record_state_changed ()
3247 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3249 if (!session || !big_clock_window) {
3250 /* why bother - the clock isn't visible */
3254 Session::RecordState const r = session->record_status ();
3255 bool const h = session->have_rec_enabled_diskstream ();
3257 if (r == Session::Recording && h) {
3258 big_clock.set_widget_name ("BigClockRecording");
3260 big_clock.set_widget_name ("BigClockNonRecording");
3265 ARDOUR_UI::first_idle ()
3268 session->allow_auto_play (true);
3272 editor->first_idle();
3275 Keyboard::set_can_save_keybindings (true);
3280 ARDOUR_UI::store_clock_modes ()
3282 XMLNode* node = new XMLNode(X_("ClockModes"));
3284 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3285 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3288 session->add_extra_xml (*node);
3289 session->set_dirty ();
3294 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3295 : Controllable (name), ui (u), type(tp)
3301 ARDOUR_UI::TransportControllable::set_value (float val)
3303 if (type == ShuttleControl) {
3310 fract = -((0.5f - val)/0.5f);
3312 fract = ((val - 0.5f)/0.5f);
3316 ui.set_shuttle_fract (fract);
3321 /* do nothing: these are radio-style actions */
3325 const char *action = 0;
3329 action = X_("Roll");
3332 action = X_("Stop");
3335 action = X_("Goto Start");
3338 action = X_("Goto End");
3341 action = X_("Loop");
3344 action = X_("Play Selection");
3347 action = X_("Record");
3357 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3365 ARDOUR_UI::TransportControllable::get_value (void) const
3384 case ShuttleControl:
3394 ARDOUR_UI::TransportControllable::set_id (const string& str)
3400 ARDOUR_UI::setup_profile ()
3402 if (gdk_screen_width() < 1200) {
3403 Profile->set_small_screen ();
3407 if (getenv ("ARDOUR_SAE")) {
3408 Profile->set_sae ();
3409 Profile->set_single_package ();