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"
87 #include "new_session_dialog.h"
91 #include "gui_thread.h"
92 #include "theme_manager.h"
93 #include "bundle_manager.h"
94 #include "session_metadata_dialog.h"
95 #include "gain_meter.h"
96 #include "route_time_axis.h"
100 using namespace ARDOUR;
102 using namespace Gtkmm2ext;
104 using namespace sigc;
106 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
107 UIConfiguration *ARDOUR_UI::ui_config = 0;
109 sigc::signal<void,bool> ARDOUR_UI::Blink;
110 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
111 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
112 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
114 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
116 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
118 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
119 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
120 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
121 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
125 preroll_button (_("pre\nroll")),
126 postroll_button (_("post\nroll")),
130 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
134 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
135 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
136 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
137 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
138 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
139 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
140 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
141 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
142 shuttle_controller_binding_proxy (shuttle_controllable),
144 roll_button (roll_controllable),
145 stop_button (stop_controllable),
146 goto_start_button (goto_start_controllable),
147 goto_end_button (goto_end_controllable),
148 auto_loop_button (auto_loop_controllable),
149 play_selection_button (play_selection_controllable),
150 rec_button (rec_controllable),
152 shuttle_units_button (_("% ")),
154 punch_in_button (_("Punch In")),
155 punch_out_button (_("Punch Out")),
156 auto_return_button (_("Auto Return")),
157 auto_play_button (_("Auto Play")),
158 auto_input_button (_("Auto Input")),
159 click_button (_("Click")),
160 time_master_button (_("time\nmaster")),
162 auditioning_alert_button (_("AUDITION")),
163 solo_alert_button (_("SOLO")),
164 midi_panic_button (_("Panic")),
166 error_log_button (_("Errors"))
169 using namespace Gtk::Menu_Helpers;
175 _auto_display_errors = false;
181 if (ARDOUR_COMMAND_LINE::session_name.length()) {
182 /* only show this if we're not going to post the new session dialog */
186 if (theArdourUI == 0) {
190 ui_config = new UIConfiguration();
191 theme_manager = new ThemeManager();
197 _session_is_new = false;
198 big_clock_window = 0;
199 session_selector_window = 0;
200 last_key_press_time = 0;
201 connection_editor = 0;
202 _will_create_new_session_automatically = false;
203 new_session_dialog = 0;
204 add_route_dialog = 0;
208 open_session_selector = 0;
209 have_configure_timeout = false;
210 have_disk_speed_dialog_displayed = false;
211 session_loaded = false;
212 last_speed_displayed = -1.0f;
213 ignore_dual_punch = false;
215 last_configure_time= 0;
217 shuttle_grabbed = false;
219 shuttle_max_speed = 8.0f;
221 shuttle_style_menu = 0;
222 shuttle_unit_menu = 0;
224 // We do not have jack linked in yet so;
226 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
228 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
229 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
231 /* handle dialog requests */
233 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
235 /* handle pending state with a dialog */
237 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
239 /* handle sr mismatch with a dialog */
241 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
243 /* lets get this party started */
246 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
247 throw failed_constructor ();
250 setup_gtk_ardour_enums ();
251 Config->set_current_owner (ConfigVariableBase::Interface);
254 GainMeter::setup_slider_pix ();
255 RouteTimeAxisView::setup_slider_pix ();
257 } catch (failed_constructor& err) {
258 error << _("could not initialize Ardour.") << endmsg;
263 /* we like keyboards */
265 keyboard = new Keyboard;
269 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
270 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
276 ARDOUR_UI::create_engine ()
278 // this gets called every time by new_session()
284 loading_message (_("Starting audio engine"));
287 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
294 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
295 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
296 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
297 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
305 ARDOUR_UI::post_engine ()
307 extern int setup_midi ();
309 /* Things to be done once we create the AudioEngine
312 MIDI::Manager::instance()->set_api_data (engine->jack());
315 ActionManager::init ();
318 if (setup_windows ()) {
319 throw failed_constructor ();
322 check_memory_locking();
324 /* this is the first point at which all the keybindings are available */
326 if (ARDOUR_COMMAND_LINE::show_key_actions) {
327 vector<string> names;
328 vector<string> paths;
330 vector<AccelKey> bindings;
332 ActionManager::get_all_actions (names, paths, keys, bindings);
334 vector<string>::iterator n;
335 vector<string>::iterator k;
336 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
337 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
343 blink_timeout_tag = -1;
345 /* the global configuration object is now valid */
349 /* this being a GUI and all, we want peakfiles */
351 AudioFileSource::set_build_peakfiles (true);
352 AudioFileSource::set_build_missing_peakfiles (true);
354 /* set default clock modes */
356 if (Profile->get_sae()) {
357 primary_clock.set_mode (AudioClock::MinSec);
359 primary_clock.set_mode (AudioClock::SMPTE);
361 secondary_clock.set_mode (AudioClock::BBT);
363 /* start the time-of-day-clock */
366 /* OS X provides an always visible wallclock, so don't be stupid */
367 update_wall_clock ();
368 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
371 update_disk_space ();
373 update_sample_rate (engine->frame_rate());
375 /* now start and maybe save state */
377 if (do_engine_start () == 0) {
378 if (session && _session_is_new) {
379 /* we need to retain initial visual
380 settings for a new session
382 session->save_state ("");
387 ARDOUR_UI::~ARDOUR_UI ()
389 save_ardour_state ();
403 if (add_route_dialog) {
404 delete add_route_dialog;
408 if (new_session_dialog) {
409 delete new_session_dialog;
414 ARDOUR_UI::pop_back_splash ()
416 if (Splash::instance()) {
417 // Splash::instance()->pop_back();
418 Splash::instance()->hide ();
423 ARDOUR_UI::configure_timeout ()
425 if (last_configure_time == 0) {
426 /* no configure events yet */
430 /* force a gap of 0.5 seconds since the last configure event
433 if (get_microseconds() - last_configure_time < 500000) {
436 have_configure_timeout = false;
437 save_ardour_state ();
443 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
445 if (have_configure_timeout) {
446 last_configure_time = get_microseconds();
448 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
449 have_configure_timeout = true;
456 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
458 const XMLProperty* prop;
460 if ((prop = node.property ("roll")) != 0) {
461 roll_controllable->set_id (prop->value());
463 if ((prop = node.property ("stop")) != 0) {
464 stop_controllable->set_id (prop->value());
466 if ((prop = node.property ("goto_start")) != 0) {
467 goto_start_controllable->set_id (prop->value());
469 if ((prop = node.property ("goto_end")) != 0) {
470 goto_end_controllable->set_id (prop->value());
472 if ((prop = node.property ("auto_loop")) != 0) {
473 auto_loop_controllable->set_id (prop->value());
475 if ((prop = node.property ("play_selection")) != 0) {
476 play_selection_controllable->set_id (prop->value());
478 if ((prop = node.property ("rec")) != 0) {
479 rec_controllable->set_id (prop->value());
481 if ((prop = node.property ("shuttle")) != 0) {
482 shuttle_controllable->set_id (prop->value());
487 ARDOUR_UI::get_transport_controllable_state ()
489 XMLNode* node = new XMLNode(X_("TransportControllables"));
492 roll_controllable->id().print (buf, sizeof (buf));
493 node->add_property (X_("roll"), buf);
494 stop_controllable->id().print (buf, sizeof (buf));
495 node->add_property (X_("stop"), buf);
496 goto_start_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("goto_start"), buf);
498 goto_end_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("goto_end"), buf);
500 auto_loop_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("auto_loop"), buf);
502 play_selection_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("play_selection"), buf);
504 rec_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("rec"), buf);
506 shuttle_controllable->id().print (buf, sizeof (buf));
507 node->add_property (X_("shuttle"), buf);
513 ARDOUR_UI::save_ardour_state ()
515 if (!keyboard || !mixer || !editor) {
519 /* XXX this is all a bit dubious. add_extra_xml() uses
520 a different lifetime model from add_instant_xml().
523 XMLNode* node = new XMLNode (keyboard->get_state());
524 Config->add_extra_xml (*node);
525 Config->add_extra_xml (get_transport_controllable_state());
526 Config->save_state();
527 ui_config->save_state ();
529 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
530 XMLNode mnode(mixer->get_state());
533 session->add_instant_xml (enode);
534 session->add_instant_xml (mnode);
536 Config->add_instant_xml (enode);
537 Config->add_instant_xml (mnode);
540 Keyboard::save_keybindings ();
544 ARDOUR_UI::autosave_session ()
546 if (g_main_depth() > 1) {
547 /* inside a recursive main loop,
548 give up because we may not be able to
554 if (!Config->get_periodic_safety_backups()) {
559 session->maybe_write_autosave();
566 ARDOUR_UI::update_autosave ()
568 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
570 if (session->dirty()) {
571 if (_autosave_connection.connected()) {
572 _autosave_connection.disconnect();
575 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
576 Config->get_periodic_safety_backup_interval() * 1000);
579 if (_autosave_connection.connected()) {
580 _autosave_connection.disconnect();
586 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
590 title = _("Ardour could not start JACK");
592 title = _("Ardour could not connect to JACK.");
595 MessageDialog win (title,
601 win.set_secondary_text(_("There are several possible reasons:\n\
603 1) You requested audio parameters that are not supported..\n\
604 2) JACK is running as another user.\n\
606 Please consider the possibilities, and perhaps try different parameters."));
608 win.set_secondary_text(_("There are several possible reasons:\n\
610 1) JACK is not running.\n\
611 2) JACK is running as another user, perhaps root.\n\
612 3) There is already another client called \"ardour\".\n\
614 Please consider the possibilities, and perhaps (re)start JACK."));
618 win.set_transient_for (*toplevel);
622 win.add_button (Stock::OK, RESPONSE_CLOSE);
624 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
627 win.set_default_response (RESPONSE_CLOSE);
630 win.set_position (Gtk::WIN_POS_CENTER);
633 /* we just don't care about the result, but we want to block */
639 ARDOUR_UI::startup ()
643 new_session_dialog = new NewSessionDialog();
645 bool backend_audio_is_running = EngineControl::engine_running();
646 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
649 new_session_dialog->engine_control.set_state (*audio_setup);
652 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
656 BootMessage (_("Ardour is ready for use"));
661 ARDOUR_UI::no_memory_warning ()
663 XMLNode node (X_("no-memory-warning"));
664 Config->add_instant_xml (node);
668 ARDOUR_UI::check_memory_locking ()
671 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
675 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
677 if (engine->is_realtime() && memory_warning_node == 0) {
679 struct rlimit limits;
681 long pages, page_size;
683 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
686 ram = (int64_t) pages * (int64_t) page_size;
689 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
693 if (limits.rlim_cur != RLIM_INFINITY) {
695 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
698 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
699 "This might cause Ardour to run out of memory before your system "
700 "runs out of memory. \n\n"
701 "You can view the memory limit with 'ulimit -l', "
702 "and it is normally controlled by /etc/security/limits.conf"));
704 VBox* vbox = msg.get_vbox();
706 CheckButton cb (_("Do not show this window again"));
708 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
710 hbox.pack_start (cb, true, false);
711 vbox->pack_start (hbox);
718 editor->ensure_float (msg);
732 if (session->transport_rolling()) {
733 session->request_stop ();
737 if (session->dirty()) {
738 switch (ask_about_saving_session(_("quit"))) {
743 /* use the default name */
744 if (save_state_canfail ("")) {
745 /* failed - don't quit */
746 MessageDialog msg (*editor,
748 Ardour was unable to save your session.\n\n\
749 If you still wish to quit, please use the\n\n\
750 \"Just quit\" option."));
761 session->set_deletion_in_progress ();
765 Config->save_state();
766 ARDOUR_UI::config()->save_state();
771 ARDOUR_UI::ask_about_saving_session (const string & what)
773 ArdourDialog window (_("ardour: save session?"));
774 Gtk::HBox dhbox; // the hbox for the image and text
775 Gtk::Label prompt_label;
776 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
780 msg = string_compose(_("Don't %1"), what);
781 window.add_button (msg, RESPONSE_REJECT);
782 msg = string_compose(_("Just %1"), what);
783 window.add_button (msg, RESPONSE_APPLY);
784 msg = string_compose(_("Save and %1"), what);
785 window.add_button (msg, RESPONSE_ACCEPT);
787 window.set_default_response (RESPONSE_ACCEPT);
789 Gtk::Button noquit_button (msg);
790 noquit_button.set_name ("EditorGTKButton");
795 if (session->snap_name() == session->name()) {
798 type = _("snapshot");
800 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?"),
801 type, session->snap_name());
803 prompt_label.set_text (prompt);
804 prompt_label.set_name (X_("PrompterLabel"));
805 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
807 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
808 dhbox.set_homogeneous (false);
809 dhbox.pack_start (*dimage, false, false, 5);
810 dhbox.pack_start (prompt_label, true, false, 5);
811 window.get_vbox()->pack_start (dhbox);
813 window.set_name (_("Prompter"));
814 window.set_position (Gtk::WIN_POS_MOUSE);
815 window.set_modal (true);
816 window.set_resizable (false);
822 window.set_keep_above (true);
825 ResponseType r = (ResponseType) window.run();
830 case RESPONSE_ACCEPT: // save and get out of here
832 case RESPONSE_APPLY: // get out of here
842 ARDOUR_UI::every_second ()
845 update_buffer_load ();
846 update_disk_space ();
851 ARDOUR_UI::every_point_one_seconds ()
853 update_speed_display ();
854 RapidScreenUpdate(); /* EMIT_SIGNAL */
859 ARDOUR_UI::every_point_zero_one_seconds ()
861 // august 2007: actual update frequency: 40Hz, not 100Hz
863 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::update_sample_rate (nframes_t ignored)
872 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
874 if (!engine->connected()) {
876 snprintf (buf, sizeof (buf), _("disconnected"));
880 nframes_t rate = engine->frame_rate();
882 if (fmod (rate, 1000.0) != 0.0) {
883 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
884 (float) rate/1000.0f,
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
887 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
893 sample_rate_label.set_text (buf);
897 ARDOUR_UI::update_cpu_load ()
900 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
901 cpu_load_label.set_text (buf);
905 ARDOUR_UI::update_buffer_load ()
910 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
911 session->playback_load(), session->capture_load());
912 buffer_load_label.set_text (buf);
914 buffer_load_label.set_text ("");
919 ARDOUR_UI::count_recenabled_streams (Route& route)
921 Track* track = dynamic_cast<Track*>(&route);
922 if (track && track->diskstream()->record_enabled()) {
923 rec_enabled_streams += track->n_inputs().n_total();
928 ARDOUR_UI::update_disk_space()
934 nframes_t frames = session->available_capture_duration();
937 if (frames == max_frames) {
938 strcpy (buf, _("Disk: 24hrs+"));
943 nframes_t fr = session->frame_rate();
945 rec_enabled_streams = 0;
946 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
948 if (rec_enabled_streams) {
949 frames /= rec_enabled_streams;
952 hrs = frames / (fr * 3600);
953 frames -= hrs * fr * 3600;
954 mins = frames / (fr * 60);
955 frames -= mins * fr * 60;
958 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
961 disk_space_label.set_text (buf);
965 ARDOUR_UI::update_wall_clock ()
972 tm_now = localtime (&now);
974 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
975 wall_clock_label.set_text (buf);
981 ARDOUR_UI::session_menu (GdkEventButton *ev)
983 session_popup_menu->popup (0, 0);
988 ARDOUR_UI::redisplay_recent_sessions ()
990 std::vector<sys::path> session_directories;
991 RecentSessionsSorter cmp;
993 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
994 recent_session_model->clear ();
996 ARDOUR::RecentSessions rs;
997 ARDOUR::read_recent_sessions (rs);
1000 recent_session_display.set_model (recent_session_model);
1004 // sort them alphabetically
1005 sort (rs.begin(), rs.end(), cmp);
1007 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1008 session_directories.push_back ((*i).second);
1011 for (vector<sys::path>::const_iterator i = session_directories.begin();
1012 i != session_directories.end(); ++i)
1014 std::vector<sys::path> state_file_paths;
1016 // now get available states for this session
1018 get_state_files_in_directory (*i, state_file_paths);
1020 vector<string*>* states;
1021 vector<const gchar*> item;
1022 string fullpath = (*i).to_string();
1024 /* remove any trailing / */
1026 if (fullpath[fullpath.length()-1] == '/') {
1027 fullpath = fullpath.substr (0, fullpath.length()-1);
1030 /* check whether session still exists */
1031 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1032 /* session doesn't exist */
1033 cerr << "skipping non-existent session " << fullpath << endl;
1037 /* now get available states for this session */
1039 if ((states = Session::possible_states (fullpath)) == 0) {
1040 /* no state file? */
1044 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1046 Gtk::TreeModel::Row row = *(recent_session_model->append());
1048 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1049 row[recent_session_columns.fullpath] = fullpath;
1051 if (state_file_names.size() > 1) {
1055 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1056 i2 != state_file_names.end(); ++i2)
1059 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1061 child_row[recent_session_columns.visible_name] = *i2;
1062 child_row[recent_session_columns.fullpath] = fullpath;
1067 recent_session_display.set_model (recent_session_model);
1071 ARDOUR_UI::build_session_selector ()
1073 session_selector_window = new ArdourDialog ("session selector");
1075 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1077 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1078 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1079 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1080 recent_session_model = TreeStore::create (recent_session_columns);
1081 recent_session_display.set_model (recent_session_model);
1082 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1083 recent_session_display.set_headers_visible (false);
1084 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1085 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1087 scroller->add (recent_session_display);
1088 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1090 session_selector_window->set_name ("SessionSelectorWindow");
1091 session_selector_window->set_size_request (200, 400);
1092 session_selector_window->get_vbox()->pack_start (*scroller);
1094 recent_session_display.show();
1096 //session_selector_window->get_vbox()->show();
1100 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1102 session_selector_window->response (RESPONSE_ACCEPT);
1106 ARDOUR_UI::open_recent_session ()
1108 bool can_return = (session != 0);
1110 if (session_selector_window == 0) {
1111 build_session_selector ();
1114 redisplay_recent_sessions ();
1118 session_selector_window->set_position (WIN_POS_MOUSE);
1120 ResponseType r = (ResponseType) session_selector_window->run ();
1123 case RESPONSE_ACCEPT:
1127 session_selector_window->hide();
1134 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1138 session_selector_window->hide();
1140 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1142 if (i == recent_session_model->children().end()) {
1146 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1147 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1149 _session_is_new = false;
1151 if (load_session (path, state) == 0) {
1160 ARDOUR_UI::check_audioengine ()
1163 if (!engine->connected()) {
1164 MessageDialog msg (_("Ardour is not connected to JACK\n"
1165 "You cannot open or close sessions in this condition"));
1177 ARDOUR_UI::open_session ()
1179 if (!check_audioengine()) {
1184 /* popup selector window */
1186 if (open_session_selector == 0) {
1188 /* ardour sessions are folders */
1190 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1191 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1192 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1193 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1195 FileFilter session_filter;
1196 session_filter.add_pattern ("*.ardour");
1197 session_filter.set_name (_("Ardour sessions"));
1198 open_session_selector->add_filter (session_filter);
1199 open_session_selector->set_filter (session_filter);
1202 int response = open_session_selector->run();
1203 open_session_selector->hide ();
1206 case RESPONSE_ACCEPT:
1209 open_session_selector->hide();
1213 open_session_selector->hide();
1214 string session_path = open_session_selector->get_filename();
1218 if (session_path.length() > 0) {
1219 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1220 _session_is_new = isnew;
1221 load_session (path, name);
1228 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1230 list<boost::shared_ptr<MidiTrack> > tracks;
1233 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1240 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1242 if (tracks.size() != how_many) {
1243 if (how_many == 1) {
1244 error << _("could not create a new midi track") << endmsg;
1246 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1250 if ((route = session->new_midi_route ()) == 0) {
1251 error << _("could not create new midi bus") << endmsg;
1257 MessageDialog msg (*editor,
1258 _("There are insufficient JACK ports available\n\
1259 to create a new track or bus.\n\
1260 You should save Ardour, exit and\n\
1261 restart JACK with more ports."));
1268 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1270 list<boost::shared_ptr<AudioTrack> > tracks;
1271 Session::RouteList routes;
1274 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1280 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1282 if (tracks.size() != how_many) {
1283 if (how_many == 1) {
1284 error << _("could not create a new audio track") << endmsg;
1286 error << string_compose (_("could only create %1 of %2 new audio %3"),
1287 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1293 routes = session->new_audio_route (input_channels, output_channels, how_many);
1295 if (routes.size() != how_many) {
1296 if (how_many == 1) {
1297 error << _("could not create a new audio track") << endmsg;
1299 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1305 if (need_control_room_outs) {
1311 route->set_stereo_control_outs (control_lr_channels);
1312 route->control_outs()->set_stereo_pan (pans, this);
1314 #endif /* CONTROLOUTS */
1318 MessageDialog msg (*editor,
1319 _("There are insufficient JACK ports available\n\
1320 to create a new track or bus.\n\
1321 You should save Ardour, exit and\n\
1322 restart JACK with more ports."));
1329 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1331 nframes_t _preroll = 0;
1334 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1335 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1337 if (new_position > _preroll) {
1338 new_position -= _preroll;
1343 session->request_locate (new_position);
1348 ARDOUR_UI::transport_goto_start ()
1351 session->goto_start();
1354 /* force displayed area in editor to start no matter
1355 what "follow playhead" setting is.
1359 editor->reset_x_origin (session->current_start_frame());
1365 ARDOUR_UI::transport_goto_zero ()
1368 session->request_locate (0);
1371 /* force displayed area in editor to start no matter
1372 what "follow playhead" setting is.
1376 editor->reset_x_origin (0);
1382 ARDOUR_UI::transport_goto_wallclock ()
1384 if (session && editor) {
1391 localtime_r (&now, &tmnow);
1393 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1394 frames += tmnow.tm_min * (60 * session->frame_rate());
1395 frames += tmnow.tm_sec * session->frame_rate();
1397 session->request_locate (frames);
1399 /* force displayed area in editor to start no matter
1400 what "follow playhead" setting is.
1404 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1410 ARDOUR_UI::transport_goto_end ()
1413 nframes_t frame = session->current_end_frame();
1414 session->request_locate (frame);
1416 /* force displayed area in editor to start no matter
1417 what "follow playhead" setting is.
1421 editor->reset_x_origin (frame);
1427 ARDOUR_UI::transport_stop ()
1433 if (session->is_auditioning()) {
1434 session->cancel_audition ();
1438 if (session->get_play_loop ()) {
1439 session->request_play_loop (false);
1442 session->request_stop ();
1446 ARDOUR_UI::transport_stop_and_forget_capture ()
1449 session->request_stop (true);
1454 ARDOUR_UI::remove_last_capture()
1457 editor->remove_last_capture();
1462 ARDOUR_UI::transport_record (bool roll)
1466 switch (session->record_status()) {
1467 case Session::Disabled:
1468 if (session->ntracks() == 0) {
1469 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1473 session->maybe_enable_record ();
1478 case Session::Recording:
1480 session->request_stop();
1482 session->disable_record (false, true);
1486 case Session::Enabled:
1487 session->disable_record (false, true);
1490 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1494 ARDOUR_UI::transport_roll ()
1502 rolling = session->transport_rolling ();
1504 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1506 if (session->get_play_loop()) {
1507 session->request_play_loop (false);
1508 auto_loop_button.set_visual_state (1);
1509 roll_button.set_visual_state (1);
1510 } else if (session->get_play_range ()) {
1511 session->request_play_range (false);
1512 play_selection_button.set_visual_state (0);
1513 } else if (rolling) {
1514 session->request_locate (session->last_transport_start(), true);
1517 session->request_transport_speed (1.0f);
1521 ARDOUR_UI::transport_loop()
1524 if (session->get_play_loop()) {
1525 if (session->transport_rolling()) {
1526 Location * looploc = session->locations()->auto_loop_location();
1528 session->request_locate (looploc->start(), true);
1533 session->request_play_loop (true);
1539 ARDOUR_UI::transport_play_selection ()
1545 if (!session->get_play_range()) {
1546 session->request_stop ();
1549 editor->play_selection ();
1553 ARDOUR_UI::transport_rewind (int option)
1555 float current_transport_speed;
1558 current_transport_speed = session->transport_speed();
1560 if (current_transport_speed >= 0.0f) {
1563 session->request_transport_speed (-1.0f);
1566 session->request_transport_speed (-4.0f);
1569 session->request_transport_speed (-0.5f);
1574 session->request_transport_speed (current_transport_speed * 1.5f);
1580 ARDOUR_UI::transport_forward (int option)
1582 float current_transport_speed;
1585 current_transport_speed = session->transport_speed();
1587 if (current_transport_speed <= 0.0f) {
1590 session->request_transport_speed (1.0f);
1593 session->request_transport_speed (4.0f);
1596 session->request_transport_speed (0.5f);
1601 session->request_transport_speed (current_transport_speed * 1.5f);
1607 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1613 boost::shared_ptr<Route> r;
1615 if ((r = session->route_by_remote_id (dstream)) != 0) {
1619 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1620 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1629 ARDOUR_UI::queue_transport_change ()
1631 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1635 ARDOUR_UI::map_transport_state ()
1637 float sp = session->transport_speed();
1640 transport_rolling ();
1641 } else if (sp < 0.0f) {
1642 transport_rewinding ();
1643 } else if (sp > 0.0f) {
1644 transport_forwarding ();
1646 transport_stopped ();
1651 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1653 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1654 (int) adj.get_value()].c_str());
1658 ARDOUR_UI::engine_stopped ()
1660 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1661 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1662 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1666 ARDOUR_UI::engine_running ()
1668 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1669 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1670 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1672 Glib::RefPtr<Action> action;
1673 const char* action_name = 0;
1675 switch (engine->frames_per_cycle()) {
1677 action_name = X_("JACKLatency32");
1680 action_name = X_("JACKLatency64");
1683 action_name = X_("JACKLatency128");
1686 action_name = X_("JACKLatency512");
1689 action_name = X_("JACKLatency1024");
1692 action_name = X_("JACKLatency2048");
1695 action_name = X_("JACKLatency4096");
1698 action_name = X_("JACKLatency8192");
1701 /* XXX can we do anything useful ? */
1707 action = ActionManager::get_action (X_("JACK"), action_name);
1710 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1711 ract->set_active ();
1717 ARDOUR_UI::engine_halted ()
1719 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1721 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1722 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1724 update_sample_rate (0);
1726 MessageDialog msg (*editor,
1728 JACK has either been shutdown or it\n\
1729 disconnected Ardour because Ardour\n\
1730 was not fast enough. You can save the\n\
1731 session and/or try to reconnect to JACK ."));
1737 ARDOUR_UI::do_engine_start ()
1745 error << _("Unable to start the session running")
1755 ARDOUR_UI::setup_theme ()
1757 theme_manager->setup_theme();
1761 ARDOUR_UI::update_clocks ()
1763 if (!editor || !editor->dragging_playhead()) {
1764 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1769 ARDOUR_UI::start_clocking ()
1771 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1775 ARDOUR_UI::stop_clocking ()
1777 clock_signal_connection.disconnect ();
1781 ARDOUR_UI::toggle_clocking ()
1784 if (clock_button.get_active()) {
1793 ARDOUR_UI::_blink (void *arg)
1796 ((ARDOUR_UI *) arg)->blink ();
1803 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1807 ARDOUR_UI::start_blinking ()
1809 /* Start the blink signal. Everybody with a blinking widget
1810 uses Blink to drive the widget's state.
1813 if (blink_timeout_tag < 0) {
1815 blink_timeout_tag = g_timeout_add (240, _blink, this);
1820 ARDOUR_UI::stop_blinking ()
1822 if (blink_timeout_tag >= 0) {
1823 g_source_remove (blink_timeout_tag);
1824 blink_timeout_tag = -1;
1829 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1834 vector<string> connections;
1837 if (io.n_inputs().n_total() == 0) {
1842 /* XXX we're not handling multiple ports yet. */
1844 if (io.input(0)->get_connections(connections) == 0) {
1847 buf = connections.front();
1852 if (io.n_outputs().n_total() == 0) {
1857 /* XXX we're not handling multiple ports yet. */
1859 if (io.output(0)->get_connections(connections) == 0) {
1862 buf = connections.front();
1867 /** Ask the user for the name of a new shapshot and then take it.
1870 ARDOUR_UI::snapshot_session ()
1872 ArdourPrompter prompter (true);
1876 struct tm local_time;
1879 localtime_r (&n, &local_time);
1880 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1882 prompter.set_name ("Prompter");
1883 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1884 prompter.set_prompt (_("Name of New Snapshot"));
1885 prompter.set_initial_text (timebuf);
1887 switch (prompter.run()) {
1888 case RESPONSE_ACCEPT:
1889 prompter.get_result (snapname);
1890 if (snapname.length()){
1891 save_state (snapname);
1901 ARDOUR_UI::save_state (const string & name)
1903 (void) save_state_canfail (name);
1907 ARDOUR_UI::save_state_canfail (string name)
1912 if (name.length() == 0) {
1913 name = session->snap_name();
1916 if ((ret = session->save_state (name)) != 0) {
1920 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1925 ARDOUR_UI::primary_clock_value_changed ()
1928 session->request_locate (primary_clock.current_time ());
1933 ARDOUR_UI::big_clock_value_changed ()
1936 session->request_locate (big_clock.current_time ());
1941 ARDOUR_UI::secondary_clock_value_changed ()
1944 session->request_locate (secondary_clock.current_time ());
1949 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1955 switch (session->record_status()) {
1956 case Session::Enabled:
1958 rec_button.set_visual_state (2);
1960 rec_button.set_visual_state (0);
1964 case Session::Recording:
1965 rec_button.set_visual_state (1);
1969 rec_button.set_visual_state (0);
1975 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1983 ARDOUR_UI::save_template ()
1986 ArdourPrompter prompter (true);
1989 if (!check_audioengine()) {
1993 prompter.set_name (X_("Prompter"));
1994 prompter.set_prompt (_("Name for mix template:"));
1995 prompter.set_initial_text(session->name() + _("-template"));
1996 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1998 switch (prompter.run()) {
1999 case RESPONSE_ACCEPT:
2000 prompter.get_result (name);
2002 if (name.length()) {
2003 session->save_template (name);
2013 ARDOUR_UI::edit_metadata ()
2015 SessionMetadataEditor dialog;
2016 dialog.set_session (session);
2017 editor->ensure_float (dialog);
2022 ARDOUR_UI::import_metadata ()
2024 SessionMetadataImporter dialog;
2025 dialog.set_session (session);
2026 editor->ensure_float (dialog);
2031 ARDOUR_UI::fontconfig_dialog ()
2034 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2035 may not and it can take a while to build it. Warn them.
2038 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2040 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2041 MessageDialog msg (*new_session_dialog,
2042 _("Welcome to Ardour.\n\n"
2043 "The program will take a bit longer to start up\n"
2044 "while the system fonts are checked.\n\n"
2045 "This will only be done once, and you will\n"
2046 "not see this message again\n"),
2059 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2061 existing_session = false;
2063 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2064 session_path = cmdline_path;
2065 existing_session = true;
2066 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2067 session_path = Glib::path_get_dirname (string (cmdline_path));
2068 existing_session = true;
2070 /* it doesn't exist, assume the best */
2071 session_path = Glib::path_get_dirname (string (cmdline_path));
2074 session_name = basename_nosuffix (string (cmdline_path));
2078 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2080 /* when this is called, the backend audio system must be running */
2082 /* the main idea here is to deal with the fact that a cmdline argument for the session
2083 can be interpreted in different ways - it could be a directory or a file, and before
2084 we load, we need to know both the session directory and the snapshot (statefile) within it
2085 that we are supposed to use.
2088 if (session_name.length() == 0 || session_path.length() == 0) {
2092 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2094 Glib::ustring predicted_session_file;
2096 predicted_session_file = session_path;
2097 predicted_session_file += '/';
2098 predicted_session_file += session_name;
2099 predicted_session_file += ARDOUR::statefile_suffix;
2101 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2102 existing_session = true;
2105 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2107 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2108 /* existing .ardour file */
2109 existing_session = true;
2113 existing_session = false;
2116 /* lets just try to load it */
2118 if (create_engine ()) {
2119 backend_audio_error (false, new_session_dialog);
2123 return load_session (session_path, session_name);
2127 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2129 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2131 MessageDialog msg (str,
2133 Gtk::MESSAGE_WARNING,
2134 Gtk::BUTTONS_YES_NO,
2138 msg.set_name (X_("CleanupDialog"));
2139 msg.set_wmclass (X_("existing_session"), "Ardour");
2140 msg.set_position (Gtk::WIN_POS_MOUSE);
2143 switch (msg.run()) {
2152 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2157 AutoConnectOption iconnect;
2158 AutoConnectOption oconnect;
2162 if (Profile->get_sae()) {
2166 iconnect = AutoConnectPhysical;
2167 oconnect = AutoConnectMaster;
2168 nphysin = 0; // use all available
2169 nphysout = 0; // use all available
2173 /* get settings from advanced section of NSD */
2175 if (new_session_dialog->create_control_bus()) {
2176 cchns = (uint32_t) new_session_dialog->control_channel_count();
2181 if (new_session_dialog->create_master_bus()) {
2182 mchns = (uint32_t) new_session_dialog->master_channel_count();
2187 if (new_session_dialog->connect_inputs()) {
2188 iconnect = AutoConnectPhysical;
2190 iconnect = AutoConnectOption (0);
2193 /// @todo some minor tweaks.
2195 if (new_session_dialog->connect_outs_to_master()) {
2196 oconnect = AutoConnectMaster;
2197 } else if (new_session_dialog->connect_outs_to_physical()) {
2198 oconnect = AutoConnectPhysical;
2200 oconnect = AutoConnectOption (0);
2203 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2204 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2207 if (build_session (session_path,
2215 engine->frame_rate() * 60 * 5)) {
2224 ARDOUR_UI::end_loading_messages ()
2230 ARDOUR_UI::loading_message (const std::string& msg)
2233 splash->message (msg);
2238 ARDOUR_UI::idle_load (const Glib::ustring& path)
2241 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2242 /* /path/to/foo => /path/to/foo, foo */
2243 load_session (path, basename_nosuffix (path));
2245 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2246 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2249 ARDOUR_COMMAND_LINE::session_name = path;
2250 if (new_session_dialog) {
2251 /* make it break out of Dialog::run() and
2254 new_session_dialog->response (1);
2260 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2262 bool existing_session = false;
2263 Glib::ustring session_name;
2264 Glib::ustring session_path;
2265 Glib::ustring template_name;
2269 response = Gtk::RESPONSE_NONE;
2271 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2273 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2275 /* don't ever reuse this */
2277 ARDOUR_COMMAND_LINE::session_name = string();
2279 if (existing_session && backend_audio_is_running) {
2281 /* just load the thing already */
2283 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2288 /* make the NSD use whatever information we have */
2290 new_session_dialog->set_session_name (session_name);
2291 new_session_dialog->set_session_folder (session_path);
2294 /* loading failed, or we need the NSD for something */
2296 new_session_dialog->set_modal (false);
2297 new_session_dialog->set_position (WIN_POS_CENTER);
2298 new_session_dialog->set_current_page (0);
2299 new_session_dialog->set_existing_session (existing_session);
2300 new_session_dialog->reset_recent();
2303 new_session_dialog->set_have_engine (backend_audio_is_running);
2304 new_session_dialog->present ();
2305 end_loading_messages ();
2306 response = new_session_dialog->run ();
2308 _session_is_new = false;
2310 /* handle possible negative responses */
2314 /* sent by idle_load, meaning restart the whole process again */
2315 new_session_dialog->hide();
2316 new_session_dialog->reset();
2320 case Gtk::RESPONSE_CANCEL:
2321 case Gtk::RESPONSE_DELETE_EVENT:
2325 new_session_dialog->hide ();
2328 case Gtk::RESPONSE_NONE:
2329 /* "Clear" was pressed */
2333 fontconfig_dialog();
2335 if (!backend_audio_is_running) {
2336 int ret = new_session_dialog->engine_control.setup_engine ();
2339 } else if (ret > 0) {
2340 response = Gtk::RESPONSE_REJECT;
2345 if (create_engine ()) {
2347 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2350 new_session_dialog->set_existing_session (false);
2351 new_session_dialog->set_current_page (2);
2353 response = Gtk::RESPONSE_NONE;
2357 backend_audio_is_running = true;
2359 if (response == Gtk::RESPONSE_OK) {
2361 session_name = new_session_dialog->session_name();
2363 if (session_name.empty()) {
2364 response = Gtk::RESPONSE_NONE;
2368 /* if the user mistakenly typed path information into the session filename entry,
2369 convert what they typed into a path & a name
2372 if (session_name[0] == '/' ||
2373 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2374 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2376 session_path = Glib::path_get_dirname (session_name);
2377 session_name = Glib::path_get_basename (session_name);
2381 session_path = new_session_dialog->session_folder();
2384 template_name = Glib::ustring();
2385 switch (new_session_dialog->which_page()) {
2387 case NewSessionDialog::OpenPage:
2388 case NewSessionDialog::EnginePage:
2392 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2394 should_be_new = true;
2396 //XXX This is needed because session constructor wants a
2397 //non-existant path. hopefully this will be fixed at some point.
2399 session_path = Glib::build_filename (session_path, session_name);
2401 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2403 if (ask_about_loading_existing_session (session_path)) {
2406 response = RESPONSE_NONE;
2411 _session_is_new = true;
2413 if (new_session_dialog->use_session_template()) {
2415 template_name = new_session_dialog->session_template_name();
2419 if (build_session_from_nsd (session_path, session_name)) {
2420 response = RESPONSE_NONE;
2432 new_session_dialog->hide ();
2434 if (load_session (session_path, session_name, template_name)) {
2436 response = Gtk::RESPONSE_NONE;
2440 if (response == Gtk::RESPONSE_NONE) {
2441 new_session_dialog->set_existing_session (false);
2442 new_session_dialog->reset ();
2446 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2450 new_session_dialog->hide();
2451 new_session_dialog->reset();
2452 goto_editor_window ();
2457 ARDOUR_UI::close_session()
2459 if (!check_audioengine()) {
2463 unload_session (true);
2465 get_session_parameters (true, false);
2469 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2471 Session *new_session;
2475 session_loaded = false;
2477 if (!check_audioengine()) {
2481 unload_status = unload_session ();
2483 if (unload_status < 0) {
2485 } else if (unload_status > 0) {
2490 /* if it already exists, we must have write access */
2492 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2493 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2494 "This prevents the session from being loaded."));
2500 loading_message (_("Please wait while Ardour loads your session"));
2503 new_session = new Session (*engine, path, snap_name, mix_template);
2506 /* this one is special */
2508 catch (AudioEngine::PortRegistrationFailure& err) {
2510 MessageDialog msg (err.what(),
2513 Gtk::BUTTONS_OK_CANCEL);
2515 msg.set_title (_("Loading Error"));
2516 msg.set_secondary_text (_("Click the OK button to try again."));
2517 msg.set_position (Gtk::WIN_POS_CENTER);
2521 int response = msg.run ();
2526 case RESPONSE_CANCEL:
2536 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2539 Gtk::BUTTONS_OK_CANCEL);
2541 msg.set_title (_("Loading Error"));
2542 msg.set_secondary_text (_("Click the OK button to try again."));
2543 msg.set_position (Gtk::WIN_POS_CENTER);
2547 int response = msg.run ();
2552 case RESPONSE_CANCEL:
2560 connect_to_session (new_session);
2562 Config->set_current_owner (ConfigVariableBase::Interface);
2564 session_loaded = true;
2566 goto_editor_window ();
2569 session->set_clean ();
2580 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2581 uint32_t control_channels,
2582 uint32_t master_channels,
2583 AutoConnectOption input_connect,
2584 AutoConnectOption output_connect,
2587 nframes_t initial_length)
2589 Session *new_session;
2592 if (!check_audioengine()) {
2596 session_loaded = false;
2598 x = unload_session ();
2606 _session_is_new = true;
2609 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2610 control_channels, master_channels, nphysin, nphysout, initial_length);
2615 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2621 connect_to_session (new_session);
2623 session_loaded = true;
2631 editor->show_window ();
2642 ARDOUR_UI::show_about ()
2646 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2653 ARDOUR_UI::hide_about ()
2656 about->get_window()->set_cursor ();
2662 ARDOUR_UI::about_signal_response(int response)
2668 ARDOUR_UI::show_splash ()
2672 splash = new Splash;
2680 splash->queue_draw ();
2681 splash->get_window()->process_updates (true);
2686 ARDOUR_UI::hide_splash ()
2694 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2698 removed = rep.paths.size();
2701 MessageDialog msgd (*editor,
2702 _("No audio files were ready for cleanup"),
2705 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2706 msgd.set_secondary_text (_("If this seems suprising, \n\
2707 check for any existing snapshots.\n\
2708 These may still include regions that\n\
2709 require some unused files to continue to exist."));
2715 ArdourDialog results (_("ardour: cleanup"), true, false);
2717 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2718 CleanupResultsModelColumns() {
2722 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2723 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2727 CleanupResultsModelColumns results_columns;
2728 Glib::RefPtr<Gtk::ListStore> results_model;
2729 Gtk::TreeView results_display;
2731 results_model = ListStore::create (results_columns);
2732 results_display.set_model (results_model);
2733 results_display.append_column (list_title, results_columns.visible_name);
2735 results_display.set_name ("CleanupResultsList");
2736 results_display.set_headers_visible (true);
2737 results_display.set_headers_clickable (false);
2738 results_display.set_reorderable (false);
2740 Gtk::ScrolledWindow list_scroller;
2743 Gtk::HBox dhbox; // the hbox for the image and text
2744 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2745 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2747 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2749 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2751 if (rep.space < 1048576.0f) {
2753 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2755 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2759 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2761 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2765 dhbox.pack_start (*dimage, true, false, 5);
2766 dhbox.pack_start (txt, true, false, 5);
2768 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2769 TreeModel::Row row = *(results_model->append());
2770 row[results_columns.visible_name] = *i;
2771 row[results_columns.fullpath] = *i;
2774 list_scroller.add (results_display);
2775 list_scroller.set_size_request (-1, 150);
2776 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2778 dvbox.pack_start (dhbox, true, false, 5);
2779 dvbox.pack_start (list_scroller, true, false, 5);
2780 ddhbox.pack_start (dvbox, true, false, 5);
2782 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2783 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2784 results.set_default_response (RESPONSE_CLOSE);
2785 results.set_position (Gtk::WIN_POS_MOUSE);
2787 results_display.show();
2788 list_scroller.show();
2795 //results.get_vbox()->show();
2796 results.set_resizable (false);
2803 ARDOUR_UI::cleanup ()
2806 /* shouldn't happen: menu item is insensitive */
2811 MessageDialog checker (_("Are you sure you want to cleanup?"),
2813 Gtk::MESSAGE_QUESTION,
2814 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2816 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2817 ALL undo/redo information will be lost if you cleanup.\n\
2818 After cleanup, unused audio files will be moved to a \
2819 \"dead sounds\" location."));
2821 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2822 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2823 checker.set_default_response (RESPONSE_CANCEL);
2825 checker.set_name (_("CleanupDialog"));
2826 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2827 checker.set_position (Gtk::WIN_POS_MOUSE);
2829 switch (checker.run()) {
2830 case RESPONSE_ACCEPT:
2836 Session::cleanup_report rep;
2838 editor->prepare_for_cleanup ();
2840 /* do not allow flush until a session is reloaded */
2842 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2844 act->set_sensitive (false);
2847 if (session->cleanup_sources (rep)) {
2848 editor->finish_cleanup ();
2852 editor->finish_cleanup ();
2855 display_cleanup_results (rep,
2858 The following %1 %2 not in use and \n\
2859 have been moved to:\n\
2861 Flushing the wastebasket will \n\
2862 release an additional\n\
2863 %4 %5bytes of disk space.\n"
2869 ARDOUR_UI::flush_trash ()
2872 /* shouldn't happen: menu item is insensitive */
2876 Session::cleanup_report rep;
2878 if (session->cleanup_trash_sources (rep)) {
2882 display_cleanup_results (rep,
2884 _("The following %1 %2 deleted from\n\
2886 releasing %4 %5bytes of disk space"));
2890 ARDOUR_UI::add_route (Gtk::Window* float_window)
2898 if (add_route_dialog == 0) {
2899 add_route_dialog = new AddRouteDialog;
2901 add_route_dialog->set_transient_for (*float_window);
2905 if (add_route_dialog->is_visible()) {
2906 /* we're already doing this */
2910 ResponseType r = (ResponseType) add_route_dialog->run ();
2912 add_route_dialog->hide();
2915 case RESPONSE_ACCEPT:
2922 if ((count = add_route_dialog->count()) <= 0) {
2926 uint32_t input_chan = add_route_dialog->channels ();
2927 uint32_t output_chan;
2928 string name_template = add_route_dialog->name_template ();
2929 bool track = add_route_dialog->track ();
2931 AutoConnectOption oac = Config->get_output_auto_connect();
2933 if (oac & AutoConnectMaster) {
2934 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2936 output_chan = input_chan;
2939 /* XXX do something with name template */
2941 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2943 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2945 session_add_midi_track(count);
2947 MessageDialog msg (*editor,
2948 _("Sorry, MIDI Busses are not supported at this time."));
2950 //session_add_midi_bus();
2954 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2956 session_add_audio_bus (input_chan, output_chan, count);
2962 ARDOUR_UI::mixer_settings () const
2967 node = session->instant_xml(X_("Mixer"));
2969 node = Config->instant_xml(X_("Mixer"));
2973 node = new XMLNode (X_("Mixer"));
2980 ARDOUR_UI::editor_settings () const
2985 node = session->instant_xml(X_("Editor"));
2987 node = Config->instant_xml(X_("Editor"));
2991 node = new XMLNode (X_("Editor"));
2997 ARDOUR_UI::keyboard_settings () const
3001 node = Config->extra_xml(X_("Keyboard"));
3004 node = new XMLNode (X_("Keyboard"));
3010 ARDOUR_UI::create_xrun_marker(nframes_t where)
3012 editor->mouse_add_new_marker (where, false, true);
3016 ARDOUR_UI::halt_on_xrun_message ()
3018 MessageDialog msg (*editor,
3019 _("Recording was stopped because your system could not keep up."));
3024 ARDOUR_UI::xrun_handler(nframes_t where)
3026 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3028 if (Config->get_create_xrun_marker() && session->actively_recording()) {
3029 create_xrun_marker(where);
3032 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3033 halt_on_xrun_message ();
3038 ARDOUR_UI::disk_overrun_handler ()
3040 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3042 if (!have_disk_speed_dialog_displayed) {
3043 have_disk_speed_dialog_displayed = true;
3044 MessageDialog* msg = new MessageDialog (*editor, _("\
3045 The disk system on your computer\n\
3046 was not able to keep up with Ardour.\n\
3048 Specifically, it failed to write data to disk\n\
3049 quickly enough to keep up with recording.\n"));
3050 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3056 ARDOUR_UI::disk_underrun_handler ()
3058 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3060 if (!have_disk_speed_dialog_displayed) {
3061 have_disk_speed_dialog_displayed = true;
3062 MessageDialog* msg = new MessageDialog (*editor,
3063 _("The disk system on your computer\n\
3064 was not able to keep up with Ardour.\n\
3066 Specifically, it failed to read data from disk\n\
3067 quickly enough to keep up with playback.\n"));
3068 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3074 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3076 have_disk_speed_dialog_displayed = false;
3081 ARDOUR_UI::session_dialog (std::string msg)
3083 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3088 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3090 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3099 ARDOUR_UI::pending_state_dialog ()
3101 HBox* hbox = new HBox();
3102 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3103 ArdourDialog dialog (_("Crash Recovery"), true);
3105 This session appears to have been in\n\
3106 middle of recording when ardour or\n\
3107 the computer was shutdown.\n\
3109 Ardour can recover any captured audio for\n\
3110 you, or it can ignore it. Please decide\n\
3111 what you would like to do.\n"));
3112 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3113 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3114 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3115 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3116 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3117 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3118 dialog.set_default_response (RESPONSE_ACCEPT);
3119 dialog.set_position (WIN_POS_CENTER);
3124 switch (dialog.run ()) {
3125 case RESPONSE_ACCEPT:
3133 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3135 HBox* hbox = new HBox();
3136 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3137 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3138 Label message (string_compose (_("\
3139 This session was created with a sample rate of %1 Hz\n\
3141 The audioengine is currently running at %2 Hz\n"), desired, actual));
3143 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3144 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3145 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3146 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3147 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3148 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3149 dialog.set_default_response (RESPONSE_ACCEPT);
3150 dialog.set_position (WIN_POS_CENTER);
3155 switch (dialog.run ()) {
3156 case RESPONSE_ACCEPT:
3165 ARDOUR_UI::disconnect_from_jack ()
3168 if( engine->disconnect_from_jack ()) {
3169 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3173 update_sample_rate (0);
3178 ARDOUR_UI::reconnect_to_jack ()
3181 if (engine->reconnect_to_jack ()) {
3182 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3186 update_sample_rate (0);
3191 ARDOUR_UI::use_config ()
3193 Glib::RefPtr<Action> act;
3195 switch (Config->get_native_file_data_format ()) {
3197 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3200 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3203 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3208 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3209 ract->set_active ();
3212 switch (Config->get_native_file_header_format ()) {
3214 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3217 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3220 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3223 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3226 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3229 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3232 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3237 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3238 ract->set_active ();
3241 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3243 set_transport_controllable_state (*node);
3248 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3250 if (Config->get_primary_clock_delta_edit_cursor()) {
3251 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3253 primary_clock.set (pos, 0, true);
3256 if (Config->get_secondary_clock_delta_edit_cursor()) {
3257 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3259 secondary_clock.set (pos);
3262 if (big_clock_window) {
3263 big_clock.set (pos);
3268 ARDOUR_UI::record_state_changed ()
3270 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3272 if (!session || !big_clock_window) {
3273 /* why bother - the clock isn't visible */
3277 switch (session->record_status()) {
3278 case Session::Recording:
3279 big_clock.set_widget_name ("BigClockRecording");
3282 big_clock.set_widget_name ("BigClockNonRecording");
3288 ARDOUR_UI::first_idle ()
3291 session->allow_auto_play (true);
3295 editor->first_idle();
3298 Keyboard::set_can_save_keybindings (true);
3303 ARDOUR_UI::store_clock_modes ()
3305 XMLNode* node = new XMLNode(X_("ClockModes"));
3307 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3308 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3311 session->add_extra_xml (*node);
3312 session->set_dirty ();
3317 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3318 : Controllable (name), ui (u), type(tp)
3324 ARDOUR_UI::TransportControllable::set_value (float val)
3326 if (type == ShuttleControl) {
3333 fract = -((0.5f - val)/0.5f);
3335 fract = ((val - 0.5f)/0.5f);
3339 ui.set_shuttle_fract (fract);
3344 /* do nothing: these are radio-style actions */
3348 const char *action = 0;
3352 action = X_("Roll");
3355 action = X_("Stop");
3358 action = X_("Goto Start");
3361 action = X_("Goto End");
3364 action = X_("Loop");
3367 action = X_("Play Selection");
3370 action = X_("Record");
3380 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3388 ARDOUR_UI::TransportControllable::get_value (void) const
3407 case ShuttleControl:
3417 ARDOUR_UI::TransportControllable::set_id (const string& str)
3423 ARDOUR_UI::setup_profile ()
3425 if (gdk_screen_width() < 1200) {
3426 Profile->set_small_screen ();
3430 if (getenv ("ARDOUR_SAE")) {
3431 Profile->set_sae ();
3432 Profile->set_single_package ();