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"
79 #include "gui_thread.h"
80 #include "theme_manager.h"
81 #include "engine_dialog.h"
85 using namespace ARDOUR;
87 using namespace Gtkmm2ext;
91 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
92 UIConfiguration *ARDOUR_UI::ui_config = 0;
94 sigc::signal<void,bool> ARDOUR_UI::Blink;
95 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
96 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
97 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
99 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
101 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
103 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
104 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
105 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
106 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
110 adjuster_table (3, 3),
114 preroll_button (_("pre\nroll")),
115 postroll_button (_("post\nroll")),
119 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
123 roll_controllable ("transport roll", *this, TransportControllable::Roll),
124 stop_controllable ("transport stop", *this, TransportControllable::Stop),
125 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
126 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
127 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
128 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
129 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
130 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
131 shuttle_controller_binding_proxy (shuttle_controllable),
133 roll_button (roll_controllable),
134 stop_button (stop_controllable),
135 goto_start_button (goto_start_controllable),
136 goto_end_button (goto_end_controllable),
137 auto_loop_button (auto_loop_controllable),
138 play_selection_button (play_selection_controllable),
139 rec_button (rec_controllable),
141 shuttle_units_button (_("% ")),
143 punch_in_button (_("Punch In")),
144 punch_out_button (_("Punch Out")),
145 auto_return_button (_("Auto Return")),
146 auto_play_button (_("Auto Play")),
147 auto_input_button (_("Auto Input")),
148 click_button (_("Click")),
149 time_master_button (_("time\nmaster")),
151 auditioning_alert_button (_("AUDITION")),
152 solo_alert_button (_("SOLO")),
154 error_log_button (_("Errors"))
156 using namespace Gtk::Menu_Helpers;
161 _auto_display_errors = false;
164 if (getenv ("ARDOUR_DEBUG_UPDATES")) {
165 gdk_window_set_debug_updates (true);
170 if (theArdourUI == 0) {
174 ui_config = new UIConfiguration();
175 theme_manager = new ThemeManager();
181 _session_is_new = false;
182 big_clock_window = 0;
183 session_selector_window = 0;
184 new_session_dialog = 0;
185 last_key_press_time = 0;
186 connection_editor = 0;
187 add_route_dialog = 0;
192 open_session_selector = 0;
193 have_configure_timeout = false;
194 have_disk_speed_dialog_displayed = false;
195 _will_create_new_session_automatically = false;
196 session_loaded = false;
198 last_speed_displayed = -1.0f;
200 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
201 /* all changes go to the user directory */
202 user_keybindings_path = get_user_ardour_path ();
203 user_keybindings_path += '/';
204 user_keybindings_path += "ardour.bindings";
206 can_save_keybindings = false;
208 last_configure_time.tv_sec = 0;
209 last_configure_time.tv_usec = 0;
211 shuttle_grabbed = false;
213 shuttle_max_speed = 8.0f;
215 shuttle_style_menu = 0;
216 shuttle_unit_menu = 0;
218 gettimeofday (&last_peak_grab, 0);
219 gettimeofday (&last_shuttle_request, 0);
221 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
222 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
224 /* handle pending state with a dialog */
226 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
228 /* lets get this party started */
231 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
232 setup_gtk_ardour_enums ();
233 Config->set_current_owner (ConfigVariableBase::Interface);
236 } catch (failed_constructor& err) {
237 error << _("could not initialize Ardour.") << endmsg;
242 /* we like keyboards */
244 keyboard = new Keyboard;
246 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
247 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
254 ARDOUR_UI::create_engine ()
256 // this gets called every time by new_session()
263 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
270 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
271 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
272 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
273 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
281 ARDOUR_UI::post_engine ()
283 /* Things to be done once we create the AudioEngine
286 check_memory_locking();
288 ActionManager::init ();
291 if (setup_windows ()) {
292 throw failed_constructor ();
295 /* this is the first point at which all the keybindings are available */
297 if (ARDOUR_COMMAND_LINE::show_key_actions) {
298 vector<string> names;
299 vector<string> paths;
301 vector<AccelKey> bindings;
303 ActionManager::get_all_actions (names, paths, keys, bindings);
305 vector<string>::iterator n;
306 vector<string>::iterator k;
307 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
308 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
314 blink_timeout_tag = -1;
316 /* the global configuration object is now valid */
320 /* this being a GUI and all, we want peakfiles */
322 AudioFileSource::set_build_peakfiles (true);
323 AudioFileSource::set_build_missing_peakfiles (true);
325 /* set default clock modes */
327 primary_clock.set_mode (AudioClock::SMPTE);
328 secondary_clock.set_mode (AudioClock::BBT);
330 /* start the time-of-day-clock */
333 /* OS X provides an always visible wallclock, so don't be stupid */
334 update_wall_clock ();
335 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
338 update_disk_space ();
340 update_sample_rate (engine->frame_rate());
342 platform_specific ();
344 /* now start and maybe save state */
346 if (do_engine_start () == 0) {
347 if (session && _session_is_new) {
348 /* we need to retain initial visual
349 settings for a new session
351 session->save_state ("");
356 ARDOUR_UI::~ARDOUR_UI ()
358 save_ardour_state ();
372 if (add_route_dialog) {
373 delete add_route_dialog;
376 if (new_session_dialog) {
377 delete new_session_dialog;
382 ARDOUR_UI::configure_timeout ()
387 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
388 /* no configure events yet */
392 gettimeofday (&now, 0);
393 timersub (&now, &last_configure_time, &diff);
395 /* force a gap of 0.5 seconds since the last configure event
398 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
401 have_configure_timeout = false;
402 save_ardour_state ();
408 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
410 if (have_configure_timeout) {
411 gettimeofday (&last_configure_time, 0);
413 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
414 have_configure_timeout = true;
421 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
423 const XMLProperty* prop;
425 if ((prop = node.property ("roll")) != 0) {
426 roll_controllable.set_id (prop->value());
428 if ((prop = node.property ("stop")) != 0) {
429 stop_controllable.set_id (prop->value());
431 if ((prop = node.property ("goto_start")) != 0) {
432 goto_start_controllable.set_id (prop->value());
434 if ((prop = node.property ("goto_end")) != 0) {
435 goto_end_controllable.set_id (prop->value());
437 if ((prop = node.property ("auto_loop")) != 0) {
438 auto_loop_controllable.set_id (prop->value());
440 if ((prop = node.property ("play_selection")) != 0) {
441 play_selection_controllable.set_id (prop->value());
443 if ((prop = node.property ("rec")) != 0) {
444 rec_controllable.set_id (prop->value());
446 if ((prop = node.property ("shuttle")) != 0) {
447 shuttle_controllable.set_id (prop->value());
452 ARDOUR_UI::get_transport_controllable_state ()
454 XMLNode* node = new XMLNode(X_("TransportControllables"));
457 roll_controllable.id().print (buf, sizeof (buf));
458 node->add_property (X_("roll"), buf);
459 stop_controllable.id().print (buf, sizeof (buf));
460 node->add_property (X_("stop"), buf);
461 goto_start_controllable.id().print (buf, sizeof (buf));
462 node->add_property (X_("goto_start"), buf);
463 goto_end_controllable.id().print (buf, sizeof (buf));
464 node->add_property (X_("goto_end"), buf);
465 auto_loop_controllable.id().print (buf, sizeof (buf));
466 node->add_property (X_("auto_loop"), buf);
467 play_selection_controllable.id().print (buf, sizeof (buf));
468 node->add_property (X_("play_selection"), buf);
469 rec_controllable.id().print (buf, sizeof (buf));
470 node->add_property (X_("rec"), buf);
471 shuttle_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("shuttle"), buf);
478 ARDOUR_UI::save_ardour_state ()
480 if (!keyboard || !mixer || !editor) {
484 /* XXX this is all a bit dubious. add_extra_xml() uses
485 a different lifetime model from add_instant_xml().
488 XMLNode* node = new XMLNode (keyboard->get_state());
489 Config->add_extra_xml (*node);
490 Config->add_extra_xml (get_transport_controllable_state());
491 if (new_session_dialog) {
492 if (new_session_dialog->engine_control.was_used()) {
493 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
496 Config->save_state();
497 ui_config->save_state ();
499 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
500 XMLNode mnode(mixer->get_state());
503 session->add_instant_xml (enode, session->path());
504 session->add_instant_xml (mnode, session->path());
506 Config->add_instant_xml (enode, get_user_ardour_path());
507 Config->add_instant_xml (mnode, get_user_ardour_path());
514 ARDOUR_UI::autosave_session ()
516 if (!Config->get_periodic_safety_backups())
520 session->maybe_write_autosave();
527 ARDOUR_UI::update_autosave ()
529 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
531 if (session->dirty()) {
532 if (_autosave_connection.connected()) {
533 _autosave_connection.disconnect();
536 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
537 Config->get_periodic_safety_backup_interval() * 1000);
540 if (_autosave_connection.connected()) {
541 _autosave_connection.disconnect();
547 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
551 title = _("Ardour could not start JACK");
553 title = _("Ardour could not connect to JACK.");
556 MessageDialog win (title,
562 win.set_secondary_text(_("There are several possible reasons:\n\
564 1) You requested audio parameters that are not supported..\n\
565 2) JACK is running as another user.\n\
567 Please consider the possibilities, and perhaps try different parameters."));
569 win.set_secondary_text(_("There are several possible reasons:\n\
571 1) JACK is not running.\n\
572 2) JACK is running as another user, perhaps root.\n\
573 3) There is already another client called \"ardour\".\n\
575 Please consider the possibilities, and perhaps (re)start JACK."));
579 win.set_transient_for (*toplevel);
583 win.add_button (Stock::OK, RESPONSE_CLOSE);
585 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
588 win.set_default_response (RESPONSE_CLOSE);
591 win.set_position (Gtk::WIN_POS_CENTER);
593 if (!ARDOUR_COMMAND_LINE::no_splash) {
597 /* we just don't care about the result, but we want to block */
603 ARDOUR_UI::startup ()
608 new_session_dialog = new NewSessionDialog();
610 /* If no session name is given: we're not loading a session yet, nor creating a new one */
612 if (ARDOUR_COMMAND_LINE::session_name.length()) {
614 /* Load session or start the new session dialog */
616 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
618 MessageDialog msg (string_compose(_("Could not find command line session \"%1\""),
619 ARDOUR_COMMAND_LINE::session_name),
624 msg.set_position (Gtk::WIN_POS_MOUSE);
631 if (!ARDOUR_COMMAND_LINE::new_session) {
633 /* Supposed to be loading an existing session, but the session doesn't exist */
636 MessageDialog msg (string_compose (_("\n\nNo session named \"%1\" exists.\n"
637 "To create it from the command line, start ardour as:\n ardour --new %1"), path),
642 msg.set_position (Gtk::WIN_POS_MOUSE);
653 bool have_backend = EngineControl::engine_running();
654 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
657 new_session_dialog->engine_control.set_state (*audio_setup);
660 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
668 ARDOUR_UI::no_memory_warning ()
670 XMLNode node (X_("no-memory-warning"));
671 Config->add_instant_xml (node, get_user_ardour_path());
675 ARDOUR_UI::check_memory_locking ()
678 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
682 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
684 if (engine->is_realtime() && memory_warning_node == 0) {
686 struct rlimit limits;
688 long pages, page_size;
690 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
693 ram = (int64_t) pages * (int64_t) page_size;
696 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
700 if (limits.rlim_cur != RLIM_INFINITY) {
702 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
705 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
706 "This might cause Ardour to run out of memory before your system "
707 "runs out of memory. \n\n"
708 "You can view the memory limit with 'ulimit -l', "
709 "and it is normally controlled by /etc/security/limits.conf"));
711 VBox* vbox = msg.get_vbox();
713 CheckButton cb (_("Do not show this window again"));
715 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
717 hbox.pack_start (cb, true, false);
718 vbox->pack_start (hbox);
734 if (session->transport_rolling()) {
735 session->request_stop ();
739 if (session->dirty()) {
740 switch (ask_about_saving_session(_("quit"))) {
745 /* use the default name */
746 if (save_state_canfail ("")) {
747 /* failed - don't quit */
748 MessageDialog msg (*editor,
750 Ardour was unable to save your session.\n\n\
751 If you still wish to quit, please use the\n\n\
752 \"Just quit\" option."));
762 session->set_deletion_in_progress ();
766 save_ardour_state ();
771 ARDOUR_UI::ask_about_saving_session (const string & what)
773 ArdourDialog window (_("ardour: save session?"));
774 Gtk::HBox dhbox; // the hbox for the image and text
775 Gtk::Label prompt_label;
776 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
780 msg = string_compose(_("Don't %1"), what);
781 window.add_button (msg, RESPONSE_REJECT);
782 msg = string_compose(_("Just %1"), what);
783 window.add_button (msg, RESPONSE_APPLY);
784 msg = string_compose(_("Save and %1"), what);
785 window.add_button (msg, RESPONSE_ACCEPT);
787 window.set_default_response (RESPONSE_ACCEPT);
789 Gtk::Button noquit_button (msg);
790 noquit_button.set_name ("EditorGTKButton");
795 if (session->snap_name() == session->name()) {
798 type = _("snapshot");
800 prompt = string_compose(_("The %1\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
801 type, session->snap_name());
803 prompt_label.set_text (prompt);
804 prompt_label.set_name (X_("PrompterLabel"));
805 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
807 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
809 dhbox.set_homogeneous (false);
810 dhbox.pack_start (*dimage, false, false, 5);
811 dhbox.pack_start (prompt_label, true, false, 5);
812 window.get_vbox()->pack_start (dhbox);
814 window.set_name (_("Prompter"));
815 window.set_position (Gtk::WIN_POS_MOUSE);
816 window.set_modal (true);
817 window.set_resizable (false);
820 save_the_session = 0;
822 window.set_keep_above (true);
825 ResponseType r = (ResponseType) window.run();
830 case RESPONSE_ACCEPT: // save and get out of here
832 case RESPONSE_APPLY: // get out of here
842 ARDOUR_UI::every_second ()
845 update_buffer_load ();
846 update_disk_space ();
851 ARDOUR_UI::every_point_one_seconds ()
853 update_speed_display ();
854 RapidScreenUpdate(); /* EMIT_SIGNAL */
859 ARDOUR_UI::every_point_zero_one_seconds ()
861 // august 2007: actual update frequency: 40Hz, not 100Hz
863 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::update_sample_rate (nframes_t ignored)
872 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
874 if (!engine->connected()) {
876 snprintf (buf, sizeof (buf), _("disconnected"));
880 nframes_t rate = engine->frame_rate();
882 if (fmod (rate, 1000.0) != 0.0) {
883 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
884 (float) rate/1000.0f,
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
887 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
893 sample_rate_label.set_text (buf);
897 ARDOUR_UI::update_cpu_load ()
900 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
901 cpu_load_label.set_text (buf);
905 ARDOUR_UI::update_buffer_load ()
910 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
911 session->playback_load(), session->capture_load());
912 buffer_load_label.set_text (buf);
914 buffer_load_label.set_text ("");
919 ARDOUR_UI::count_recenabled_streams (Route& route)
921 Track* track = dynamic_cast<Track*>(&route);
922 if (track && track->diskstream()->record_enabled()) {
923 rec_enabled_streams += track->n_inputs();
928 ARDOUR_UI::update_disk_space()
934 nframes_t frames = session->available_capture_duration();
937 if (frames == max_frames) {
938 strcpy (buf, _("Disk: 24hrs+"));
943 nframes_t fr = session->frame_rate();
945 rec_enabled_streams = 0;
946 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
948 if (rec_enabled_streams) {
949 frames /= rec_enabled_streams;
952 hrs = frames / (fr * 3600);
953 frames -= hrs * fr * 3600;
954 mins = frames / (fr * 60);
955 frames -= mins * fr * 60;
958 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
961 disk_space_label.set_text (buf);
965 ARDOUR_UI::update_wall_clock ()
972 tm_now = localtime (&now);
974 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
975 wall_clock_label.set_text (buf);
981 ARDOUR_UI::session_menu (GdkEventButton *ev)
983 session_popup_menu->popup (0, 0);
988 ARDOUR_UI::redisplay_recent_sessions ()
990 vector<string *> *sessions;
991 vector<string *>::iterator i;
992 RecentSessionsSorter cmp;
994 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
995 recent_session_model->clear ();
998 ARDOUR::read_recent_sessions (rs);
1001 recent_session_display.set_model (recent_session_model);
1005 /* sort them alphabetically */
1006 sort (rs.begin(), rs.end(), cmp);
1007 sessions = new vector<string*>;
1009 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1010 sessions->push_back (new string ((*i).second));
1013 for (i = sessions->begin(); i != sessions->end(); ++i) {
1015 vector<string*>* states;
1016 vector<const gchar*> item;
1017 string fullpath = *(*i);
1019 /* remove any trailing / */
1021 if (fullpath[fullpath.length()-1] == '/') {
1022 fullpath = fullpath.substr (0, fullpath.length()-1);
1025 /* now get available states for this session */
1027 if ((states = Session::possible_states (fullpath)) == 0) {
1028 /* no state file? */
1032 TreeModel::Row row = *(recent_session_model->append());
1034 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1035 row[recent_session_columns.fullpath] = fullpath;
1037 if (states->size() > 1) {
1039 /* add the children */
1041 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1043 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1045 child_row[recent_session_columns.visible_name] = **i2;
1046 child_row[recent_session_columns.fullpath] = fullpath;
1055 recent_session_display.set_model (recent_session_model);
1060 ARDOUR_UI::build_session_selector ()
1062 session_selector_window = new ArdourDialog ("session selector");
1064 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1066 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1067 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1068 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1069 recent_session_model = TreeStore::create (recent_session_columns);
1070 recent_session_display.set_model (recent_session_model);
1071 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1072 recent_session_display.set_headers_visible (false);
1073 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1074 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1076 scroller->add (recent_session_display);
1077 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1079 session_selector_window->set_name ("SessionSelectorWindow");
1080 session_selector_window->set_size_request (200, 400);
1081 session_selector_window->get_vbox()->pack_start (*scroller);
1082 session_selector_window->show_all_children();
1086 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1088 session_selector_window->response (RESPONSE_ACCEPT);
1092 ARDOUR_UI::open_recent_session ()
1094 bool can_return = (session != 0);
1096 if (session_selector_window == 0) {
1097 build_session_selector ();
1100 redisplay_recent_sessions ();
1104 session_selector_window->set_position (WIN_POS_MOUSE);
1106 ResponseType r = (ResponseType) session_selector_window->run ();
1109 case RESPONSE_ACCEPT:
1113 session_selector_window->hide();
1120 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1124 session_selector_window->hide();
1126 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1128 if (i == recent_session_model->children().end()) {
1132 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1133 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1135 _session_is_new = false;
1137 if (load_session (path, state) == 0) {
1146 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1148 struct stat statbuf;
1150 if (stat (info.filename.c_str(), &statbuf) != 0) {
1154 if (!S_ISDIR(statbuf.st_mode)) {
1160 string session_file = info.filename;
1161 session_file += '/';
1162 session_file += Glib::path_get_basename (info.filename);
1163 session_file += ".ardour";
1165 if (stat (session_file.c_str(), &statbuf) != 0) {
1169 return S_ISREG (statbuf.st_mode);
1173 ARDOUR_UI::check_audioengine ()
1176 if (!engine->connected()) {
1177 MessageDialog msg (_("Ardour is not connected to JACK\n"
1178 "You cannot open or close sessions in this condition"));
1189 ARDOUR_UI::open_session ()
1191 if (!check_audioengine()) {
1195 /* popup selector window */
1197 if (open_session_selector == 0) {
1199 /* ardour sessions are folders */
1201 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1202 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1203 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1204 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1206 FileFilter session_filter;
1207 session_filter.add_pattern ("*.ardour");
1208 session_filter.set_name (_("Ardour sessions"));
1209 open_session_selector->add_filter (session_filter);
1210 open_session_selector->set_filter (session_filter);
1213 int response = open_session_selector->run();
1214 open_session_selector->hide ();
1217 case RESPONSE_ACCEPT:
1220 open_session_selector->hide();
1224 open_session_selector->hide();
1225 string session_path = open_session_selector->get_filename();
1229 if (session_path.length() > 0) {
1230 if (Session::find_session (session_path, path, name, isnew) == 0) {
1231 _session_is_new = isnew;
1232 load_session (path, name);
1239 ARDOUR_UI::session_add_midi_track ()
1241 cerr << _("Patience is a virtue.\n");
1245 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1247 list<boost::shared_ptr<AudioTrack> > tracks;
1248 Session::RouteList routes;
1251 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1257 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1259 if (tracks.size() != how_many) {
1260 if (how_many == 1) {
1261 error << _("could not create a new audio track") << endmsg;
1263 error << string_compose (_("could only create %1 of %2 new audio %3"),
1264 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1270 routes = session->new_audio_route (input_channels, output_channels, how_many);
1272 if (routes.size() != how_many) {
1273 if (how_many == 1) {
1274 error << _("could not create a new audio track") << endmsg;
1276 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1282 if (need_control_room_outs) {
1288 route->set_stereo_control_outs (control_lr_channels);
1289 route->control_outs()->set_stereo_pan (pans, this);
1291 #endif /* CONTROLOUTS */
1295 cerr << "About to complain about JACK\n";
1296 MessageDialog msg (*editor,
1297 _("There are insufficient JACK ports available\n\
1298 to create a new track or bus.\n\
1299 You should save Ardour, exit and\n\
1300 restart JACK with more ports."));
1306 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1308 nframes_t _preroll = 0;
1311 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1312 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1314 if (new_position > _preroll) {
1315 new_position -= _preroll;
1320 session->request_locate (new_position);
1325 ARDOUR_UI::transport_goto_start ()
1328 session->goto_start();
1331 /* force displayed area in editor to start no matter
1332 what "follow playhead" setting is.
1336 editor->reset_x_origin (session->current_start_frame());
1342 ARDOUR_UI::transport_goto_zero ()
1345 session->request_locate (0);
1348 /* force displayed area in editor to start no matter
1349 what "follow playhead" setting is.
1353 editor->reset_x_origin (0);
1359 ARDOUR_UI::transport_goto_end ()
1362 nframes_t frame = session->current_end_frame();
1363 session->request_locate (frame);
1365 /* force displayed area in editor to start no matter
1366 what "follow playhead" setting is.
1370 editor->reset_x_origin (frame);
1376 ARDOUR_UI::transport_stop ()
1382 if (session->is_auditioning()) {
1383 session->cancel_audition ();
1387 if (session->get_play_loop ()) {
1388 session->request_play_loop (false);
1391 session->request_stop ();
1395 ARDOUR_UI::transport_stop_and_forget_capture ()
1398 session->request_stop (true);
1403 ARDOUR_UI::remove_last_capture()
1406 editor->remove_last_capture();
1411 ARDOUR_UI::transport_record (bool roll)
1414 switch (session->record_status()) {
1415 case Session::Disabled:
1416 if (session->ntracks() == 0) {
1417 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1421 session->maybe_enable_record ();
1426 case Session::Recording:
1428 session->request_stop();
1430 session->disable_record (false, true);
1434 case Session::Enabled:
1435 session->disable_record (false, true);
1441 ARDOUR_UI::transport_roll ()
1449 rolling = session->transport_rolling ();
1451 if (session->get_play_loop()) {
1452 session->request_play_loop (false);
1453 auto_loop_button.set_visual_state (1);
1454 roll_button.set_visual_state (1);
1455 } else if (session->get_play_range ()) {
1456 session->request_play_range (false);
1457 play_selection_button.set_visual_state (0);
1458 } else if (rolling) {
1459 session->request_locate (session->last_transport_start(), true);
1462 session->request_transport_speed (1.0f);
1466 ARDOUR_UI::transport_loop()
1469 if (session->get_play_loop()) {
1470 if (session->transport_rolling()) {
1471 Location * looploc = session->locations()->auto_loop_location();
1473 session->request_locate (looploc->start(), true);
1478 session->request_play_loop (true);
1484 ARDOUR_UI::transport_play_selection ()
1490 if (!session->get_play_range()) {
1491 session->request_stop ();
1494 editor->play_selection ();
1498 ARDOUR_UI::transport_rewind (int option)
1500 float current_transport_speed;
1503 current_transport_speed = session->transport_speed();
1505 if (current_transport_speed >= 0.0f) {
1508 session->request_transport_speed (-1.0f);
1511 session->request_transport_speed (-4.0f);
1514 session->request_transport_speed (-0.5f);
1519 session->request_transport_speed (current_transport_speed * 1.5f);
1525 ARDOUR_UI::transport_forward (int option)
1527 float current_transport_speed;
1530 current_transport_speed = session->transport_speed();
1532 if (current_transport_speed <= 0.0f) {
1535 session->request_transport_speed (1.0f);
1538 session->request_transport_speed (4.0f);
1541 session->request_transport_speed (0.5f);
1546 session->request_transport_speed (current_transport_speed * 1.5f);
1552 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1558 boost::shared_ptr<Route> r;
1560 if ((r = session->route_by_remote_id (dstream)) != 0) {
1564 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1565 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1574 ARDOUR_UI::queue_transport_change ()
1576 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1580 ARDOUR_UI::map_transport_state ()
1582 float sp = session->transport_speed();
1585 transport_rolling ();
1586 } else if (sp < 0.0f) {
1587 transport_rewinding ();
1588 } else if (sp > 0.0f) {
1589 transport_forwarding ();
1591 transport_stopped ();
1596 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1598 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1599 (int) adj.get_value()].c_str());
1603 ARDOUR_UI::engine_stopped ()
1605 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1606 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1607 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1611 ARDOUR_UI::engine_running ()
1613 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1614 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1615 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1617 Glib::RefPtr<Action> action;
1618 char* action_name = 0;
1620 switch (engine->frames_per_cycle()) {
1622 action_name = X_("JACKLatency32");
1625 action_name = X_("JACKLatency64");
1628 action_name = X_("JACKLatency128");
1631 action_name = X_("JACKLatency512");
1634 action_name = X_("JACKLatency1024");
1637 action_name = X_("JACKLatency2048");
1640 action_name = X_("JACKLatency4096");
1643 action_name = X_("JACKLatency8192");
1646 /* XXX can we do anything useful ? */
1652 action = ActionManager::get_action (X_("JACK"), action_name);
1655 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1656 ract->set_active ();
1662 ARDOUR_UI::engine_halted ()
1664 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1666 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1667 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1669 update_sample_rate (0);
1671 MessageDialog msg (*editor,
1673 JACK has either been shutdown or it\n\
1674 disconnected Ardour because Ardour\n\
1675 was not fast enough. You can save the\n\
1676 session and/or try to reconnect to JACK ."));
1681 ARDOUR_UI::do_engine_start ()
1689 error << _("Unable to start the session running")
1699 ARDOUR_UI::setup_theme ()
1701 theme_manager->setup_theme();
1705 ARDOUR_UI::update_clocks ()
1707 if (!editor || !editor->dragging_playhead()) {
1708 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1713 ARDOUR_UI::start_clocking ()
1715 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1719 ARDOUR_UI::stop_clocking ()
1721 clock_signal_connection.disconnect ();
1725 ARDOUR_UI::toggle_clocking ()
1728 if (clock_button.get_active()) {
1737 ARDOUR_UI::_blink (void *arg)
1740 ((ARDOUR_UI *) arg)->blink ();
1747 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1751 ARDOUR_UI::start_blinking ()
1753 /* Start the blink signal. Everybody with a blinking widget
1754 uses Blink to drive the widget's state.
1757 if (blink_timeout_tag < 0) {
1759 blink_timeout_tag = g_timeout_add (240, _blink, this);
1764 ARDOUR_UI::stop_blinking ()
1766 if (blink_timeout_tag >= 0) {
1767 g_source_remove (blink_timeout_tag);
1768 blink_timeout_tag = -1;
1773 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1779 if (io.n_inputs() == 0) {
1784 /* XXX we're not handling multiple ports yet. */
1786 const char **connections = io.input(0)->get_connections();
1788 if (connections == 0 || connections[0] == '\0') {
1791 buf = connections[0];
1798 if (io.n_outputs() == 0) {
1803 /* XXX we're not handling multiple ports yet. */
1805 const char **connections = io.output(0)->get_connections();
1807 if (connections == 0 || connections[0] == '\0') {
1810 buf = connections[0];
1817 /** Ask the user for the name of a new shapshot and then take it.
1820 ARDOUR_UI::snapshot_session ()
1822 ArdourPrompter prompter (true);
1826 struct tm local_time;
1829 localtime_r (&n, &local_time);
1830 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1832 prompter.set_name ("Prompter");
1833 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1834 prompter.set_prompt (_("Name of New Snapshot"));
1835 prompter.set_initial_text (timebuf);
1837 switch (prompter.run()) {
1838 case RESPONSE_ACCEPT:
1839 prompter.get_result (snapname);
1840 if (snapname.length()){
1841 save_state (snapname);
1851 ARDOUR_UI::save_state (const string & name)
1853 (void) save_state_canfail (name);
1857 ARDOUR_UI::save_state_canfail (string name)
1862 if (name.length() == 0) {
1863 name = session->snap_name();
1866 if ((ret = session->save_state (name)) != 0) {
1870 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1875 ARDOUR_UI::restore_state (string name)
1878 if (name.length() == 0) {
1879 name = session->name();
1881 session->restore_state (name);
1886 ARDOUR_UI::primary_clock_value_changed ()
1889 session->request_locate (primary_clock.current_time ());
1894 ARDOUR_UI::big_clock_value_changed ()
1897 session->request_locate (big_clock.current_time ());
1902 ARDOUR_UI::secondary_clock_value_changed ()
1905 session->request_locate (secondary_clock.current_time ());
1910 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1912 if (session && dstream && dstream->record_enabled()) {
1914 Session::RecordState rs;
1916 rs = session->record_status ();
1919 case Session::Disabled:
1920 case Session::Enabled:
1921 if (w->get_state() != STATE_SELECTED) {
1922 w->set_state (STATE_SELECTED);
1926 case Session::Recording:
1927 if (w->get_state() != STATE_ACTIVE) {
1928 w->set_state (STATE_ACTIVE);
1934 if (w->get_state() != STATE_NORMAL) {
1935 w->set_state (STATE_NORMAL);
1941 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1947 switch (session->record_status()) {
1948 case Session::Enabled:
1950 rec_button.set_visual_state (2);
1952 rec_button.set_visual_state (0);
1956 case Session::Recording:
1957 rec_button.set_visual_state (1);
1961 rec_button.set_visual_state (0);
1967 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1975 ARDOUR_UI::save_template ()
1978 ArdourPrompter prompter (true);
1981 if (!check_audioengine()) {
1985 prompter.set_name (X_("Prompter"));
1986 prompter.set_prompt (_("Name for mix template:"));
1987 prompter.set_initial_text(session->name() + _("-template"));
1988 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1990 switch (prompter.run()) {
1991 case RESPONSE_ACCEPT:
1992 prompter.get_result (name);
1994 if (name.length()) {
1995 session->save_template (name);
2005 ARDOUR_UI::fontconfig_dialog ()
2008 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2009 may not and it can take a while to build it. Warn them.
2012 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2014 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2015 MessageDialog msg (*new_session_dialog,
2016 _("Welcome to Ardour.\n\n"
2017 "The program will take a bit longer to start up\n"
2018 "while the system fonts are checked.\n\n"
2019 "This will only be done once, and you will\n"
2020 "not see this message again\n"),
2032 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2034 bool existing_session = false;
2035 Glib::ustring session_name;
2036 Glib::ustring session_path;
2037 Glib::ustring template_name;
2039 if (!loading_dialog) {
2040 loading_dialog = new MessageDialog (*new_session_dialog,
2048 int response = Gtk::RESPONSE_NONE;
2050 if (predetermined_path.length()) {
2052 /* before we start, lets see if the given path looks like
2053 an existing ardour session. if it does, skip the
2054 tabs that we don't need
2057 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2058 session_path = predetermined_path;
2059 existing_session = true;
2060 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_REGULAR)) {
2061 session_path = Glib::path_get_dirname (string (predetermined_path));
2062 existing_session = true;
2064 /* it doesn't exist, assume the best */
2065 session_path = Glib::path_get_dirname (string (predetermined_path));
2068 session_name = basename_nosuffix (string (predetermined_path));
2070 new_session_dialog->set_session_name (session_name);
2071 cerr << "set sF to " << session_path << endl;
2072 new_session_dialog->set_session_folder (session_path);
2073 new_session_dialog->set_modal (true);
2075 if (existing_session) {
2077 if (session_name.length() == 0 || session_path.length() == 0) {
2078 error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
2082 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2083 Glib::ustring predicted_session_file;
2085 predicted_session_file = predetermined_path;
2086 predicted_session_file += '/';
2087 predicted_session_file += session_name;
2088 predicted_session_file += Session::statefile_suffix();
2090 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2091 existing_session = true;
2094 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
2096 if (predetermined_path.find (Session::statefile_suffix()) == predetermined_path.length() - 7) {
2097 /* existing .ardour file */
2098 existing_session = true;
2101 existing_session = false;
2104 if (existing_session && have_engine) {
2105 /* lets just try to load it */
2107 loading_dialog->set_message (_("Starting audio engine"));
2108 loading_dialog->show_all ();
2111 if (create_engine ()) {
2112 backend_audio_error (!have_engine, new_session_dialog);
2113 loading_dialog->hide ();
2117 if (load_session (session_path, session_name) == 0) {
2124 /* loading failed, or we need the NSD for something */
2126 new_session_dialog->set_position (WIN_POS_CENTER);
2127 new_session_dialog->set_current_page (0);
2128 new_session_dialog->set_existing_session (existing_session);
2129 new_session_dialog->reset_recent();
2132 new_session_dialog->set_have_engine (have_engine);
2133 new_session_dialog->present ();
2134 response = new_session_dialog->run ();
2135 loading_dialog->hide ();
2137 _session_is_new = false;
2139 /* handle possible negative responses */
2141 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2146 new_session_dialog->hide ();
2149 } else if (response == Gtk::RESPONSE_NONE) {
2150 /* "Clear" was pressed */
2155 fontconfig_dialog();
2157 /* if we're here to help set up audio parameters this is where want to do that.
2161 if (new_session_dialog->engine_control.setup_engine ()) {
2162 new_session_dialog->hide ();
2166 loading_dialog->set_message (_("Starting audio engine"));
2167 loading_dialog->show_all ();
2171 if (create_engine ()) {
2172 backend_audio_error (!have_engine, new_session_dialog);
2173 loading_dialog->hide ();
2175 /* audio setup page */
2176 new_session_dialog->set_existing_session (false);
2177 new_session_dialog->set_current_page (2);
2178 response = Gtk::RESPONSE_NONE;
2182 loading_dialog->hide ();
2185 /* now handle possible affirmative responses */
2187 if (response == Gtk::RESPONSE_YES) {
2189 /* YES == OPEN from the session selector */
2191 session_name = new_session_dialog->session_name();
2193 if (session_name.empty()) {
2194 response = Gtk::RESPONSE_NONE;
2198 if (session_name[0] == '/' ||
2199 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2200 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2201 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2202 response = Gtk::RESPONSE_NONE;
2206 session_path = new_session_dialog->session_folder();
2207 if (load_session (session_path, session_name)) {
2208 response = Gtk::RESPONSE_NONE;
2213 } else if (response == Gtk::RESPONSE_OK) {
2215 /* OK == OPEN button */
2217 session_name = new_session_dialog->session_name();
2219 if (session_name.empty()) {
2220 response = Gtk::RESPONSE_NONE;
2224 switch (new_session_dialog->which_page()) {
2225 case NewSessionDialog::OpenPage:
2226 case NewSessionDialog::EnginePage:
2228 if (session_name[0] == '/' ||
2229 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2230 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2231 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2232 response = Gtk::RESPONSE_NONE;
2237 session_path = new_session_dialog->session_folder();
2238 if (load_session (session_path, session_name)) {
2239 response = Gtk::RESPONSE_NONE;
2245 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2247 cerr << "on page zero\n";
2249 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2250 should_be_new = true;
2253 /* handle what appear to be paths rather than just a name */
2255 if (session_name[0] == '/' ||
2256 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2257 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2259 session_path = Glib::path_get_dirname (session_name);
2260 session_name = Glib::path_get_basename (session_name);
2264 session_path = new_session_dialog->session_folder();
2268 //XXX This is needed because session constructor wants a
2269 //non-existant path. hopefully this will be fixed at some point.
2271 session_path = Glib::build_filename (session_path, session_name);
2273 if (!should_be_new) {
2275 if (load_session (session_path, session_name)) {
2276 response = Gtk::RESPONSE_NONE;
2280 continue; /* leaves while() loop because response != NONE */
2282 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2284 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2286 MessageDialog msg (str,
2288 Gtk::MESSAGE_WARNING,
2289 Gtk::BUTTONS_YES_NO,
2293 msg.set_name (X_("CleanupDialog"));
2294 msg.set_wmclass (X_("existing_session"), "Ardour");
2295 msg.set_position (Gtk::WIN_POS_MOUSE);
2297 switch (msg.run()) {
2299 new_session_dialog->hide ();
2300 goto_editor_window ();
2302 if (load_session (session_path, session_name)) {
2303 response = Gtk::RESPONSE_NONE;
2309 response = RESPONSE_NONE;
2310 new_session_dialog->reset ();
2311 new_session_dialog->set_existing_session (false);
2312 loading_dialog->hide ();
2317 _session_is_new = true;
2319 if (new_session_dialog->use_session_template()) {
2321 template_name = new_session_dialog->session_template_name();
2323 new_session_dialog->hide ();
2324 goto_editor_window ();
2327 if (load_session (session_path, session_name, template_name)) {
2328 response = Gtk::RESPONSE_NONE;
2337 AutoConnectOption iconnect;
2338 AutoConnectOption oconnect;
2342 if (Profile->get_sae()) {
2346 iconnect = AutoConnectPhysical;
2347 oconnect = AutoConnectMaster;
2348 nphysin = 0; // use all available
2349 nphysout = 0; // use all available
2353 /* get settings from advanced section of NSD */
2355 if (new_session_dialog->create_control_bus()) {
2356 cchns = (uint32_t) new_session_dialog->control_channel_count();
2361 if (new_session_dialog->create_master_bus()) {
2362 mchns = (uint32_t) new_session_dialog->master_channel_count();
2367 if (new_session_dialog->connect_inputs()) {
2368 iconnect = AutoConnectPhysical;
2370 iconnect = AutoConnectOption (0);
2373 /// @todo some minor tweaks.
2375 if (new_session_dialog->connect_outs_to_master()) {
2376 oconnect = AutoConnectMaster;
2377 } else if (new_session_dialog->connect_outs_to_physical()) {
2378 oconnect = AutoConnectPhysical;
2380 oconnect = AutoConnectOption (0);
2383 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2384 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2387 if (build_session (session_path,
2395 engine->frame_rate() * 60 * 5)) {
2397 response = Gtk::RESPONSE_NONE;
2401 new_session_dialog->hide ();
2402 goto_editor_window ();
2413 if (response == Gtk::RESPONSE_NONE) {
2414 loading_dialog->hide ();
2415 new_session_dialog->set_existing_session (false);
2416 new_session_dialog->reset ();
2419 } while (response == Gtk::RESPONSE_NONE);
2423 loading_dialog->hide ();
2424 new_session_dialog->hide();
2429 ARDOUR_UI::close_session ()
2431 if (!check_audioengine()) {
2435 unload_session (true);
2437 get_session_parameters ("", true, false);
2441 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2443 Session *new_session;
2447 session_loaded = false;
2449 if (!check_audioengine()) {
2453 unload_status = unload_session ();
2455 if (unload_status < 0) {
2457 } else if (unload_status > 0) {
2462 /* if it already exists, we must have write access */
2464 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2465 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2466 "This prevents the session from being loaded."));
2471 if (loading_dialog) {
2472 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2476 disable_screen_updates ();
2479 new_session = new Session (*engine, path, snap_name, mix_template);
2482 /* this one is special */
2484 catch (AudioEngine::PortRegistrationFailure& err) {
2486 MessageDialog msg (err.what(),
2489 Gtk::BUTTONS_OK_CANCEL);
2491 msg.set_title (_("Loading Error"));
2492 msg.set_secondary_text (_("Click the OK button to try again."));
2493 msg.set_position (Gtk::WIN_POS_CENTER);
2496 int response = msg.run ();
2501 case RESPONSE_CANCEL:
2511 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2514 Gtk::BUTTONS_OK_CANCEL);
2516 msg.set_title (_("Loading Error"));
2517 msg.set_secondary_text (_("Click the OK button to try again."));
2518 msg.set_position (Gtk::WIN_POS_CENTER);
2521 int response = msg.run ();
2526 case RESPONSE_CANCEL:
2534 connect_to_session (new_session);
2536 Config->set_current_owner (ConfigVariableBase::Interface);
2538 session_loaded = true;
2540 goto_editor_window ();
2543 session->set_clean ();
2546 enable_screen_updates ();
2555 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2556 uint32_t control_channels,
2557 uint32_t master_channels,
2558 AutoConnectOption input_connect,
2559 AutoConnectOption output_connect,
2562 nframes_t initial_length)
2564 Session *new_session;
2567 if (!check_audioengine()) {
2571 session_loaded = false;
2573 x = unload_session ();
2581 _session_is_new = true;
2584 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2585 control_channels, master_channels, nphysin, nphysout, initial_length);
2590 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2595 connect_to_session (new_session);
2597 session_loaded = true;
2605 editor->show_window ();
2616 ARDOUR_UI::show_splash ()
2619 about = new About();
2620 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2627 ARDOUR_UI::about_signal_response(int response)
2633 ARDOUR_UI::hide_splash ()
2636 about->get_window()->set_cursor ();
2642 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2646 removed = rep.paths.size();
2649 MessageDialog msgd (*editor,
2650 _("No audio files were ready for cleanup"),
2653 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2654 msgd.set_secondary_text (_("If this seems suprising, \n\
2655 check for any existing snapshots.\n\
2656 These may still include regions that\n\
2657 require some unused files to continue to exist."));
2663 ArdourDialog results (_("ardour: cleanup"), true, false);
2665 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2666 CleanupResultsModelColumns() {
2670 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2671 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2675 CleanupResultsModelColumns results_columns;
2676 Glib::RefPtr<Gtk::ListStore> results_model;
2677 Gtk::TreeView results_display;
2679 results_model = ListStore::create (results_columns);
2680 results_display.set_model (results_model);
2681 results_display.append_column (list_title, results_columns.visible_name);
2683 results_display.set_name ("CleanupResultsList");
2684 results_display.set_headers_visible (true);
2685 results_display.set_headers_clickable (false);
2686 results_display.set_reorderable (false);
2688 Gtk::ScrolledWindow list_scroller;
2691 Gtk::HBox dhbox; // the hbox for the image and text
2692 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2693 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2695 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2697 if (rep.space < 1048576.0f) {
2699 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2701 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2705 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2707 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2711 dhbox.pack_start (*dimage, true, false, 5);
2712 dhbox.pack_start (txt, true, false, 5);
2714 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2715 TreeModel::Row row = *(results_model->append());
2716 row[results_columns.visible_name] = *i;
2717 row[results_columns.fullpath] = *i;
2720 list_scroller.add (results_display);
2721 list_scroller.set_size_request (-1, 150);
2722 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2724 dvbox.pack_start (dhbox, true, false, 5);
2725 dvbox.pack_start (list_scroller, true, false, 5);
2726 ddhbox.pack_start (dvbox, true, false, 5);
2728 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2729 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2730 results.set_default_response (RESPONSE_CLOSE);
2731 results.set_position (Gtk::WIN_POS_MOUSE);
2732 results.show_all_children ();
2733 results.set_resizable (false);
2740 ARDOUR_UI::cleanup ()
2743 /* shouldn't happen: menu item is insensitive */
2748 MessageDialog checker (_("Are you sure you want to cleanup?"),
2750 Gtk::MESSAGE_QUESTION,
2751 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2753 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2754 ALL undo/redo information will be lost if you cleanup.\n\
2755 After cleanup, unused audio files will be moved to a \
2756 \"dead sounds\" location."));
2758 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2759 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2760 checker.set_default_response (RESPONSE_CANCEL);
2762 checker.set_name (_("CleanupDialog"));
2763 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2764 checker.set_position (Gtk::WIN_POS_MOUSE);
2766 switch (checker.run()) {
2767 case RESPONSE_ACCEPT:
2773 Session::cleanup_report rep;
2775 editor->prepare_for_cleanup ();
2777 /* do not allow flush until a session is reloaded */
2779 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2781 act->set_sensitive (false);
2784 if (session->cleanup_sources (rep)) {
2789 display_cleanup_results (rep,
2792 The following %1 %2 not in use and \n\
2793 have been moved to:\n\
2795 Flushing the wastebasket will \n\
2796 release an additional\n\
2797 %4 %5bytes of disk space.\n"
2805 ARDOUR_UI::flush_trash ()
2808 /* shouldn't happen: menu item is insensitive */
2812 Session::cleanup_report rep;
2814 if (session->cleanup_trash_sources (rep)) {
2818 display_cleanup_results (rep,
2820 _("The following %1 %2 deleted from\n\
2822 releasing %4 %5bytes of disk space"));
2826 ARDOUR_UI::add_route (Gtk::Window* float_window)
2834 if (add_route_dialog == 0) {
2835 add_route_dialog = new AddRouteDialog;
2837 add_route_dialog->set_transient_for (*float_window);
2841 if (add_route_dialog->is_visible()) {
2842 /* we're already doing this */
2846 ResponseType r = (ResponseType) add_route_dialog->run ();
2848 add_route_dialog->hide();
2851 case RESPONSE_ACCEPT:
2858 if ((count = add_route_dialog->count()) <= 0) {
2862 uint32_t input_chan = add_route_dialog->channels ();
2863 uint32_t output_chan;
2864 string name_template = add_route_dialog->name_template ();
2865 bool track = add_route_dialog->track ();
2867 AutoConnectOption oac = Config->get_output_auto_connect();
2869 if (oac & AutoConnectMaster) {
2870 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2872 output_chan = input_chan;
2875 /* XXX do something with name template */
2878 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2880 session_add_audio_bus (input_chan, output_chan, count);
2885 ARDOUR_UI::mixer_settings () const
2890 node = session->instant_xml(X_("Mixer"), session->path());
2892 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2896 node = new XMLNode (X_("Mixer"));
2903 ARDOUR_UI::editor_settings () const
2908 node = session->instant_xml(X_("Editor"), session->path());
2910 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2914 node = new XMLNode (X_("Editor"));
2920 ARDOUR_UI::keyboard_settings () const
2924 node = Config->extra_xml(X_("Keyboard"));
2927 node = new XMLNode (X_("Keyboard"));
2933 ARDOUR_UI::halt_on_xrun_message ()
2935 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2937 MessageDialog msg (*editor,
2938 _("Recording was stopped because your system could not keep up."));
2943 ARDOUR_UI::disk_overrun_handler ()
2945 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2947 if (!have_disk_speed_dialog_displayed) {
2948 have_disk_speed_dialog_displayed = true;
2949 MessageDialog* msg = new MessageDialog (*editor, _("\
2950 The disk system on your computer\n\
2951 was not able to keep up with Ardour.\n\
2953 Specifically, it failed to write data to disk\n\
2954 quickly enough to keep up with recording.\n"));
2955 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2961 ARDOUR_UI::disk_underrun_handler ()
2963 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2965 if (!have_disk_speed_dialog_displayed) {
2966 have_disk_speed_dialog_displayed = true;
2967 MessageDialog* msg = new MessageDialog (*editor,
2968 _("The disk system on your computer\n\
2969 was not able to keep up with Ardour.\n\
2971 Specifically, it failed to read data from disk\n\
2972 quickly enough to keep up with playback.\n"));
2973 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2979 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2981 have_disk_speed_dialog_displayed = false;
2986 ARDOUR_UI::pending_state_dialog ()
2988 HBox* hbox = new HBox();
2989 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2990 ArdourDialog dialog (_("Crash Recovery"), true);
2992 This session appears to have been in\n\
2993 middle of recording when ardour or\n\
2994 the computer was shutdown.\n\
2996 Ardour can recover any captured audio for\n\
2997 you, or it can ignore it. Please decide\n\
2998 what you would like to do.\n"));
2999 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3000 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3001 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3002 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3003 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3004 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3005 dialog.set_default_response (RESPONSE_ACCEPT);
3006 dialog.set_position (WIN_POS_CENTER);
3011 switch (dialog.run ()) {
3012 case RESPONSE_ACCEPT:
3020 ARDOUR_UI::disconnect_from_jack ()
3023 if( engine->disconnect_from_jack ()) {
3024 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3028 update_sample_rate (0);
3033 ARDOUR_UI::reconnect_to_jack ()
3036 if (engine->reconnect_to_jack ()) {
3037 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3041 update_sample_rate (0);
3046 ARDOUR_UI::cmdline_new_session (string path)
3048 if (path[0] != '/') {
3049 char buf[PATH_MAX+1];
3052 getcwd (buf, sizeof (buf));
3059 get_session_parameters (path, false, true);
3061 _will_create_new_session_automatically = false; /* done it */
3062 return FALSE; /* don't call it again */
3066 ARDOUR_UI::use_config ()
3068 Glib::RefPtr<Action> act;
3070 switch (Config->get_native_file_data_format ()) {
3072 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3075 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3078 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3083 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3084 ract->set_active ();
3087 switch (Config->get_native_file_header_format ()) {
3089 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3092 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3095 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3098 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3101 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3104 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3107 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3112 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3113 ract->set_active ();
3116 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3118 set_transport_controllable_state (*node);
3123 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3125 if (Config->get_primary_clock_delta_edit_cursor()) {
3126 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3128 primary_clock.set (pos, 0, true);
3131 if (Config->get_secondary_clock_delta_edit_cursor()) {
3132 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3134 secondary_clock.set (pos);
3137 if (big_clock_window) {
3138 big_clock.set (pos);
3143 ARDOUR_UI::record_state_changed ()
3145 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3147 if (!session || !big_clock_window) {
3148 /* why bother - the clock isn't visible */
3152 switch (session->record_status()) {
3153 case Session::Recording:
3154 big_clock.set_widget_name ("BigClockRecording");
3157 big_clock.set_widget_name ("BigClockNonRecording");
3163 ARDOUR_UI::set_keybindings_path (string path)
3165 keybindings_path = path;
3169 ARDOUR_UI::save_keybindings ()
3171 if (can_save_keybindings) {
3172 AccelMap::save (user_keybindings_path);
3177 ARDOUR_UI::first_idle ()
3180 session->allow_auto_play (true);
3182 can_save_keybindings = true;
3187 ARDOUR_UI::store_clock_modes ()
3189 XMLNode* node = new XMLNode(X_("ClockModes"));
3191 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3192 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3195 session->add_extra_xml (*node);
3196 session->set_dirty ();
3201 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3202 : Controllable (name), ui (u), type(tp)
3208 ARDOUR_UI::TransportControllable::set_value (float val)
3210 if (type == ShuttleControl) {
3217 fract = -((0.5f - val)/0.5f);
3219 fract = ((val - 0.5f)/0.5f);
3223 ui.set_shuttle_fract (fract);
3228 /* do nothing: these are radio-style actions */
3236 action = X_("Roll");
3239 action = X_("Stop");
3242 action = X_("Goto Start");
3245 action = X_("Goto End");
3248 action = X_("Loop");
3251 action = X_("Play Selection");
3254 action = X_("Record");
3264 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3272 ARDOUR_UI::TransportControllable::get_value (void) const
3291 case ShuttleControl:
3301 ARDOUR_UI::TransportControllable::set_id (const string& str)
3307 ARDOUR_UI::setup_profile ()
3309 if (gdk_screen_width() < 1200) {
3310 Profile->set_small_screen ();
3313 if (getenv ("ARDOUR_SAE")) {
3314 Profile->set_sae ();
3315 Profile->set_single_package ();