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/compose.h>
37 #include <pbd/pathscanner.h>
38 #include <pbd/failed_constructor.h>
39 #include <pbd/enumwriter.h>
40 #include <pbd/stacktrace.h>
41 #include <gtkmm2ext/gtk_ui.h>
42 #include <gtkmm2ext/utils.h>
43 #include <gtkmm2ext/click_box.h>
44 #include <gtkmm2ext/fastmeter.h>
45 #include <gtkmm2ext/stop_signal.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/window_title.h>
49 #include <midi++/port.h>
50 #include <midi++/mmc.h>
52 #include <ardour/ardour.h>
53 #include <ardour/profile.h>
54 #include <ardour/session_route.h>
55 #include <ardour/port.h>
56 #include <ardour/audioengine.h>
57 #include <ardour/playlist.h>
58 #include <ardour/utils.h>
59 #include <ardour/audio_diskstream.h>
60 #include <ardour/audiofilesource.h>
61 #include <ardour/recent_sessions.h>
62 #include <ardour/port.h>
63 #include <ardour/audio_track.h>
66 #include "ardour_ui.h"
67 #include "public_editor.h"
68 #include "audio_clock.h"
73 #include "add_route_dialog.h"
74 #include "new_session_dialog.h"
77 #include "gui_thread.h"
78 #include "theme_manager.h"
79 #include "engine_dialog.h"
83 using namespace ARDOUR;
85 using namespace Gtkmm2ext;
89 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
90 UIConfiguration *ARDOUR_UI::ui_config = 0;
92 sigc::signal<void,bool> ARDOUR_UI::Blink;
93 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
94 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
95 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
97 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
99 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
101 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
102 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
103 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
104 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
108 adjuster_table (3, 3),
112 preroll_button (_("pre\nroll")),
113 postroll_button (_("post\nroll")),
117 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
121 roll_controllable ("transport roll", *this, TransportControllable::Roll),
122 stop_controllable ("transport stop", *this, TransportControllable::Stop),
123 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
124 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
125 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
126 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
127 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
128 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
129 shuttle_controller_binding_proxy (shuttle_controllable),
131 roll_button (roll_controllable),
132 stop_button (stop_controllable),
133 goto_start_button (goto_start_controllable),
134 goto_end_button (goto_end_controllable),
135 auto_loop_button (auto_loop_controllable),
136 play_selection_button (play_selection_controllable),
137 rec_button (rec_controllable),
139 shuttle_units_button (_("% ")),
141 punch_in_button (_("Punch In")),
142 punch_out_button (_("Punch Out")),
143 auto_return_button (_("Auto Return")),
144 auto_play_button (_("Auto Play")),
145 auto_input_button (_("Auto Input")),
146 click_button (_("Click")),
147 time_master_button (_("time\nmaster")),
149 auditioning_alert_button (_("AUDITION")),
150 solo_alert_button (_("SOLO")),
153 using namespace Gtk::Menu_Helpers;
159 if (theArdourUI == 0) {
163 ui_config = new UIConfiguration();
164 theme_manager = new ThemeManager();
170 _session_is_new = false;
171 big_clock_window = 0;
172 session_selector_window = 0;
173 new_session_dialog = 0;
174 last_key_press_time = 0;
175 connection_editor = 0;
176 add_route_dialog = 0;
180 open_session_selector = 0;
181 have_configure_timeout = false;
182 have_disk_speed_dialog_displayed = false;
183 _will_create_new_session_automatically = false;
184 session_loaded = false;
185 last_speed_displayed = -1.0f;
187 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
188 /* all changes go to the user directory */
189 user_keybindings_path = get_user_ardour_path ();
190 user_keybindings_path += '/';
191 user_keybindings_path += "ardour.bindings";
193 can_save_keybindings = false;
195 last_configure_time.tv_sec = 0;
196 last_configure_time.tv_usec = 0;
198 shuttle_grabbed = false;
200 shuttle_max_speed = 8.0f;
202 shuttle_style_menu = 0;
203 shuttle_unit_menu = 0;
205 gettimeofday (&last_peak_grab, 0);
206 gettimeofday (&last_shuttle_request, 0);
208 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
209 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
211 /* handle pending state with a dialog */
213 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
215 /* lets get this party started */
218 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
219 setup_gtk_ardour_enums ();
220 Config->set_current_owner (ConfigVariableBase::Interface);
223 } catch (failed_constructor& err) {
224 error << _("could not initialize Ardour.") << endmsg;
229 /* we like keyboards */
231 keyboard = new Keyboard;
233 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
234 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
238 ARDOUR_UI::start_backend_audio ()
240 if (new_session_dialog->engine_control.start_engine ()) {
248 ARDOUR_UI::create_engine ()
250 // this gets called every time by new_session()
257 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
258 } catch (AudioEngine::NoBackendAvailable& err) {
259 backend_audio_error ();
260 error << string_compose (_("Could not connect to JACK server as \"%1\""), ARDOUR_COMMAND_LINE::jack_client_name) << endmsg;
264 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
265 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
266 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
267 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
273 ARDOUR_UI::post_engine ()
275 /* Things to be done once we create the AudioEngine
278 check_memory_locking();
280 ActionManager::init ();
283 if (setup_windows ()) {
284 throw failed_constructor ();
287 /* this is the first point at which all the keybindings are available */
289 if (ARDOUR_COMMAND_LINE::show_key_actions) {
290 vector<string> names;
291 vector<string> paths;
293 vector<AccelKey> bindings;
295 ActionManager::get_all_actions (names, paths, keys, bindings);
297 vector<string>::iterator n;
298 vector<string>::iterator k;
299 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
300 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
306 blink_timeout_tag = -1;
308 /* the global configuration object is now valid */
312 /* this being a GUI and all, we want peakfiles */
314 AudioFileSource::set_build_peakfiles (true);
315 AudioFileSource::set_build_missing_peakfiles (true);
317 /* set default clock modes */
319 primary_clock.set_mode (AudioClock::SMPTE);
320 secondary_clock.set_mode (AudioClock::BBT);
322 /* start the time-of-day-clock */
324 update_wall_clock ();
325 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
327 update_disk_space ();
329 update_sample_rate (engine->frame_rate());
331 /* now start and maybe save state */
333 if (do_engine_start () == 0) {
334 if (session && _session_is_new) {
335 /* we need to retain initial visual
336 settings for a new session
338 session->save_state ("");
343 ARDOUR_UI::~ARDOUR_UI ()
345 save_ardour_state ();
359 if (add_route_dialog) {
360 delete add_route_dialog;
363 if (new_session_dialog) {
364 delete new_session_dialog;
369 ARDOUR_UI::configure_timeout ()
374 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
375 /* no configure events yet */
379 gettimeofday (&now, 0);
380 timersub (&now, &last_configure_time, &diff);
382 /* force a gap of 0.5 seconds since the last configure event
385 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
388 have_configure_timeout = false;
389 save_ardour_state ();
395 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
397 if (have_configure_timeout) {
398 gettimeofday (&last_configure_time, 0);
400 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
401 have_configure_timeout = true;
408 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
410 const XMLProperty* prop;
412 if ((prop = node.property ("roll")) != 0) {
413 roll_controllable.set_id (prop->value());
415 if ((prop = node.property ("stop")) != 0) {
416 stop_controllable.set_id (prop->value());
418 if ((prop = node.property ("goto_start")) != 0) {
419 goto_start_controllable.set_id (prop->value());
421 if ((prop = node.property ("goto_end")) != 0) {
422 goto_end_controllable.set_id (prop->value());
424 if ((prop = node.property ("auto_loop")) != 0) {
425 auto_loop_controllable.set_id (prop->value());
427 if ((prop = node.property ("play_selection")) != 0) {
428 play_selection_controllable.set_id (prop->value());
430 if ((prop = node.property ("rec")) != 0) {
431 rec_controllable.set_id (prop->value());
433 if ((prop = node.property ("shuttle")) != 0) {
434 shuttle_controllable.set_id (prop->value());
439 ARDOUR_UI::get_transport_controllable_state ()
441 XMLNode* node = new XMLNode(X_("TransportControllables"));
444 roll_controllable.id().print (buf, sizeof (buf));
445 node->add_property (X_("roll"), buf);
446 stop_controllable.id().print (buf, sizeof (buf));
447 node->add_property (X_("stop"), buf);
448 goto_start_controllable.id().print (buf, sizeof (buf));
449 node->add_property (X_("goto_start"), buf);
450 goto_end_controllable.id().print (buf, sizeof (buf));
451 node->add_property (X_("goto_end"), buf);
452 auto_loop_controllable.id().print (buf, sizeof (buf));
453 node->add_property (X_("auto_loop"), buf);
454 play_selection_controllable.id().print (buf, sizeof (buf));
455 node->add_property (X_("play_selection"), buf);
456 rec_controllable.id().print (buf, sizeof (buf));
457 node->add_property (X_("rec"), buf);
458 shuttle_controllable.id().print (buf, sizeof (buf));
459 node->add_property (X_("shuttle"), buf);
465 ARDOUR_UI::save_ardour_state ()
467 if (!keyboard || !mixer || !editor) {
471 /* XXX this is all a bit dubious. add_extra_xml() uses
472 a different lifetime model from add_instant_xml().
475 XMLNode* node = new XMLNode (keyboard->get_state());
476 Config->add_extra_xml (*node);
477 Config->add_extra_xml (get_transport_controllable_state());
478 if (new_session_dialog) {
479 if (new_session_dialog->engine_control.was_used()) {
480 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
483 Config->save_state();
485 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
486 XMLNode mnode(mixer->get_state());
489 session->add_instant_xml (enode, session->path());
490 session->add_instant_xml (mnode, session->path());
492 Config->add_instant_xml (enode, get_user_ardour_path());
493 Config->add_instant_xml (mnode, get_user_ardour_path());
500 ARDOUR_UI::autosave_session ()
502 if (!Config->get_periodic_safety_backups())
506 session->maybe_write_autosave();
513 ARDOUR_UI::update_autosave ()
515 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
517 if (session->dirty()) {
518 if (_autosave_connection.connected()) {
519 _autosave_connection.disconnect();
522 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
523 Config->get_periodic_safety_backup_interval() * 1000);
526 if (_autosave_connection.connected()) {
527 _autosave_connection.disconnect();
533 ARDOUR_UI::backend_audio_error ()
535 MessageDialog win (_("Ardour could not connect to JACK."),
538 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
539 win.set_secondary_text(_("There are several possible reasons:\n\
541 1) JACK is not running.\n\
542 2) JACK is running as another user, perhaps root.\n\
543 3) There is already another client called \"ardour\".\n\
545 Please consider the possibilities, and perhaps (re)start JACK."));
547 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
548 win.set_default_response (RESPONSE_CLOSE);
551 win.set_position (Gtk::WIN_POS_CENTER);
553 if (!ARDOUR_COMMAND_LINE::no_splash) {
557 /* we just don't care about the result, but we want to block */
563 ARDOUR_UI::startup ()
565 using namespace ARDOUR_COMMAND_LINE;
569 new_session_dialog = new NewSessionDialog();
571 /* If no session name is given: we're not loading a session yet, nor creating a new one */
573 if (session_name.length()) {
575 /* Load session or start the new session dialog */
577 if (Session::find_session (session_name, path, name, isnew)) {
578 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
582 if (!ARDOUR_COMMAND_LINE::new_session) {
584 /* Supposed to be loading an existing session, but the session doesn't exist */
587 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
588 "To create it from the command line, start ardour as \"ardour --new %1"), path)
594 new_session_dialog->set_session_name (name);
595 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
596 _session_is_new = isnew;
601 bool have_backend = EngineControl::engine_running();
603 bool load_needed = false;
607 /* backend audio is working */
609 if (session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
610 /* need NSD to get session name and other info */
618 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
621 new_session_dialog->engine_control.set_state (*audio_setup);
624 /* no backend audio, must bring up NSD to check configuration */
631 if (!new_session (session_name,have_backend)) {
643 if (load_session (session_name, name)) {
652 ARDOUR_UI::no_memory_warning ()
654 XMLNode node (X_("no-memory-warning"));
655 Config->add_instant_xml (node, get_user_ardour_path());
659 ARDOUR_UI::check_memory_locking ()
662 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
666 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
668 if (engine->is_realtime() && memory_warning_node == 0) {
670 struct rlimit limits;
672 long pages, page_size;
674 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
677 ram = (int64_t) pages * (int64_t) page_size;
680 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
684 if (limits.rlim_cur != RLIM_INFINITY) {
686 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
689 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
690 "This might cause Ardour to run out of memory before your system "
691 "runs out of memory. \n\n"
692 "You can view the memory limit with 'ulimit -l', "
693 "and it is normally controlled by /etc/security/limits.conf"));
695 VBox* vbox = msg.get_vbox();
697 CheckButton cb (_("Do not show this window again"));
699 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
701 hbox.pack_start (cb, true, false);
702 vbox->pack_start (hbox);
705 editor->ensure_float (msg);
717 if (session && session->dirty()) {
718 switch (ask_about_saving_session(_("quit"))) {
723 /* use the default name */
724 if (save_state_canfail ("")) {
725 /* failed - don't quit */
726 MessageDialog msg (*editor,
728 Ardour was unable to save your session.\n\n\
729 If you still wish to quit, please use the\n\n\
730 \"Just quit\" option."));
741 session->set_deletion_in_progress ();
744 Config->save_state();
745 ARDOUR_UI::config()->save_state();
750 ARDOUR_UI::ask_about_saving_session (const string & what)
752 ArdourDialog window (_("ardour: save session?"));
753 Gtk::HBox dhbox; // the hbox for the image and text
754 Gtk::Label prompt_label;
755 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
759 msg = string_compose(_("Don't %1"), what);
760 window.add_button (msg, RESPONSE_REJECT);
761 msg = string_compose(_("Just %1"), what);
762 window.add_button (msg, RESPONSE_APPLY);
763 msg = string_compose(_("Save and %1"), what);
764 window.add_button (msg, RESPONSE_ACCEPT);
766 window.set_default_response (RESPONSE_ACCEPT);
768 Gtk::Button noquit_button (msg);
769 noquit_button.set_name ("EditorGTKButton");
774 if (session->snap_name() == session->name()) {
777 type = _("snapshot");
779 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?"),
780 type, session->snap_name());
782 prompt_label.set_text (prompt);
783 prompt_label.set_name (X_("PrompterLabel"));
784 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
786 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
788 dhbox.set_homogeneous (false);
789 dhbox.pack_start (*dimage, false, false, 5);
790 dhbox.pack_start (prompt_label, true, false, 5);
791 window.get_vbox()->pack_start (dhbox);
793 window.set_name (_("Prompter"));
794 window.set_position (Gtk::WIN_POS_MOUSE);
795 window.set_modal (true);
796 window.set_resizable (false);
799 save_the_session = 0;
801 window.set_keep_above (true);
804 ResponseType r = (ResponseType) window.run();
809 case RESPONSE_ACCEPT: // save and get out of here
811 case RESPONSE_APPLY: // get out of here
821 ARDOUR_UI::every_second ()
824 update_buffer_load ();
825 update_disk_space ();
830 ARDOUR_UI::every_point_one_seconds ()
832 update_speed_display ();
833 RapidScreenUpdate(); /* EMIT_SIGNAL */
838 ARDOUR_UI::every_point_zero_one_seconds ()
840 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
845 ARDOUR_UI::update_sample_rate (nframes_t ignored)
849 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
851 if (!engine->connected()) {
853 snprintf (buf, sizeof (buf), _("disconnected"));
857 nframes_t rate = engine->frame_rate();
859 if (fmod (rate, 1000.0) != 0.0) {
860 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
861 (float) rate/1000.0f,
862 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
864 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
866 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
870 sample_rate_label.set_text (buf);
874 ARDOUR_UI::update_cpu_load ()
877 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
878 cpu_load_label.set_text (buf);
882 ARDOUR_UI::update_buffer_load ()
887 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
888 session->playback_load(), session->capture_load());
889 buffer_load_label.set_text (buf);
891 buffer_load_label.set_text ("");
896 ARDOUR_UI::count_recenabled_streams (Route& route)
898 Track* track = dynamic_cast<Track*>(&route);
899 if (track && track->diskstream()->record_enabled()) {
900 rec_enabled_streams += track->n_inputs();
905 ARDOUR_UI::update_disk_space()
911 nframes_t frames = session->available_capture_duration();
914 if (frames == max_frames) {
915 strcpy (buf, _("Disk: 24hrs+"));
920 nframes_t fr = session->frame_rate();
922 rec_enabled_streams = 0;
923 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
925 if (rec_enabled_streams) {
926 frames /= rec_enabled_streams;
929 hrs = frames / (fr * 3600);
930 frames -= hrs * fr * 3600;
931 mins = frames / (fr * 60);
932 frames -= mins * fr * 60;
935 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
938 disk_space_label.set_text (buf);
942 ARDOUR_UI::update_wall_clock ()
949 tm_now = localtime (&now);
951 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
952 wall_clock_label.set_text (buf);
958 ARDOUR_UI::session_menu (GdkEventButton *ev)
960 session_popup_menu->popup (0, 0);
965 ARDOUR_UI::redisplay_recent_sessions ()
967 vector<string *> *sessions;
968 vector<string *>::iterator i;
969 RecentSessionsSorter cmp;
971 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
972 recent_session_model->clear ();
975 ARDOUR::read_recent_sessions (rs);
978 recent_session_display.set_model (recent_session_model);
982 /* sort them alphabetically */
983 sort (rs.begin(), rs.end(), cmp);
984 sessions = new vector<string*>;
986 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
987 sessions->push_back (new string ((*i).second));
990 for (i = sessions->begin(); i != sessions->end(); ++i) {
992 vector<string*>* states;
993 vector<const gchar*> item;
994 string fullpath = *(*i);
996 /* remove any trailing / */
998 if (fullpath[fullpath.length()-1] == '/') {
999 fullpath = fullpath.substr (0, fullpath.length()-1);
1002 /* now get available states for this session */
1004 if ((states = Session::possible_states (fullpath)) == 0) {
1005 /* no state file? */
1009 TreeModel::Row row = *(recent_session_model->append());
1011 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1012 row[recent_session_columns.fullpath] = fullpath;
1014 if (states->size() > 1) {
1016 /* add the children */
1018 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1020 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1022 child_row[recent_session_columns.visible_name] = **i2;
1023 child_row[recent_session_columns.fullpath] = fullpath;
1032 recent_session_display.set_model (recent_session_model);
1037 ARDOUR_UI::build_session_selector ()
1039 session_selector_window = new ArdourDialog ("session selector");
1041 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1043 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1044 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1045 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1046 recent_session_model = TreeStore::create (recent_session_columns);
1047 recent_session_display.set_model (recent_session_model);
1048 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1049 recent_session_display.set_headers_visible (false);
1050 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1052 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1054 scroller->add (recent_session_display);
1055 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1057 session_selector_window->set_name ("SessionSelectorWindow");
1058 session_selector_window->set_size_request (200, 400);
1059 session_selector_window->get_vbox()->pack_start (*scroller);
1060 session_selector_window->show_all_children();
1064 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1066 session_selector_window->response (RESPONSE_ACCEPT);
1070 ARDOUR_UI::open_recent_session ()
1072 /* popup selector window */
1074 if (session_selector_window == 0) {
1075 build_session_selector ();
1078 redisplay_recent_sessions ();
1080 ResponseType r = (ResponseType) session_selector_window->run ();
1082 session_selector_window->hide();
1085 case RESPONSE_ACCEPT:
1091 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1093 if (i == recent_session_model->children().end()) {
1097 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1098 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1100 _session_is_new = false;
1102 load_session (path, state);
1106 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1108 struct stat statbuf;
1110 if (stat (info.filename.c_str(), &statbuf) != 0) {
1114 if (!S_ISDIR(statbuf.st_mode)) {
1120 string session_file = info.filename;
1121 session_file += '/';
1122 session_file += Glib::path_get_basename (info.filename);
1123 session_file += ".ardour";
1125 if (stat (session_file.c_str(), &statbuf) != 0) {
1129 return S_ISREG (statbuf.st_mode);
1133 ARDOUR_UI::check_audioengine ()
1136 if (!engine->connected()) {
1137 MessageDialog msg (_("Ardour is not connected to JACK\n"
1138 "You cannot open or close sessions in this condition"));
1149 ARDOUR_UI::open_session ()
1151 if (!check_audioengine()) {
1155 /* popup selector window */
1157 if (open_session_selector == 0) {
1159 /* ardour sessions are folders */
1161 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1162 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1163 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1165 FileFilter session_filter;
1166 session_filter.add_pattern ("*.ardour");
1167 session_filter.set_name (_("Ardour sessions"));
1168 open_session_selector->add_filter (session_filter);
1169 open_session_selector->set_filter (session_filter);
1172 int response = open_session_selector->run();
1173 open_session_selector->hide ();
1176 case RESPONSE_ACCEPT:
1179 open_session_selector->hide();
1183 open_session_selector->hide();
1184 string session_path = open_session_selector->get_filename();
1188 if (session_path.length() > 0) {
1189 if (Session::find_session (session_path, path, name, isnew) == 0) {
1190 _session_is_new = isnew;
1191 load_session (path, name);
1198 ARDOUR_UI::session_add_midi_track ()
1200 cerr << _("Patience is a virtue.\n");
1204 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1206 list<boost::shared_ptr<AudioTrack> > tracks;
1207 Session::RouteList routes;
1210 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1216 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1218 if (tracks.size() != how_many) {
1219 if (how_many == 1) {
1220 error << _("could not create a new audio track") << endmsg;
1222 error << string_compose (_("could only create %1 of %2 new audio %3"),
1223 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1229 routes = session->new_audio_route (input_channels, output_channels, how_many);
1231 if (routes.size() != how_many) {
1232 if (how_many == 1) {
1233 error << _("could not create a new audio track") << endmsg;
1235 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1241 if (need_control_room_outs) {
1247 route->set_stereo_control_outs (control_lr_channels);
1248 route->control_outs()->set_stereo_pan (pans, this);
1250 #endif /* CONTROLOUTS */
1254 cerr << "About to complain about JACK\n";
1255 MessageDialog msg (*editor,
1256 _("There are insufficient JACK ports available\n\
1257 to create a new track or bus.\n\
1258 You should save Ardour, exit and\n\
1259 restart JACK with more ports."));
1265 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1267 nframes_t _preroll = 0;
1270 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1271 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1273 if (new_position > _preroll) {
1274 new_position -= _preroll;
1279 session->request_locate (new_position);
1284 ARDOUR_UI::transport_goto_start ()
1287 session->goto_start();
1290 /* force displayed area in editor to start no matter
1291 what "follow playhead" setting is.
1295 editor->reset_x_origin (session->current_start_frame());
1301 ARDOUR_UI::transport_goto_zero ()
1304 session->request_locate (0);
1307 /* force displayed area in editor to start no matter
1308 what "follow playhead" setting is.
1312 editor->reset_x_origin (0);
1318 ARDOUR_UI::transport_goto_end ()
1321 nframes_t frame = session->current_end_frame();
1322 session->request_locate (frame);
1324 /* force displayed area in editor to start no matter
1325 what "follow playhead" setting is.
1329 editor->reset_x_origin (frame);
1335 ARDOUR_UI::transport_stop ()
1341 if (session->is_auditioning()) {
1342 session->cancel_audition ();
1346 if (session->get_play_loop ()) {
1347 session->request_play_loop (false);
1350 session->request_stop ();
1354 ARDOUR_UI::transport_stop_and_forget_capture ()
1357 session->request_stop (true);
1362 ARDOUR_UI::remove_last_capture()
1365 editor->remove_last_capture();
1370 ARDOUR_UI::transport_record ()
1373 switch (session->record_status()) {
1374 case Session::Disabled:
1375 if (session->ntracks() == 0) {
1376 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1380 session->maybe_enable_record ();
1382 case Session::Recording:
1383 case Session::Enabled:
1384 session->disable_record (false, true);
1390 ARDOUR_UI::transport_roll ()
1398 rolling = session->transport_rolling ();
1400 if (session->get_play_loop()) {
1401 session->request_play_loop (false);
1402 auto_loop_button.set_visual_state (1);
1403 roll_button.set_visual_state (1);
1404 } else if (session->get_play_range ()) {
1405 session->request_play_range (false);
1406 play_selection_button.set_visual_state (0);
1407 } else if (rolling) {
1408 session->request_locate (session->last_transport_start(), true);
1411 session->request_transport_speed (1.0f);
1415 ARDOUR_UI::transport_loop()
1418 if (session->get_play_loop()) {
1419 if (session->transport_rolling()) {
1420 Location * looploc = session->locations()->auto_loop_location();
1422 session->request_locate (looploc->start(), true);
1427 session->request_play_loop (true);
1433 ARDOUR_UI::transport_play_selection ()
1439 if (!session->get_play_range()) {
1440 session->request_stop ();
1443 editor->play_selection ();
1447 ARDOUR_UI::transport_rewind (int option)
1449 float current_transport_speed;
1452 current_transport_speed = session->transport_speed();
1454 if (current_transport_speed >= 0.0f) {
1457 session->request_transport_speed (-1.0f);
1460 session->request_transport_speed (-4.0f);
1463 session->request_transport_speed (-0.5f);
1468 session->request_transport_speed (current_transport_speed * 1.5f);
1474 ARDOUR_UI::transport_forward (int option)
1476 float current_transport_speed;
1479 current_transport_speed = session->transport_speed();
1481 if (current_transport_speed <= 0.0f) {
1484 session->request_transport_speed (1.0f);
1487 session->request_transport_speed (4.0f);
1490 session->request_transport_speed (0.5f);
1495 session->request_transport_speed (current_transport_speed * 1.5f);
1501 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1507 boost::shared_ptr<Route> r;
1509 if ((r = session->route_by_remote_id (dstream)) != 0) {
1513 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1514 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1523 ARDOUR_UI::queue_transport_change ()
1525 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1529 ARDOUR_UI::map_transport_state ()
1531 float sp = session->transport_speed();
1534 transport_rolling ();
1535 } else if (sp < 0.0f) {
1536 transport_rewinding ();
1537 } else if (sp > 0.0f) {
1538 transport_forwarding ();
1540 transport_stopped ();
1545 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1547 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1548 (int) adj.get_value()].c_str());
1552 ARDOUR_UI::engine_stopped ()
1554 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1555 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1556 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1560 ARDOUR_UI::engine_running ()
1562 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1563 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1564 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1566 Glib::RefPtr<Action> action;
1567 char* action_name = 0;
1569 switch (engine->frames_per_cycle()) {
1571 action_name = X_("JACKLatency32");
1574 action_name = X_("JACKLatency64");
1577 action_name = X_("JACKLatency128");
1580 action_name = X_("JACKLatency512");
1583 action_name = X_("JACKLatency1024");
1586 action_name = X_("JACKLatency2048");
1589 action_name = X_("JACKLatency4096");
1592 action_name = X_("JACKLatency8192");
1595 /* XXX can we do anything useful ? */
1601 action = ActionManager::get_action (X_("JACK"), action_name);
1604 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1605 ract->set_active ();
1611 ARDOUR_UI::engine_halted ()
1613 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1615 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1616 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1618 update_sample_rate (0);
1620 MessageDialog msg (*editor,
1622 JACK has either been shutdown or it\n\
1623 disconnected Ardour because Ardour\n\
1624 was not fast enough. You can save the\n\
1625 session and/or try to reconnect to JACK ."));
1630 ARDOUR_UI::do_engine_start ()
1638 error << _("Unable to start the session running")
1648 ARDOUR_UI::setup_theme ()
1650 theme_manager->setup_theme();
1654 ARDOUR_UI::update_clocks ()
1656 if (!editor || !editor->dragging_playhead()) {
1657 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1662 ARDOUR_UI::start_clocking ()
1664 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1668 ARDOUR_UI::stop_clocking ()
1670 clock_signal_connection.disconnect ();
1674 ARDOUR_UI::toggle_clocking ()
1677 if (clock_button.get_active()) {
1686 ARDOUR_UI::_blink (void *arg)
1689 ((ARDOUR_UI *) arg)->blink ();
1696 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1700 ARDOUR_UI::start_blinking ()
1702 /* Start the blink signal. Everybody with a blinking widget
1703 uses Blink to drive the widget's state.
1706 if (blink_timeout_tag < 0) {
1708 blink_timeout_tag = g_timeout_add (240, _blink, this);
1713 ARDOUR_UI::stop_blinking ()
1715 if (blink_timeout_tag >= 0) {
1716 g_source_remove (blink_timeout_tag);
1717 blink_timeout_tag = -1;
1722 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1728 if (io.n_inputs() == 0) {
1733 /* XXX we're not handling multiple ports yet. */
1735 const char **connections = io.input(0)->get_connections();
1737 if (connections == 0 || connections[0] == '\0') {
1740 buf = connections[0];
1747 if (io.n_outputs() == 0) {
1752 /* XXX we're not handling multiple ports yet. */
1754 const char **connections = io.output(0)->get_connections();
1756 if (connections == 0 || connections[0] == '\0') {
1759 buf = connections[0];
1766 /** Ask the user for the name of a new shapshot and then take it.
1769 ARDOUR_UI::snapshot_session ()
1771 ArdourPrompter prompter (true);
1775 struct tm local_time;
1778 localtime_r (&n, &local_time);
1779 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1781 prompter.set_name ("Prompter");
1782 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1783 prompter.set_prompt (_("Name of New Snapshot"));
1784 prompter.set_initial_text (timebuf);
1786 switch (prompter.run()) {
1787 case RESPONSE_ACCEPT:
1788 prompter.get_result (snapname);
1789 if (snapname.length()){
1790 save_state (snapname);
1800 ARDOUR_UI::save_state (const string & name)
1802 (void) save_state_canfail (name);
1806 ARDOUR_UI::save_state_canfail (string name)
1811 if (name.length() == 0) {
1812 name = session->snap_name();
1815 if ((ret = session->save_state (name)) != 0) {
1819 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1824 ARDOUR_UI::restore_state (string name)
1827 if (name.length() == 0) {
1828 name = session->name();
1830 session->restore_state (name);
1835 ARDOUR_UI::primary_clock_value_changed ()
1838 session->request_locate (primary_clock.current_time ());
1843 ARDOUR_UI::secondary_clock_value_changed ()
1846 session->request_locate (secondary_clock.current_time ());
1851 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1853 if (session && dstream && dstream->record_enabled()) {
1855 Session::RecordState rs;
1857 rs = session->record_status ();
1860 case Session::Disabled:
1861 case Session::Enabled:
1862 if (w->get_state() != STATE_SELECTED) {
1863 w->set_state (STATE_SELECTED);
1867 case Session::Recording:
1868 if (w->get_state() != STATE_ACTIVE) {
1869 w->set_state (STATE_ACTIVE);
1875 if (w->get_state() != STATE_NORMAL) {
1876 w->set_state (STATE_NORMAL);
1882 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1888 switch (session->record_status()) {
1889 case Session::Enabled:
1891 rec_button.set_visual_state (2);
1893 rec_button.set_visual_state (0);
1897 case Session::Recording:
1898 rec_button.set_visual_state (1);
1902 rec_button.set_visual_state (0);
1908 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1916 ARDOUR_UI::save_template ()
1919 ArdourPrompter prompter (true);
1922 if (!check_audioengine()) {
1926 prompter.set_name (X_("Prompter"));
1927 prompter.set_prompt (_("Name for mix template:"));
1928 prompter.set_initial_text(session->name() + _("-template"));
1929 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1931 switch (prompter.run()) {
1932 case RESPONSE_ACCEPT:
1933 prompter.get_result (name);
1935 if (name.length()) {
1936 session->save_template (name);
1946 ARDOUR_UI::new_session (Glib::ustring predetermined_path, bool have_engine)
1948 string session_name;
1949 string session_path;
1951 int response = Gtk::RESPONSE_NONE;
1953 new_session_dialog->set_modal(true);
1954 new_session_dialog->set_name (predetermined_path);
1955 new_session_dialog->reset_recent();
1956 new_session_dialog->show();
1957 new_session_dialog->present ();
1958 new_session_dialog->set_current_page (0);
1962 new_session_dialog->set_have_engine (have_engine);
1964 response = new_session_dialog->run ();
1966 _session_is_new = false;
1968 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1973 new_session_dialog->hide ();
1976 } else if (response == Gtk::RESPONSE_NONE) {
1978 /* Clear was pressed */
1979 new_session_dialog->reset();
1983 /* first things first ... we need an audio engine running */
1986 if (start_backend_audio ()) {
1987 new_session_dialog->hide ();
1995 /* now handle possible affirmative responses */
1997 if (response == Gtk::RESPONSE_YES) {
1999 /* YES == OPEN from the open session tab */
2001 session_name = new_session_dialog->session_name();
2003 if (session_name.empty()) {
2004 response = Gtk::RESPONSE_NONE;
2008 if (session_name[0] == '/' ||
2009 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2010 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2011 load_session (Glib::path_get_dirname (session_name), session_name);
2013 session_path = new_session_dialog->session_folder();
2014 load_session (session_path, session_name);
2017 } else if (response == Gtk::RESPONSE_OK) {
2019 /* OK == OPEN from new session tab */
2021 session_name = new_session_dialog->session_name();
2023 if (new_session_dialog->get_current_page() == 1) {
2025 if (session_name.empty()) {
2026 response = Gtk::RESPONSE_NONE;
2030 if (session_name[0] == '/' ||
2031 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2032 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2033 load_session (Glib::path_get_dirname (session_name), session_name);
2035 session_path = new_session_dialog->session_folder();
2036 load_session (session_path, session_name);
2041 if (session_name.empty()) {
2042 response = Gtk::RESPONSE_NONE;
2046 /* handle what appear to be paths rather than just a name */
2048 if (session_name[0] == '/' ||
2049 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2050 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2052 session_path = Glib::path_get_dirname (session_name);
2053 session_name = Glib::path_get_basename (session_name);
2057 session_path = new_session_dialog->session_folder();
2061 //XXX This is needed because session constructor wants a
2062 //non-existant path. hopefully this will be fixed at some point.
2064 session_path = Glib::build_filename (session_path, session_name);
2066 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2068 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2070 MessageDialog msg (str,
2072 Gtk::MESSAGE_WARNING,
2073 Gtk::BUTTONS_YES_NO,
2077 msg.set_name (X_("CleanupDialog"));
2078 msg.set_wmclass (X_("existing_session"), "Ardour");
2079 msg.set_position (Gtk::WIN_POS_MOUSE);
2081 switch (msg.run()) {
2083 load_session (session_path, session_name);
2087 response = RESPONSE_NONE;
2088 new_session_dialog->reset ();
2093 _session_is_new = true;
2095 std::string template_name = new_session_dialog->session_template_name();
2097 if (new_session_dialog->use_session_template()) {
2099 load_session (session_path, session_name, &template_name);
2105 AutoConnectOption iconnect;
2106 AutoConnectOption oconnect;
2110 if (Profile->get_sae()) {
2114 iconnect = AutoConnectPhysical;
2115 oconnect = AutoConnectMaster;
2116 nphysin = 0; // use all available
2117 nphysout = 0; // use all available
2121 /* get settings from advanced section of NSD */
2123 if (new_session_dialog->create_control_bus()) {
2124 cchns = (uint32_t) new_session_dialog->control_channel_count();
2129 if (new_session_dialog->create_master_bus()) {
2130 mchns = (uint32_t) new_session_dialog->master_channel_count();
2135 if (new_session_dialog->connect_inputs()) {
2136 iconnect = AutoConnectPhysical;
2138 iconnect = AutoConnectOption (0);
2141 /// @todo some minor tweaks.
2143 if (new_session_dialog->connect_outs_to_master()) {
2144 oconnect = AutoConnectMaster;
2145 } else if (new_session_dialog->connect_outs_to_physical()) {
2146 oconnect = AutoConnectPhysical;
2148 oconnect = AutoConnectOption (0);
2151 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2152 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2155 if (build_session (session_path,
2163 engine->frame_rate() * 60 * 5)) {
2165 response = Gtk::RESPONSE_NONE;
2166 new_session_dialog->reset ();
2173 } while (response == Gtk::RESPONSE_NONE);
2177 new_session_dialog->get_window()->set_cursor();
2178 new_session_dialog->hide();
2183 ARDOUR_UI::close_session()
2185 if (!check_audioengine()) {
2190 new_session ("", true);
2194 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2196 Session *new_session;
2198 session_loaded = false;
2200 if (!check_audioengine()) {
2204 x = unload_session ();
2212 /* if it already exists, we must have write access */
2214 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2215 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2216 "This prevents the session from being loaded."));
2222 new_session = new Session (*engine, path, snap_name, mix_template);
2227 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2231 connect_to_session (new_session);
2233 Config->set_current_owner (ConfigVariableBase::Interface);
2235 session_loaded = true;
2237 goto_editor_window ();
2240 session->set_clean ();
2243 editor->edit_cursor_position (true);
2248 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2249 uint32_t control_channels,
2250 uint32_t master_channels,
2251 AutoConnectOption input_connect,
2252 AutoConnectOption output_connect,
2255 nframes_t initial_length)
2257 Session *new_session;
2260 if (!check_audioengine()) {
2264 session_loaded = false;
2266 x = unload_session ();
2274 _session_is_new = true;
2277 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2278 control_channels, master_channels, nphysin, nphysout, initial_length);
2283 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2288 connect_to_session (new_session);
2290 session_loaded = true;
2298 editor->show_window ();
2309 ARDOUR_UI::show_splash ()
2312 about = new About();
2313 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2320 ARDOUR_UI::about_signal_response(int response)
2326 ARDOUR_UI::hide_splash ()
2329 about->get_window()->set_cursor ();
2335 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2339 removed = rep.paths.size();
2342 MessageDialog msgd (*editor,
2343 _("No audio files were ready for cleanup"),
2346 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2347 msgd.set_secondary_text (_("If this seems suprising, \n\
2348 check for any existing snapshots.\n\
2349 These may still include regions that\n\
2350 require some unused files to continue to exist."));
2356 ArdourDialog results (_("ardour: cleanup"), true, false);
2358 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2359 CleanupResultsModelColumns() {
2363 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2364 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2368 CleanupResultsModelColumns results_columns;
2369 Glib::RefPtr<Gtk::ListStore> results_model;
2370 Gtk::TreeView results_display;
2372 results_model = ListStore::create (results_columns);
2373 results_display.set_model (results_model);
2374 results_display.append_column (list_title, results_columns.visible_name);
2376 results_display.set_name ("CleanupResultsList");
2377 results_display.set_headers_visible (true);
2378 results_display.set_headers_clickable (false);
2379 results_display.set_reorderable (false);
2381 Gtk::ScrolledWindow list_scroller;
2384 Gtk::HBox dhbox; // the hbox for the image and text
2385 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2386 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2388 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2390 if (rep.space < 1048576.0f) {
2392 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2394 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2398 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2400 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2404 dhbox.pack_start (*dimage, true, false, 5);
2405 dhbox.pack_start (txt, true, false, 5);
2407 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2408 TreeModel::Row row = *(results_model->append());
2409 row[results_columns.visible_name] = *i;
2410 row[results_columns.fullpath] = *i;
2413 list_scroller.add (results_display);
2414 list_scroller.set_size_request (-1, 150);
2415 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2417 dvbox.pack_start (dhbox, true, false, 5);
2418 dvbox.pack_start (list_scroller, true, false, 5);
2419 ddhbox.pack_start (dvbox, true, false, 5);
2421 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2422 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2423 results.set_default_response (RESPONSE_CLOSE);
2424 results.set_position (Gtk::WIN_POS_MOUSE);
2425 results.show_all_children ();
2426 results.set_resizable (false);
2433 ARDOUR_UI::cleanup ()
2436 /* shouldn't happen: menu item is insensitive */
2441 MessageDialog checker (_("Are you sure you want to cleanup?"),
2443 Gtk::MESSAGE_QUESTION,
2444 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2446 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2447 ALL undo/redo information will be lost if you cleanup.\n\
2448 After cleanup, unused audio files will be moved to a \
2449 \"dead sounds\" location."));
2451 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2452 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2453 checker.set_default_response (RESPONSE_CANCEL);
2455 checker.set_name (_("CleanupDialog"));
2456 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2457 checker.set_position (Gtk::WIN_POS_MOUSE);
2459 switch (checker.run()) {
2460 case RESPONSE_ACCEPT:
2466 Session::cleanup_report rep;
2468 editor->prepare_for_cleanup ();
2470 /* do not allow flush until a session is reloaded */
2472 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2474 act->set_sensitive (false);
2477 if (session->cleanup_sources (rep)) {
2482 display_cleanup_results (rep,
2485 The following %1 %2 not in use and \n\
2486 have been moved to:\n\
2488 Flushing the wastebasket will \n\
2489 release an additional\n\
2490 %4 %5bytes of disk space.\n"
2498 ARDOUR_UI::flush_trash ()
2501 /* shouldn't happen: menu item is insensitive */
2505 Session::cleanup_report rep;
2507 if (session->cleanup_trash_sources (rep)) {
2511 display_cleanup_results (rep,
2513 _("The following %1 %2 deleted from\n\
2515 releasing %4 %5bytes of disk space"));
2519 ARDOUR_UI::add_route (Gtk::Window* float_window)
2527 if (add_route_dialog == 0) {
2528 add_route_dialog = new AddRouteDialog;
2530 add_route_dialog->set_transient_for (*float_window);
2534 if (add_route_dialog->is_visible()) {
2535 /* we're already doing this */
2539 ResponseType r = (ResponseType) add_route_dialog->run ();
2541 add_route_dialog->hide();
2544 case RESPONSE_ACCEPT:
2551 if ((count = add_route_dialog->count()) <= 0) {
2555 uint32_t input_chan = add_route_dialog->channels ();
2556 uint32_t output_chan;
2557 string name_template = add_route_dialog->name_template ();
2558 bool track = add_route_dialog->track ();
2560 AutoConnectOption oac = Config->get_output_auto_connect();
2562 if (oac & AutoConnectMaster) {
2563 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2565 output_chan = input_chan;
2568 /* XXX do something with name template */
2571 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2573 session_add_audio_bus (input_chan, output_chan, count);
2578 ARDOUR_UI::mixer_settings () const
2583 node = session->instant_xml(X_("Mixer"), session->path());
2585 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2589 node = new XMLNode (X_("Mixer"));
2596 ARDOUR_UI::editor_settings () const
2601 node = session->instant_xml(X_("Editor"), session->path());
2603 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2607 node = new XMLNode (X_("Editor"));
2613 ARDOUR_UI::keyboard_settings () const
2617 node = Config->extra_xml(X_("Keyboard"));
2620 node = new XMLNode (X_("Keyboard"));
2626 ARDOUR_UI::halt_on_xrun_message ()
2628 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2630 MessageDialog msg (*editor,
2631 _("Recording was stopped because your system could not keep up."));
2636 ARDOUR_UI::disk_overrun_handler ()
2638 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2640 if (!have_disk_speed_dialog_displayed) {
2641 have_disk_speed_dialog_displayed = true;
2642 MessageDialog* msg = new MessageDialog (*editor, _("\
2643 The disk system on your computer\n\
2644 was not able to keep up with Ardour.\n\
2646 Specifically, it failed to write data to disk\n\
2647 quickly enough to keep up with recording.\n"));
2648 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2654 ARDOUR_UI::disk_underrun_handler ()
2656 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2658 if (!have_disk_speed_dialog_displayed) {
2659 have_disk_speed_dialog_displayed = true;
2660 MessageDialog* msg = new MessageDialog (*editor,
2661 _("The disk system on your computer\n\
2662 was not able to keep up with Ardour.\n\
2664 Specifically, it failed to read data from disk\n\
2665 quickly enough to keep up with playback.\n"));
2666 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2672 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2674 have_disk_speed_dialog_displayed = false;
2679 ARDOUR_UI::pending_state_dialog ()
2681 ArdourDialog dialog ("pending state dialog");
2683 This session appears to have been in\n\
2684 middle of recording when ardour or\n\
2685 the computer was shutdown.\n\
2687 Ardour can recover any captured audio for\n\
2688 you, or it can ignore it. Please decide\n\
2689 what you would like to do.\n"));
2691 dialog.get_vbox()->pack_start (message);
2692 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2693 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2695 dialog.set_position (WIN_POS_CENTER);
2698 switch (dialog.run ()) {
2699 case RESPONSE_ACCEPT:
2707 ARDOUR_UI::disconnect_from_jack ()
2710 if( engine->disconnect_from_jack ()) {
2711 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2715 update_sample_rate (0);
2720 ARDOUR_UI::reconnect_to_jack ()
2723 if (engine->reconnect_to_jack ()) {
2724 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2728 update_sample_rate (0);
2733 ARDOUR_UI::cmdline_new_session (string path)
2735 if (path[0] != '/') {
2736 char buf[PATH_MAX+1];
2739 getcwd (buf, sizeof (buf));
2748 _will_create_new_session_automatically = false; /* done it */
2749 return FALSE; /* don't call it again */
2753 ARDOUR_UI::use_config ()
2755 Glib::RefPtr<Action> act;
2757 switch (Config->get_native_file_data_format ()) {
2759 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2762 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2765 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2770 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2771 ract->set_active ();
2774 switch (Config->get_native_file_header_format ()) {
2776 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2779 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2782 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2785 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2788 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2791 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2794 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2799 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2800 ract->set_active ();
2803 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2805 set_transport_controllable_state (*node);
2810 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2812 if (Config->get_primary_clock_delta_edit_cursor()) {
2813 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2815 primary_clock.set (pos, 0, true);
2818 if (Config->get_secondary_clock_delta_edit_cursor()) {
2819 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2821 secondary_clock.set (pos);
2824 if (big_clock_window) {
2825 big_clock.set (pos);
2830 ARDOUR_UI::record_state_changed ()
2832 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2834 if (!session || !big_clock_window) {
2835 /* why bother - the clock isn't visible */
2839 switch (session->record_status()) {
2840 case Session::Recording:
2841 big_clock.set_widget_name ("BigClockRecording");
2844 big_clock.set_widget_name ("BigClockNonRecording");
2850 ARDOUR_UI::set_keybindings_path (string path)
2852 keybindings_path = path;
2856 ARDOUR_UI::save_keybindings ()
2858 if (can_save_keybindings) {
2859 AccelMap::save (user_keybindings_path);
2864 ARDOUR_UI::first_idle ()
2867 session->allow_auto_play (true);
2869 can_save_keybindings = true;
2874 ARDOUR_UI::store_clock_modes ()
2876 XMLNode* node = new XMLNode(X_("ClockModes"));
2878 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2879 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2882 session->add_extra_xml (*node);
2883 session->set_dirty ();
2888 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2889 : Controllable (name), ui (u), type(tp)
2895 ARDOUR_UI::TransportControllable::set_value (float val)
2897 if (type == ShuttleControl) {
2904 fract = -((0.5f - val)/0.5f);
2906 fract = ((val - 0.5f)/0.5f);
2910 ui.set_shuttle_fract (fract);
2915 /* do nothing: these are radio-style actions */
2923 action = X_("Roll");
2926 action = X_("Stop");
2929 action = X_("Goto Start");
2932 action = X_("Goto End");
2935 action = X_("Loop");
2938 action = X_("Play Selection");
2941 action = X_("Record");
2951 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2959 ARDOUR_UI::TransportControllable::get_value (void) const
2978 case ShuttleControl:
2988 ARDOUR_UI::TransportControllable::set_id (const string& str)
2994 ARDOUR_UI::setup_profile ()
2996 if (gdk_screen_width() < 1200) {
2997 Profile->set_small_screen ();
3000 if (getenv ("ARDOUR_SAE")) {
3001 Profile->set_sae ();
3002 Profile->set_single_package ();
3007 ARDOUR_UI::audioengine_setup ()