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;
204 last_speed_displayed = -1.0f;
206 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
207 /* all changes go to the user directory */
208 user_keybindings_path = get_user_ardour_path ();
209 user_keybindings_path += '/';
210 user_keybindings_path += "ardour.bindings";
212 can_save_keybindings = false;
214 last_configure_time.tv_sec = 0;
215 last_configure_time.tv_usec = 0;
217 shuttle_grabbed = false;
219 shuttle_max_speed = 8.0f;
221 shuttle_style_menu = 0;
222 shuttle_unit_menu = 0;
224 gettimeofday (&last_peak_grab, 0);
225 gettimeofday (&last_shuttle_request, 0);
227 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
228 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
230 /* handle pending state with a dialog */
232 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
234 /* lets get this party started */
237 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
238 throw failed_constructor ();
241 setup_gtk_ardour_enums ();
242 Config->set_current_owner (ConfigVariableBase::Interface);
245 } catch (failed_constructor& err) {
246 error << _("could not initialize Ardour.") << endmsg;
251 /* we like keyboards */
253 keyboard = new Keyboard;
255 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
256 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
262 ARDOUR_UI::create_engine ()
264 // this gets called every time by new_session()
270 loading_message (_("Starting audio engine"));
273 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
280 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
281 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
282 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
283 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
291 ARDOUR_UI::post_engine ()
293 /* Things to be done once we create the AudioEngine
296 check_memory_locking();
298 ActionManager::init ();
301 if (setup_windows ()) {
302 throw failed_constructor ();
305 /* this is the first point at which all the keybindings are available */
307 if (ARDOUR_COMMAND_LINE::show_key_actions) {
308 vector<string> names;
309 vector<string> paths;
311 vector<AccelKey> bindings;
313 ActionManager::get_all_actions (names, paths, keys, bindings);
315 vector<string>::iterator n;
316 vector<string>::iterator k;
317 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
318 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
324 blink_timeout_tag = -1;
326 /* the global configuration object is now valid */
330 /* this being a GUI and all, we want peakfiles */
332 AudioFileSource::set_build_peakfiles (true);
333 AudioFileSource::set_build_missing_peakfiles (true);
335 /* set default clock modes */
337 primary_clock.set_mode (AudioClock::SMPTE);
338 secondary_clock.set_mode (AudioClock::BBT);
340 /* start the time-of-day-clock */
343 /* OS X provides an always visible wallclock, so don't be stupid */
344 update_wall_clock ();
345 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
348 update_disk_space ();
350 update_sample_rate (engine->frame_rate());
352 platform_specific ();
354 /* now start and maybe save state */
356 if (do_engine_start () == 0) {
357 if (session && _session_is_new) {
358 /* we need to retain initial visual
359 settings for a new session
361 session->save_state ("");
366 ARDOUR_UI::~ARDOUR_UI ()
368 save_ardour_state ();
382 if (add_route_dialog) {
383 delete add_route_dialog;
386 if (new_session_dialog) {
387 delete new_session_dialog;
392 ARDOUR_UI::configure_timeout ()
397 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
398 /* no configure events yet */
402 gettimeofday (&now, 0);
403 timersub (&now, &last_configure_time, &diff);
405 /* force a gap of 0.5 seconds since the last configure event
408 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
411 have_configure_timeout = false;
412 save_ardour_state ();
418 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
420 if (have_configure_timeout) {
421 gettimeofday (&last_configure_time, 0);
423 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
424 have_configure_timeout = true;
431 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
433 const XMLProperty* prop;
435 if ((prop = node.property ("roll")) != 0) {
436 roll_controllable.set_id (prop->value());
438 if ((prop = node.property ("stop")) != 0) {
439 stop_controllable.set_id (prop->value());
441 if ((prop = node.property ("goto_start")) != 0) {
442 goto_start_controllable.set_id (prop->value());
444 if ((prop = node.property ("goto_end")) != 0) {
445 goto_end_controllable.set_id (prop->value());
447 if ((prop = node.property ("auto_loop")) != 0) {
448 auto_loop_controllable.set_id (prop->value());
450 if ((prop = node.property ("play_selection")) != 0) {
451 play_selection_controllable.set_id (prop->value());
453 if ((prop = node.property ("rec")) != 0) {
454 rec_controllable.set_id (prop->value());
456 if ((prop = node.property ("shuttle")) != 0) {
457 shuttle_controllable.set_id (prop->value());
462 ARDOUR_UI::get_transport_controllable_state ()
464 XMLNode* node = new XMLNode(X_("TransportControllables"));
467 roll_controllable.id().print (buf, sizeof (buf));
468 node->add_property (X_("roll"), buf);
469 stop_controllable.id().print (buf, sizeof (buf));
470 node->add_property (X_("stop"), buf);
471 goto_start_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("goto_start"), buf);
473 goto_end_controllable.id().print (buf, sizeof (buf));
474 node->add_property (X_("goto_end"), buf);
475 auto_loop_controllable.id().print (buf, sizeof (buf));
476 node->add_property (X_("auto_loop"), buf);
477 play_selection_controllable.id().print (buf, sizeof (buf));
478 node->add_property (X_("play_selection"), buf);
479 rec_controllable.id().print (buf, sizeof (buf));
480 node->add_property (X_("rec"), buf);
481 shuttle_controllable.id().print (buf, sizeof (buf));
482 node->add_property (X_("shuttle"), buf);
488 ARDOUR_UI::save_ardour_state ()
490 if (!keyboard || !mixer || !editor) {
494 /* XXX this is all a bit dubious. add_extra_xml() uses
495 a different lifetime model from add_instant_xml().
498 XMLNode* node = new XMLNode (keyboard->get_state());
499 Config->add_extra_xml (*node);
500 Config->add_extra_xml (get_transport_controllable_state());
501 if (new_session_dialog) {
502 if (new_session_dialog->engine_control.was_used()) {
503 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
506 Config->save_state();
507 ui_config->save_state ();
509 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
510 XMLNode mnode(mixer->get_state());
513 session->add_instant_xml (enode, session->path());
514 session->add_instant_xml (mnode, session->path());
516 Config->add_instant_xml (enode, get_user_ardour_path());
517 Config->add_instant_xml (mnode, get_user_ardour_path());
524 ARDOUR_UI::autosave_session ()
526 if (!Config->get_periodic_safety_backups())
530 session->maybe_write_autosave();
537 ARDOUR_UI::update_autosave ()
539 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
541 if (session->dirty()) {
542 if (_autosave_connection.connected()) {
543 _autosave_connection.disconnect();
546 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
547 Config->get_periodic_safety_backup_interval() * 1000);
550 if (_autosave_connection.connected()) {
551 _autosave_connection.disconnect();
557 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
561 title = _("Ardour could not start JACK");
563 title = _("Ardour could not connect to JACK.");
566 MessageDialog win (title,
572 win.set_secondary_text(_("There are several possible reasons:\n\
574 1) You requested audio parameters that are not supported..\n\
575 2) JACK is running as another user.\n\
577 Please consider the possibilities, and perhaps try different parameters."));
579 win.set_secondary_text(_("There are several possible reasons:\n\
581 1) JACK is not running.\n\
582 2) JACK is running as another user, perhaps root.\n\
583 3) There is already another client called \"ardour\".\n\
585 Please consider the possibilities, and perhaps (re)start JACK."));
589 win.set_transient_for (*toplevel);
593 win.add_button (Stock::OK, RESPONSE_CLOSE);
595 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
598 win.set_default_response (RESPONSE_CLOSE);
601 win.set_position (Gtk::WIN_POS_CENTER);
605 /* we just don't care about the result, but we want to block */
611 ARDOUR_UI::startup ()
615 new_session_dialog = new NewSessionDialog();
617 bool backend_audio_is_running = EngineControl::engine_running();
618 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
621 new_session_dialog->engine_control.set_state (*audio_setup);
624 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
632 ARDOUR_UI::no_memory_warning ()
634 XMLNode node (X_("no-memory-warning"));
635 Config->add_instant_xml (node, get_user_ardour_path());
639 ARDOUR_UI::check_memory_locking ()
642 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
646 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
648 if (engine->is_realtime() && memory_warning_node == 0) {
650 struct rlimit limits;
652 long pages, page_size;
654 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
657 ram = (int64_t) pages * (int64_t) page_size;
660 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
664 if (limits.rlim_cur != RLIM_INFINITY) {
666 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
669 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
670 "This might cause Ardour to run out of memory before your system "
671 "runs out of memory. \n\n"
672 "You can view the memory limit with 'ulimit -l', "
673 "and it is normally controlled by /etc/security/limits.conf"));
675 VBox* vbox = msg.get_vbox();
677 CheckButton cb (_("Do not show this window again"));
679 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
681 hbox.pack_start (cb, true, false);
682 vbox->pack_start (hbox);
698 if (session->transport_rolling()) {
699 session->request_stop ();
703 if (session->dirty()) {
704 switch (ask_about_saving_session(_("quit"))) {
709 /* use the default name */
710 if (save_state_canfail ("")) {
711 /* failed - don't quit */
712 MessageDialog msg (*editor,
714 Ardour was unable to save your session.\n\n\
715 If you still wish to quit, please use the\n\n\
716 \"Just quit\" option."));
726 session->set_deletion_in_progress ();
730 save_ardour_state ();
735 ARDOUR_UI::ask_about_saving_session (const string & what)
737 ArdourDialog window (_("ardour: save session?"));
738 Gtk::HBox dhbox; // the hbox for the image and text
739 Gtk::Label prompt_label;
740 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
744 msg = string_compose(_("Don't %1"), what);
745 window.add_button (msg, RESPONSE_REJECT);
746 msg = string_compose(_("Just %1"), what);
747 window.add_button (msg, RESPONSE_APPLY);
748 msg = string_compose(_("Save and %1"), what);
749 window.add_button (msg, RESPONSE_ACCEPT);
751 window.set_default_response (RESPONSE_ACCEPT);
753 Gtk::Button noquit_button (msg);
754 noquit_button.set_name ("EditorGTKButton");
759 if (session->snap_name() == session->name()) {
762 type = _("snapshot");
764 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?"),
765 type, session->snap_name());
767 prompt_label.set_text (prompt);
768 prompt_label.set_name (X_("PrompterLabel"));
769 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
771 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
773 dhbox.set_homogeneous (false);
774 dhbox.pack_start (*dimage, false, false, 5);
775 dhbox.pack_start (prompt_label, true, false, 5);
776 window.get_vbox()->pack_start (dhbox);
778 window.set_name (_("Prompter"));
779 window.set_position (Gtk::WIN_POS_MOUSE);
780 window.set_modal (true);
781 window.set_resizable (false);
784 save_the_session = 0;
786 window.set_keep_above (true);
789 ResponseType r = (ResponseType) window.run();
794 case RESPONSE_ACCEPT: // save and get out of here
796 case RESPONSE_APPLY: // get out of here
806 ARDOUR_UI::every_second ()
809 update_buffer_load ();
810 update_disk_space ();
815 ARDOUR_UI::every_point_one_seconds ()
817 update_speed_display ();
818 RapidScreenUpdate(); /* EMIT_SIGNAL */
823 ARDOUR_UI::every_point_zero_one_seconds ()
825 // august 2007: actual update frequency: 40Hz, not 100Hz
827 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
832 ARDOUR_UI::update_sample_rate (nframes_t ignored)
836 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
838 if (!engine->connected()) {
840 snprintf (buf, sizeof (buf), _("disconnected"));
844 nframes_t rate = engine->frame_rate();
846 if (fmod (rate, 1000.0) != 0.0) {
847 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
848 (float) rate/1000.0f,
849 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
851 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
853 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
857 sample_rate_label.set_text (buf);
861 ARDOUR_UI::update_cpu_load ()
864 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
865 cpu_load_label.set_text (buf);
869 ARDOUR_UI::update_buffer_load ()
874 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
875 session->playback_load(), session->capture_load());
876 buffer_load_label.set_text (buf);
878 buffer_load_label.set_text ("");
883 ARDOUR_UI::count_recenabled_streams (Route& route)
885 Track* track = dynamic_cast<Track*>(&route);
886 if (track && track->diskstream()->record_enabled()) {
887 rec_enabled_streams += track->n_inputs();
892 ARDOUR_UI::update_disk_space()
898 nframes_t frames = session->available_capture_duration();
901 if (frames == max_frames) {
902 strcpy (buf, _("Disk: 24hrs+"));
907 nframes_t fr = session->frame_rate();
909 rec_enabled_streams = 0;
910 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
912 if (rec_enabled_streams) {
913 frames /= rec_enabled_streams;
916 hrs = frames / (fr * 3600);
917 frames -= hrs * fr * 3600;
918 mins = frames / (fr * 60);
919 frames -= mins * fr * 60;
922 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
925 disk_space_label.set_text (buf);
929 ARDOUR_UI::update_wall_clock ()
936 tm_now = localtime (&now);
938 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
939 wall_clock_label.set_text (buf);
945 ARDOUR_UI::session_menu (GdkEventButton *ev)
947 session_popup_menu->popup (0, 0);
952 ARDOUR_UI::redisplay_recent_sessions ()
954 vector<string *> *sessions;
955 vector<string *>::iterator i;
956 RecentSessionsSorter cmp;
958 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
959 recent_session_model->clear ();
962 ARDOUR::read_recent_sessions (rs);
965 recent_session_display.set_model (recent_session_model);
969 /* sort them alphabetically */
970 sort (rs.begin(), rs.end(), cmp);
971 sessions = new vector<string*>;
973 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
974 sessions->push_back (new string ((*i).second));
977 for (i = sessions->begin(); i != sessions->end(); ++i) {
979 vector<string*>* states;
980 vector<const gchar*> item;
981 string fullpath = *(*i);
983 /* remove any trailing / */
985 if (fullpath[fullpath.length()-1] == '/') {
986 fullpath = fullpath.substr (0, fullpath.length()-1);
989 /* now get available states for this session */
991 if ((states = Session::possible_states (fullpath)) == 0) {
996 TreeModel::Row row = *(recent_session_model->append());
998 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
999 row[recent_session_columns.fullpath] = fullpath;
1001 if (states->size() > 1) {
1003 /* add the children */
1005 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1007 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1009 child_row[recent_session_columns.visible_name] = **i2;
1010 child_row[recent_session_columns.fullpath] = fullpath;
1019 recent_session_display.set_model (recent_session_model);
1024 ARDOUR_UI::build_session_selector ()
1026 session_selector_window = new ArdourDialog ("session selector");
1028 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1030 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1031 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1032 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1033 recent_session_model = TreeStore::create (recent_session_columns);
1034 recent_session_display.set_model (recent_session_model);
1035 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1036 recent_session_display.set_headers_visible (false);
1037 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1038 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1040 scroller->add (recent_session_display);
1041 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1043 session_selector_window->set_name ("SessionSelectorWindow");
1044 session_selector_window->set_size_request (200, 400);
1045 session_selector_window->get_vbox()->pack_start (*scroller);
1046 session_selector_window->show_all_children();
1050 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1052 session_selector_window->response (RESPONSE_ACCEPT);
1056 ARDOUR_UI::open_recent_session ()
1058 bool can_return = (session != 0);
1060 if (session_selector_window == 0) {
1061 build_session_selector ();
1064 redisplay_recent_sessions ();
1068 session_selector_window->set_position (WIN_POS_MOUSE);
1070 ResponseType r = (ResponseType) session_selector_window->run ();
1073 case RESPONSE_ACCEPT:
1077 session_selector_window->hide();
1084 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1088 session_selector_window->hide();
1090 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1092 if (i == recent_session_model->children().end()) {
1096 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1097 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1099 _session_is_new = false;
1101 if (load_session (path, state) == 0) {
1110 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1112 struct stat statbuf;
1114 if (stat (info.filename.c_str(), &statbuf) != 0) {
1118 if (!S_ISDIR(statbuf.st_mode)) {
1124 string session_file = info.filename;
1125 session_file += '/';
1126 session_file += Glib::path_get_basename (info.filename);
1127 session_file += ".ardour";
1129 if (stat (session_file.c_str(), &statbuf) != 0) {
1133 return S_ISREG (statbuf.st_mode);
1137 ARDOUR_UI::check_audioengine ()
1140 if (!engine->connected()) {
1141 MessageDialog msg (_("Ardour is not connected to JACK\n"
1142 "You cannot open or close sessions in this condition"));
1153 ARDOUR_UI::open_session ()
1155 if (!check_audioengine()) {
1159 /* popup selector window */
1161 if (open_session_selector == 0) {
1163 /* ardour sessions are folders */
1165 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1166 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1167 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1168 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1170 FileFilter session_filter;
1171 session_filter.add_pattern ("*.ardour");
1172 session_filter.set_name (_("Ardour sessions"));
1173 open_session_selector->add_filter (session_filter);
1174 open_session_selector->set_filter (session_filter);
1177 int response = open_session_selector->run();
1178 open_session_selector->hide ();
1181 case RESPONSE_ACCEPT:
1184 open_session_selector->hide();
1188 open_session_selector->hide();
1189 string session_path = open_session_selector->get_filename();
1193 if (session_path.length() > 0) {
1194 if (Session::find_session (session_path, path, name, isnew) == 0) {
1195 _session_is_new = isnew;
1196 load_session (path, name);
1203 ARDOUR_UI::session_add_midi_track ()
1205 cerr << _("Patience is a virtue.\n");
1209 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1211 list<boost::shared_ptr<AudioTrack> > tracks;
1212 Session::RouteList routes;
1215 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1221 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1223 if (tracks.size() != how_many) {
1224 if (how_many == 1) {
1225 error << _("could not create a new audio track") << endmsg;
1227 error << string_compose (_("could only create %1 of %2 new audio %3"),
1228 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1234 routes = session->new_audio_route (input_channels, output_channels, how_many);
1236 if (routes.size() != how_many) {
1237 if (how_many == 1) {
1238 error << _("could not create a new audio track") << endmsg;
1240 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1246 if (need_control_room_outs) {
1252 route->set_stereo_control_outs (control_lr_channels);
1253 route->control_outs()->set_stereo_pan (pans, this);
1255 #endif /* CONTROLOUTS */
1259 MessageDialog msg (*editor,
1260 _("There are insufficient JACK ports available\n\
1261 to create a new track or bus.\n\
1262 You should save Ardour, exit and\n\
1263 restart JACK with more ports."));
1269 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1271 nframes_t _preroll = 0;
1274 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1275 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1277 if (new_position > _preroll) {
1278 new_position -= _preroll;
1283 session->request_locate (new_position);
1288 ARDOUR_UI::transport_goto_start ()
1291 session->goto_start();
1294 /* force displayed area in editor to start no matter
1295 what "follow playhead" setting is.
1299 editor->reset_x_origin (session->current_start_frame());
1305 ARDOUR_UI::transport_goto_zero ()
1308 session->request_locate (0);
1311 /* force displayed area in editor to start no matter
1312 what "follow playhead" setting is.
1316 editor->reset_x_origin (0);
1322 ARDOUR_UI::transport_goto_end ()
1325 nframes_t frame = session->current_end_frame();
1326 session->request_locate (frame);
1328 /* force displayed area in editor to start no matter
1329 what "follow playhead" setting is.
1333 editor->reset_x_origin (frame);
1339 ARDOUR_UI::transport_stop ()
1345 if (session->is_auditioning()) {
1346 session->cancel_audition ();
1350 if (session->get_play_loop ()) {
1351 session->request_play_loop (false);
1354 session->request_stop ();
1358 ARDOUR_UI::transport_stop_and_forget_capture ()
1361 session->request_stop (true);
1366 ARDOUR_UI::remove_last_capture()
1369 editor->remove_last_capture();
1374 ARDOUR_UI::transport_record (bool roll)
1377 switch (session->record_status()) {
1378 case Session::Disabled:
1379 if (session->ntracks() == 0) {
1380 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1384 session->maybe_enable_record ();
1389 case Session::Recording:
1391 session->request_stop();
1393 session->disable_record (false, true);
1397 case Session::Enabled:
1398 session->disable_record (false, true);
1404 ARDOUR_UI::transport_roll ()
1412 rolling = session->transport_rolling ();
1414 if (session->get_play_loop()) {
1415 session->request_play_loop (false);
1416 auto_loop_button.set_visual_state (1);
1417 roll_button.set_visual_state (1);
1418 } else if (session->get_play_range ()) {
1419 session->request_play_range (false);
1420 play_selection_button.set_visual_state (0);
1421 } else if (rolling) {
1422 session->request_locate (session->last_transport_start(), true);
1425 session->request_transport_speed (1.0f);
1429 ARDOUR_UI::transport_loop()
1432 if (session->get_play_loop()) {
1433 if (session->transport_rolling()) {
1434 Location * looploc = session->locations()->auto_loop_location();
1436 session->request_locate (looploc->start(), true);
1441 session->request_play_loop (true);
1447 ARDOUR_UI::transport_play_selection ()
1453 if (!session->get_play_range()) {
1454 session->request_stop ();
1457 editor->play_selection ();
1461 ARDOUR_UI::transport_rewind (int option)
1463 float current_transport_speed;
1466 current_transport_speed = session->transport_speed();
1468 if (current_transport_speed >= 0.0f) {
1471 session->request_transport_speed (-1.0f);
1474 session->request_transport_speed (-4.0f);
1477 session->request_transport_speed (-0.5f);
1482 session->request_transport_speed (current_transport_speed * 1.5f);
1488 ARDOUR_UI::transport_forward (int option)
1490 float current_transport_speed;
1493 current_transport_speed = session->transport_speed();
1495 if (current_transport_speed <= 0.0f) {
1498 session->request_transport_speed (1.0f);
1501 session->request_transport_speed (4.0f);
1504 session->request_transport_speed (0.5f);
1509 session->request_transport_speed (current_transport_speed * 1.5f);
1515 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1521 boost::shared_ptr<Route> r;
1523 if ((r = session->route_by_remote_id (dstream)) != 0) {
1527 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1528 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1537 ARDOUR_UI::queue_transport_change ()
1539 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1543 ARDOUR_UI::map_transport_state ()
1545 float sp = session->transport_speed();
1548 transport_rolling ();
1549 } else if (sp < 0.0f) {
1550 transport_rewinding ();
1551 } else if (sp > 0.0f) {
1552 transport_forwarding ();
1554 transport_stopped ();
1559 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1561 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1562 (int) adj.get_value()].c_str());
1566 ARDOUR_UI::engine_stopped ()
1568 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1569 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1570 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1574 ARDOUR_UI::engine_running ()
1576 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1577 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1578 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1580 Glib::RefPtr<Action> action;
1581 char* action_name = 0;
1583 switch (engine->frames_per_cycle()) {
1585 action_name = X_("JACKLatency32");
1588 action_name = X_("JACKLatency64");
1591 action_name = X_("JACKLatency128");
1594 action_name = X_("JACKLatency512");
1597 action_name = X_("JACKLatency1024");
1600 action_name = X_("JACKLatency2048");
1603 action_name = X_("JACKLatency4096");
1606 action_name = X_("JACKLatency8192");
1609 /* XXX can we do anything useful ? */
1615 action = ActionManager::get_action (X_("JACK"), action_name);
1618 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1619 ract->set_active ();
1625 ARDOUR_UI::engine_halted ()
1627 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1629 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1630 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1632 update_sample_rate (0);
1634 MessageDialog msg (*editor,
1636 JACK has either been shutdown or it\n\
1637 disconnected Ardour because Ardour\n\
1638 was not fast enough. You can save the\n\
1639 session and/or try to reconnect to JACK ."));
1644 ARDOUR_UI::do_engine_start ()
1652 error << _("Unable to start the session running")
1662 ARDOUR_UI::setup_theme ()
1664 theme_manager->setup_theme();
1668 ARDOUR_UI::update_clocks ()
1670 if (!editor || !editor->dragging_playhead()) {
1671 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1676 ARDOUR_UI::start_clocking ()
1678 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1682 ARDOUR_UI::stop_clocking ()
1684 clock_signal_connection.disconnect ();
1688 ARDOUR_UI::toggle_clocking ()
1691 if (clock_button.get_active()) {
1700 ARDOUR_UI::_blink (void *arg)
1703 ((ARDOUR_UI *) arg)->blink ();
1710 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1714 ARDOUR_UI::start_blinking ()
1716 /* Start the blink signal. Everybody with a blinking widget
1717 uses Blink to drive the widget's state.
1720 if (blink_timeout_tag < 0) {
1722 blink_timeout_tag = g_timeout_add (240, _blink, this);
1727 ARDOUR_UI::stop_blinking ()
1729 if (blink_timeout_tag >= 0) {
1730 g_source_remove (blink_timeout_tag);
1731 blink_timeout_tag = -1;
1736 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1742 if (io.n_inputs() == 0) {
1747 /* XXX we're not handling multiple ports yet. */
1749 const char **connections = io.input(0)->get_connections();
1751 if (connections == 0 || connections[0] == '\0') {
1754 buf = connections[0];
1761 if (io.n_outputs() == 0) {
1766 /* XXX we're not handling multiple ports yet. */
1768 const char **connections = io.output(0)->get_connections();
1770 if (connections == 0 || connections[0] == '\0') {
1773 buf = connections[0];
1780 /** Ask the user for the name of a new shapshot and then take it.
1783 ARDOUR_UI::snapshot_session ()
1785 ArdourPrompter prompter (true);
1789 struct tm local_time;
1792 localtime_r (&n, &local_time);
1793 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1795 prompter.set_name ("Prompter");
1796 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1797 prompter.set_prompt (_("Name of New Snapshot"));
1798 prompter.set_initial_text (timebuf);
1800 switch (prompter.run()) {
1801 case RESPONSE_ACCEPT:
1802 prompter.get_result (snapname);
1803 if (snapname.length()){
1804 save_state (snapname);
1814 ARDOUR_UI::save_state (const string & name)
1816 (void) save_state_canfail (name);
1820 ARDOUR_UI::save_state_canfail (string name)
1825 if (name.length() == 0) {
1826 name = session->snap_name();
1829 if ((ret = session->save_state (name)) != 0) {
1833 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1838 ARDOUR_UI::restore_state (string name)
1841 if (name.length() == 0) {
1842 name = session->name();
1844 session->restore_state (name);
1849 ARDOUR_UI::primary_clock_value_changed ()
1852 session->request_locate (primary_clock.current_time ());
1857 ARDOUR_UI::big_clock_value_changed ()
1860 session->request_locate (big_clock.current_time ());
1865 ARDOUR_UI::secondary_clock_value_changed ()
1868 session->request_locate (secondary_clock.current_time ());
1873 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1875 if (session && dstream && dstream->record_enabled()) {
1877 Session::RecordState rs;
1879 rs = session->record_status ();
1882 case Session::Disabled:
1883 case Session::Enabled:
1884 if (w->get_state() != STATE_SELECTED) {
1885 w->set_state (STATE_SELECTED);
1889 case Session::Recording:
1890 if (w->get_state() != STATE_ACTIVE) {
1891 w->set_state (STATE_ACTIVE);
1897 if (w->get_state() != STATE_NORMAL) {
1898 w->set_state (STATE_NORMAL);
1904 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1910 switch (session->record_status()) {
1911 case Session::Enabled:
1913 rec_button.set_visual_state (2);
1915 rec_button.set_visual_state (0);
1919 case Session::Recording:
1920 rec_button.set_visual_state (1);
1924 rec_button.set_visual_state (0);
1930 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1938 ARDOUR_UI::save_template ()
1941 ArdourPrompter prompter (true);
1944 if (!check_audioengine()) {
1948 prompter.set_name (X_("Prompter"));
1949 prompter.set_prompt (_("Name for mix template:"));
1950 prompter.set_initial_text(session->name() + _("-template"));
1951 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1953 switch (prompter.run()) {
1954 case RESPONSE_ACCEPT:
1955 prompter.get_result (name);
1957 if (name.length()) {
1958 session->save_template (name);
1968 ARDOUR_UI::fontconfig_dialog ()
1971 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1972 may not and it can take a while to build it. Warn them.
1975 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1977 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1978 MessageDialog msg (*new_session_dialog,
1979 _("Welcome to Ardour.\n\n"
1980 "The program will take a bit longer to start up\n"
1981 "while the system fonts are checked.\n\n"
1982 "This will only be done once, and you will\n"
1983 "not see this message again\n"),
1995 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
1997 existing_session = false;
1999 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2000 session_path = cmdline_path;
2001 existing_session = true;
2002 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2003 session_path = Glib::path_get_dirname (string (cmdline_path));
2004 existing_session = true;
2006 /* it doesn't exist, assume the best */
2007 session_path = Glib::path_get_dirname (string (cmdline_path));
2010 session_name = basename_nosuffix (string (cmdline_path));
2014 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2016 /* when this is called, the backend audio system must be running */
2018 /* the main idea here is to deal with the fact that a cmdline argument for the session
2019 can be interpreted in different ways - it could be a directory or a file, and before
2020 we load, we need to know both the session directory and the snapshot (statefile) within it
2021 that we are supposed to use.
2024 if (session_name.length() == 0 || session_path.length() == 0) {
2028 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2030 Glib::ustring predicted_session_file;
2032 predicted_session_file = session_path;
2033 predicted_session_file += '/';
2034 predicted_session_file += session_name;
2035 predicted_session_file += Session::statefile_suffix();
2037 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2038 existing_session = true;
2041 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2043 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2044 /* existing .ardour file */
2045 existing_session = true;
2049 existing_session = false;
2052 /* lets just try to load it */
2054 if (create_engine ()) {
2055 backend_audio_error (false, new_session_dialog);
2059 return load_session (session_path, session_name);
2063 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2065 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2067 MessageDialog msg (str,
2069 Gtk::MESSAGE_WARNING,
2070 Gtk::BUTTONS_YES_NO,
2074 msg.set_name (X_("CleanupDialog"));
2075 msg.set_wmclass (X_("existing_session"), "Ardour");
2076 msg.set_position (Gtk::WIN_POS_MOUSE);
2078 switch (msg.run()) {
2087 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2092 AutoConnectOption iconnect;
2093 AutoConnectOption oconnect;
2097 if (Profile->get_sae()) {
2101 iconnect = AutoConnectPhysical;
2102 oconnect = AutoConnectMaster;
2103 nphysin = 0; // use all available
2104 nphysout = 0; // use all available
2108 /* get settings from advanced section of NSD */
2110 if (new_session_dialog->create_control_bus()) {
2111 cchns = (uint32_t) new_session_dialog->control_channel_count();
2116 if (new_session_dialog->create_master_bus()) {
2117 mchns = (uint32_t) new_session_dialog->master_channel_count();
2122 if (new_session_dialog->connect_inputs()) {
2123 iconnect = AutoConnectPhysical;
2125 iconnect = AutoConnectOption (0);
2128 /// @todo some minor tweaks.
2130 if (new_session_dialog->connect_outs_to_master()) {
2131 oconnect = AutoConnectMaster;
2132 } else if (new_session_dialog->connect_outs_to_physical()) {
2133 oconnect = AutoConnectPhysical;
2135 oconnect = AutoConnectOption (0);
2138 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2139 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2142 if (build_session (session_path,
2150 engine->frame_rate() * 60 * 5)) {
2159 ARDOUR_UI::end_loading_messages ()
2165 ARDOUR_UI::loading_message (const std::string& msg)
2168 splash->message (msg);
2173 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2175 bool existing_session = false;
2176 Glib::ustring session_name;
2177 Glib::ustring session_path;
2178 Glib::ustring template_name;
2180 int response = Gtk::RESPONSE_NONE;
2182 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2184 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2186 /* don't ever reuse this */
2188 ARDOUR_COMMAND_LINE::session_name = string();
2190 if (existing_session && backend_audio_is_running) {
2192 /* just load the thing already */
2194 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2199 /* make the NSD use whatever information we have */
2201 new_session_dialog->set_session_name (session_name);
2202 new_session_dialog->set_session_folder (session_path);
2205 /* loading failed, or we need the NSD for something */
2207 new_session_dialog->set_modal (false);
2208 new_session_dialog->set_position (WIN_POS_CENTER);
2209 new_session_dialog->set_current_page (0);
2210 new_session_dialog->set_existing_session (existing_session);
2211 new_session_dialog->reset_recent();
2213 /* get this out of the way */
2218 new_session_dialog->set_have_engine (backend_audio_is_running);
2219 new_session_dialog->present ();
2220 end_loading_messages ();
2221 response = new_session_dialog->run ();
2223 _session_is_new = false;
2225 /* handle possible negative responses */
2228 case Gtk::RESPONSE_CANCEL:
2229 case Gtk::RESPONSE_DELETE_EVENT:
2233 new_session_dialog->hide ();
2236 case Gtk::RESPONSE_NONE:
2237 /* "Clear" was pressed */
2241 fontconfig_dialog();
2243 if (!backend_audio_is_running) {
2244 if (new_session_dialog->engine_control.setup_engine ()) {
2245 new_session_dialog->hide ();
2250 if (create_engine ()) {
2252 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2255 new_session_dialog->set_existing_session (false);
2256 new_session_dialog->set_current_page (2);
2258 response = Gtk::RESPONSE_NONE;
2262 backend_audio_is_running = true;
2264 if (response == Gtk::RESPONSE_OK) {
2266 session_name = new_session_dialog->session_name();
2268 if (session_name.empty()) {
2269 response = Gtk::RESPONSE_NONE;
2273 /* if the user mistakenly typed path information into the session filename entry,
2274 convert what they typed into a path & a name
2277 if (session_name[0] == '/' ||
2278 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2279 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2281 session_path = Glib::path_get_dirname (session_name);
2282 session_name = Glib::path_get_basename (session_name);
2286 session_path = new_session_dialog->session_folder();
2289 switch (new_session_dialog->which_page()) {
2291 case NewSessionDialog::OpenPage:
2292 case NewSessionDialog::EnginePage:
2296 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2298 should_be_new = true;
2300 //XXX This is needed because session constructor wants a
2301 //non-existant path. hopefully this will be fixed at some point.
2303 session_path = Glib::build_filename (session_path, session_name);
2305 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2307 if (ask_about_loading_existing_session (session_path)) {
2310 response = RESPONSE_NONE;
2315 _session_is_new = true;
2317 if (new_session_dialog->use_session_template()) {
2319 template_name = new_session_dialog->session_template_name();
2323 if (build_session_from_nsd (session_path, session_name)) {
2324 response = RESPONSE_NONE;
2336 new_session_dialog->hide ();
2338 if (load_session (session_path, session_name)) {
2340 response = Gtk::RESPONSE_NONE;
2344 if (response == Gtk::RESPONSE_NONE) {
2345 new_session_dialog->set_existing_session (false);
2346 new_session_dialog->reset ();
2350 } while (response == Gtk::RESPONSE_NONE);
2354 new_session_dialog->hide();
2355 new_session_dialog->reset();
2356 goto_editor_window ();
2361 ARDOUR_UI::close_session ()
2363 if (!check_audioengine()) {
2367 unload_session (true);
2369 get_session_parameters (true, false);
2373 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2375 Session *new_session;
2379 session_loaded = false;
2381 if (!check_audioengine()) {
2385 unload_status = unload_session ();
2387 if (unload_status < 0) {
2389 } else if (unload_status > 0) {
2394 /* if it already exists, we must have write access */
2396 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2397 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2398 "This prevents the session from being loaded."));
2403 loading_message (_("Please wait while Ardour loads your session"));
2404 disable_screen_updates ();
2407 new_session = new Session (*engine, path, snap_name, mix_template);
2410 /* this one is special */
2412 catch (AudioEngine::PortRegistrationFailure& err) {
2414 MessageDialog msg (err.what(),
2417 Gtk::BUTTONS_OK_CANCEL);
2419 msg.set_title (_("Loading Error"));
2420 msg.set_secondary_text (_("Click the OK button to try again."));
2421 msg.set_position (Gtk::WIN_POS_CENTER);
2424 int response = msg.run ();
2429 case RESPONSE_CANCEL:
2439 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
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:
2462 connect_to_session (new_session);
2464 Config->set_current_owner (ConfigVariableBase::Interface);
2466 session_loaded = true;
2468 goto_editor_window ();
2471 session->set_clean ();
2474 enable_screen_updates ();
2483 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2484 uint32_t control_channels,
2485 uint32_t master_channels,
2486 AutoConnectOption input_connect,
2487 AutoConnectOption output_connect,
2490 nframes_t initial_length)
2492 Session *new_session;
2495 if (!check_audioengine()) {
2499 session_loaded = false;
2501 x = unload_session ();
2509 _session_is_new = true;
2512 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2513 control_channels, master_channels, nphysin, nphysout, initial_length);
2518 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2523 connect_to_session (new_session);
2525 session_loaded = true;
2533 editor->show_window ();
2544 ARDOUR_UI::show_about ()
2548 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2555 ARDOUR_UI::hide_about ()
2558 about->get_window()->set_cursor ();
2564 ARDOUR_UI::about_signal_response(int response)
2570 ARDOUR_UI::show_splash ()
2574 splash = new Splash;
2581 splash->queue_draw ();
2582 splash->get_window()->process_updates (true);
2587 ARDOUR_UI::hide_splash ()
2595 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2599 removed = rep.paths.size();
2602 MessageDialog msgd (*editor,
2603 _("No audio files were ready for cleanup"),
2606 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2607 msgd.set_secondary_text (_("If this seems suprising, \n\
2608 check for any existing snapshots.\n\
2609 These may still include regions that\n\
2610 require some unused files to continue to exist."));
2616 ArdourDialog results (_("ardour: cleanup"), true, false);
2618 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2619 CleanupResultsModelColumns() {
2623 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2624 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2628 CleanupResultsModelColumns results_columns;
2629 Glib::RefPtr<Gtk::ListStore> results_model;
2630 Gtk::TreeView results_display;
2632 results_model = ListStore::create (results_columns);
2633 results_display.set_model (results_model);
2634 results_display.append_column (list_title, results_columns.visible_name);
2636 results_display.set_name ("CleanupResultsList");
2637 results_display.set_headers_visible (true);
2638 results_display.set_headers_clickable (false);
2639 results_display.set_reorderable (false);
2641 Gtk::ScrolledWindow list_scroller;
2644 Gtk::HBox dhbox; // the hbox for the image and text
2645 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2646 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2648 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2650 if (rep.space < 1048576.0f) {
2652 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2654 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2658 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2660 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2664 dhbox.pack_start (*dimage, true, false, 5);
2665 dhbox.pack_start (txt, true, false, 5);
2667 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2668 TreeModel::Row row = *(results_model->append());
2669 row[results_columns.visible_name] = *i;
2670 row[results_columns.fullpath] = *i;
2673 list_scroller.add (results_display);
2674 list_scroller.set_size_request (-1, 150);
2675 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2677 dvbox.pack_start (dhbox, true, false, 5);
2678 dvbox.pack_start (list_scroller, true, false, 5);
2679 ddhbox.pack_start (dvbox, true, false, 5);
2681 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2682 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2683 results.set_default_response (RESPONSE_CLOSE);
2684 results.set_position (Gtk::WIN_POS_MOUSE);
2685 results.show_all_children ();
2686 results.set_resizable (false);
2693 ARDOUR_UI::cleanup ()
2696 /* shouldn't happen: menu item is insensitive */
2701 MessageDialog checker (_("Are you sure you want to cleanup?"),
2703 Gtk::MESSAGE_QUESTION,
2704 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2706 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2707 ALL undo/redo information will be lost if you cleanup.\n\
2708 After cleanup, unused audio files will be moved to a \
2709 \"dead sounds\" location."));
2711 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2712 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2713 checker.set_default_response (RESPONSE_CANCEL);
2715 checker.set_name (_("CleanupDialog"));
2716 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2717 checker.set_position (Gtk::WIN_POS_MOUSE);
2719 switch (checker.run()) {
2720 case RESPONSE_ACCEPT:
2726 Session::cleanup_report rep;
2728 editor->prepare_for_cleanup ();
2730 /* do not allow flush until a session is reloaded */
2732 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2734 act->set_sensitive (false);
2737 if (session->cleanup_sources (rep)) {
2742 display_cleanup_results (rep,
2745 The following %1 %2 not in use and \n\
2746 have been moved to:\n\
2748 Flushing the wastebasket will \n\
2749 release an additional\n\
2750 %4 %5bytes of disk space.\n"
2758 ARDOUR_UI::flush_trash ()
2761 /* shouldn't happen: menu item is insensitive */
2765 Session::cleanup_report rep;
2767 if (session->cleanup_trash_sources (rep)) {
2771 display_cleanup_results (rep,
2773 _("The following %1 %2 deleted from\n\
2775 releasing %4 %5bytes of disk space"));
2779 ARDOUR_UI::add_route (Gtk::Window* float_window)
2787 if (add_route_dialog == 0) {
2788 add_route_dialog = new AddRouteDialog;
2790 add_route_dialog->set_transient_for (*float_window);
2794 if (add_route_dialog->is_visible()) {
2795 /* we're already doing this */
2799 ResponseType r = (ResponseType) add_route_dialog->run ();
2801 add_route_dialog->hide();
2804 case RESPONSE_ACCEPT:
2811 if ((count = add_route_dialog->count()) <= 0) {
2815 uint32_t input_chan = add_route_dialog->channels ();
2816 uint32_t output_chan;
2817 string name_template = add_route_dialog->name_template ();
2818 bool track = add_route_dialog->track ();
2820 AutoConnectOption oac = Config->get_output_auto_connect();
2822 if (oac & AutoConnectMaster) {
2823 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2825 output_chan = input_chan;
2828 /* XXX do something with name template */
2831 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2833 session_add_audio_bus (input_chan, output_chan, count);
2838 ARDOUR_UI::mixer_settings () const
2843 node = session->instant_xml(X_("Mixer"), session->path());
2845 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2849 node = new XMLNode (X_("Mixer"));
2856 ARDOUR_UI::editor_settings () const
2861 node = session->instant_xml(X_("Editor"), session->path());
2863 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2867 node = new XMLNode (X_("Editor"));
2873 ARDOUR_UI::keyboard_settings () const
2877 node = Config->extra_xml(X_("Keyboard"));
2880 node = new XMLNode (X_("Keyboard"));
2886 ARDOUR_UI::halt_on_xrun_message ()
2888 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2890 MessageDialog msg (*editor,
2891 _("Recording was stopped because your system could not keep up."));
2896 ARDOUR_UI::disk_overrun_handler ()
2898 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2900 if (!have_disk_speed_dialog_displayed) {
2901 have_disk_speed_dialog_displayed = true;
2902 MessageDialog* msg = new MessageDialog (*editor, _("\
2903 The disk system on your computer\n\
2904 was not able to keep up with Ardour.\n\
2906 Specifically, it failed to write data to disk\n\
2907 quickly enough to keep up with recording.\n"));
2908 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2914 ARDOUR_UI::disk_underrun_handler ()
2916 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2918 if (!have_disk_speed_dialog_displayed) {
2919 have_disk_speed_dialog_displayed = true;
2920 MessageDialog* msg = new MessageDialog (*editor,
2921 _("The disk system on your computer\n\
2922 was not able to keep up with Ardour.\n\
2924 Specifically, it failed to read data from disk\n\
2925 quickly enough to keep up with playback.\n"));
2926 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2932 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2934 have_disk_speed_dialog_displayed = false;
2939 ARDOUR_UI::pending_state_dialog ()
2941 HBox* hbox = new HBox();
2942 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2943 ArdourDialog dialog (_("Crash Recovery"), true);
2945 This session appears to have been in\n\
2946 middle of recording when ardour or\n\
2947 the computer was shutdown.\n\
2949 Ardour can recover any captured audio for\n\
2950 you, or it can ignore it. Please decide\n\
2951 what you would like to do.\n"));
2952 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2953 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2954 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2955 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2956 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2957 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2958 dialog.set_default_response (RESPONSE_ACCEPT);
2959 dialog.set_position (WIN_POS_CENTER);
2964 switch (dialog.run ()) {
2965 case RESPONSE_ACCEPT:
2973 ARDOUR_UI::disconnect_from_jack ()
2976 if( engine->disconnect_from_jack ()) {
2977 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2981 update_sample_rate (0);
2986 ARDOUR_UI::reconnect_to_jack ()
2989 if (engine->reconnect_to_jack ()) {
2990 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2994 update_sample_rate (0);
2999 ARDOUR_UI::use_config ()
3001 Glib::RefPtr<Action> act;
3003 switch (Config->get_native_file_data_format ()) {
3005 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3008 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3011 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3016 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3017 ract->set_active ();
3020 switch (Config->get_native_file_header_format ()) {
3022 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3025 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3028 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3031 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3034 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3037 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3040 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3045 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3046 ract->set_active ();
3049 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3051 set_transport_controllable_state (*node);
3056 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3058 if (Config->get_primary_clock_delta_edit_cursor()) {
3059 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3061 primary_clock.set (pos, 0, true);
3064 if (Config->get_secondary_clock_delta_edit_cursor()) {
3065 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3067 secondary_clock.set (pos);
3070 if (big_clock_window) {
3071 big_clock.set (pos);
3076 ARDOUR_UI::record_state_changed ()
3078 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3080 if (!session || !big_clock_window) {
3081 /* why bother - the clock isn't visible */
3085 switch (session->record_status()) {
3086 case Session::Recording:
3087 big_clock.set_widget_name ("BigClockRecording");
3090 big_clock.set_widget_name ("BigClockNonRecording");
3096 ARDOUR_UI::set_keybindings_path (string path)
3098 keybindings_path = path;
3102 ARDOUR_UI::save_keybindings ()
3104 if (can_save_keybindings) {
3105 AccelMap::save (user_keybindings_path);
3110 ARDOUR_UI::first_idle ()
3113 session->allow_auto_play (true);
3115 can_save_keybindings = true;
3120 ARDOUR_UI::store_clock_modes ()
3122 XMLNode* node = new XMLNode(X_("ClockModes"));
3124 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3125 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3128 session->add_extra_xml (*node);
3129 session->set_dirty ();
3134 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3135 : Controllable (name), ui (u), type(tp)
3141 ARDOUR_UI::TransportControllable::set_value (float val)
3143 if (type == ShuttleControl) {
3150 fract = -((0.5f - val)/0.5f);
3152 fract = ((val - 0.5f)/0.5f);
3156 ui.set_shuttle_fract (fract);
3161 /* do nothing: these are radio-style actions */
3169 action = X_("Roll");
3172 action = X_("Stop");
3175 action = X_("Goto Start");
3178 action = X_("Goto End");
3181 action = X_("Loop");
3184 action = X_("Play Selection");
3187 action = X_("Record");
3197 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3205 ARDOUR_UI::TransportControllable::get_value (void) const
3224 case ShuttleControl:
3234 ARDOUR_UI::TransportControllable::set_id (const string& str)
3240 ARDOUR_UI::setup_profile ()
3242 if (gdk_screen_width() < 1200) {
3243 Profile->set_small_screen ();
3246 if (getenv ("ARDOUR_SAE")) {
3247 Profile->set_sae ();
3248 Profile->set_single_package ();