2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define __STDC_FORMAT_MACROS 1
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
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>
77 #include "ardour_ui.h"
78 #include "public_editor.h"
79 #include "audio_clock.h"
84 #include "add_route_dialog.h"
85 #include "new_session_dialog.h"
89 #include "gui_thread.h"
90 #include "theme_manager.h"
91 #include "bundle_manager.h"
95 using namespace ARDOUR;
97 using namespace Gtkmm2ext;
101 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
102 UIConfiguration *ARDOUR_UI::ui_config = 0;
104 sigc::signal<void,bool> ARDOUR_UI::Blink;
105 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
106 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
107 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
109 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
111 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
113 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
114 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
115 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
116 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
120 adjuster_table (3, 3),
124 preroll_button (_("pre\nroll")),
125 postroll_button (_("post\nroll")),
129 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
133 roll_controllable ("transport roll", *this, TransportControllable::Roll),
134 stop_controllable ("transport stop", *this, TransportControllable::Stop),
135 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
136 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
137 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
138 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
139 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
140 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
141 shuttle_controller_binding_proxy (shuttle_controllable),
143 roll_button (roll_controllable),
144 stop_button (stop_controllable),
145 goto_start_button (goto_start_controllable),
146 goto_end_button (goto_end_controllable),
147 auto_loop_button (auto_loop_controllable),
148 play_selection_button (play_selection_controllable),
149 rec_button (rec_controllable),
151 shuttle_units_button (_("% ")),
153 punch_in_button (_("Punch In")),
154 punch_out_button (_("Punch Out")),
155 auto_return_button (_("Auto Return")),
156 auto_play_button (_("Auto Play")),
157 auto_input_button (_("Auto Input")),
158 click_button (_("Click")),
159 time_master_button (_("time\nmaster")),
161 auditioning_alert_button (_("AUDITION")),
162 solo_alert_button (_("SOLO")),
164 error_log_button (_("Errors"))
167 using namespace Gtk::Menu_Helpers;
173 _auto_display_errors = false;
178 if (ARDOUR_COMMAND_LINE::session_name.length()) {
179 /* only show this if we're not going to post the new session dialog */
183 if (theArdourUI == 0) {
187 ui_config = new UIConfiguration();
188 theme_manager = new ThemeManager();
194 _session_is_new = false;
195 big_clock_window = 0;
196 session_selector_window = 0;
197 last_key_press_time = 0;
198 connection_editor = 0;
199 _will_create_new_session_automatically = false;
200 new_session_dialog = 0;
201 add_route_dialog = 0;
205 open_session_selector = 0;
206 have_configure_timeout = false;
207 have_disk_speed_dialog_displayed = false;
208 session_loaded = false;
209 last_speed_displayed = -1.0f;
211 sys::path key_bindings_file;
213 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
214 "ardour.bindings", key_bindings_file);
216 keybindings_path = key_bindings_file.to_string();
218 /* store all bindings changes in per-user file, no matter where they were loaded from */
219 user_keybindings_path = user_config_directory().to_string ();
220 user_keybindings_path += '/';
221 user_keybindings_path += "ardour.bindings";
223 can_save_keybindings = false;
225 last_configure_time.tv_sec = 0;
226 last_configure_time.tv_usec = 0;
228 shuttle_grabbed = false;
230 shuttle_max_speed = 8.0f;
232 shuttle_style_menu = 0;
233 shuttle_unit_menu = 0;
235 gettimeofday (&last_peak_grab, 0);
236 gettimeofday (&last_shuttle_request, 0);
238 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241 /* handle pending state with a dialog */
243 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
245 /* lets get this party started */
248 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
249 throw failed_constructor ();
252 setup_gtk_ardour_enums ();
253 Config->set_current_owner (ConfigVariableBase::Interface);
256 } catch (failed_constructor& err) {
257 error << _("could not initialize Ardour.") << endmsg;
262 /* we like keyboards */
264 keyboard = new Keyboard;
266 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
267 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
273 ARDOUR_UI::create_engine ()
275 // this gets called every time by new_session()
281 loading_message (_("Starting audio engine"));
284 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
291 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
292 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
293 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
294 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
302 ARDOUR_UI::post_engine ()
304 extern int setup_midi ();
306 /* Things to be done once we create the AudioEngine
309 MIDI::Manager::instance()->set_api_data (engine->jack());
312 ActionManager::init ();
315 if (setup_windows ()) {
316 throw failed_constructor ();
319 check_memory_locking();
321 /* this is the first point at which all the keybindings are available */
323 if (ARDOUR_COMMAND_LINE::show_key_actions) {
324 vector<string> names;
325 vector<string> paths;
327 vector<AccelKey> bindings;
329 ActionManager::get_all_actions (names, paths, keys, bindings);
331 vector<string>::iterator n;
332 vector<string>::iterator k;
333 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
334 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
340 blink_timeout_tag = -1;
342 /* the global configuration object is now valid */
346 /* this being a GUI and all, we want peakfiles */
348 AudioFileSource::set_build_peakfiles (true);
349 AudioFileSource::set_build_missing_peakfiles (true);
351 /* set default clock modes */
353 primary_clock.set_mode (AudioClock::SMPTE);
354 secondary_clock.set_mode (AudioClock::BBT);
356 /* start the time-of-day-clock */
359 /* OS X provides an always visible wallclock, so don't be stupid */
360 update_wall_clock ();
361 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
364 update_disk_space ();
366 update_sample_rate (engine->frame_rate());
368 /* now start and maybe save state */
370 if (do_engine_start () == 0) {
371 if (session && _session_is_new) {
372 /* we need to retain initial visual
373 settings for a new session
375 session->save_state ("");
380 ARDOUR_UI::~ARDOUR_UI ()
382 save_ardour_state ();
396 if (add_route_dialog) {
397 delete add_route_dialog;
401 if (new_session_dialog) {
402 delete new_session_dialog;
407 ARDOUR_UI::configure_timeout ()
412 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
413 /* no configure events yet */
417 gettimeofday (&now, 0);
418 timersub (&now, &last_configure_time, &diff);
420 /* force a gap of 0.5 seconds since the last configure event
423 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
426 have_configure_timeout = false;
427 save_ardour_state ();
433 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
435 if (have_configure_timeout) {
436 gettimeofday (&last_configure_time, 0);
438 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
439 have_configure_timeout = true;
446 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
448 const XMLProperty* prop;
450 if ((prop = node.property ("roll")) != 0) {
451 roll_controllable.set_id (prop->value());
453 if ((prop = node.property ("stop")) != 0) {
454 stop_controllable.set_id (prop->value());
456 if ((prop = node.property ("goto_start")) != 0) {
457 goto_start_controllable.set_id (prop->value());
459 if ((prop = node.property ("goto_end")) != 0) {
460 goto_end_controllable.set_id (prop->value());
462 if ((prop = node.property ("auto_loop")) != 0) {
463 auto_loop_controllable.set_id (prop->value());
465 if ((prop = node.property ("play_selection")) != 0) {
466 play_selection_controllable.set_id (prop->value());
468 if ((prop = node.property ("rec")) != 0) {
469 rec_controllable.set_id (prop->value());
471 if ((prop = node.property ("shuttle")) != 0) {
472 shuttle_controllable.set_id (prop->value());
477 ARDOUR_UI::get_transport_controllable_state ()
479 XMLNode* node = new XMLNode(X_("TransportControllables"));
482 roll_controllable.id().print (buf, sizeof (buf));
483 node->add_property (X_("roll"), buf);
484 stop_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("stop"), buf);
486 goto_start_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("goto_start"), buf);
488 goto_end_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("goto_end"), buf);
490 auto_loop_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("auto_loop"), buf);
492 play_selection_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("play_selection"), buf);
494 rec_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("rec"), buf);
496 shuttle_controllable.id().print (buf, sizeof (buf));
497 node->add_property (X_("shuttle"), buf);
503 ARDOUR_UI::save_ardour_state ()
505 if (!keyboard || !mixer || !editor) {
509 /* XXX this is all a bit dubious. add_extra_xml() uses
510 a different lifetime model from add_instant_xml().
513 XMLNode* node = new XMLNode (keyboard->get_state());
514 Config->add_extra_xml (*node);
515 Config->add_extra_xml (get_transport_controllable_state());
516 Config->save_state();
517 ui_config->save_state ();
519 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
520 XMLNode mnode(mixer->get_state());
523 session->add_instant_xml (enode);
524 session->add_instant_xml (mnode);
526 Config->add_instant_xml (enode);
527 Config->add_instant_xml (mnode);
534 ARDOUR_UI::autosave_session ()
536 if (!Config->get_periodic_safety_backups())
540 session->maybe_write_autosave();
547 ARDOUR_UI::update_autosave ()
549 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
551 if (session->dirty()) {
552 if (_autosave_connection.connected()) {
553 _autosave_connection.disconnect();
556 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
557 Config->get_periodic_safety_backup_interval() * 1000);
560 if (_autosave_connection.connected()) {
561 _autosave_connection.disconnect();
567 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
571 title = _("Ardour could not start JACK");
573 title = _("Ardour could not connect to JACK.");
576 MessageDialog win (title,
582 win.set_secondary_text(_("There are several possible reasons:\n\
584 1) You requested audio parameters that are not supported..\n\
585 2) JACK is running as another user.\n\
587 Please consider the possibilities, and perhaps try different parameters."));
589 win.set_secondary_text(_("There are several possible reasons:\n\
591 1) JACK is not running.\n\
592 2) JACK is running as another user, perhaps root.\n\
593 3) There is already another client called \"ardour\".\n\
595 Please consider the possibilities, and perhaps (re)start JACK."));
599 win.set_transient_for (*toplevel);
603 win.add_button (Stock::OK, RESPONSE_CLOSE);
605 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
608 win.set_default_response (RESPONSE_CLOSE);
611 win.set_position (Gtk::WIN_POS_CENTER);
615 /* we just don't care about the result, but we want to block */
621 ARDOUR_UI::startup ()
625 new_session_dialog = new NewSessionDialog();
627 bool backend_audio_is_running = EngineControl::engine_running();
628 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
631 new_session_dialog->engine_control.set_state (*audio_setup);
634 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
642 ARDOUR_UI::no_memory_warning ()
644 XMLNode node (X_("no-memory-warning"));
645 Config->add_instant_xml (node);
649 ARDOUR_UI::check_memory_locking ()
652 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
656 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
658 if (engine->is_realtime() && memory_warning_node == 0) {
660 struct rlimit limits;
662 long pages, page_size;
664 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
667 ram = (int64_t) pages * (int64_t) page_size;
670 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
674 if (limits.rlim_cur != RLIM_INFINITY) {
676 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
679 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
680 "This might cause Ardour to run out of memory before your system "
681 "runs out of memory. \n\n"
682 "You can view the memory limit with 'ulimit -l', "
683 "and it is normally controlled by /etc/security/limits.conf"));
685 VBox* vbox = msg.get_vbox();
687 CheckButton cb (_("Do not show this window again"));
689 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
691 hbox.pack_start (cb, true, false);
692 vbox->pack_start (hbox);
697 editor->ensure_float (msg);
711 if (session->transport_rolling()) {
712 session->request_stop ();
716 if (session->dirty()) {
717 switch (ask_about_saving_session(_("quit"))) {
722 /* use the default name */
723 if (save_state_canfail ("")) {
724 /* failed - don't quit */
725 MessageDialog msg (*editor,
727 Ardour was unable to save your session.\n\n\
728 If you still wish to quit, please use the\n\n\
729 \"Just quit\" option."));
739 session->set_deletion_in_progress ();
743 Config->save_state();
744 ARDOUR_UI::config()->save_state();
749 ARDOUR_UI::ask_about_saving_session (const string & what)
751 ArdourDialog window (_("ardour: save session?"));
752 Gtk::HBox dhbox; // the hbox for the image and text
753 Gtk::Label prompt_label;
754 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
758 msg = string_compose(_("Don't %1"), what);
759 window.add_button (msg, RESPONSE_REJECT);
760 msg = string_compose(_("Just %1"), what);
761 window.add_button (msg, RESPONSE_APPLY);
762 msg = string_compose(_("Save and %1"), what);
763 window.add_button (msg, RESPONSE_ACCEPT);
765 window.set_default_response (RESPONSE_ACCEPT);
767 Gtk::Button noquit_button (msg);
768 noquit_button.set_name ("EditorGTKButton");
773 if (session->snap_name() == session->name()) {
776 type = _("snapshot");
778 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?"),
779 type, session->snap_name());
781 prompt_label.set_text (prompt);
782 prompt_label.set_name (X_("PrompterLabel"));
783 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
785 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
787 dhbox.set_homogeneous (false);
788 dhbox.pack_start (*dimage, false, false, 5);
789 dhbox.pack_start (prompt_label, true, false, 5);
790 window.get_vbox()->pack_start (dhbox);
792 window.set_name (_("Prompter"));
793 window.set_position (Gtk::WIN_POS_MOUSE);
794 window.set_modal (true);
795 window.set_resizable (false);
802 save_the_session = 0;
804 window.set_keep_above (true);
807 ResponseType r = (ResponseType) window.run();
812 case RESPONSE_ACCEPT: // save and get out of here
814 case RESPONSE_APPLY: // get out of here
824 ARDOUR_UI::every_second ()
827 update_buffer_load ();
828 update_disk_space ();
833 ARDOUR_UI::every_point_one_seconds ()
835 update_speed_display ();
836 RapidScreenUpdate(); /* EMIT_SIGNAL */
841 ARDOUR_UI::every_point_zero_one_seconds ()
843 // august 2007: actual update frequency: 40Hz, not 100Hz
845 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
850 ARDOUR_UI::update_sample_rate (nframes_t ignored)
854 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
856 if (!engine->connected()) {
858 snprintf (buf, sizeof (buf), _("disconnected"));
862 nframes_t rate = engine->frame_rate();
864 if (fmod (rate, 1000.0) != 0.0) {
865 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
866 (float) rate/1000.0f,
867 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
869 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
871 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
875 sample_rate_label.set_text (buf);
879 ARDOUR_UI::update_cpu_load ()
882 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
883 cpu_load_label.set_text (buf);
887 ARDOUR_UI::update_buffer_load ()
892 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
893 session->playback_load(), session->capture_load());
894 buffer_load_label.set_text (buf);
896 buffer_load_label.set_text ("");
901 ARDOUR_UI::count_recenabled_streams (Route& route)
903 Track* track = dynamic_cast<Track*>(&route);
904 if (track && track->diskstream()->record_enabled()) {
905 rec_enabled_streams += track->n_inputs().n_total();
910 ARDOUR_UI::update_disk_space()
916 nframes_t frames = session->available_capture_duration();
919 if (frames == max_frames) {
920 strcpy (buf, _("Disk: 24hrs+"));
925 nframes_t fr = session->frame_rate();
927 rec_enabled_streams = 0;
928 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
930 if (rec_enabled_streams) {
931 frames /= rec_enabled_streams;
934 hrs = frames / (fr * 3600);
935 frames -= hrs * fr * 3600;
936 mins = frames / (fr * 60);
937 frames -= mins * fr * 60;
940 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
943 disk_space_label.set_text (buf);
947 ARDOUR_UI::update_wall_clock ()
954 tm_now = localtime (&now);
956 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
957 wall_clock_label.set_text (buf);
963 ARDOUR_UI::session_menu (GdkEventButton *ev)
965 session_popup_menu->popup (0, 0);
970 ARDOUR_UI::redisplay_recent_sessions ()
972 std::vector<sys::path> session_directories;
973 RecentSessionsSorter cmp;
975 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
976 recent_session_model->clear ();
978 ARDOUR::RecentSessions rs;
979 ARDOUR::read_recent_sessions (rs);
982 recent_session_display.set_model (recent_session_model);
986 // sort them alphabetically
987 sort (rs.begin(), rs.end(), cmp);
989 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
990 session_directories.push_back ((*i).second);
993 for (vector<sys::path>::const_iterator i = session_directories.begin();
994 i != session_directories.end(); ++i)
996 std::vector<sys::path> state_file_paths;
998 // now get available states for this session
1000 get_state_files_in_directory (*i, state_file_paths);
1002 if (state_file_paths.empty()) {
1007 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1009 Gtk::TreeModel::Row row = *(recent_session_model->append());
1011 const string fullpath = (*i).to_string();
1013 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1014 row[recent_session_columns.fullpath] = fullpath;
1016 if (state_file_names.size() > 1) {
1020 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1021 i2 != state_file_names.end(); ++i2)
1024 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1026 child_row[recent_session_columns.visible_name] = *i2;
1027 child_row[recent_session_columns.fullpath] = fullpath;
1032 recent_session_display.set_model (recent_session_model);
1036 ARDOUR_UI::build_session_selector ()
1038 session_selector_window = new ArdourDialog ("session selector");
1040 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1042 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1043 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1044 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1045 recent_session_model = TreeStore::create (recent_session_columns);
1046 recent_session_display.set_model (recent_session_model);
1047 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1048 recent_session_display.set_headers_visible (false);
1049 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1050 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1052 scroller->add (recent_session_display);
1053 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1055 session_selector_window->set_name ("SessionSelectorWindow");
1056 session_selector_window->set_size_request (200, 400);
1057 session_selector_window->get_vbox()->pack_start (*scroller);
1059 recent_session_display.show();
1061 //session_selector_window->get_vbox()->show();
1065 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1067 session_selector_window->response (RESPONSE_ACCEPT);
1071 ARDOUR_UI::open_recent_session ()
1073 bool can_return = (session != 0);
1075 if (session_selector_window == 0) {
1076 build_session_selector ();
1079 redisplay_recent_sessions ();
1083 session_selector_window->set_position (WIN_POS_MOUSE);
1085 ResponseType r = (ResponseType) session_selector_window->run ();
1088 case RESPONSE_ACCEPT:
1092 session_selector_window->hide();
1099 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1103 session_selector_window->hide();
1105 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1107 if (i == recent_session_model->children().end()) {
1111 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1112 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1114 _session_is_new = false;
1116 if (load_session (path, state) == 0) {
1125 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1127 struct stat statbuf;
1129 if (stat (info.filename.c_str(), &statbuf) != 0) {
1133 if (!S_ISDIR(statbuf.st_mode)) {
1139 string session_file = info.filename;
1140 session_file += '/';
1141 session_file += Glib::path_get_basename (info.filename);
1142 session_file += ".ardour";
1144 if (stat (session_file.c_str(), &statbuf) != 0) {
1148 return S_ISREG (statbuf.st_mode);
1152 ARDOUR_UI::check_audioengine ()
1155 if (!engine->connected()) {
1156 MessageDialog msg (_("Ardour is not connected to JACK\n"
1157 "You cannot open or close sessions in this condition"));
1168 ARDOUR_UI::open_session ()
1170 if (!check_audioengine()) {
1175 /* popup selector window */
1177 if (open_session_selector == 0) {
1179 /* ardour sessions are folders */
1181 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1182 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1183 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1184 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1186 FileFilter session_filter;
1187 session_filter.add_pattern ("*.ardour");
1188 session_filter.set_name (_("Ardour sessions"));
1189 open_session_selector->add_filter (session_filter);
1190 open_session_selector->set_filter (session_filter);
1193 int response = open_session_selector->run();
1194 open_session_selector->hide ();
1197 case RESPONSE_ACCEPT:
1200 open_session_selector->hide();
1204 open_session_selector->hide();
1205 string session_path = open_session_selector->get_filename();
1209 if (session_path.length() > 0) {
1210 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1211 _session_is_new = isnew;
1212 load_session (path, name);
1219 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1221 list<boost::shared_ptr<MidiTrack> > tracks;
1224 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1231 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1233 if (tracks.size() != how_many) {
1234 if (how_many == 1) {
1235 error << _("could not create a new midi track") << endmsg;
1237 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1241 if ((route = session->new_midi_route ()) == 0) {
1242 error << _("could not create new midi bus") << endmsg;
1248 MessageDialog msg (*editor,
1249 _("There are insufficient JACK ports available\n\
1250 to create a new track or bus.\n\
1251 You should save Ardour, exit and\n\
1252 restart JACK with more ports."));
1259 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1261 list<boost::shared_ptr<AudioTrack> > tracks;
1262 Session::RouteList routes;
1265 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1271 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1273 if (tracks.size() != how_many) {
1274 if (how_many == 1) {
1275 error << _("could not create a new audio track") << endmsg;
1277 error << string_compose (_("could only create %1 of %2 new audio %3"),
1278 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1284 routes = session->new_audio_route (input_channels, output_channels, how_many);
1286 if (routes.size() != how_many) {
1287 if (how_many == 1) {
1288 error << _("could not create a new audio track") << endmsg;
1290 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1296 if (need_control_room_outs) {
1302 route->set_stereo_control_outs (control_lr_channels);
1303 route->control_outs()->set_stereo_pan (pans, this);
1305 #endif /* CONTROLOUTS */
1309 MessageDialog msg (*editor,
1310 _("There are insufficient JACK ports available\n\
1311 to create a new track or bus.\n\
1312 You should save Ardour, exit and\n\
1313 restart JACK with more ports."));
1319 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1321 nframes_t _preroll = 0;
1324 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1325 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1327 if (new_position > _preroll) {
1328 new_position -= _preroll;
1333 session->request_locate (new_position);
1338 ARDOUR_UI::transport_goto_start ()
1341 session->goto_start();
1344 /* force displayed area in editor to start no matter
1345 what "follow playhead" setting is.
1349 editor->reset_x_origin (session->current_start_frame());
1355 ARDOUR_UI::transport_goto_zero ()
1358 session->request_locate (0);
1361 /* force displayed area in editor to start no matter
1362 what "follow playhead" setting is.
1366 editor->reset_x_origin (0);
1372 ARDOUR_UI::transport_goto_end ()
1375 nframes_t frame = session->current_end_frame();
1376 session->request_locate (frame);
1378 /* force displayed area in editor to start no matter
1379 what "follow playhead" setting is.
1383 editor->reset_x_origin (frame);
1389 ARDOUR_UI::transport_stop ()
1395 if (session->is_auditioning()) {
1396 session->cancel_audition ();
1400 if (session->get_play_loop ()) {
1401 session->request_play_loop (false);
1404 session->request_stop ();
1408 ARDOUR_UI::transport_stop_and_forget_capture ()
1411 session->request_stop (true);
1416 ARDOUR_UI::remove_last_capture()
1419 editor->remove_last_capture();
1424 ARDOUR_UI::transport_record (bool roll)
1427 switch (session->record_status()) {
1428 case Session::Disabled:
1429 if (session->ntracks() == 0) {
1430 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1434 session->maybe_enable_record ();
1439 case Session::Recording:
1441 session->request_stop();
1443 session->disable_record (false, true);
1447 case Session::Enabled:
1448 session->disable_record (false, true);
1454 ARDOUR_UI::transport_roll ()
1462 rolling = session->transport_rolling ();
1464 if (session->get_play_loop()) {
1465 session->request_play_loop (false);
1466 auto_loop_button.set_visual_state (1);
1467 roll_button.set_visual_state (1);
1468 } else if (session->get_play_range ()) {
1469 session->request_play_range (false);
1470 play_selection_button.set_visual_state (0);
1471 } else if (rolling) {
1472 session->request_locate (session->last_transport_start(), true);
1475 session->request_transport_speed (1.0f);
1479 ARDOUR_UI::transport_loop()
1482 if (session->get_play_loop()) {
1483 if (session->transport_rolling()) {
1484 Location * looploc = session->locations()->auto_loop_location();
1486 session->request_locate (looploc->start(), true);
1491 session->request_play_loop (true);
1497 ARDOUR_UI::transport_play_selection ()
1503 if (!session->get_play_range()) {
1504 session->request_stop ();
1507 editor->play_selection ();
1511 ARDOUR_UI::transport_rewind (int option)
1513 float current_transport_speed;
1516 current_transport_speed = session->transport_speed();
1518 if (current_transport_speed >= 0.0f) {
1521 session->request_transport_speed (-1.0f);
1524 session->request_transport_speed (-4.0f);
1527 session->request_transport_speed (-0.5f);
1532 session->request_transport_speed (current_transport_speed * 1.5f);
1538 ARDOUR_UI::transport_forward (int option)
1540 float current_transport_speed;
1543 current_transport_speed = session->transport_speed();
1545 if (current_transport_speed <= 0.0f) {
1548 session->request_transport_speed (1.0f);
1551 session->request_transport_speed (4.0f);
1554 session->request_transport_speed (0.5f);
1559 session->request_transport_speed (current_transport_speed * 1.5f);
1565 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1571 boost::shared_ptr<Route> r;
1573 if ((r = session->route_by_remote_id (dstream)) != 0) {
1577 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1578 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1587 ARDOUR_UI::queue_transport_change ()
1589 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1593 ARDOUR_UI::map_transport_state ()
1595 float sp = session->transport_speed();
1598 transport_rolling ();
1599 } else if (sp < 0.0f) {
1600 transport_rewinding ();
1601 } else if (sp > 0.0f) {
1602 transport_forwarding ();
1604 transport_stopped ();
1609 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1611 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1612 (int) adj.get_value()].c_str());
1616 ARDOUR_UI::engine_stopped ()
1618 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1619 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1620 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1624 ARDOUR_UI::engine_running ()
1626 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1627 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1628 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1630 Glib::RefPtr<Action> action;
1631 const char* action_name = 0;
1633 switch (engine->frames_per_cycle()) {
1635 action_name = X_("JACKLatency32");
1638 action_name = X_("JACKLatency64");
1641 action_name = X_("JACKLatency128");
1644 action_name = X_("JACKLatency512");
1647 action_name = X_("JACKLatency1024");
1650 action_name = X_("JACKLatency2048");
1653 action_name = X_("JACKLatency4096");
1656 action_name = X_("JACKLatency8192");
1659 /* XXX can we do anything useful ? */
1665 action = ActionManager::get_action (X_("JACK"), action_name);
1668 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1669 ract->set_active ();
1675 ARDOUR_UI::engine_halted ()
1677 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1679 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1680 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1682 update_sample_rate (0);
1684 MessageDialog msg (*editor,
1686 JACK has either been shutdown or it\n\
1687 disconnected Ardour because Ardour\n\
1688 was not fast enough. You can save the\n\
1689 session and/or try to reconnect to JACK ."));
1694 ARDOUR_UI::do_engine_start ()
1702 error << _("Unable to start the session running")
1712 ARDOUR_UI::setup_theme ()
1714 theme_manager->setup_theme();
1718 ARDOUR_UI::update_clocks ()
1720 if (!editor || !editor->dragging_playhead()) {
1721 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1726 ARDOUR_UI::start_clocking ()
1728 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1732 ARDOUR_UI::stop_clocking ()
1734 clock_signal_connection.disconnect ();
1738 ARDOUR_UI::toggle_clocking ()
1741 if (clock_button.get_active()) {
1750 ARDOUR_UI::_blink (void *arg)
1753 ((ARDOUR_UI *) arg)->blink ();
1760 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1764 ARDOUR_UI::start_blinking ()
1766 /* Start the blink signal. Everybody with a blinking widget
1767 uses Blink to drive the widget's state.
1770 if (blink_timeout_tag < 0) {
1772 blink_timeout_tag = g_timeout_add (240, _blink, this);
1777 ARDOUR_UI::stop_blinking ()
1779 if (blink_timeout_tag >= 0) {
1780 g_source_remove (blink_timeout_tag);
1781 blink_timeout_tag = -1;
1786 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1791 vector<string> connections;
1794 if (io.n_inputs().n_total() == 0) {
1799 /* XXX we're not handling multiple ports yet. */
1801 if (io.input(0)->get_connections(connections) == 0) {
1804 buf = connections.front();
1809 if (io.n_outputs().n_total() == 0) {
1814 /* XXX we're not handling multiple ports yet. */
1816 if (io.output(0)->get_connections(connections) == 0) {
1819 buf = connections.front();
1824 /** Ask the user for the name of a new shapshot and then take it.
1827 ARDOUR_UI::snapshot_session ()
1829 ArdourPrompter prompter (true);
1833 struct tm local_time;
1836 localtime_r (&n, &local_time);
1837 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1839 prompter.set_name ("Prompter");
1840 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1841 prompter.set_prompt (_("Name of New Snapshot"));
1842 prompter.set_initial_text (timebuf);
1844 switch (prompter.run()) {
1845 case RESPONSE_ACCEPT:
1846 prompter.get_result (snapname);
1847 if (snapname.length()){
1848 save_state (snapname);
1858 ARDOUR_UI::save_state (const string & name)
1860 (void) save_state_canfail (name);
1864 ARDOUR_UI::save_state_canfail (string name)
1869 if (name.length() == 0) {
1870 name = session->snap_name();
1873 if ((ret = session->save_state (name)) != 0) {
1877 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1882 ARDOUR_UI::restore_state (string name)
1885 if (name.length() == 0) {
1886 name = session->name();
1888 session->restore_state (name);
1893 ARDOUR_UI::primary_clock_value_changed ()
1896 session->request_locate (primary_clock.current_time ());
1901 ARDOUR_UI::big_clock_value_changed ()
1904 session->request_locate (big_clock.current_time ());
1909 ARDOUR_UI::secondary_clock_value_changed ()
1912 session->request_locate (secondary_clock.current_time ());
1917 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1919 if (session && dstream && dstream->record_enabled()) {
1921 Session::RecordState rs;
1923 rs = session->record_status ();
1926 case Session::Disabled:
1927 case Session::Enabled:
1928 if (w->get_state() != STATE_SELECTED) {
1929 w->set_state (STATE_SELECTED);
1933 case Session::Recording:
1934 if (w->get_state() != STATE_ACTIVE) {
1935 w->set_state (STATE_ACTIVE);
1941 if (w->get_state() != STATE_NORMAL) {
1942 w->set_state (STATE_NORMAL);
1948 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1954 switch (session->record_status()) {
1955 case Session::Enabled:
1957 rec_button.set_visual_state (2);
1959 rec_button.set_visual_state (0);
1963 case Session::Recording:
1964 rec_button.set_visual_state (1);
1968 rec_button.set_visual_state (0);
1974 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1982 ARDOUR_UI::save_template ()
1985 ArdourPrompter prompter (true);
1988 if (!check_audioengine()) {
1992 prompter.set_name (X_("Prompter"));
1993 prompter.set_prompt (_("Name for mix template:"));
1994 prompter.set_initial_text(session->name() + _("-template"));
1995 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1997 switch (prompter.run()) {
1998 case RESPONSE_ACCEPT:
1999 prompter.get_result (name);
2001 if (name.length()) {
2002 session->save_template (name);
2012 ARDOUR_UI::fontconfig_dialog ()
2015 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2016 may not and it can take a while to build it. Warn them.
2019 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2021 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2022 MessageDialog msg (*new_session_dialog,
2023 _("Welcome to Ardour.\n\n"
2024 "The program will take a bit longer to start up\n"
2025 "while the system fonts are checked.\n\n"
2026 "This will only be done once, and you will\n"
2027 "not see this message again\n"),
2039 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2041 existing_session = false;
2043 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2044 session_path = cmdline_path;
2045 existing_session = true;
2046 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2047 session_path = Glib::path_get_dirname (string (cmdline_path));
2048 existing_session = true;
2050 /* it doesn't exist, assume the best */
2051 session_path = Glib::path_get_dirname (string (cmdline_path));
2054 session_name = basename_nosuffix (string (cmdline_path));
2058 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2060 /* when this is called, the backend audio system must be running */
2062 /* the main idea here is to deal with the fact that a cmdline argument for the session
2063 can be interpreted in different ways - it could be a directory or a file, and before
2064 we load, we need to know both the session directory and the snapshot (statefile) within it
2065 that we are supposed to use.
2068 if (session_name.length() == 0 || session_path.length() == 0) {
2072 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2074 Glib::ustring predicted_session_file;
2076 predicted_session_file = session_path;
2077 predicted_session_file += '/';
2078 predicted_session_file += session_name;
2079 predicted_session_file += ARDOUR::statefile_suffix;
2081 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2082 existing_session = true;
2085 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2087 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2088 /* existing .ardour file */
2089 existing_session = true;
2093 existing_session = false;
2096 /* lets just try to load it */
2098 if (create_engine ()) {
2099 backend_audio_error (false, new_session_dialog);
2103 return load_session (session_path, session_name);
2107 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2109 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2111 MessageDialog msg (str,
2113 Gtk::MESSAGE_WARNING,
2114 Gtk::BUTTONS_YES_NO,
2118 msg.set_name (X_("CleanupDialog"));
2119 msg.set_wmclass (X_("existing_session"), "Ardour");
2120 msg.set_position (Gtk::WIN_POS_MOUSE);
2122 switch (msg.run()) {
2131 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2136 AutoConnectOption iconnect;
2137 AutoConnectOption oconnect;
2141 if (Profile->get_sae()) {
2145 iconnect = AutoConnectPhysical;
2146 oconnect = AutoConnectMaster;
2147 nphysin = 0; // use all available
2148 nphysout = 0; // use all available
2152 /* get settings from advanced section of NSD */
2154 if (new_session_dialog->create_control_bus()) {
2155 cchns = (uint32_t) new_session_dialog->control_channel_count();
2160 if (new_session_dialog->create_master_bus()) {
2161 mchns = (uint32_t) new_session_dialog->master_channel_count();
2166 if (new_session_dialog->connect_inputs()) {
2167 iconnect = AutoConnectPhysical;
2169 iconnect = AutoConnectOption (0);
2172 /// @todo some minor tweaks.
2174 if (new_session_dialog->connect_outs_to_master()) {
2175 oconnect = AutoConnectMaster;
2176 } else if (new_session_dialog->connect_outs_to_physical()) {
2177 oconnect = AutoConnectPhysical;
2179 oconnect = AutoConnectOption (0);
2182 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2183 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2186 if (build_session (session_path,
2194 engine->frame_rate() * 60 * 5)) {
2203 ARDOUR_UI::end_loading_messages ()
2209 ARDOUR_UI::loading_message (const std::string& msg)
2212 splash->message (msg);
2217 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2219 bool existing_session = false;
2220 Glib::ustring session_name;
2221 Glib::ustring session_path;
2222 Glib::ustring template_name;
2224 int response = Gtk::RESPONSE_NONE;
2226 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2228 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2230 /* don't ever reuse this */
2232 ARDOUR_COMMAND_LINE::session_name = string();
2234 if (existing_session && backend_audio_is_running) {
2236 /* just load the thing already */
2238 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2243 /* make the NSD use whatever information we have */
2245 new_session_dialog->set_session_name (session_name);
2246 new_session_dialog->set_session_folder (session_path);
2249 /* loading failed, or we need the NSD for something */
2251 new_session_dialog->set_modal (false);
2252 new_session_dialog->set_position (WIN_POS_CENTER);
2253 new_session_dialog->set_current_page (0);
2254 new_session_dialog->set_existing_session (existing_session);
2255 new_session_dialog->reset_recent();
2257 /* get this out of the way */
2262 new_session_dialog->set_have_engine (backend_audio_is_running);
2263 new_session_dialog->present ();
2264 end_loading_messages ();
2265 response = new_session_dialog->run ();
2267 _session_is_new = false;
2269 /* handle possible negative responses */
2272 case Gtk::RESPONSE_CANCEL:
2273 case Gtk::RESPONSE_DELETE_EVENT:
2277 new_session_dialog->hide ();
2280 case Gtk::RESPONSE_NONE:
2281 /* "Clear" was pressed */
2285 fontconfig_dialog();
2287 if (!backend_audio_is_running) {
2288 if (new_session_dialog->engine_control.setup_engine ()) {
2289 new_session_dialog->hide ();
2294 if (create_engine ()) {
2296 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2299 new_session_dialog->set_existing_session (false);
2300 new_session_dialog->set_current_page (2);
2302 response = Gtk::RESPONSE_NONE;
2306 backend_audio_is_running = true;
2308 if (response == Gtk::RESPONSE_OK) {
2310 session_name = new_session_dialog->session_name();
2312 if (session_name.empty()) {
2313 response = Gtk::RESPONSE_NONE;
2317 /* if the user mistakenly typed path information into the session filename entry,
2318 convert what they typed into a path & a name
2321 if (session_name[0] == '/' ||
2322 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2323 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2325 session_path = Glib::path_get_dirname (session_name);
2326 session_name = Glib::path_get_basename (session_name);
2330 session_path = new_session_dialog->session_folder();
2333 switch (new_session_dialog->which_page()) {
2335 case NewSessionDialog::OpenPage:
2336 case NewSessionDialog::EnginePage:
2340 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2342 should_be_new = true;
2344 //XXX This is needed because session constructor wants a
2345 //non-existant path. hopefully this will be fixed at some point.
2347 session_path = Glib::build_filename (session_path, session_name);
2349 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2351 if (ask_about_loading_existing_session (session_path)) {
2354 response = RESPONSE_NONE;
2359 _session_is_new = true;
2361 if (new_session_dialog->use_session_template()) {
2363 template_name = new_session_dialog->session_template_name();
2367 if (build_session_from_nsd (session_path, session_name)) {
2368 response = RESPONSE_NONE;
2380 new_session_dialog->hide ();
2382 if (load_session (session_path, session_name)) {
2384 response = Gtk::RESPONSE_NONE;
2388 if (response == Gtk::RESPONSE_NONE) {
2389 new_session_dialog->set_existing_session (false);
2390 new_session_dialog->reset ();
2394 } while (response == Gtk::RESPONSE_NONE);
2398 new_session_dialog->hide();
2399 new_session_dialog->reset();
2400 goto_editor_window ();
2405 ARDOUR_UI::close_session()
2407 if (!check_audioengine()) {
2411 unload_session (true);
2413 get_session_parameters (true, false);
2417 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2419 Session *new_session;
2423 session_loaded = false;
2425 if (!check_audioengine()) {
2429 unload_status = unload_session ();
2431 if (unload_status < 0) {
2433 } else if (unload_status > 0) {
2438 /* if it already exists, we must have write access */
2440 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2441 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2442 "This prevents the session from being loaded."));
2447 loading_message (_("Please wait while Ardour loads your session"));
2448 disable_screen_updates ();
2451 new_session = new Session (*engine, path, snap_name, mix_template);
2454 /* this one is special */
2456 catch (AudioEngine::PortRegistrationFailure& err) {
2458 MessageDialog msg (err.what(),
2461 Gtk::BUTTONS_OK_CANCEL);
2463 msg.set_title (_("Loading Error"));
2464 msg.set_secondary_text (_("Click the OK button to try again."));
2465 msg.set_position (Gtk::WIN_POS_CENTER);
2468 int response = msg.run ();
2473 case RESPONSE_CANCEL:
2483 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2486 Gtk::BUTTONS_OK_CANCEL);
2488 msg.set_title (_("Loading Error"));
2489 msg.set_secondary_text (_("Click the OK button to try again."));
2490 msg.set_position (Gtk::WIN_POS_CENTER);
2493 int response = msg.run ();
2498 case RESPONSE_CANCEL:
2506 connect_to_session (new_session);
2508 Config->set_current_owner (ConfigVariableBase::Interface);
2510 session_loaded = true;
2512 goto_editor_window ();
2515 session->set_clean ();
2518 enable_screen_updates ();
2527 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2528 uint32_t control_channels,
2529 uint32_t master_channels,
2530 AutoConnectOption input_connect,
2531 AutoConnectOption output_connect,
2534 nframes_t initial_length)
2536 Session *new_session;
2539 if (!check_audioengine()) {
2543 session_loaded = false;
2545 x = unload_session ();
2553 _session_is_new = true;
2556 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2557 control_channels, master_channels, nphysin, nphysout, initial_length);
2562 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2567 connect_to_session (new_session);
2569 session_loaded = true;
2577 editor->show_window ();
2588 ARDOUR_UI::show_about ()
2592 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2599 ARDOUR_UI::hide_about ()
2602 about->get_window()->set_cursor ();
2608 ARDOUR_UI::about_signal_response(int response)
2614 ARDOUR_UI::show_splash ()
2618 splash = new Splash;
2625 splash->queue_draw ();
2626 splash->get_window()->process_updates (true);
2631 ARDOUR_UI::hide_splash ()
2639 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2643 removed = rep.paths.size();
2646 MessageDialog msgd (*editor,
2647 _("No audio files were ready for cleanup"),
2650 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2651 msgd.set_secondary_text (_("If this seems suprising, \n\
2652 check for any existing snapshots.\n\
2653 These may still include regions that\n\
2654 require some unused files to continue to exist."));
2660 ArdourDialog results (_("ardour: cleanup"), true, false);
2662 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2663 CleanupResultsModelColumns() {
2667 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2668 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2672 CleanupResultsModelColumns results_columns;
2673 Glib::RefPtr<Gtk::ListStore> results_model;
2674 Gtk::TreeView results_display;
2676 results_model = ListStore::create (results_columns);
2677 results_display.set_model (results_model);
2678 results_display.append_column (list_title, results_columns.visible_name);
2680 results_display.set_name ("CleanupResultsList");
2681 results_display.set_headers_visible (true);
2682 results_display.set_headers_clickable (false);
2683 results_display.set_reorderable (false);
2685 Gtk::ScrolledWindow list_scroller;
2688 Gtk::HBox dhbox; // the hbox for the image and text
2689 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2690 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2692 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2694 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2696 if (rep.space < 1048576.0f) {
2698 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2700 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2704 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2706 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2710 dhbox.pack_start (*dimage, true, false, 5);
2711 dhbox.pack_start (txt, true, false, 5);
2713 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2714 TreeModel::Row row = *(results_model->append());
2715 row[results_columns.visible_name] = *i;
2716 row[results_columns.fullpath] = *i;
2719 list_scroller.add (results_display);
2720 list_scroller.set_size_request (-1, 150);
2721 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2723 dvbox.pack_start (dhbox, true, false, 5);
2724 dvbox.pack_start (list_scroller, true, false, 5);
2725 ddhbox.pack_start (dvbox, true, false, 5);
2727 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2728 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2729 results.set_default_response (RESPONSE_CLOSE);
2730 results.set_position (Gtk::WIN_POS_MOUSE);
2732 results_display.show();
2733 list_scroller.show();
2740 //results.get_vbox()->show();
2741 results.set_resizable (false);
2748 ARDOUR_UI::cleanup ()
2751 /* shouldn't happen: menu item is insensitive */
2756 MessageDialog checker (_("Are you sure you want to cleanup?"),
2758 Gtk::MESSAGE_QUESTION,
2759 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2761 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2762 ALL undo/redo information will be lost if you cleanup.\n\
2763 After cleanup, unused audio files will be moved to a \
2764 \"dead sounds\" location."));
2766 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2767 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2768 checker.set_default_response (RESPONSE_CANCEL);
2770 checker.set_name (_("CleanupDialog"));
2771 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2772 checker.set_position (Gtk::WIN_POS_MOUSE);
2774 switch (checker.run()) {
2775 case RESPONSE_ACCEPT:
2781 Session::cleanup_report rep;
2783 editor->prepare_for_cleanup ();
2785 /* do not allow flush until a session is reloaded */
2787 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2789 act->set_sensitive (false);
2792 if (session->cleanup_sources (rep)) {
2797 display_cleanup_results (rep,
2800 The following %1 %2 not in use and \n\
2801 have been moved to:\n\
2803 Flushing the wastebasket will \n\
2804 release an additional\n\
2805 %4 %5bytes of disk space.\n"
2813 ARDOUR_UI::flush_trash ()
2816 /* shouldn't happen: menu item is insensitive */
2820 Session::cleanup_report rep;
2822 if (session->cleanup_trash_sources (rep)) {
2826 display_cleanup_results (rep,
2828 _("The following %1 %2 deleted from\n\
2830 releasing %4 %5bytes of disk space"));
2834 ARDOUR_UI::add_route (Gtk::Window* float_window)
2842 if (add_route_dialog == 0) {
2843 add_route_dialog = new AddRouteDialog;
2845 add_route_dialog->set_transient_for (*float_window);
2849 if (add_route_dialog->is_visible()) {
2850 /* we're already doing this */
2854 ResponseType r = (ResponseType) add_route_dialog->run ();
2856 add_route_dialog->hide();
2859 case RESPONSE_ACCEPT:
2866 if ((count = add_route_dialog->count()) <= 0) {
2870 uint32_t input_chan = add_route_dialog->channels ();
2871 uint32_t output_chan;
2872 string name_template = add_route_dialog->name_template ();
2873 bool track = add_route_dialog->track ();
2875 AutoConnectOption oac = Config->get_output_auto_connect();
2877 if (oac & AutoConnectMaster) {
2878 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2880 output_chan = input_chan;
2883 /* XXX do something with name template */
2885 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2887 session_add_midi_track(count);
2889 MessageDialog msg (*editor,
2890 _("Sorry, MIDI Busses are not supported at this time."));
2892 //session_add_midi_bus();
2896 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2898 session_add_audio_bus (input_chan, output_chan, count);
2904 ARDOUR_UI::mixer_settings () const
2909 node = session->instant_xml(X_("Mixer"));
2911 node = Config->instant_xml(X_("Mixer"));
2915 node = new XMLNode (X_("Mixer"));
2922 ARDOUR_UI::editor_settings () const
2927 node = session->instant_xml(X_("Editor"));
2929 node = Config->instant_xml(X_("Editor"));
2933 node = new XMLNode (X_("Editor"));
2939 ARDOUR_UI::keyboard_settings () const
2943 node = Config->extra_xml(X_("Keyboard"));
2946 node = new XMLNode (X_("Keyboard"));
2952 ARDOUR_UI::halt_on_xrun_message ()
2954 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2956 MessageDialog msg (*editor,
2957 _("Recording was stopped because your system could not keep up."));
2962 ARDOUR_UI::disk_overrun_handler ()
2964 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2966 if (!have_disk_speed_dialog_displayed) {
2967 have_disk_speed_dialog_displayed = true;
2968 MessageDialog* msg = new MessageDialog (*editor, _("\
2969 The disk system on your computer\n\
2970 was not able to keep up with Ardour.\n\
2972 Specifically, it failed to write data to disk\n\
2973 quickly enough to keep up with recording.\n"));
2974 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2980 ARDOUR_UI::disk_underrun_handler ()
2982 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2984 if (!have_disk_speed_dialog_displayed) {
2985 have_disk_speed_dialog_displayed = true;
2986 MessageDialog* msg = new MessageDialog (*editor,
2987 _("The disk system on your computer\n\
2988 was not able to keep up with Ardour.\n\
2990 Specifically, it failed to read data from disk\n\
2991 quickly enough to keep up with playback.\n"));
2992 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2998 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3000 have_disk_speed_dialog_displayed = false;
3005 ARDOUR_UI::pending_state_dialog ()
3007 HBox* hbox = new HBox();
3008 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3009 ArdourDialog dialog (_("Crash Recovery"), true);
3011 This session appears to have been in\n\
3012 middle of recording when ardour or\n\
3013 the computer was shutdown.\n\
3015 Ardour can recover any captured audio for\n\
3016 you, or it can ignore it. Please decide\n\
3017 what you would like to do.\n"));
3018 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3019 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3020 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3021 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3022 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3023 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3024 dialog.set_default_response (RESPONSE_ACCEPT);
3025 dialog.set_position (WIN_POS_CENTER);
3030 switch (dialog.run ()) {
3031 case RESPONSE_ACCEPT:
3039 ARDOUR_UI::disconnect_from_jack ()
3042 if( engine->disconnect_from_jack ()) {
3043 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3047 update_sample_rate (0);
3052 ARDOUR_UI::reconnect_to_jack ()
3055 if (engine->reconnect_to_jack ()) {
3056 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3060 update_sample_rate (0);
3065 ARDOUR_UI::use_config ()
3067 Glib::RefPtr<Action> act;
3069 switch (Config->get_native_file_data_format ()) {
3071 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3074 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3077 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3082 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3083 ract->set_active ();
3086 switch (Config->get_native_file_header_format ()) {
3088 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3091 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3094 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3097 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3100 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3103 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3106 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3111 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3112 ract->set_active ();
3115 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3117 set_transport_controllable_state (*node);
3122 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3124 if (Config->get_primary_clock_delta_edit_cursor()) {
3125 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3127 primary_clock.set (pos, 0, true);
3130 if (Config->get_secondary_clock_delta_edit_cursor()) {
3131 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3133 secondary_clock.set (pos);
3136 if (big_clock_window) {
3137 big_clock.set (pos);
3142 ARDOUR_UI::record_state_changed ()
3144 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3146 if (!session || !big_clock_window) {
3147 /* why bother - the clock isn't visible */
3151 switch (session->record_status()) {
3152 case Session::Recording:
3153 big_clock.set_widget_name ("BigClockRecording");
3156 big_clock.set_widget_name ("BigClockNonRecording");
3162 ARDOUR_UI::set_keybindings_path (string path)
3164 keybindings_path = path;
3168 ARDOUR_UI::save_keybindings ()
3170 if (can_save_keybindings) {
3171 AccelMap::save (user_keybindings_path);
3176 ARDOUR_UI::first_idle ()
3179 session->allow_auto_play (true);
3181 can_save_keybindings = true;
3186 ARDOUR_UI::store_clock_modes ()
3188 XMLNode* node = new XMLNode(X_("ClockModes"));
3190 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3191 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3194 session->add_extra_xml (*node);
3195 session->set_dirty ();
3200 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3201 : Controllable (name), ui (u), type(tp)
3207 ARDOUR_UI::TransportControllable::set_value (float val)
3209 if (type == ShuttleControl) {
3216 fract = -((0.5f - val)/0.5f);
3218 fract = ((val - 0.5f)/0.5f);
3222 ui.set_shuttle_fract (fract);
3227 /* do nothing: these are radio-style actions */
3231 const char *action = 0;
3235 action = X_("Roll");
3238 action = X_("Stop");
3241 action = X_("Goto Start");
3244 action = X_("Goto End");
3247 action = X_("Loop");
3250 action = X_("Play Selection");
3253 action = X_("Record");
3263 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3271 ARDOUR_UI::TransportControllable::get_value (void) const
3290 case ShuttleControl:
3300 ARDOUR_UI::TransportControllable::set_id (const string& str)
3306 ARDOUR_UI::setup_profile ()
3308 if (gdk_screen_width() < 1200) {
3309 Profile->set_small_screen ();
3313 if (getenv ("ARDOUR_SAE")) {
3314 Profile->set_sae ();
3315 Profile->set_single_package ();