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.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/basename.h>
37 #include <pbd/compose.h>
38 #include <pbd/pathscanner.h>
39 #include <pbd/failed_constructor.h>
40 #include <pbd/enumwriter.h>
41 #include <pbd/stacktrace.h>
42 #include <gtkmm2ext/gtk_ui.h>
43 #include <gtkmm2ext/utils.h>
44 #include <gtkmm2ext/click_box.h>
45 #include <gtkmm2ext/fastmeter.h>
46 #include <gtkmm2ext/stop_signal.h>
47 #include <gtkmm2ext/popup.h>
48 #include <gtkmm2ext/window_title.h>
50 #include <midi++/port.h>
51 #include <midi++/mmc.h>
53 #include <ardour/ardour.h>
54 #include <ardour/profile.h>
55 #include <ardour/session_route.h>
56 #include <ardour/port.h>
57 #include <ardour/audioengine.h>
58 #include <ardour/playlist.h>
59 #include <ardour/utils.h>
60 #include <ardour/audio_diskstream.h>
61 #include <ardour/audiofilesource.h>
62 #include <ardour/recent_sessions.h>
63 #include <ardour/port.h>
64 #include <ardour/audio_track.h>
67 #include "ardour_ui.h"
68 #include "public_editor.h"
69 #include "audio_clock.h"
74 #include "add_route_dialog.h"
75 #include "new_session_dialog.h"
79 #include "gui_thread.h"
80 #include "theme_manager.h"
81 #include "engine_dialog.h"
85 using namespace ARDOUR;
87 using namespace Gtkmm2ext;
91 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
92 UIConfiguration *ARDOUR_UI::ui_config = 0;
94 sigc::signal<void,bool> ARDOUR_UI::Blink;
95 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
96 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
97 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
99 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
101 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
103 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
104 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
105 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
106 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
110 preroll_button (_("pre\nroll")),
111 postroll_button (_("post\nroll")),
115 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
119 roll_controllable ("transport roll", *this, TransportControllable::Roll),
120 stop_controllable ("transport stop", *this, TransportControllable::Stop),
121 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
122 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
123 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
124 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
125 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
126 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
127 shuttle_controller_binding_proxy (shuttle_controllable),
129 roll_button (roll_controllable),
130 stop_button (stop_controllable),
131 goto_start_button (goto_start_controllable),
132 goto_end_button (goto_end_controllable),
133 auto_loop_button (auto_loop_controllable),
134 play_selection_button (play_selection_controllable),
135 rec_button (rec_controllable),
137 shuttle_units_button (_("% ")),
139 punch_in_button (_("Punch In")),
140 punch_out_button (_("Punch Out")),
141 auto_return_button (_("Auto Return")),
142 auto_play_button (_("Auto Play")),
143 auto_input_button (_("Auto Input")),
144 click_button (_("Click")),
145 time_master_button (_("time\nmaster")),
147 auditioning_alert_button (_("AUDITION")),
148 solo_alert_button (_("SOLO")),
150 error_log_button (_("Errors"))
152 using namespace Gtk::Menu_Helpers;
157 _auto_display_errors = false;
163 if (ARDOUR_COMMAND_LINE::session_name.length()) {
164 /* only show this if we're not going to post the new session dialog */
168 if (theArdourUI == 0) {
172 ui_config = new UIConfiguration();
173 theme_manager = new ThemeManager();
179 _session_is_new = false;
180 big_clock_window = 0;
181 session_selector_window = 0;
182 new_session_dialog = 0;
183 last_key_press_time = 0;
184 connection_editor = 0;
185 add_route_dialog = 0;
190 open_session_selector = 0;
191 have_configure_timeout = false;
192 have_disk_speed_dialog_displayed = false;
193 _will_create_new_session_automatically = false;
194 session_loaded = false;
195 last_speed_displayed = -1.0f;
196 ignore_dual_punch = false;
198 last_configure_time.tv_sec = 0;
199 last_configure_time.tv_usec = 0;
201 shuttle_grabbed = false;
203 shuttle_max_speed = 8.0f;
205 shuttle_style_menu = 0;
206 shuttle_unit_menu = 0;
208 gettimeofday (&last_peak_grab, 0);
209 gettimeofday (&last_shuttle_request, 0);
211 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
212 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
214 /* handle dialog requests */
216 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
218 /* handle pending state with a dialog */
220 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
222 /* handle sr mismatch with a dialog */
224 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
226 /* lets get this party started */
229 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
230 throw failed_constructor ();
233 setup_gtk_ardour_enums ();
234 Config->set_current_owner (ConfigVariableBase::Interface);
237 } catch (failed_constructor& err) {
238 error << _("could not initialize Ardour.") << endmsg;
243 /* we like keyboards */
245 keyboard = new Keyboard;
249 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
250 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
256 ARDOUR_UI::create_engine ()
258 // this gets called every time by new_session()
264 loading_message (_("Starting audio engine"));
267 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
274 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
275 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
276 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
277 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
285 ARDOUR_UI::post_engine ()
287 /* Things to be done once we create the AudioEngine
290 check_memory_locking();
292 ActionManager::init ();
295 if (setup_windows ()) {
296 throw failed_constructor ();
299 /* this is the first point at which all the keybindings are available */
301 if (ARDOUR_COMMAND_LINE::show_key_actions) {
302 vector<string> names;
303 vector<string> paths;
305 vector<AccelKey> bindings;
307 ActionManager::get_all_actions (names, paths, keys, bindings);
309 vector<string>::iterator n;
310 vector<string>::iterator k;
311 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
312 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
318 blink_timeout_tag = -1;
320 /* the global configuration object is now valid */
324 /* this being a GUI and all, we want peakfiles */
326 AudioFileSource::set_build_peakfiles (true);
327 AudioFileSource::set_build_missing_peakfiles (true);
329 /* set default clock modes */
331 if (Profile->get_sae()) {
332 primary_clock.set_mode (AudioClock::MinSec);
334 primary_clock.set_mode (AudioClock::SMPTE);
336 secondary_clock.set_mode (AudioClock::BBT);
338 /* start the time-of-day-clock */
341 /* OS X provides an always visible wallclock, so don't be stupid */
342 update_wall_clock ();
343 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
346 update_disk_space ();
348 update_sample_rate (engine->frame_rate());
350 platform_specific ();
352 /* now start and maybe save state */
354 if (do_engine_start () == 0) {
355 if (session && _session_is_new) {
356 /* we need to retain initial visual
357 settings for a new session
359 session->save_state ("");
364 ARDOUR_UI::~ARDOUR_UI ()
366 save_ardour_state ();
380 if (add_route_dialog) {
381 delete add_route_dialog;
384 if (new_session_dialog) {
385 delete new_session_dialog;
390 ARDOUR_UI::pop_back_splash ()
392 if (Splash::instance()) {
393 // Splash::instance()->pop_back();
394 Splash::instance()->hide ();
399 ARDOUR_UI::configure_timeout ()
404 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
405 /* no configure events yet */
409 gettimeofday (&now, 0);
410 timersub (&now, &last_configure_time, &diff);
412 /* force a gap of 0.5 seconds since the last configure event
415 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
418 have_configure_timeout = false;
419 save_ardour_state ();
425 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
427 if (have_configure_timeout) {
428 gettimeofday (&last_configure_time, 0);
430 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
431 have_configure_timeout = true;
438 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
440 const XMLProperty* prop;
442 if ((prop = node.property ("roll")) != 0) {
443 roll_controllable.set_id (prop->value());
445 if ((prop = node.property ("stop")) != 0) {
446 stop_controllable.set_id (prop->value());
448 if ((prop = node.property ("goto_start")) != 0) {
449 goto_start_controllable.set_id (prop->value());
451 if ((prop = node.property ("goto_end")) != 0) {
452 goto_end_controllable.set_id (prop->value());
454 if ((prop = node.property ("auto_loop")) != 0) {
455 auto_loop_controllable.set_id (prop->value());
457 if ((prop = node.property ("play_selection")) != 0) {
458 play_selection_controllable.set_id (prop->value());
460 if ((prop = node.property ("rec")) != 0) {
461 rec_controllable.set_id (prop->value());
463 if ((prop = node.property ("shuttle")) != 0) {
464 shuttle_controllable.set_id (prop->value());
469 ARDOUR_UI::get_transport_controllable_state ()
471 XMLNode* node = new XMLNode(X_("TransportControllables"));
474 roll_controllable.id().print (buf, sizeof (buf));
475 node->add_property (X_("roll"), buf);
476 stop_controllable.id().print (buf, sizeof (buf));
477 node->add_property (X_("stop"), buf);
478 goto_start_controllable.id().print (buf, sizeof (buf));
479 node->add_property (X_("goto_start"), buf);
480 goto_end_controllable.id().print (buf, sizeof (buf));
481 node->add_property (X_("goto_end"), buf);
482 auto_loop_controllable.id().print (buf, sizeof (buf));
483 node->add_property (X_("auto_loop"), buf);
484 play_selection_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("play_selection"), buf);
486 rec_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("rec"), buf);
488 shuttle_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("shuttle"), buf);
495 ARDOUR_UI::save_ardour_state ()
497 if (!keyboard || !mixer || !editor) {
501 /* XXX this is all a bit dubious. add_extra_xml() uses
502 a different lifetime model from add_instant_xml().
505 XMLNode* node = new XMLNode (keyboard->get_state());
506 Config->add_extra_xml (*node);
507 Config->add_extra_xml (get_transport_controllable_state());
508 if (new_session_dialog) {
509 if (new_session_dialog->engine_control.was_used()) {
510 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
513 Config->save_state();
514 ui_config->save_state ();
516 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
517 XMLNode mnode(mixer->get_state());
520 session->add_instant_xml (enode, session->path());
521 session->add_instant_xml (mnode, session->path());
523 Config->add_instant_xml (enode, get_user_ardour_path());
524 Config->add_instant_xml (mnode, get_user_ardour_path());
527 Keyboard::save_keybindings ();
531 ARDOUR_UI::autosave_session ()
533 if (!Config->get_periodic_safety_backups())
537 session->maybe_write_autosave();
544 ARDOUR_UI::update_autosave ()
546 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
548 if (session->dirty()) {
549 if (_autosave_connection.connected()) {
550 _autosave_connection.disconnect();
553 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
554 Config->get_periodic_safety_backup_interval() * 1000);
557 if (_autosave_connection.connected()) {
558 _autosave_connection.disconnect();
564 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
568 title = _("Ardour could not start JACK");
570 title = _("Ardour could not connect to JACK.");
573 MessageDialog win (title,
579 win.set_secondary_text(_("There are several possible reasons:\n\
581 1) You requested audio parameters that are not supported..\n\
582 2) JACK is running as another user.\n\
584 Please consider the possibilities, and perhaps try different parameters."));
586 win.set_secondary_text(_("There are several possible reasons:\n\
588 1) JACK is not running.\n\
589 2) JACK is running as another user, perhaps root.\n\
590 3) There is already another client called \"ardour\".\n\
592 Please consider the possibilities, and perhaps (re)start JACK."));
596 win.set_transient_for (*toplevel);
600 win.add_button (Stock::OK, RESPONSE_CLOSE);
602 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
605 win.set_default_response (RESPONSE_CLOSE);
608 win.set_position (Gtk::WIN_POS_CENTER);
611 /* we just don't care about the result, but we want to block */
617 ARDOUR_UI::startup ()
621 new_session_dialog = new NewSessionDialog();
623 bool backend_audio_is_running = EngineControl::engine_running();
624 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
627 new_session_dialog->engine_control.set_state (*audio_setup);
630 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
634 BootMessage (_("Ardour is ready for use"));
639 ARDOUR_UI::no_memory_warning ()
641 XMLNode node (X_("no-memory-warning"));
642 Config->add_instant_xml (node, get_user_ardour_path());
646 ARDOUR_UI::check_memory_locking ()
649 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
653 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
655 if (engine->is_realtime() && memory_warning_node == 0) {
657 struct rlimit limits;
659 long pages, page_size;
661 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
664 ram = (int64_t) pages * (int64_t) page_size;
667 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
671 if (limits.rlim_cur != RLIM_INFINITY) {
673 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
676 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
677 "This might cause Ardour to run out of memory before your system "
678 "runs out of memory. \n\n"
679 "You can view the memory limit with 'ulimit -l', "
680 "and it is normally controlled by /etc/security/limits.conf"));
682 VBox* vbox = msg.get_vbox();
684 CheckButton cb (_("Do not show this window again"));
686 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
688 hbox.pack_start (cb, true, false);
689 vbox->pack_start (hbox);
707 if (session->transport_rolling()) {
708 session->request_stop ();
712 if (session->dirty()) {
713 switch (ask_about_saving_session(_("quit"))) {
718 /* use the default name */
719 if (save_state_canfail ("")) {
720 /* failed - don't quit */
721 MessageDialog msg (*editor,
723 Ardour was unable to save your session.\n\n\
724 If you still wish to quit, please use the\n\n\
725 \"Just quit\" option."));
736 session->set_deletion_in_progress ();
740 save_ardour_state ();
745 ARDOUR_UI::ask_about_saving_session (const string & what)
747 ArdourDialog window (_("ardour: save session?"));
748 Gtk::HBox dhbox; // the hbox for the image and text
749 Gtk::Label prompt_label;
750 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
754 msg = string_compose(_("Don't %1"), what);
755 window.add_button (msg, RESPONSE_REJECT);
756 msg = string_compose(_("Just %1"), what);
757 window.add_button (msg, RESPONSE_APPLY);
758 msg = string_compose(_("Save and %1"), what);
759 window.add_button (msg, RESPONSE_ACCEPT);
761 window.set_default_response (RESPONSE_ACCEPT);
763 Gtk::Button noquit_button (msg);
764 noquit_button.set_name ("EditorGTKButton");
769 if (session->snap_name() == session->name()) {
772 type = _("snapshot");
774 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?"),
775 type, session->snap_name());
777 prompt_label.set_text (prompt);
778 prompt_label.set_name (X_("PrompterLabel"));
779 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
781 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
783 dhbox.set_homogeneous (false);
784 dhbox.pack_start (*dimage, false, false, 5);
785 dhbox.pack_start (prompt_label, true, false, 5);
786 window.get_vbox()->pack_start (dhbox);
788 window.set_name (_("Prompter"));
789 window.set_position (Gtk::WIN_POS_MOUSE);
790 window.set_modal (true);
791 window.set_resizable (false);
794 window.set_keep_above (true);
797 ResponseType r = (ResponseType) window.run();
802 case RESPONSE_ACCEPT: // save and get out of here
804 case RESPONSE_APPLY: // get out of here
814 ARDOUR_UI::every_second ()
817 update_buffer_load ();
818 update_disk_space ();
823 ARDOUR_UI::every_point_one_seconds ()
825 update_speed_display ();
826 RapidScreenUpdate(); /* EMIT_SIGNAL */
831 ARDOUR_UI::every_point_zero_one_seconds ()
833 // august 2007: actual update frequency: 40Hz, not 100Hz
835 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
840 ARDOUR_UI::update_sample_rate (nframes_t ignored)
844 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
846 if (!engine->connected()) {
848 snprintf (buf, sizeof (buf), _("disconnected"));
852 nframes_t rate = engine->frame_rate();
854 if (fmod (rate, 1000.0) != 0.0) {
855 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
856 (float) rate/1000.0f,
857 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
859 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
861 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
865 sample_rate_label.set_text (buf);
869 ARDOUR_UI::update_cpu_load ()
872 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
873 cpu_load_label.set_text (buf);
877 ARDOUR_UI::update_buffer_load ()
882 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
883 session->playback_load(), session->capture_load());
884 buffer_load_label.set_text (buf);
886 buffer_load_label.set_text ("");
891 ARDOUR_UI::count_recenabled_streams (Route& route)
893 Track* track = dynamic_cast<Track*>(&route);
894 if (track && track->diskstream()->record_enabled()) {
895 rec_enabled_streams += track->n_inputs();
900 ARDOUR_UI::update_disk_space()
906 nframes_t frames = session->available_capture_duration();
909 if (frames == max_frames) {
910 strcpy (buf, _("Disk: 24hrs+"));
915 nframes_t fr = session->frame_rate();
917 rec_enabled_streams = 0;
918 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
920 if (rec_enabled_streams) {
921 frames /= rec_enabled_streams;
924 hrs = frames / (fr * 3600);
925 frames -= hrs * fr * 3600;
926 mins = frames / (fr * 60);
927 frames -= mins * fr * 60;
930 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
933 disk_space_label.set_text (buf);
937 ARDOUR_UI::update_wall_clock ()
944 tm_now = localtime (&now);
946 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
947 wall_clock_label.set_text (buf);
953 ARDOUR_UI::session_menu (GdkEventButton *ev)
955 session_popup_menu->popup (0, 0);
960 ARDOUR_UI::redisplay_recent_sessions ()
962 vector<string *> *sessions;
963 vector<string *>::iterator i;
964 RecentSessionsSorter cmp;
966 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
967 recent_session_model->clear ();
970 ARDOUR::read_recent_sessions (rs);
973 recent_session_display.set_model (recent_session_model);
977 /* sort them alphabetically */
978 sort (rs.begin(), rs.end(), cmp);
979 sessions = new vector<string*>;
981 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
982 sessions->push_back (new string ((*i).second));
985 for (i = sessions->begin(); i != sessions->end(); ++i) {
987 vector<string*>* states;
988 vector<const gchar*> item;
989 string fullpath = *(*i);
991 /* remove any trailing / */
993 if (fullpath[fullpath.length()-1] == '/') {
994 fullpath = fullpath.substr (0, fullpath.length()-1);
997 /* check whether session still exists */
998 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
999 /* session doesn't exist */
1000 cerr << "skipping non-existent session " << fullpath << endl;
1004 /* now get available states for this session */
1006 if ((states = Session::possible_states (fullpath)) == 0) {
1007 /* no state file? */
1011 TreeModel::Row row = *(recent_session_model->append());
1013 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1014 row[recent_session_columns.fullpath] = fullpath;
1016 if (states->size() > 1) {
1018 /* add the children */
1020 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1022 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1024 child_row[recent_session_columns.visible_name] = **i2;
1025 child_row[recent_session_columns.fullpath] = fullpath;
1034 recent_session_display.set_model (recent_session_model);
1039 ARDOUR_UI::build_session_selector ()
1041 session_selector_window = new ArdourDialog ("session selector");
1043 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1045 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1046 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1047 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1048 recent_session_model = TreeStore::create (recent_session_columns);
1049 recent_session_display.set_model (recent_session_model);
1050 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1051 recent_session_display.set_headers_visible (false);
1052 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1053 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1055 scroller->add (recent_session_display);
1056 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1058 session_selector_window->set_name ("SessionSelectorWindow");
1059 session_selector_window->set_size_request (200, 400);
1060 session_selector_window->get_vbox()->pack_start (*scroller);
1061 session_selector_window->show_all_children();
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::check_audioengine ()
1128 if (!engine->connected()) {
1129 MessageDialog msg (_("Ardour is not connected to JACK\n"
1130 "You cannot open or close sessions in this condition"));
1142 ARDOUR_UI::open_session ()
1144 if (!check_audioengine()) {
1148 /* popup selector window */
1150 if (open_session_selector == 0) {
1152 /* ardour sessions are folders */
1154 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1155 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1156 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1157 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1159 FileFilter session_filter;
1160 session_filter.add_pattern ("*.ardour");
1161 session_filter.set_name (_("Ardour sessions"));
1162 open_session_selector->add_filter (session_filter);
1163 open_session_selector->set_filter (session_filter);
1166 int response = open_session_selector->run();
1167 open_session_selector->hide ();
1170 case RESPONSE_ACCEPT:
1173 open_session_selector->hide();
1177 open_session_selector->hide();
1178 string session_path = open_session_selector->get_filename();
1182 if (session_path.length() > 0) {
1183 if (Session::find_session (session_path, path, name, isnew) == 0) {
1184 _session_is_new = isnew;
1185 load_session (path, name);
1192 ARDOUR_UI::session_add_midi_track ()
1194 cerr << _("Patience is a virtue.\n");
1198 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1200 list<boost::shared_ptr<AudioTrack> > tracks;
1201 Session::RouteList routes;
1204 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1210 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1212 if (tracks.size() != how_many) {
1213 if (how_many == 1) {
1214 error << _("could not create a new audio track") << endmsg;
1216 error << string_compose (_("could only create %1 of %2 new audio %3"),
1217 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1223 routes = session->new_audio_route (input_channels, output_channels, how_many);
1225 if (routes.size() != how_many) {
1226 if (how_many == 1) {
1227 error << _("could not create a new audio track") << endmsg;
1229 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1235 if (need_control_room_outs) {
1241 route->set_stereo_control_outs (control_lr_channels);
1242 route->control_outs()->set_stereo_pan (pans, this);
1244 #endif /* CONTROLOUTS */
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::do_transport_locate (nframes_t new_position)
1261 nframes_t _preroll = 0;
1264 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1265 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1267 if (new_position > _preroll) {
1268 new_position -= _preroll;
1273 session->request_locate (new_position);
1278 ARDOUR_UI::transport_goto_start ()
1281 session->goto_start();
1284 /* force displayed area in editor to start no matter
1285 what "follow playhead" setting is.
1289 editor->reset_x_origin (session->current_start_frame());
1295 ARDOUR_UI::transport_goto_zero ()
1298 session->request_locate (0);
1301 /* force displayed area in editor to start no matter
1302 what "follow playhead" setting is.
1306 editor->reset_x_origin (0);
1312 ARDOUR_UI::transport_goto_end ()
1315 nframes_t frame = session->current_end_frame();
1316 session->request_locate (frame);
1318 /* force displayed area in editor to start no matter
1319 what "follow playhead" setting is.
1323 editor->reset_x_origin (frame);
1329 ARDOUR_UI::transport_stop ()
1335 if (session->is_auditioning()) {
1336 session->cancel_audition ();
1340 if (session->get_play_loop ()) {
1341 session->request_play_loop (false);
1344 session->request_stop ();
1348 ARDOUR_UI::transport_stop_and_forget_capture ()
1351 session->request_stop (true);
1356 ARDOUR_UI::remove_last_capture()
1359 editor->remove_last_capture();
1364 ARDOUR_UI::transport_record (bool roll)
1368 switch (session->record_status()) {
1369 case Session::Disabled:
1370 if (session->ntracks() == 0) {
1371 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1375 session->maybe_enable_record ();
1380 case Session::Recording:
1382 session->request_stop();
1384 session->disable_record (false, true);
1388 case Session::Enabled:
1389 session->disable_record (false, true);
1392 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1396 ARDOUR_UI::transport_roll ()
1404 rolling = session->transport_rolling ();
1406 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1408 if (session->get_play_loop()) {
1409 session->request_play_loop (false);
1410 auto_loop_button.set_visual_state (1);
1411 roll_button.set_visual_state (1);
1412 } else if (session->get_play_range ()) {
1413 session->request_play_range (false);
1414 play_selection_button.set_visual_state (0);
1415 } else if (rolling) {
1416 session->request_locate (session->last_transport_start(), true);
1419 session->request_transport_speed (1.0f);
1423 ARDOUR_UI::transport_loop()
1426 if (session->get_play_loop()) {
1427 if (session->transport_rolling()) {
1428 Location * looploc = session->locations()->auto_loop_location();
1430 session->request_locate (looploc->start(), true);
1435 session->request_play_loop (true);
1441 ARDOUR_UI::transport_play_selection ()
1447 if (!session->get_play_range()) {
1448 session->request_stop ();
1451 editor->play_selection ();
1455 ARDOUR_UI::transport_rewind (int option)
1457 float current_transport_speed;
1460 current_transport_speed = session->transport_speed();
1462 if (current_transport_speed >= 0.0f) {
1465 session->request_transport_speed (-1.0f);
1468 session->request_transport_speed (-4.0f);
1471 session->request_transport_speed (-0.5f);
1476 session->request_transport_speed (current_transport_speed * 1.5f);
1482 ARDOUR_UI::transport_forward (int option)
1484 float current_transport_speed;
1487 current_transport_speed = session->transport_speed();
1489 if (current_transport_speed <= 0.0f) {
1492 session->request_transport_speed (1.0f);
1495 session->request_transport_speed (4.0f);
1498 session->request_transport_speed (0.5f);
1503 session->request_transport_speed (current_transport_speed * 1.5f);
1509 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1515 boost::shared_ptr<Route> r;
1517 if ((r = session->route_by_remote_id (dstream)) != 0) {
1521 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1522 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1531 ARDOUR_UI::queue_transport_change ()
1533 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1537 ARDOUR_UI::map_transport_state ()
1539 float sp = session->transport_speed();
1542 transport_rolling ();
1543 } else if (sp < 0.0f) {
1544 transport_rewinding ();
1545 } else if (sp > 0.0f) {
1546 transport_forwarding ();
1548 transport_stopped ();
1553 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1555 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1556 (int) adj.get_value()].c_str());
1560 ARDOUR_UI::engine_stopped ()
1562 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1563 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1564 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1568 ARDOUR_UI::engine_running ()
1570 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1571 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1572 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1574 Glib::RefPtr<Action> action;
1575 const char* action_name = 0;
1577 switch (engine->frames_per_cycle()) {
1579 action_name = X_("JACKLatency32");
1582 action_name = X_("JACKLatency64");
1585 action_name = X_("JACKLatency128");
1588 action_name = X_("JACKLatency512");
1591 action_name = X_("JACKLatency1024");
1594 action_name = X_("JACKLatency2048");
1597 action_name = X_("JACKLatency4096");
1600 action_name = X_("JACKLatency8192");
1603 /* XXX can we do anything useful ? */
1609 action = ActionManager::get_action (X_("JACK"), action_name);
1612 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1613 ract->set_active ();
1619 ARDOUR_UI::engine_halted ()
1621 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1623 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1624 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1626 update_sample_rate (0);
1628 MessageDialog msg (*editor,
1630 JACK has either been shutdown or it\n\
1631 disconnected Ardour because Ardour\n\
1632 was not fast enough. You can save the\n\
1633 session and/or try to reconnect to JACK ."));
1639 ARDOUR_UI::do_engine_start ()
1647 error << _("Unable to start the session running")
1657 ARDOUR_UI::setup_theme ()
1659 theme_manager->setup_theme();
1663 ARDOUR_UI::update_clocks ()
1665 if (!editor || !editor->dragging_playhead()) {
1666 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1671 ARDOUR_UI::start_clocking ()
1673 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1677 ARDOUR_UI::stop_clocking ()
1679 clock_signal_connection.disconnect ();
1683 ARDOUR_UI::toggle_clocking ()
1686 if (clock_button.get_active()) {
1695 ARDOUR_UI::_blink (void *arg)
1698 ((ARDOUR_UI *) arg)->blink ();
1705 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1709 ARDOUR_UI::start_blinking ()
1711 /* Start the blink signal. Everybody with a blinking widget
1712 uses Blink to drive the widget's state.
1715 if (blink_timeout_tag < 0) {
1717 blink_timeout_tag = g_timeout_add (240, _blink, this);
1722 ARDOUR_UI::stop_blinking ()
1724 if (blink_timeout_tag >= 0) {
1725 g_source_remove (blink_timeout_tag);
1726 blink_timeout_tag = -1;
1731 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1737 if (io.n_inputs() == 0) {
1742 /* XXX we're not handling multiple ports yet. */
1744 const char **connections = io.input(0)->get_connections();
1746 if (connections == 0 || connections[0] == '\0') {
1749 buf = connections[0];
1756 if (io.n_outputs() == 0) {
1761 /* XXX we're not handling multiple ports yet. */
1763 const char **connections = io.output(0)->get_connections();
1765 if (connections == 0 || connections[0] == '\0') {
1768 buf = connections[0];
1775 /** Ask the user for the name of a new shapshot and then take it.
1778 ARDOUR_UI::snapshot_session ()
1780 ArdourPrompter prompter (true);
1784 struct tm local_time;
1787 localtime_r (&n, &local_time);
1788 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1790 prompter.set_name ("Prompter");
1791 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1792 prompter.set_prompt (_("Name of New Snapshot"));
1793 prompter.set_initial_text (timebuf);
1795 switch (prompter.run()) {
1796 case RESPONSE_ACCEPT:
1797 prompter.get_result (snapname);
1798 if (snapname.length()){
1799 save_state (snapname);
1809 ARDOUR_UI::save_state (const string & name)
1811 (void) save_state_canfail (name);
1815 ARDOUR_UI::save_state_canfail (string name)
1820 if (name.length() == 0) {
1821 name = session->snap_name();
1824 if ((ret = session->save_state (name)) != 0) {
1828 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1833 ARDOUR_UI::primary_clock_value_changed ()
1836 session->request_locate (primary_clock.current_time ());
1841 ARDOUR_UI::big_clock_value_changed ()
1844 session->request_locate (big_clock.current_time ());
1849 ARDOUR_UI::secondary_clock_value_changed ()
1852 session->request_locate (secondary_clock.current_time ());
1857 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1863 switch (session->record_status()) {
1864 case Session::Enabled:
1866 rec_button.set_visual_state (2);
1868 rec_button.set_visual_state (0);
1872 case Session::Recording:
1873 rec_button.set_visual_state (1);
1877 rec_button.set_visual_state (0);
1883 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1891 ARDOUR_UI::save_template ()
1894 ArdourPrompter prompter (true);
1897 if (!check_audioengine()) {
1901 prompter.set_name (X_("Prompter"));
1902 prompter.set_prompt (_("Name for mix template:"));
1903 prompter.set_initial_text(session->name() + _("-template"));
1904 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1906 switch (prompter.run()) {
1907 case RESPONSE_ACCEPT:
1908 prompter.get_result (name);
1910 if (name.length()) {
1911 session->save_template (name);
1921 ARDOUR_UI::fontconfig_dialog ()
1924 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1925 may not and it can take a while to build it. Warn them.
1928 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1930 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1931 MessageDialog msg (*new_session_dialog,
1932 _("Welcome to Ardour.\n\n"
1933 "The program will take a bit longer to start up\n"
1934 "while the system fonts are checked.\n\n"
1935 "This will only be done once, and you will\n"
1936 "not see this message again\n"),
1949 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
1951 existing_session = false;
1953 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
1954 session_path = cmdline_path;
1955 existing_session = true;
1956 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
1957 session_path = Glib::path_get_dirname (string (cmdline_path));
1958 existing_session = true;
1960 /* it doesn't exist, assume the best */
1961 session_path = Glib::path_get_dirname (string (cmdline_path));
1964 session_name = basename_nosuffix (string (cmdline_path));
1968 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
1970 /* when this is called, the backend audio system must be running */
1972 /* the main idea here is to deal with the fact that a cmdline argument for the session
1973 can be interpreted in different ways - it could be a directory or a file, and before
1974 we load, we need to know both the session directory and the snapshot (statefile) within it
1975 that we are supposed to use.
1978 if (session_name.length() == 0 || session_path.length() == 0) {
1982 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
1984 Glib::ustring predicted_session_file;
1986 predicted_session_file = session_path;
1987 predicted_session_file += '/';
1988 predicted_session_file += session_name;
1989 predicted_session_file += Session::statefile_suffix();
1991 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
1992 existing_session = true;
1995 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
1997 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
1998 /* existing .ardour file */
1999 existing_session = true;
2003 existing_session = false;
2006 /* lets just try to load it */
2008 if (create_engine ()) {
2009 backend_audio_error (false, new_session_dialog);
2013 return load_session (session_path, session_name);
2017 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2019 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2021 MessageDialog msg (str,
2023 Gtk::MESSAGE_WARNING,
2024 Gtk::BUTTONS_YES_NO,
2028 msg.set_name (X_("CleanupDialog"));
2029 msg.set_wmclass (X_("existing_session"), "Ardour");
2030 msg.set_position (Gtk::WIN_POS_MOUSE);
2033 switch (msg.run()) {
2042 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2047 AutoConnectOption iconnect;
2048 AutoConnectOption oconnect;
2052 if (Profile->get_sae()) {
2056 iconnect = AutoConnectPhysical;
2057 oconnect = AutoConnectMaster;
2058 nphysin = 0; // use all available
2059 nphysout = 0; // use all available
2063 /* get settings from advanced section of NSD */
2065 if (new_session_dialog->create_control_bus()) {
2066 cchns = (uint32_t) new_session_dialog->control_channel_count();
2071 if (new_session_dialog->create_master_bus()) {
2072 mchns = (uint32_t) new_session_dialog->master_channel_count();
2077 if (new_session_dialog->connect_inputs()) {
2078 iconnect = AutoConnectPhysical;
2080 iconnect = AutoConnectOption (0);
2083 /// @todo some minor tweaks.
2085 if (new_session_dialog->connect_outs_to_master()) {
2086 oconnect = AutoConnectMaster;
2087 } else if (new_session_dialog->connect_outs_to_physical()) {
2088 oconnect = AutoConnectPhysical;
2090 oconnect = AutoConnectOption (0);
2093 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2094 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2097 if (build_session (session_path,
2105 engine->frame_rate() * 60 * 5)) {
2114 ARDOUR_UI::end_loading_messages ()
2120 ARDOUR_UI::loading_message (const std::string& msg)
2123 splash->message (msg);
2128 ARDOUR_UI::idle_load (const Glib::ustring& path)
2131 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2132 /* /path/to/foo => /path/to/foo, foo */
2133 load_session (path, basename_nosuffix (path));
2135 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2136 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2139 ARDOUR_COMMAND_LINE::session_name = path;
2140 if (new_session_dialog) {
2141 /* make it break out of Dialog::run() and
2144 new_session_dialog->response (1);
2150 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2152 bool existing_session = false;
2153 Glib::ustring session_name;
2154 Glib::ustring session_path;
2155 Glib::ustring template_name;
2159 response = Gtk::RESPONSE_NONE;
2161 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2163 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2165 /* don't ever reuse this */
2167 ARDOUR_COMMAND_LINE::session_name = string();
2169 if (existing_session && backend_audio_is_running) {
2171 /* just load the thing already */
2173 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2178 /* make the NSD use whatever information we have */
2180 new_session_dialog->set_session_name (session_name);
2181 new_session_dialog->set_session_folder (session_path);
2184 /* loading failed, or we need the NSD for something */
2186 new_session_dialog->set_modal (false);
2187 new_session_dialog->set_position (WIN_POS_CENTER);
2188 new_session_dialog->set_current_page (0);
2189 new_session_dialog->set_existing_session (existing_session);
2190 new_session_dialog->reset_recent();
2193 new_session_dialog->set_have_engine (backend_audio_is_running);
2194 new_session_dialog->present ();
2195 response = new_session_dialog->run ();
2197 _session_is_new = false;
2199 /* handle possible negative responses */
2203 /* sent by idle_load, meaning restart the whole process again */
2204 new_session_dialog->hide();
2205 new_session_dialog->reset();
2209 case Gtk::RESPONSE_CANCEL:
2210 case Gtk::RESPONSE_DELETE_EVENT:
2214 new_session_dialog->hide ();
2217 case Gtk::RESPONSE_NONE:
2218 /* "Clear" was pressed */
2222 fontconfig_dialog();
2224 if (!backend_audio_is_running) {
2225 if (new_session_dialog->engine_control.setup_engine ()) {
2226 new_session_dialog->hide ();
2231 if (create_engine ()) {
2233 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2236 new_session_dialog->set_existing_session (false);
2237 new_session_dialog->set_current_page (2);
2239 response = Gtk::RESPONSE_NONE;
2243 backend_audio_is_running = true;
2245 if (response == Gtk::RESPONSE_OK) {
2247 session_name = new_session_dialog->session_name();
2249 if (session_name.empty()) {
2250 response = Gtk::RESPONSE_NONE;
2254 /* if the user mistakenly typed path information into the session filename entry,
2255 convert what they typed into a path & a name
2258 if (session_name[0] == '/' ||
2259 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2260 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2262 session_path = Glib::path_get_dirname (session_name);
2263 session_name = Glib::path_get_basename (session_name);
2267 session_path = new_session_dialog->session_folder();
2270 template_name = Glib::ustring();
2271 switch (new_session_dialog->which_page()) {
2273 case NewSessionDialog::OpenPage:
2274 case NewSessionDialog::EnginePage:
2278 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2280 should_be_new = true;
2282 //XXX This is needed because session constructor wants a
2283 //non-existant path. hopefully this will be fixed at some point.
2285 session_path = Glib::build_filename (session_path, session_name);
2287 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2289 if (ask_about_loading_existing_session (session_path)) {
2292 response = RESPONSE_NONE;
2297 _session_is_new = true;
2299 if (new_session_dialog->use_session_template()) {
2301 template_name = new_session_dialog->session_template_name();
2305 if (build_session_from_nsd (session_path, session_name)) {
2306 response = RESPONSE_NONE;
2318 new_session_dialog->hide ();
2320 if (load_session (session_path, session_name, template_name)) {
2322 response = Gtk::RESPONSE_NONE;
2326 if (response == Gtk::RESPONSE_NONE) {
2327 new_session_dialog->set_existing_session (false);
2328 new_session_dialog->reset ();
2332 } while (response == Gtk::RESPONSE_NONE);
2336 new_session_dialog->hide();
2337 new_session_dialog->reset();
2338 goto_editor_window ();
2343 ARDOUR_UI::close_session ()
2345 if (!check_audioengine()) {
2349 unload_session (true);
2351 get_session_parameters (true, false);
2355 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2357 Session *new_session;
2361 session_loaded = false;
2363 if (!check_audioengine()) {
2367 unload_status = unload_session ();
2369 if (unload_status < 0) {
2371 } else if (unload_status > 0) {
2376 /* if it already exists, we must have write access */
2378 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2379 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2380 "This prevents the session from being loaded."));
2386 loading_message (_("Please wait while Ardour loads your session"));
2389 new_session = new Session (*engine, path, snap_name, mix_template);
2392 /* this one is special */
2394 catch (AudioEngine::PortRegistrationFailure& err) {
2396 MessageDialog msg (err.what(),
2399 Gtk::BUTTONS_OK_CANCEL);
2401 msg.set_title (_("Loading Error"));
2402 msg.set_secondary_text (_("Click the OK button to try again."));
2403 msg.set_position (Gtk::WIN_POS_CENTER);
2407 int response = msg.run ();
2412 case RESPONSE_CANCEL:
2422 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2425 Gtk::BUTTONS_OK_CANCEL);
2427 msg.set_title (_("Loading Error"));
2428 msg.set_secondary_text (_("Click the OK button to try again."));
2429 msg.set_position (Gtk::WIN_POS_CENTER);
2433 int response = msg.run ();
2438 case RESPONSE_CANCEL:
2446 connect_to_session (new_session);
2448 Config->set_current_owner (ConfigVariableBase::Interface);
2450 session_loaded = true;
2452 goto_editor_window ();
2455 session->set_clean ();
2466 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2467 uint32_t control_channels,
2468 uint32_t master_channels,
2469 AutoConnectOption input_connect,
2470 AutoConnectOption output_connect,
2473 nframes_t initial_length)
2475 Session *new_session;
2478 if (!check_audioengine()) {
2482 session_loaded = false;
2484 x = unload_session ();
2492 _session_is_new = true;
2495 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2496 control_channels, master_channels, nphysin, nphysout, initial_length);
2501 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2507 connect_to_session (new_session);
2509 session_loaded = true;
2517 editor->show_window ();
2528 ARDOUR_UI::show_about ()
2532 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2539 ARDOUR_UI::hide_about ()
2542 about->get_window()->set_cursor ();
2548 ARDOUR_UI::about_signal_response(int response)
2554 ARDOUR_UI::show_splash ()
2558 splash = new Splash;
2566 splash->queue_draw ();
2567 splash->get_window()->process_updates (true);
2572 ARDOUR_UI::hide_splash ()
2580 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2584 removed = rep.paths.size();
2587 MessageDialog msgd (*editor,
2588 _("No audio files were ready for cleanup"),
2591 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2592 msgd.set_secondary_text (_("If this seems suprising, \n\
2593 check for any existing snapshots.\n\
2594 These may still include regions that\n\
2595 require some unused files to continue to exist."));
2601 ArdourDialog results (_("ardour: cleanup"), true, false);
2603 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2604 CleanupResultsModelColumns() {
2608 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2609 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2613 CleanupResultsModelColumns results_columns;
2614 Glib::RefPtr<Gtk::ListStore> results_model;
2615 Gtk::TreeView results_display;
2617 results_model = ListStore::create (results_columns);
2618 results_display.set_model (results_model);
2619 results_display.append_column (list_title, results_columns.visible_name);
2621 results_display.set_name ("CleanupResultsList");
2622 results_display.set_headers_visible (true);
2623 results_display.set_headers_clickable (false);
2624 results_display.set_reorderable (false);
2626 Gtk::ScrolledWindow list_scroller;
2629 Gtk::HBox dhbox; // the hbox for the image and text
2630 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2631 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2633 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2635 if (rep.space < 1048576.0f) {
2637 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2639 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2643 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2645 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2649 dhbox.pack_start (*dimage, true, false, 5);
2650 dhbox.pack_start (txt, true, false, 5);
2652 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2653 TreeModel::Row row = *(results_model->append());
2654 row[results_columns.visible_name] = *i;
2655 row[results_columns.fullpath] = *i;
2658 list_scroller.add (results_display);
2659 list_scroller.set_size_request (-1, 150);
2660 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2662 dvbox.pack_start (dhbox, true, false, 5);
2663 dvbox.pack_start (list_scroller, true, false, 5);
2664 ddhbox.pack_start (dvbox, true, false, 5);
2666 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2667 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2668 results.set_default_response (RESPONSE_CLOSE);
2669 results.set_position (Gtk::WIN_POS_MOUSE);
2670 results.show_all_children ();
2671 results.set_resizable (false);
2678 ARDOUR_UI::cleanup ()
2681 /* shouldn't happen: menu item is insensitive */
2686 MessageDialog checker (_("Are you sure you want to cleanup?"),
2688 Gtk::MESSAGE_QUESTION,
2689 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2691 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2692 ALL undo/redo information will be lost if you cleanup.\n\
2693 After cleanup, unused audio files will be moved to a \
2694 \"dead sounds\" location."));
2696 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2697 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2698 checker.set_default_response (RESPONSE_CANCEL);
2700 checker.set_name (_("CleanupDialog"));
2701 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2702 checker.set_position (Gtk::WIN_POS_MOUSE);
2704 switch (checker.run()) {
2705 case RESPONSE_ACCEPT:
2711 Session::cleanup_report rep;
2713 editor->prepare_for_cleanup ();
2715 /* do not allow flush until a session is reloaded */
2717 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2719 act->set_sensitive (false);
2722 if (session->cleanup_sources (rep)) {
2727 display_cleanup_results (rep,
2730 The following %1 %2 not in use and \n\
2731 have been moved to:\n\
2733 Flushing the wastebasket will \n\
2734 release an additional\n\
2735 %4 %5bytes of disk space.\n"
2743 ARDOUR_UI::flush_trash ()
2746 /* shouldn't happen: menu item is insensitive */
2750 Session::cleanup_report rep;
2752 if (session->cleanup_trash_sources (rep)) {
2756 display_cleanup_results (rep,
2758 _("The following %1 %2 deleted from\n\
2760 releasing %4 %5bytes of disk space"));
2764 ARDOUR_UI::add_route (Gtk::Window* float_window)
2772 if (add_route_dialog == 0) {
2773 add_route_dialog = new AddRouteDialog;
2775 add_route_dialog->set_transient_for (*float_window);
2779 if (add_route_dialog->is_visible()) {
2780 /* we're already doing this */
2784 ResponseType r = (ResponseType) add_route_dialog->run ();
2786 add_route_dialog->hide();
2789 case RESPONSE_ACCEPT:
2796 if ((count = add_route_dialog->count()) <= 0) {
2800 uint32_t input_chan = add_route_dialog->channels ();
2801 uint32_t output_chan;
2802 string name_template = add_route_dialog->name_template ();
2803 bool track = add_route_dialog->track ();
2805 AutoConnectOption oac = Config->get_output_auto_connect();
2807 if (oac & AutoConnectMaster) {
2808 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2810 output_chan = input_chan;
2813 /* XXX do something with name template */
2815 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2818 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2820 session_add_audio_bus (input_chan, output_chan, count);
2825 ARDOUR_UI::mixer_settings () const
2830 node = session->instant_xml(X_("Mixer"), session->path());
2832 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2836 node = new XMLNode (X_("Mixer"));
2843 ARDOUR_UI::editor_settings () const
2848 node = session->instant_xml(X_("Editor"), session->path());
2850 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2854 node = new XMLNode (X_("Editor"));
2860 ARDOUR_UI::keyboard_settings () const
2864 node = Config->extra_xml(X_("Keyboard"));
2867 node = new XMLNode (X_("Keyboard"));
2873 ARDOUR_UI::create_xrun_marker(nframes_t where)
2875 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where));
2876 editor->mouse_add_new_marker (where, false, true);
2880 ARDOUR_UI::halt_on_xrun_message ()
2882 MessageDialog msg (*editor,
2883 _("Recording was stopped because your system could not keep up."));
2888 ARDOUR_UI::xrun_handler(nframes_t where)
2890 if (Config->get_create_xrun_marker() && session->actively_recording()) {
2891 create_xrun_marker(where);
2894 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2895 halt_on_xrun_message ();
2900 ARDOUR_UI::disk_overrun_handler ()
2902 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2904 if (!have_disk_speed_dialog_displayed) {
2905 have_disk_speed_dialog_displayed = true;
2906 MessageDialog* msg = new MessageDialog (*editor, _("\
2907 The disk system on your computer\n\
2908 was not able to keep up with Ardour.\n\
2910 Specifically, it failed to write data to disk\n\
2911 quickly enough to keep up with recording.\n"));
2912 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2918 ARDOUR_UI::disk_underrun_handler ()
2920 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2922 if (!have_disk_speed_dialog_displayed) {
2923 have_disk_speed_dialog_displayed = true;
2924 MessageDialog* msg = new MessageDialog (*editor,
2925 _("The disk system on your computer\n\
2926 was not able to keep up with Ardour.\n\
2928 Specifically, it failed to read data from disk\n\
2929 quickly enough to keep up with playback.\n"));
2930 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2936 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2938 have_disk_speed_dialog_displayed = false;
2943 ARDOUR_UI::session_dialog (std::string msg)
2945 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
2950 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
2952 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
2961 ARDOUR_UI::pending_state_dialog ()
2963 HBox* hbox = new HBox();
2964 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2965 ArdourDialog dialog (_("Crash Recovery"), true);
2967 This session appears to have been in\n\
2968 middle of recording when ardour or\n\
2969 the computer was shutdown.\n\
2971 Ardour can recover any captured audio for\n\
2972 you, or it can ignore it. Please decide\n\
2973 what you would like to do.\n"));
2974 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2975 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2976 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2977 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2978 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2979 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2980 dialog.set_default_response (RESPONSE_ACCEPT);
2981 dialog.set_position (WIN_POS_CENTER);
2986 switch (dialog.run ()) {
2987 case RESPONSE_ACCEPT:
2995 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
2997 HBox* hbox = new HBox();
2998 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2999 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3000 Label message (string_compose (_("\
3001 This session was created with a sample rate of %1 Hz\n\
3003 The audioengine is currently running at %2 Hz\n"), desired, actual));
3005 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3006 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3007 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3008 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3009 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3010 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3011 dialog.set_default_response (RESPONSE_ACCEPT);
3012 dialog.set_position (WIN_POS_CENTER);
3017 switch (dialog.run ()) {
3018 case RESPONSE_ACCEPT:
3027 ARDOUR_UI::disconnect_from_jack ()
3030 if( engine->disconnect_from_jack ()) {
3031 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3035 update_sample_rate (0);
3040 ARDOUR_UI::reconnect_to_jack ()
3043 if (engine->reconnect_to_jack ()) {
3044 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3048 update_sample_rate (0);
3053 ARDOUR_UI::use_config ()
3055 Glib::RefPtr<Action> act;
3057 switch (Config->get_native_file_data_format ()) {
3059 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3062 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3065 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3070 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3071 ract->set_active ();
3074 switch (Config->get_native_file_header_format ()) {
3076 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3079 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3082 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3085 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3088 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3091 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3094 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3099 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3100 ract->set_active ();
3103 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3105 set_transport_controllable_state (*node);
3110 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3112 if (Config->get_primary_clock_delta_edit_cursor()) {
3113 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3115 primary_clock.set (pos, 0, true);
3118 if (Config->get_secondary_clock_delta_edit_cursor()) {
3119 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3121 secondary_clock.set (pos);
3124 if (big_clock_window) {
3125 big_clock.set (pos);
3130 ARDOUR_UI::record_state_changed ()
3132 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3134 if (!session || !big_clock_window) {
3135 /* why bother - the clock isn't visible */
3139 switch (session->record_status()) {
3140 case Session::Recording:
3141 big_clock.set_widget_name ("BigClockRecording");
3144 big_clock.set_widget_name ("BigClockNonRecording");
3150 ARDOUR_UI::first_idle ()
3153 session->allow_auto_play (true);
3157 editor->first_idle();
3160 Keyboard::set_can_save_keybindings (true);
3165 ARDOUR_UI::store_clock_modes ()
3167 XMLNode* node = new XMLNode(X_("ClockModes"));
3169 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3170 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3173 session->add_extra_xml (*node);
3174 session->set_dirty ();
3179 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3180 : Controllable (name), ui (u), type(tp)
3186 ARDOUR_UI::TransportControllable::set_value (float val)
3188 if (type == ShuttleControl) {
3195 fract = -((0.5f - val)/0.5f);
3197 fract = ((val - 0.5f)/0.5f);
3201 ui.set_shuttle_fract (fract);
3206 /* do nothing: these are radio-style actions */
3210 const char *action = 0;
3214 action = X_("Roll");
3217 action = X_("Stop");
3220 action = X_("Goto Start");
3223 action = X_("Goto End");
3226 action = X_("Loop");
3229 action = X_("Play Selection");
3232 action = X_("Record");
3242 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3250 ARDOUR_UI::TransportControllable::get_value (void) const
3269 case ShuttleControl:
3279 ARDOUR_UI::TransportControllable::set_id (const string& str)
3285 ARDOUR_UI::setup_profile ()
3287 if (gdk_screen_width() < 1200) {
3288 Profile->set_small_screen ();
3291 if (getenv ("ARDOUR_SAE")) {
3292 Profile->set_sae ();
3293 Profile->set_single_package ();