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>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/audio_diskstream.h>
62 #include <ardour/audiofilesource.h>
63 #include <ardour/recent_sessions.h>
64 #include <ardour/port.h>
65 #include <ardour/audio_track.h>
68 #include "ardour_ui.h"
69 #include "public_editor.h"
70 #include "audio_clock.h"
75 #include "add_route_dialog.h"
76 #include "new_session_dialog.h"
80 #include "gui_thread.h"
81 #include "theme_manager.h"
82 #include "engine_dialog.h"
86 using namespace ARDOUR;
88 using namespace Gtkmm2ext;
92 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
93 UIConfiguration *ARDOUR_UI::ui_config = 0;
95 sigc::signal<void,bool> ARDOUR_UI::Blink;
96 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
97 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
98 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
100 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
102 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
104 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
105 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
106 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
107 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
111 adjuster_table (3, 3),
115 preroll_button (_("pre\nroll")),
116 postroll_button (_("post\nroll")),
120 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
124 roll_controllable ("transport roll", *this, TransportControllable::Roll),
125 stop_controllable ("transport stop", *this, TransportControllable::Stop),
126 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
127 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
128 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
129 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
130 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
131 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
132 shuttle_controller_binding_proxy (shuttle_controllable),
134 roll_button (roll_controllable),
135 stop_button (stop_controllable),
136 goto_start_button (goto_start_controllable),
137 goto_end_button (goto_end_controllable),
138 auto_loop_button (auto_loop_controllable),
139 play_selection_button (play_selection_controllable),
140 rec_button (rec_controllable),
142 shuttle_units_button (_("% ")),
144 punch_in_button (_("Punch In")),
145 punch_out_button (_("Punch Out")),
146 auto_return_button (_("Auto Return")),
147 auto_play_button (_("Auto Play")),
148 auto_input_button (_("Auto Input")),
149 click_button (_("Click")),
150 time_master_button (_("time\nmaster")),
152 auditioning_alert_button (_("AUDITION")),
153 solo_alert_button (_("SOLO")),
155 error_log_button (_("Errors"))
157 using namespace Gtk::Menu_Helpers;
162 _auto_display_errors = false;
165 if (getenv ("ARDOUR_DEBUG_UPDATES")) {
166 gdk_window_set_debug_updates (true);
172 if (ARDOUR_COMMAND_LINE::session_name.length()) {
173 /* only show this if we're not going to post the new session dialog */
177 if (theArdourUI == 0) {
181 ui_config = new UIConfiguration();
182 theme_manager = new ThemeManager();
188 _session_is_new = false;
189 big_clock_window = 0;
190 session_selector_window = 0;
191 new_session_dialog = 0;
192 last_key_press_time = 0;
193 connection_editor = 0;
194 add_route_dialog = 0;
199 open_session_selector = 0;
200 have_configure_timeout = false;
201 have_disk_speed_dialog_displayed = false;
202 _will_create_new_session_automatically = false;
203 session_loaded = false;
205 last_speed_displayed = -1.0f;
207 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
208 /* all changes go to the user directory */
209 user_keybindings_path = get_user_ardour_path ();
210 user_keybindings_path += '/';
211 user_keybindings_path += "ardour.bindings";
213 can_save_keybindings = false;
215 last_configure_time.tv_sec = 0;
216 last_configure_time.tv_usec = 0;
218 shuttle_grabbed = false;
220 shuttle_max_speed = 8.0f;
222 shuttle_style_menu = 0;
223 shuttle_unit_menu = 0;
225 gettimeofday (&last_peak_grab, 0);
226 gettimeofday (&last_shuttle_request, 0);
228 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
229 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
231 /* handle pending state with a dialog */
233 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
235 /* lets get this party started */
238 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
239 throw failed_constructor ();
242 setup_gtk_ardour_enums ();
243 Config->set_current_owner (ConfigVariableBase::Interface);
246 } catch (failed_constructor& err) {
247 error << _("could not initialize Ardour.") << endmsg;
252 /* we like keyboards */
254 keyboard = new Keyboard;
256 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
257 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
263 ARDOUR_UI::create_engine ()
265 // this gets called every time by new_session()
272 // OS X where everything is sllloooowwww
273 loading_dialog->set_message (_("Starting audio engine"));
274 loading_dialog->show_all ();
279 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
286 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
287 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
288 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
289 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
297 ARDOUR_UI::post_engine ()
299 /* Things to be done once we create the AudioEngine
302 check_memory_locking();
304 ActionManager::init ();
307 if (setup_windows ()) {
308 throw failed_constructor ();
311 /* this is the first point at which all the keybindings are available */
313 if (ARDOUR_COMMAND_LINE::show_key_actions) {
314 vector<string> names;
315 vector<string> paths;
317 vector<AccelKey> bindings;
319 ActionManager::get_all_actions (names, paths, keys, bindings);
321 vector<string>::iterator n;
322 vector<string>::iterator k;
323 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
324 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
330 blink_timeout_tag = -1;
332 /* the global configuration object is now valid */
336 /* this being a GUI and all, we want peakfiles */
338 AudioFileSource::set_build_peakfiles (true);
339 AudioFileSource::set_build_missing_peakfiles (true);
341 /* set default clock modes */
343 primary_clock.set_mode (AudioClock::SMPTE);
344 secondary_clock.set_mode (AudioClock::BBT);
346 /* start the time-of-day-clock */
349 /* OS X provides an always visible wallclock, so don't be stupid */
350 update_wall_clock ();
351 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
354 update_disk_space ();
356 update_sample_rate (engine->frame_rate());
358 platform_specific ();
360 /* now start and maybe save state */
362 if (do_engine_start () == 0) {
363 if (session && _session_is_new) {
364 /* we need to retain initial visual
365 settings for a new session
367 session->save_state ("");
372 ARDOUR_UI::~ARDOUR_UI ()
374 save_ardour_state ();
388 if (add_route_dialog) {
389 delete add_route_dialog;
392 if (new_session_dialog) {
393 delete new_session_dialog;
398 ARDOUR_UI::configure_timeout ()
403 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
404 /* no configure events yet */
408 gettimeofday (&now, 0);
409 timersub (&now, &last_configure_time, &diff);
411 /* force a gap of 0.5 seconds since the last configure event
414 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
417 have_configure_timeout = false;
418 save_ardour_state ();
424 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
426 if (have_configure_timeout) {
427 gettimeofday (&last_configure_time, 0);
429 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
430 have_configure_timeout = true;
437 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
439 const XMLProperty* prop;
441 if ((prop = node.property ("roll")) != 0) {
442 roll_controllable.set_id (prop->value());
444 if ((prop = node.property ("stop")) != 0) {
445 stop_controllable.set_id (prop->value());
447 if ((prop = node.property ("goto_start")) != 0) {
448 goto_start_controllable.set_id (prop->value());
450 if ((prop = node.property ("goto_end")) != 0) {
451 goto_end_controllable.set_id (prop->value());
453 if ((prop = node.property ("auto_loop")) != 0) {
454 auto_loop_controllable.set_id (prop->value());
456 if ((prop = node.property ("play_selection")) != 0) {
457 play_selection_controllable.set_id (prop->value());
459 if ((prop = node.property ("rec")) != 0) {
460 rec_controllable.set_id (prop->value());
462 if ((prop = node.property ("shuttle")) != 0) {
463 shuttle_controllable.set_id (prop->value());
468 ARDOUR_UI::get_transport_controllable_state ()
470 XMLNode* node = new XMLNode(X_("TransportControllables"));
473 roll_controllable.id().print (buf, sizeof (buf));
474 node->add_property (X_("roll"), buf);
475 stop_controllable.id().print (buf, sizeof (buf));
476 node->add_property (X_("stop"), buf);
477 goto_start_controllable.id().print (buf, sizeof (buf));
478 node->add_property (X_("goto_start"), buf);
479 goto_end_controllable.id().print (buf, sizeof (buf));
480 node->add_property (X_("goto_end"), buf);
481 auto_loop_controllable.id().print (buf, sizeof (buf));
482 node->add_property (X_("auto_loop"), buf);
483 play_selection_controllable.id().print (buf, sizeof (buf));
484 node->add_property (X_("play_selection"), buf);
485 rec_controllable.id().print (buf, sizeof (buf));
486 node->add_property (X_("rec"), buf);
487 shuttle_controllable.id().print (buf, sizeof (buf));
488 node->add_property (X_("shuttle"), buf);
494 ARDOUR_UI::save_ardour_state ()
496 if (!keyboard || !mixer || !editor) {
500 /* XXX this is all a bit dubious. add_extra_xml() uses
501 a different lifetime model from add_instant_xml().
504 XMLNode* node = new XMLNode (keyboard->get_state());
505 Config->add_extra_xml (*node);
506 Config->add_extra_xml (get_transport_controllable_state());
507 if (new_session_dialog) {
508 if (new_session_dialog->engine_control.was_used()) {
509 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
512 Config->save_state();
513 ui_config->save_state ();
515 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
516 XMLNode mnode(mixer->get_state());
519 session->add_instant_xml (enode, session->path());
520 session->add_instant_xml (mnode, session->path());
522 Config->add_instant_xml (enode, get_user_ardour_path());
523 Config->add_instant_xml (mnode, get_user_ardour_path());
530 ARDOUR_UI::autosave_session ()
532 if (!Config->get_periodic_safety_backups())
536 session->maybe_write_autosave();
543 ARDOUR_UI::update_autosave ()
545 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
547 if (session->dirty()) {
548 if (_autosave_connection.connected()) {
549 _autosave_connection.disconnect();
552 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
553 Config->get_periodic_safety_backup_interval() * 1000);
556 if (_autosave_connection.connected()) {
557 _autosave_connection.disconnect();
563 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
567 title = _("Ardour could not start JACK");
569 title = _("Ardour could not connect to JACK.");
572 MessageDialog win (title,
578 win.set_secondary_text(_("There are several possible reasons:\n\
580 1) You requested audio parameters that are not supported..\n\
581 2) JACK is running as another user.\n\
583 Please consider the possibilities, and perhaps try different parameters."));
585 win.set_secondary_text(_("There are several possible reasons:\n\
587 1) JACK is not running.\n\
588 2) JACK is running as another user, perhaps root.\n\
589 3) There is already another client called \"ardour\".\n\
591 Please consider the possibilities, and perhaps (re)start JACK."));
595 win.set_transient_for (*toplevel);
599 win.add_button (Stock::OK, RESPONSE_CLOSE);
601 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
604 win.set_default_response (RESPONSE_CLOSE);
607 win.set_position (Gtk::WIN_POS_CENTER);
611 /* we just don't care about the result, but we want to block */
617 _hide_splash (gpointer arg)
619 ((ARDOUR_UI*)arg)->hide_splash();
624 ARDOUR_UI::startup ()
628 new_session_dialog = new NewSessionDialog();
630 // in 4 seconds, hide the splash screen
632 Glib::signal_timeout().connect (bind (sigc::ptr_fun (_hide_splash), this), 4000);
634 bool backend_audio_is_running = EngineControl::engine_running();
635 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
638 new_session_dialog->engine_control.set_state (*audio_setup);
641 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
649 ARDOUR_UI::no_memory_warning ()
651 XMLNode node (X_("no-memory-warning"));
652 Config->add_instant_xml (node, get_user_ardour_path());
656 ARDOUR_UI::check_memory_locking ()
659 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
663 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
665 if (engine->is_realtime() && memory_warning_node == 0) {
667 struct rlimit limits;
669 long pages, page_size;
671 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
674 ram = (int64_t) pages * (int64_t) page_size;
677 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
681 if (limits.rlim_cur != RLIM_INFINITY) {
683 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
686 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
687 "This might cause Ardour to run out of memory before your system "
688 "runs out of memory. \n\n"
689 "You can view the memory limit with 'ulimit -l', "
690 "and it is normally controlled by /etc/security/limits.conf"));
692 VBox* vbox = msg.get_vbox();
694 CheckButton cb (_("Do not show this window again"));
696 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
698 hbox.pack_start (cb, true, false);
699 vbox->pack_start (hbox);
715 if (session->transport_rolling()) {
716 session->request_stop ();
720 if (session->dirty()) {
721 switch (ask_about_saving_session(_("quit"))) {
726 /* use the default name */
727 if (save_state_canfail ("")) {
728 /* failed - don't quit */
729 MessageDialog msg (*editor,
731 Ardour was unable to save your session.\n\n\
732 If you still wish to quit, please use the\n\n\
733 \"Just quit\" option."));
743 session->set_deletion_in_progress ();
747 save_ardour_state ();
752 ARDOUR_UI::ask_about_saving_session (const string & what)
754 ArdourDialog window (_("ardour: save session?"));
755 Gtk::HBox dhbox; // the hbox for the image and text
756 Gtk::Label prompt_label;
757 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
761 msg = string_compose(_("Don't %1"), what);
762 window.add_button (msg, RESPONSE_REJECT);
763 msg = string_compose(_("Just %1"), what);
764 window.add_button (msg, RESPONSE_APPLY);
765 msg = string_compose(_("Save and %1"), what);
766 window.add_button (msg, RESPONSE_ACCEPT);
768 window.set_default_response (RESPONSE_ACCEPT);
770 Gtk::Button noquit_button (msg);
771 noquit_button.set_name ("EditorGTKButton");
776 if (session->snap_name() == session->name()) {
779 type = _("snapshot");
781 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?"),
782 type, session->snap_name());
784 prompt_label.set_text (prompt);
785 prompt_label.set_name (X_("PrompterLabel"));
786 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
788 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
790 dhbox.set_homogeneous (false);
791 dhbox.pack_start (*dimage, false, false, 5);
792 dhbox.pack_start (prompt_label, true, false, 5);
793 window.get_vbox()->pack_start (dhbox);
795 window.set_name (_("Prompter"));
796 window.set_position (Gtk::WIN_POS_MOUSE);
797 window.set_modal (true);
798 window.set_resizable (false);
801 save_the_session = 0;
803 window.set_keep_above (true);
806 ResponseType r = (ResponseType) window.run();
811 case RESPONSE_ACCEPT: // save and get out of here
813 case RESPONSE_APPLY: // get out of here
823 ARDOUR_UI::every_second ()
826 update_buffer_load ();
827 update_disk_space ();
832 ARDOUR_UI::every_point_one_seconds ()
834 update_speed_display ();
835 RapidScreenUpdate(); /* EMIT_SIGNAL */
840 ARDOUR_UI::every_point_zero_one_seconds ()
842 // august 2007: actual update frequency: 40Hz, not 100Hz
844 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
849 ARDOUR_UI::update_sample_rate (nframes_t ignored)
853 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
855 if (!engine->connected()) {
857 snprintf (buf, sizeof (buf), _("disconnected"));
861 nframes_t rate = engine->frame_rate();
863 if (fmod (rate, 1000.0) != 0.0) {
864 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
865 (float) rate/1000.0f,
866 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
868 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
870 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
874 sample_rate_label.set_text (buf);
878 ARDOUR_UI::update_cpu_load ()
881 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
882 cpu_load_label.set_text (buf);
886 ARDOUR_UI::update_buffer_load ()
891 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
892 session->playback_load(), session->capture_load());
893 buffer_load_label.set_text (buf);
895 buffer_load_label.set_text ("");
900 ARDOUR_UI::count_recenabled_streams (Route& route)
902 Track* track = dynamic_cast<Track*>(&route);
903 if (track && track->diskstream()->record_enabled()) {
904 rec_enabled_streams += track->n_inputs();
909 ARDOUR_UI::update_disk_space()
915 nframes_t frames = session->available_capture_duration();
918 if (frames == max_frames) {
919 strcpy (buf, _("Disk: 24hrs+"));
924 nframes_t fr = session->frame_rate();
926 rec_enabled_streams = 0;
927 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
929 if (rec_enabled_streams) {
930 frames /= rec_enabled_streams;
933 hrs = frames / (fr * 3600);
934 frames -= hrs * fr * 3600;
935 mins = frames / (fr * 60);
936 frames -= mins * fr * 60;
939 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
942 disk_space_label.set_text (buf);
946 ARDOUR_UI::update_wall_clock ()
953 tm_now = localtime (&now);
955 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
956 wall_clock_label.set_text (buf);
962 ARDOUR_UI::session_menu (GdkEventButton *ev)
964 session_popup_menu->popup (0, 0);
969 ARDOUR_UI::redisplay_recent_sessions ()
971 vector<string *> *sessions;
972 vector<string *>::iterator i;
973 RecentSessionsSorter cmp;
975 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
976 recent_session_model->clear ();
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);
988 sessions = new vector<string*>;
990 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
991 sessions->push_back (new string ((*i).second));
994 for (i = sessions->begin(); i != sessions->end(); ++i) {
996 vector<string*>* states;
997 vector<const gchar*> item;
998 string fullpath = *(*i);
1000 /* remove any trailing / */
1002 if (fullpath[fullpath.length()-1] == '/') {
1003 fullpath = fullpath.substr (0, fullpath.length()-1);
1006 /* now get available states for this session */
1008 if ((states = Session::possible_states (fullpath)) == 0) {
1009 /* no state file? */
1013 TreeModel::Row row = *(recent_session_model->append());
1015 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1016 row[recent_session_columns.fullpath] = fullpath;
1018 if (states->size() > 1) {
1020 /* add the children */
1022 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1024 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;
1036 recent_session_display.set_model (recent_session_model);
1041 ARDOUR_UI::build_session_selector ()
1043 session_selector_window = new ArdourDialog ("session selector");
1045 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1047 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1048 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1049 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1050 recent_session_model = TreeStore::create (recent_session_columns);
1051 recent_session_display.set_model (recent_session_model);
1052 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1053 recent_session_display.set_headers_visible (false);
1054 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1055 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1057 scroller->add (recent_session_display);
1058 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1060 session_selector_window->set_name ("SessionSelectorWindow");
1061 session_selector_window->set_size_request (200, 400);
1062 session_selector_window->get_vbox()->pack_start (*scroller);
1063 session_selector_window->show_all_children();
1067 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1069 session_selector_window->response (RESPONSE_ACCEPT);
1073 ARDOUR_UI::open_recent_session ()
1075 bool can_return = (session != 0);
1077 if (session_selector_window == 0) {
1078 build_session_selector ();
1081 redisplay_recent_sessions ();
1085 session_selector_window->set_position (WIN_POS_MOUSE);
1087 ResponseType r = (ResponseType) session_selector_window->run ();
1090 case RESPONSE_ACCEPT:
1094 session_selector_window->hide();
1101 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1105 session_selector_window->hide();
1107 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1109 if (i == recent_session_model->children().end()) {
1113 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1114 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1116 _session_is_new = false;
1118 if (load_session (path, state) == 0) {
1127 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1129 struct stat statbuf;
1131 if (stat (info.filename.c_str(), &statbuf) != 0) {
1135 if (!S_ISDIR(statbuf.st_mode)) {
1141 string session_file = info.filename;
1142 session_file += '/';
1143 session_file += Glib::path_get_basename (info.filename);
1144 session_file += ".ardour";
1146 if (stat (session_file.c_str(), &statbuf) != 0) {
1150 return S_ISREG (statbuf.st_mode);
1154 ARDOUR_UI::check_audioengine ()
1157 if (!engine->connected()) {
1158 MessageDialog msg (_("Ardour is not connected to JACK\n"
1159 "You cannot open or close sessions in this condition"));
1170 ARDOUR_UI::open_session ()
1172 if (!check_audioengine()) {
1176 /* popup selector window */
1178 if (open_session_selector == 0) {
1180 /* ardour sessions are folders */
1182 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1183 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1184 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1185 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1187 FileFilter session_filter;
1188 session_filter.add_pattern ("*.ardour");
1189 session_filter.set_name (_("Ardour sessions"));
1190 open_session_selector->add_filter (session_filter);
1191 open_session_selector->set_filter (session_filter);
1194 int response = open_session_selector->run();
1195 open_session_selector->hide ();
1198 case RESPONSE_ACCEPT:
1201 open_session_selector->hide();
1205 open_session_selector->hide();
1206 string session_path = open_session_selector->get_filename();
1210 if (session_path.length() > 0) {
1211 if (Session::find_session (session_path, path, name, isnew) == 0) {
1212 _session_is_new = isnew;
1213 load_session (path, name);
1220 ARDOUR_UI::session_add_midi_track ()
1222 cerr << _("Patience is a virtue.\n");
1226 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1228 list<boost::shared_ptr<AudioTrack> > tracks;
1229 Session::RouteList routes;
1232 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1238 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1240 if (tracks.size() != how_many) {
1241 if (how_many == 1) {
1242 error << _("could not create a new audio track") << endmsg;
1244 error << string_compose (_("could only create %1 of %2 new audio %3"),
1245 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1251 routes = session->new_audio_route (input_channels, output_channels, how_many);
1253 if (routes.size() != how_many) {
1254 if (how_many == 1) {
1255 error << _("could not create a new audio track") << endmsg;
1257 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1263 if (need_control_room_outs) {
1269 route->set_stereo_control_outs (control_lr_channels);
1270 route->control_outs()->set_stereo_pan (pans, this);
1272 #endif /* CONTROLOUTS */
1276 MessageDialog msg (*editor,
1277 _("There are insufficient JACK ports available\n\
1278 to create a new track or bus.\n\
1279 You should save Ardour, exit and\n\
1280 restart JACK with more ports."));
1286 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1288 nframes_t _preroll = 0;
1291 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1292 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1294 if (new_position > _preroll) {
1295 new_position -= _preroll;
1300 session->request_locate (new_position);
1305 ARDOUR_UI::transport_goto_start ()
1308 session->goto_start();
1311 /* force displayed area in editor to start no matter
1312 what "follow playhead" setting is.
1316 editor->reset_x_origin (session->current_start_frame());
1322 ARDOUR_UI::transport_goto_zero ()
1325 session->request_locate (0);
1328 /* force displayed area in editor to start no matter
1329 what "follow playhead" setting is.
1333 editor->reset_x_origin (0);
1339 ARDOUR_UI::transport_goto_end ()
1342 nframes_t frame = session->current_end_frame();
1343 session->request_locate (frame);
1345 /* force displayed area in editor to start no matter
1346 what "follow playhead" setting is.
1350 editor->reset_x_origin (frame);
1356 ARDOUR_UI::transport_stop ()
1362 if (session->is_auditioning()) {
1363 session->cancel_audition ();
1367 if (session->get_play_loop ()) {
1368 session->request_play_loop (false);
1371 session->request_stop ();
1375 ARDOUR_UI::transport_stop_and_forget_capture ()
1378 session->request_stop (true);
1383 ARDOUR_UI::remove_last_capture()
1386 editor->remove_last_capture();
1391 ARDOUR_UI::transport_record (bool roll)
1394 switch (session->record_status()) {
1395 case Session::Disabled:
1396 if (session->ntracks() == 0) {
1397 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1401 session->maybe_enable_record ();
1406 case Session::Recording:
1408 session->request_stop();
1410 session->disable_record (false, true);
1414 case Session::Enabled:
1415 session->disable_record (false, true);
1421 ARDOUR_UI::transport_roll ()
1429 rolling = session->transport_rolling ();
1431 if (session->get_play_loop()) {
1432 session->request_play_loop (false);
1433 auto_loop_button.set_visual_state (1);
1434 roll_button.set_visual_state (1);
1435 } else if (session->get_play_range ()) {
1436 session->request_play_range (false);
1437 play_selection_button.set_visual_state (0);
1438 } else if (rolling) {
1439 session->request_locate (session->last_transport_start(), true);
1442 session->request_transport_speed (1.0f);
1446 ARDOUR_UI::transport_loop()
1449 if (session->get_play_loop()) {
1450 if (session->transport_rolling()) {
1451 Location * looploc = session->locations()->auto_loop_location();
1453 session->request_locate (looploc->start(), true);
1458 session->request_play_loop (true);
1464 ARDOUR_UI::transport_play_selection ()
1470 if (!session->get_play_range()) {
1471 session->request_stop ();
1474 editor->play_selection ();
1478 ARDOUR_UI::transport_rewind (int option)
1480 float current_transport_speed;
1483 current_transport_speed = session->transport_speed();
1485 if (current_transport_speed >= 0.0f) {
1488 session->request_transport_speed (-1.0f);
1491 session->request_transport_speed (-4.0f);
1494 session->request_transport_speed (-0.5f);
1499 session->request_transport_speed (current_transport_speed * 1.5f);
1505 ARDOUR_UI::transport_forward (int option)
1507 float current_transport_speed;
1510 current_transport_speed = session->transport_speed();
1512 if (current_transport_speed <= 0.0f) {
1515 session->request_transport_speed (1.0f);
1518 session->request_transport_speed (4.0f);
1521 session->request_transport_speed (0.5f);
1526 session->request_transport_speed (current_transport_speed * 1.5f);
1532 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1538 boost::shared_ptr<Route> r;
1540 if ((r = session->route_by_remote_id (dstream)) != 0) {
1544 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1545 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1554 ARDOUR_UI::queue_transport_change ()
1556 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1560 ARDOUR_UI::map_transport_state ()
1562 float sp = session->transport_speed();
1565 transport_rolling ();
1566 } else if (sp < 0.0f) {
1567 transport_rewinding ();
1568 } else if (sp > 0.0f) {
1569 transport_forwarding ();
1571 transport_stopped ();
1576 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1578 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1579 (int) adj.get_value()].c_str());
1583 ARDOUR_UI::engine_stopped ()
1585 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1586 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1587 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1591 ARDOUR_UI::engine_running ()
1593 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1594 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1595 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1597 Glib::RefPtr<Action> action;
1598 char* action_name = 0;
1600 switch (engine->frames_per_cycle()) {
1602 action_name = X_("JACKLatency32");
1605 action_name = X_("JACKLatency64");
1608 action_name = X_("JACKLatency128");
1611 action_name = X_("JACKLatency512");
1614 action_name = X_("JACKLatency1024");
1617 action_name = X_("JACKLatency2048");
1620 action_name = X_("JACKLatency4096");
1623 action_name = X_("JACKLatency8192");
1626 /* XXX can we do anything useful ? */
1632 action = ActionManager::get_action (X_("JACK"), action_name);
1635 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1636 ract->set_active ();
1642 ARDOUR_UI::engine_halted ()
1644 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1646 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1647 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1649 update_sample_rate (0);
1651 MessageDialog msg (*editor,
1653 JACK has either been shutdown or it\n\
1654 disconnected Ardour because Ardour\n\
1655 was not fast enough. You can save the\n\
1656 session and/or try to reconnect to JACK ."));
1661 ARDOUR_UI::do_engine_start ()
1669 error << _("Unable to start the session running")
1679 ARDOUR_UI::setup_theme ()
1681 theme_manager->setup_theme();
1685 ARDOUR_UI::update_clocks ()
1687 if (!editor || !editor->dragging_playhead()) {
1688 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1693 ARDOUR_UI::start_clocking ()
1695 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1699 ARDOUR_UI::stop_clocking ()
1701 clock_signal_connection.disconnect ();
1705 ARDOUR_UI::toggle_clocking ()
1708 if (clock_button.get_active()) {
1717 ARDOUR_UI::_blink (void *arg)
1720 ((ARDOUR_UI *) arg)->blink ();
1727 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1731 ARDOUR_UI::start_blinking ()
1733 /* Start the blink signal. Everybody with a blinking widget
1734 uses Blink to drive the widget's state.
1737 if (blink_timeout_tag < 0) {
1739 blink_timeout_tag = g_timeout_add (240, _blink, this);
1744 ARDOUR_UI::stop_blinking ()
1746 if (blink_timeout_tag >= 0) {
1747 g_source_remove (blink_timeout_tag);
1748 blink_timeout_tag = -1;
1753 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1759 if (io.n_inputs() == 0) {
1764 /* XXX we're not handling multiple ports yet. */
1766 const char **connections = io.input(0)->get_connections();
1768 if (connections == 0 || connections[0] == '\0') {
1771 buf = connections[0];
1778 if (io.n_outputs() == 0) {
1783 /* XXX we're not handling multiple ports yet. */
1785 const char **connections = io.output(0)->get_connections();
1787 if (connections == 0 || connections[0] == '\0') {
1790 buf = connections[0];
1797 /** Ask the user for the name of a new shapshot and then take it.
1800 ARDOUR_UI::snapshot_session ()
1802 ArdourPrompter prompter (true);
1806 struct tm local_time;
1809 localtime_r (&n, &local_time);
1810 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1812 prompter.set_name ("Prompter");
1813 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1814 prompter.set_prompt (_("Name of New Snapshot"));
1815 prompter.set_initial_text (timebuf);
1817 switch (prompter.run()) {
1818 case RESPONSE_ACCEPT:
1819 prompter.get_result (snapname);
1820 if (snapname.length()){
1821 save_state (snapname);
1831 ARDOUR_UI::save_state (const string & name)
1833 (void) save_state_canfail (name);
1837 ARDOUR_UI::save_state_canfail (string name)
1842 if (name.length() == 0) {
1843 name = session->snap_name();
1846 if ((ret = session->save_state (name)) != 0) {
1850 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1855 ARDOUR_UI::restore_state (string name)
1858 if (name.length() == 0) {
1859 name = session->name();
1861 session->restore_state (name);
1866 ARDOUR_UI::primary_clock_value_changed ()
1869 session->request_locate (primary_clock.current_time ());
1874 ARDOUR_UI::big_clock_value_changed ()
1877 session->request_locate (big_clock.current_time ());
1882 ARDOUR_UI::secondary_clock_value_changed ()
1885 session->request_locate (secondary_clock.current_time ());
1890 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1892 if (session && dstream && dstream->record_enabled()) {
1894 Session::RecordState rs;
1896 rs = session->record_status ();
1899 case Session::Disabled:
1900 case Session::Enabled:
1901 if (w->get_state() != STATE_SELECTED) {
1902 w->set_state (STATE_SELECTED);
1906 case Session::Recording:
1907 if (w->get_state() != STATE_ACTIVE) {
1908 w->set_state (STATE_ACTIVE);
1914 if (w->get_state() != STATE_NORMAL) {
1915 w->set_state (STATE_NORMAL);
1921 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1927 switch (session->record_status()) {
1928 case Session::Enabled:
1930 rec_button.set_visual_state (2);
1932 rec_button.set_visual_state (0);
1936 case Session::Recording:
1937 rec_button.set_visual_state (1);
1941 rec_button.set_visual_state (0);
1947 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1955 ARDOUR_UI::save_template ()
1958 ArdourPrompter prompter (true);
1961 if (!check_audioengine()) {
1965 prompter.set_name (X_("Prompter"));
1966 prompter.set_prompt (_("Name for mix template:"));
1967 prompter.set_initial_text(session->name() + _("-template"));
1968 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1970 switch (prompter.run()) {
1971 case RESPONSE_ACCEPT:
1972 prompter.get_result (name);
1974 if (name.length()) {
1975 session->save_template (name);
1985 ARDOUR_UI::fontconfig_dialog ()
1988 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1989 may not and it can take a while to build it. Warn them.
1992 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1994 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1995 MessageDialog msg (*new_session_dialog,
1996 _("Welcome to Ardour.\n\n"
1997 "The program will take a bit longer to start up\n"
1998 "while the system fonts are checked.\n\n"
1999 "This will only be done once, and you will\n"
2000 "not see this message again\n"),
2012 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2014 existing_session = false;
2016 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2017 session_path = cmdline_path;
2018 existing_session = true;
2019 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2020 session_path = Glib::path_get_dirname (string (cmdline_path));
2021 existing_session = true;
2023 /* it doesn't exist, assume the best */
2024 session_path = Glib::path_get_dirname (string (cmdline_path));
2027 session_name = basename_nosuffix (string (cmdline_path));
2031 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2033 /* when this is called, the backend audio system must be running */
2035 /* the main idea here is to deal with the fact that a cmdline argument for the session
2036 can be interpreted in different ways - it could be a directory or a file, and before
2037 we load, we need to know both the session directory and the snapshot (statefile) within it
2038 that we are supposed to use.
2041 if (session_name.length() == 0 || session_path.length() == 0) {
2045 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2047 Glib::ustring predicted_session_file;
2049 predicted_session_file = session_path;
2050 predicted_session_file += '/';
2051 predicted_session_file += session_name;
2052 predicted_session_file += Session::statefile_suffix();
2054 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2055 existing_session = true;
2058 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2060 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2061 /* existing .ardour file */
2062 existing_session = true;
2066 existing_session = false;
2069 /* lets just try to load it */
2071 if (create_engine ()) {
2073 loading_dialog->hide ();
2074 backend_audio_error (false, new_session_dialog);
2078 return load_session (session_path, session_name);
2082 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2084 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2086 MessageDialog msg (str,
2088 Gtk::MESSAGE_WARNING,
2089 Gtk::BUTTONS_YES_NO,
2093 msg.set_name (X_("CleanupDialog"));
2094 msg.set_wmclass (X_("existing_session"), "Ardour");
2095 msg.set_position (Gtk::WIN_POS_MOUSE);
2097 switch (msg.run()) {
2106 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2111 AutoConnectOption iconnect;
2112 AutoConnectOption oconnect;
2116 if (Profile->get_sae()) {
2120 iconnect = AutoConnectPhysical;
2121 oconnect = AutoConnectMaster;
2122 nphysin = 0; // use all available
2123 nphysout = 0; // use all available
2127 /* get settings from advanced section of NSD */
2129 if (new_session_dialog->create_control_bus()) {
2130 cchns = (uint32_t) new_session_dialog->control_channel_count();
2135 if (new_session_dialog->create_master_bus()) {
2136 mchns = (uint32_t) new_session_dialog->master_channel_count();
2141 if (new_session_dialog->connect_inputs()) {
2142 iconnect = AutoConnectPhysical;
2144 iconnect = AutoConnectOption (0);
2147 /// @todo some minor tweaks.
2149 if (new_session_dialog->connect_outs_to_master()) {
2150 oconnect = AutoConnectMaster;
2151 } else if (new_session_dialog->connect_outs_to_physical()) {
2152 oconnect = AutoConnectPhysical;
2154 oconnect = AutoConnectOption (0);
2157 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2158 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2161 if (build_session (session_path,
2169 engine->frame_rate() * 60 * 5)) {
2179 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2181 bool existing_session = false;
2182 Glib::ustring session_name;
2183 Glib::ustring session_path;
2184 Glib::ustring template_name;
2186 if (!loading_dialog) {
2187 loading_dialog = new MessageDialog (*new_session_dialog,
2194 int response = Gtk::RESPONSE_NONE;
2196 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2198 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2200 /* don't ever reuse this */
2202 ARDOUR_COMMAND_LINE::session_name = string();
2204 if (existing_session && backend_audio_is_running) {
2206 /* just load the thing already */
2208 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2213 /* make the NSD use whatever information we have */
2215 new_session_dialog->set_session_name (session_name);
2216 new_session_dialog->set_session_folder (session_path);
2219 /* loading failed, or we need the NSD for something */
2221 new_session_dialog->set_modal (false);
2222 new_session_dialog->set_position (WIN_POS_CENTER);
2223 new_session_dialog->set_current_page (0);
2224 new_session_dialog->set_existing_session (existing_session);
2225 new_session_dialog->reset_recent();
2227 /* get this out of the way */
2232 new_session_dialog->set_have_engine (backend_audio_is_running);
2233 new_session_dialog->present ();
2234 response = new_session_dialog->run ();
2235 loading_dialog->hide ();
2237 _session_is_new = false;
2239 /* handle possible negative responses */
2242 case Gtk::RESPONSE_CANCEL:
2243 case Gtk::RESPONSE_DELETE_EVENT:
2247 new_session_dialog->hide ();
2250 case Gtk::RESPONSE_NONE:
2251 /* "Clear" was pressed */
2255 fontconfig_dialog();
2257 if (!backend_audio_is_running) {
2258 if (new_session_dialog->engine_control.setup_engine ()) {
2259 new_session_dialog->hide ();
2264 if (create_engine ()) {
2266 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2267 loading_dialog->hide ();
2270 new_session_dialog->set_existing_session (false);
2271 new_session_dialog->set_current_page (2);
2273 response = Gtk::RESPONSE_NONE;
2277 loading_dialog->hide ();
2278 backend_audio_is_running = true;
2280 if (response == Gtk::RESPONSE_OK) {
2282 session_name = new_session_dialog->session_name();
2284 if (session_name.empty()) {
2285 response = Gtk::RESPONSE_NONE;
2289 /* if the user mistakenly typed path information into the session filename entry,
2290 convert what they typed into a path & a name
2293 if (session_name[0] == '/' ||
2294 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2295 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2297 session_path = Glib::path_get_dirname (session_name);
2298 session_name = Glib::path_get_basename (session_name);
2302 session_path = new_session_dialog->session_folder();
2305 switch (new_session_dialog->which_page()) {
2307 case NewSessionDialog::OpenPage:
2308 case NewSessionDialog::EnginePage:
2312 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2314 should_be_new = true;
2316 //XXX This is needed because session constructor wants a
2317 //non-existant path. hopefully this will be fixed at some point.
2319 session_path = Glib::build_filename (session_path, session_name);
2321 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2323 if (ask_about_loading_existing_session (session_path)) {
2326 response = RESPONSE_NONE;
2331 _session_is_new = true;
2333 if (new_session_dialog->use_session_template()) {
2335 template_name = new_session_dialog->session_template_name();
2339 if (build_session_from_nsd (session_path, session_name)) {
2340 response = RESPONSE_NONE;
2352 new_session_dialog->hide ();
2354 if (load_session (session_path, session_name)) {
2356 response = Gtk::RESPONSE_NONE;
2360 if (response == Gtk::RESPONSE_NONE) {
2361 loading_dialog->hide ();
2362 new_session_dialog->set_existing_session (false);
2363 new_session_dialog->reset ();
2367 } while (response == Gtk::RESPONSE_NONE);
2371 loading_dialog->hide ();
2372 new_session_dialog->hide();
2373 new_session_dialog->reset();
2374 goto_editor_window ();
2379 ARDOUR_UI::close_session ()
2381 if (!check_audioengine()) {
2385 unload_session (true);
2387 get_session_parameters (true, false);
2391 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2393 Session *new_session;
2397 session_loaded = false;
2399 if (!check_audioengine()) {
2403 unload_status = unload_session ();
2405 if (unload_status < 0) {
2407 } else if (unload_status > 0) {
2412 /* if it already exists, we must have write access */
2414 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2415 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2416 "This prevents the session from being loaded."));
2422 // OS X where everything is sllloooowwww
2423 if (loading_dialog) {
2424 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2429 disable_screen_updates ();
2432 new_session = new Session (*engine, path, snap_name, mix_template);
2435 /* this one is special */
2437 catch (AudioEngine::PortRegistrationFailure& err) {
2439 MessageDialog msg (err.what(),
2442 Gtk::BUTTONS_OK_CANCEL);
2444 msg.set_title (_("Loading Error"));
2445 msg.set_secondary_text (_("Click the OK button to try again."));
2446 msg.set_position (Gtk::WIN_POS_CENTER);
2449 int response = msg.run ();
2454 case RESPONSE_CANCEL:
2464 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2467 Gtk::BUTTONS_OK_CANCEL);
2469 msg.set_title (_("Loading Error"));
2470 msg.set_secondary_text (_("Click the OK button to try again."));
2471 msg.set_position (Gtk::WIN_POS_CENTER);
2474 int response = msg.run ();
2479 case RESPONSE_CANCEL:
2487 connect_to_session (new_session);
2489 Config->set_current_owner (ConfigVariableBase::Interface);
2491 session_loaded = true;
2493 goto_editor_window ();
2496 session->set_clean ();
2499 enable_screen_updates ();
2508 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2509 uint32_t control_channels,
2510 uint32_t master_channels,
2511 AutoConnectOption input_connect,
2512 AutoConnectOption output_connect,
2515 nframes_t initial_length)
2517 Session *new_session;
2520 if (!check_audioengine()) {
2524 session_loaded = false;
2526 x = unload_session ();
2534 _session_is_new = true;
2537 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2538 control_channels, master_channels, nphysin, nphysout, initial_length);
2543 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2548 connect_to_session (new_session);
2550 session_loaded = true;
2558 editor->show_window ();
2569 ARDOUR_UI::show_about ()
2573 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2580 ARDOUR_UI::hide_about ()
2583 about->get_window()->set_cursor ();
2589 ARDOUR_UI::about_signal_response(int response)
2595 ARDOUR_UI::show_splash ()
2599 splash = new Splash;
2606 splash->get_window()->process_updates (true);
2611 ARDOUR_UI::hide_splash ()
2619 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2623 removed = rep.paths.size();
2626 MessageDialog msgd (*editor,
2627 _("No audio files were ready for cleanup"),
2630 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2631 msgd.set_secondary_text (_("If this seems suprising, \n\
2632 check for any existing snapshots.\n\
2633 These may still include regions that\n\
2634 require some unused files to continue to exist."));
2640 ArdourDialog results (_("ardour: cleanup"), true, false);
2642 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2643 CleanupResultsModelColumns() {
2647 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2648 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2652 CleanupResultsModelColumns results_columns;
2653 Glib::RefPtr<Gtk::ListStore> results_model;
2654 Gtk::TreeView results_display;
2656 results_model = ListStore::create (results_columns);
2657 results_display.set_model (results_model);
2658 results_display.append_column (list_title, results_columns.visible_name);
2660 results_display.set_name ("CleanupResultsList");
2661 results_display.set_headers_visible (true);
2662 results_display.set_headers_clickable (false);
2663 results_display.set_reorderable (false);
2665 Gtk::ScrolledWindow list_scroller;
2668 Gtk::HBox dhbox; // the hbox for the image and text
2669 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2670 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2672 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2674 if (rep.space < 1048576.0f) {
2676 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2678 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2682 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2684 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2688 dhbox.pack_start (*dimage, true, false, 5);
2689 dhbox.pack_start (txt, true, false, 5);
2691 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2692 TreeModel::Row row = *(results_model->append());
2693 row[results_columns.visible_name] = *i;
2694 row[results_columns.fullpath] = *i;
2697 list_scroller.add (results_display);
2698 list_scroller.set_size_request (-1, 150);
2699 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2701 dvbox.pack_start (dhbox, true, false, 5);
2702 dvbox.pack_start (list_scroller, true, false, 5);
2703 ddhbox.pack_start (dvbox, true, false, 5);
2705 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2706 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2707 results.set_default_response (RESPONSE_CLOSE);
2708 results.set_position (Gtk::WIN_POS_MOUSE);
2709 results.show_all_children ();
2710 results.set_resizable (false);
2717 ARDOUR_UI::cleanup ()
2720 /* shouldn't happen: menu item is insensitive */
2725 MessageDialog checker (_("Are you sure you want to cleanup?"),
2727 Gtk::MESSAGE_QUESTION,
2728 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2730 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2731 ALL undo/redo information will be lost if you cleanup.\n\
2732 After cleanup, unused audio files will be moved to a \
2733 \"dead sounds\" location."));
2735 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2736 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2737 checker.set_default_response (RESPONSE_CANCEL);
2739 checker.set_name (_("CleanupDialog"));
2740 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2741 checker.set_position (Gtk::WIN_POS_MOUSE);
2743 switch (checker.run()) {
2744 case RESPONSE_ACCEPT:
2750 Session::cleanup_report rep;
2752 editor->prepare_for_cleanup ();
2754 /* do not allow flush until a session is reloaded */
2756 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2758 act->set_sensitive (false);
2761 if (session->cleanup_sources (rep)) {
2766 display_cleanup_results (rep,
2769 The following %1 %2 not in use and \n\
2770 have been moved to:\n\
2772 Flushing the wastebasket will \n\
2773 release an additional\n\
2774 %4 %5bytes of disk space.\n"
2782 ARDOUR_UI::flush_trash ()
2785 /* shouldn't happen: menu item is insensitive */
2789 Session::cleanup_report rep;
2791 if (session->cleanup_trash_sources (rep)) {
2795 display_cleanup_results (rep,
2797 _("The following %1 %2 deleted from\n\
2799 releasing %4 %5bytes of disk space"));
2803 ARDOUR_UI::add_route (Gtk::Window* float_window)
2811 if (add_route_dialog == 0) {
2812 add_route_dialog = new AddRouteDialog;
2814 add_route_dialog->set_transient_for (*float_window);
2818 if (add_route_dialog->is_visible()) {
2819 /* we're already doing this */
2823 ResponseType r = (ResponseType) add_route_dialog->run ();
2825 add_route_dialog->hide();
2828 case RESPONSE_ACCEPT:
2835 if ((count = add_route_dialog->count()) <= 0) {
2839 uint32_t input_chan = add_route_dialog->channels ();
2840 uint32_t output_chan;
2841 string name_template = add_route_dialog->name_template ();
2842 bool track = add_route_dialog->track ();
2844 AutoConnectOption oac = Config->get_output_auto_connect();
2846 if (oac & AutoConnectMaster) {
2847 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2849 output_chan = input_chan;
2852 /* XXX do something with name template */
2855 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2857 session_add_audio_bus (input_chan, output_chan, count);
2862 ARDOUR_UI::mixer_settings () const
2867 node = session->instant_xml(X_("Mixer"), session->path());
2869 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2873 node = new XMLNode (X_("Mixer"));
2880 ARDOUR_UI::editor_settings () const
2885 node = session->instant_xml(X_("Editor"), session->path());
2887 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2891 node = new XMLNode (X_("Editor"));
2897 ARDOUR_UI::keyboard_settings () const
2901 node = Config->extra_xml(X_("Keyboard"));
2904 node = new XMLNode (X_("Keyboard"));
2910 ARDOUR_UI::halt_on_xrun_message ()
2912 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2914 MessageDialog msg (*editor,
2915 _("Recording was stopped because your system could not keep up."));
2920 ARDOUR_UI::disk_overrun_handler ()
2922 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2924 if (!have_disk_speed_dialog_displayed) {
2925 have_disk_speed_dialog_displayed = true;
2926 MessageDialog* msg = new MessageDialog (*editor, _("\
2927 The disk system on your computer\n\
2928 was not able to keep up with Ardour.\n\
2930 Specifically, it failed to write data to disk\n\
2931 quickly enough to keep up with recording.\n"));
2932 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2938 ARDOUR_UI::disk_underrun_handler ()
2940 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2942 if (!have_disk_speed_dialog_displayed) {
2943 have_disk_speed_dialog_displayed = true;
2944 MessageDialog* msg = new MessageDialog (*editor,
2945 _("The disk system on your computer\n\
2946 was not able to keep up with Ardour.\n\
2948 Specifically, it failed to read data from disk\n\
2949 quickly enough to keep up with playback.\n"));
2950 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2956 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2958 have_disk_speed_dialog_displayed = false;
2963 ARDOUR_UI::pending_state_dialog ()
2965 HBox* hbox = new HBox();
2966 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2967 ArdourDialog dialog (_("Crash Recovery"), true);
2969 This session appears to have been in\n\
2970 middle of recording when ardour or\n\
2971 the computer was shutdown.\n\
2973 Ardour can recover any captured audio for\n\
2974 you, or it can ignore it. Please decide\n\
2975 what you would like to do.\n"));
2976 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2977 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2978 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2979 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2980 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2981 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2982 dialog.set_default_response (RESPONSE_ACCEPT);
2983 dialog.set_position (WIN_POS_CENTER);
2988 switch (dialog.run ()) {
2989 case RESPONSE_ACCEPT:
2997 ARDOUR_UI::disconnect_from_jack ()
3000 if( engine->disconnect_from_jack ()) {
3001 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3005 update_sample_rate (0);
3010 ARDOUR_UI::reconnect_to_jack ()
3013 if (engine->reconnect_to_jack ()) {
3014 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3018 update_sample_rate (0);
3023 ARDOUR_UI::use_config ()
3025 Glib::RefPtr<Action> act;
3027 switch (Config->get_native_file_data_format ()) {
3029 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3032 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3035 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3040 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3041 ract->set_active ();
3044 switch (Config->get_native_file_header_format ()) {
3046 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3049 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3052 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3055 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3058 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3061 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3064 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3069 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3070 ract->set_active ();
3073 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3075 set_transport_controllable_state (*node);
3080 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3082 if (Config->get_primary_clock_delta_edit_cursor()) {
3083 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3085 primary_clock.set (pos, 0, true);
3088 if (Config->get_secondary_clock_delta_edit_cursor()) {
3089 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3091 secondary_clock.set (pos);
3094 if (big_clock_window) {
3095 big_clock.set (pos);
3100 ARDOUR_UI::record_state_changed ()
3102 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3104 if (!session || !big_clock_window) {
3105 /* why bother - the clock isn't visible */
3109 switch (session->record_status()) {
3110 case Session::Recording:
3111 big_clock.set_widget_name ("BigClockRecording");
3114 big_clock.set_widget_name ("BigClockNonRecording");
3120 ARDOUR_UI::set_keybindings_path (string path)
3122 keybindings_path = path;
3126 ARDOUR_UI::save_keybindings ()
3128 if (can_save_keybindings) {
3129 AccelMap::save (user_keybindings_path);
3134 ARDOUR_UI::first_idle ()
3137 session->allow_auto_play (true);
3139 can_save_keybindings = true;
3144 ARDOUR_UI::store_clock_modes ()
3146 XMLNode* node = new XMLNode(X_("ClockModes"));
3148 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3149 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3152 session->add_extra_xml (*node);
3153 session->set_dirty ();
3158 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3159 : Controllable (name), ui (u), type(tp)
3165 ARDOUR_UI::TransportControllable::set_value (float val)
3167 if (type == ShuttleControl) {
3174 fract = -((0.5f - val)/0.5f);
3176 fract = ((val - 0.5f)/0.5f);
3180 ui.set_shuttle_fract (fract);
3185 /* do nothing: these are radio-style actions */
3193 action = X_("Roll");
3196 action = X_("Stop");
3199 action = X_("Goto Start");
3202 action = X_("Goto End");
3205 action = X_("Loop");
3208 action = X_("Play Selection");
3211 action = X_("Record");
3221 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3229 ARDOUR_UI::TransportControllable::get_value (void) const
3248 case ShuttleControl:
3258 ARDOUR_UI::TransportControllable::set_id (const string& str)
3264 ARDOUR_UI::setup_profile ()
3266 if (gdk_screen_width() < 1200) {
3267 Profile->set_small_screen ();
3270 if (getenv ("ARDOUR_SAE")) {
3271 Profile->set_sae ();
3272 Profile->set_single_package ();