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 Config->save_state();
480 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
481 XMLNode mnode(mixer->get_state());
484 session->add_instant_xml (enode, session->path());
485 session->add_instant_xml (mnode, session->path());
487 Config->add_instant_xml (enode, get_user_ardour_path());
488 Config->add_instant_xml (mnode, get_user_ardour_path());
495 ARDOUR_UI::autosave_session ()
497 if (!Config->get_periodic_safety_backups())
501 session->maybe_write_autosave();
508 ARDOUR_UI::update_autosave ()
510 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
512 if (session->dirty()) {
513 if (_autosave_connection.connected()) {
514 _autosave_connection.disconnect();
517 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
518 Config->get_periodic_safety_backup_interval() * 1000);
521 if (_autosave_connection.connected()) {
522 _autosave_connection.disconnect();
528 ARDOUR_UI::backend_audio_error ()
530 MessageDialog win (_("Ardour could not connect to JACK."),
533 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
534 win.set_secondary_text(_("There are several possible reasons:\n\
536 1) JACK is not running.\n\
537 2) JACK is running as another user, perhaps root.\n\
538 3) There is already another client called \"ardour\".\n\
540 Please consider the possibilities, and perhaps (re)start JACK."));
542 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
543 win.set_default_response (RESPONSE_CLOSE);
546 win.set_position (Gtk::WIN_POS_CENTER);
548 if (!ARDOUR_COMMAND_LINE::no_splash) {
552 /* we just don't care about the result, but we want to block */
558 ARDOUR_UI::startup ()
560 using namespace ARDOUR_COMMAND_LINE;
564 new_session_dialog = new NewSessionDialog();
566 /* If no session name is given: we're not loading a session yet, nor creating a new one */
568 if (session_name.length()) {
570 /* Load session or start the new session dialog */
572 if (Session::find_session (session_name, path, name, isnew)) {
573 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
577 if (!ARDOUR_COMMAND_LINE::new_session) {
579 /* Supposed to be loading an existing session, but the session doesn't exist */
582 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
583 "To create it from the command line, start ardour as \"ardour --new %1"), path)
589 new_session_dialog->set_session_name (name);
590 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
591 _session_is_new = isnew;
596 bool have_backend = EngineControl::engine_running();
598 bool load_needed = false;
602 /* backend audio is working */
604 if (session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
605 /* need NSD to get session name and other info */
613 /* no backend audio, must bring up NSD to check configuration */
620 if (!new_session (session_name,have_backend)) {
632 if (load_session (session_name, name)) {
641 ARDOUR_UI::no_memory_warning ()
643 XMLNode node (X_("no-memory-warning"));
644 Config->add_instant_xml (node, get_user_ardour_path());
648 ARDOUR_UI::check_memory_locking ()
651 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
655 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
657 if (engine->is_realtime() && memory_warning_node == 0) {
659 struct rlimit limits;
661 long pages, page_size;
663 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
666 ram = (int64_t) pages * (int64_t) page_size;
669 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
673 if (limits.rlim_cur != RLIM_INFINITY) {
675 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
678 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
679 "This might cause Ardour to run out of memory before your system "
680 "runs out of memory. \n\n"
681 "You can view the memory limit with 'ulimit -l', "
682 "and it is normally controlled by /etc/security/limits.conf"));
684 VBox* vbox = msg.get_vbox();
686 CheckButton cb (_("Do not show this window again"));
688 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
690 hbox.pack_start (cb, true, false);
691 vbox->pack_start (hbox);
694 editor->ensure_float (msg);
706 if (session && session->dirty()) {
707 switch (ask_about_saving_session(_("quit"))) {
712 /* use the default name */
713 if (save_state_canfail ("")) {
714 /* failed - don't quit */
715 MessageDialog msg (*editor,
717 Ardour was unable to save your session.\n\n\
718 If you still wish to quit, please use the\n\n\
719 \"Just quit\" option."));
730 session->set_deletion_in_progress ();
733 Config->save_state();
734 ARDOUR_UI::config()->save_state();
739 ARDOUR_UI::ask_about_saving_session (const string & what)
741 ArdourDialog window (_("ardour: save session?"));
742 Gtk::HBox dhbox; // the hbox for the image and text
743 Gtk::Label prompt_label;
744 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
748 msg = string_compose(_("Don't %1"), what);
749 window.add_button (msg, RESPONSE_REJECT);
750 msg = string_compose(_("Just %1"), what);
751 window.add_button (msg, RESPONSE_APPLY);
752 msg = string_compose(_("Save and %1"), what);
753 window.add_button (msg, RESPONSE_ACCEPT);
755 window.set_default_response (RESPONSE_ACCEPT);
757 Gtk::Button noquit_button (msg);
758 noquit_button.set_name ("EditorGTKButton");
763 if (session->snap_name() == session->name()) {
766 type = _("snapshot");
768 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?"),
769 type, session->snap_name());
771 prompt_label.set_text (prompt);
772 prompt_label.set_name (X_("PrompterLabel"));
773 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
775 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
777 dhbox.set_homogeneous (false);
778 dhbox.pack_start (*dimage, false, false, 5);
779 dhbox.pack_start (prompt_label, true, false, 5);
780 window.get_vbox()->pack_start (dhbox);
782 window.set_name (_("Prompter"));
783 window.set_position (Gtk::WIN_POS_MOUSE);
784 window.set_modal (true);
785 window.set_resizable (false);
788 save_the_session = 0;
790 window.set_keep_above (true);
793 ResponseType r = (ResponseType) window.run();
798 case RESPONSE_ACCEPT: // save and get out of here
800 case RESPONSE_APPLY: // get out of here
810 ARDOUR_UI::every_second ()
813 update_buffer_load ();
814 update_disk_space ();
819 ARDOUR_UI::every_point_one_seconds ()
821 update_speed_display ();
822 RapidScreenUpdate(); /* EMIT_SIGNAL */
827 ARDOUR_UI::every_point_zero_one_seconds ()
829 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
834 ARDOUR_UI::update_sample_rate (nframes_t ignored)
838 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
840 if (!engine->connected()) {
842 snprintf (buf, sizeof (buf), _("disconnected"));
846 nframes_t rate = engine->frame_rate();
848 if (fmod (rate, 1000.0) != 0.0) {
849 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
850 (float) rate/1000.0f,
851 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
853 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
855 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
859 sample_rate_label.set_text (buf);
863 ARDOUR_UI::update_cpu_load ()
866 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
867 cpu_load_label.set_text (buf);
871 ARDOUR_UI::update_buffer_load ()
876 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
877 session->playback_load(), session->capture_load());
878 buffer_load_label.set_text (buf);
880 buffer_load_label.set_text ("");
885 ARDOUR_UI::count_recenabled_streams (Route& route)
887 Track* track = dynamic_cast<Track*>(&route);
888 if (track && track->diskstream()->record_enabled()) {
889 rec_enabled_streams += track->n_inputs();
894 ARDOUR_UI::update_disk_space()
900 nframes_t frames = session->available_capture_duration();
903 if (frames == max_frames) {
904 strcpy (buf, _("Disk: 24hrs+"));
909 nframes_t fr = session->frame_rate();
911 rec_enabled_streams = 0;
912 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
914 if (rec_enabled_streams) {
915 frames /= rec_enabled_streams;
918 hrs = frames / (fr * 3600);
919 frames -= hrs * fr * 3600;
920 mins = frames / (fr * 60);
921 frames -= mins * fr * 60;
924 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
927 disk_space_label.set_text (buf);
931 ARDOUR_UI::update_wall_clock ()
938 tm_now = localtime (&now);
940 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
941 wall_clock_label.set_text (buf);
947 ARDOUR_UI::session_menu (GdkEventButton *ev)
949 session_popup_menu->popup (0, 0);
954 ARDOUR_UI::redisplay_recent_sessions ()
956 vector<string *> *sessions;
957 vector<string *>::iterator i;
958 RecentSessionsSorter cmp;
960 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
961 recent_session_model->clear ();
964 ARDOUR::read_recent_sessions (rs);
967 recent_session_display.set_model (recent_session_model);
971 /* sort them alphabetically */
972 sort (rs.begin(), rs.end(), cmp);
973 sessions = new vector<string*>;
975 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
976 sessions->push_back (new string ((*i).second));
979 for (i = sessions->begin(); i != sessions->end(); ++i) {
981 vector<string*>* states;
982 vector<const gchar*> item;
983 string fullpath = *(*i);
985 /* remove any trailing / */
987 if (fullpath[fullpath.length()-1] == '/') {
988 fullpath = fullpath.substr (0, fullpath.length()-1);
991 /* now get available states for this session */
993 if ((states = Session::possible_states (fullpath)) == 0) {
998 TreeModel::Row row = *(recent_session_model->append());
1000 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1001 row[recent_session_columns.fullpath] = fullpath;
1003 if (states->size() > 1) {
1005 /* add the children */
1007 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1009 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1011 child_row[recent_session_columns.visible_name] = **i2;
1012 child_row[recent_session_columns.fullpath] = fullpath;
1021 recent_session_display.set_model (recent_session_model);
1026 ARDOUR_UI::build_session_selector ()
1028 session_selector_window = new ArdourDialog ("session selector");
1030 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1032 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1033 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1034 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1035 recent_session_model = TreeStore::create (recent_session_columns);
1036 recent_session_display.set_model (recent_session_model);
1037 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1038 recent_session_display.set_headers_visible (false);
1039 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1041 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1043 scroller->add (recent_session_display);
1044 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1046 session_selector_window->set_name ("SessionSelectorWindow");
1047 session_selector_window->set_size_request (200, 400);
1048 session_selector_window->get_vbox()->pack_start (*scroller);
1049 session_selector_window->show_all_children();
1053 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1055 session_selector_window->response (RESPONSE_ACCEPT);
1059 ARDOUR_UI::open_recent_session ()
1061 /* popup selector window */
1063 if (session_selector_window == 0) {
1064 build_session_selector ();
1067 redisplay_recent_sessions ();
1069 ResponseType r = (ResponseType) session_selector_window->run ();
1071 session_selector_window->hide();
1074 case RESPONSE_ACCEPT:
1080 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1082 if (i == recent_session_model->children().end()) {
1086 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1087 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1089 _session_is_new = false;
1091 load_session (path, state);
1095 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1097 struct stat statbuf;
1099 if (stat (info.filename.c_str(), &statbuf) != 0) {
1103 if (!S_ISDIR(statbuf.st_mode)) {
1109 string session_file = info.filename;
1110 session_file += '/';
1111 session_file += Glib::path_get_basename (info.filename);
1112 session_file += ".ardour";
1114 if (stat (session_file.c_str(), &statbuf) != 0) {
1118 return S_ISREG (statbuf.st_mode);
1122 ARDOUR_UI::check_audioengine ()
1125 if (!engine->connected()) {
1126 MessageDialog msg (_("Ardour is not connected to JACK\n"
1127 "You cannot open or close sessions in this condition"));
1138 ARDOUR_UI::open_session ()
1140 if (!check_audioengine()) {
1144 /* popup selector window */
1146 if (open_session_selector == 0) {
1148 /* ardour sessions are folders */
1150 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1151 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1152 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1154 FileFilter session_filter;
1155 session_filter.add_pattern ("*.ardour");
1156 session_filter.set_name (_("Ardour sessions"));
1157 open_session_selector->add_filter (session_filter);
1158 open_session_selector->set_filter (session_filter);
1161 int response = open_session_selector->run();
1162 open_session_selector->hide ();
1165 case RESPONSE_ACCEPT:
1168 open_session_selector->hide();
1172 open_session_selector->hide();
1173 string session_path = open_session_selector->get_filename();
1177 if (session_path.length() > 0) {
1178 if (Session::find_session (session_path, path, name, isnew) == 0) {
1179 _session_is_new = isnew;
1180 load_session (path, name);
1187 ARDOUR_UI::session_add_midi_track ()
1189 cerr << _("Patience is a virtue.\n");
1193 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1195 list<boost::shared_ptr<AudioTrack> > tracks;
1196 Session::RouteList routes;
1199 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1205 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1207 if (tracks.size() != how_many) {
1208 if (how_many == 1) {
1209 error << _("could not create a new audio track") << endmsg;
1211 error << string_compose (_("could only create %1 of %2 new audio %3"),
1212 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1218 routes = session->new_audio_route (input_channels, output_channels, how_many);
1220 if (routes.size() != how_many) {
1221 if (how_many == 1) {
1222 error << _("could not create a new audio track") << endmsg;
1224 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1230 if (need_control_room_outs) {
1236 route->set_stereo_control_outs (control_lr_channels);
1237 route->control_outs()->set_stereo_pan (pans, this);
1239 #endif /* CONTROLOUTS */
1243 cerr << "About to complain about JACK\n";
1244 MessageDialog msg (*editor,
1245 _("There are insufficient JACK ports available\n\
1246 to create a new track or bus.\n\
1247 You should save Ardour, exit and\n\
1248 restart JACK with more ports."));
1254 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1256 nframes_t _preroll = 0;
1259 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1260 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1262 if (new_position > _preroll) {
1263 new_position -= _preroll;
1268 session->request_locate (new_position);
1273 ARDOUR_UI::transport_goto_start ()
1276 session->goto_start();
1279 /* force displayed area in editor to start no matter
1280 what "follow playhead" setting is.
1284 editor->reset_x_origin (session->current_start_frame());
1290 ARDOUR_UI::transport_goto_zero ()
1293 session->request_locate (0);
1296 /* force displayed area in editor to start no matter
1297 what "follow playhead" setting is.
1301 editor->reset_x_origin (0);
1307 ARDOUR_UI::transport_goto_end ()
1310 nframes_t frame = session->current_end_frame();
1311 session->request_locate (frame);
1313 /* force displayed area in editor to start no matter
1314 what "follow playhead" setting is.
1318 editor->reset_x_origin (frame);
1324 ARDOUR_UI::transport_stop ()
1330 if (session->is_auditioning()) {
1331 session->cancel_audition ();
1335 if (session->get_play_loop ()) {
1336 session->request_play_loop (false);
1339 session->request_stop ();
1343 ARDOUR_UI::transport_stop_and_forget_capture ()
1346 session->request_stop (true);
1351 ARDOUR_UI::remove_last_capture()
1354 editor->remove_last_capture();
1359 ARDOUR_UI::transport_record ()
1362 switch (session->record_status()) {
1363 case Session::Disabled:
1364 if (session->ntracks() == 0) {
1365 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1369 session->maybe_enable_record ();
1371 case Session::Recording:
1372 case Session::Enabled:
1373 session->disable_record (false, true);
1379 ARDOUR_UI::transport_roll ()
1387 rolling = session->transport_rolling ();
1389 if (session->get_play_loop()) {
1390 session->request_play_loop (false);
1391 auto_loop_button.set_visual_state (1);
1392 roll_button.set_visual_state (1);
1393 } else if (session->get_play_range ()) {
1394 session->request_play_range (false);
1395 play_selection_button.set_visual_state (0);
1396 } else if (rolling) {
1397 session->request_locate (session->last_transport_start(), true);
1400 session->request_transport_speed (1.0f);
1404 ARDOUR_UI::transport_loop()
1407 if (session->get_play_loop()) {
1408 if (session->transport_rolling()) {
1409 Location * looploc = session->locations()->auto_loop_location();
1411 session->request_locate (looploc->start(), true);
1416 session->request_play_loop (true);
1422 ARDOUR_UI::transport_play_selection ()
1428 if (!session->get_play_range()) {
1429 session->request_stop ();
1432 editor->play_selection ();
1436 ARDOUR_UI::transport_rewind (int option)
1438 float current_transport_speed;
1441 current_transport_speed = session->transport_speed();
1443 if (current_transport_speed >= 0.0f) {
1446 session->request_transport_speed (-1.0f);
1449 session->request_transport_speed (-4.0f);
1452 session->request_transport_speed (-0.5f);
1457 session->request_transport_speed (current_transport_speed * 1.5f);
1463 ARDOUR_UI::transport_forward (int option)
1465 float current_transport_speed;
1468 current_transport_speed = session->transport_speed();
1470 if (current_transport_speed <= 0.0f) {
1473 session->request_transport_speed (1.0f);
1476 session->request_transport_speed (4.0f);
1479 session->request_transport_speed (0.5f);
1484 session->request_transport_speed (current_transport_speed * 1.5f);
1490 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1496 boost::shared_ptr<Route> r;
1498 if ((r = session->route_by_remote_id (dstream)) != 0) {
1502 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1503 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1512 ARDOUR_UI::queue_transport_change ()
1514 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1518 ARDOUR_UI::map_transport_state ()
1520 float sp = session->transport_speed();
1523 transport_rolling ();
1524 } else if (sp < 0.0f) {
1525 transport_rewinding ();
1526 } else if (sp > 0.0f) {
1527 transport_forwarding ();
1529 transport_stopped ();
1534 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1536 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1537 (int) adj.get_value()].c_str());
1541 ARDOUR_UI::engine_stopped ()
1543 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1544 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1545 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1549 ARDOUR_UI::engine_running ()
1551 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1552 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1553 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1555 Glib::RefPtr<Action> action;
1556 char* action_name = 0;
1558 switch (engine->frames_per_cycle()) {
1560 action_name = X_("JACKLatency32");
1563 action_name = X_("JACKLatency64");
1566 action_name = X_("JACKLatency128");
1569 action_name = X_("JACKLatency512");
1572 action_name = X_("JACKLatency1024");
1575 action_name = X_("JACKLatency2048");
1578 action_name = X_("JACKLatency4096");
1581 action_name = X_("JACKLatency8192");
1584 /* XXX can we do anything useful ? */
1590 action = ActionManager::get_action (X_("JACK"), action_name);
1593 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1594 ract->set_active ();
1600 ARDOUR_UI::engine_halted ()
1602 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1604 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1605 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1607 update_sample_rate (0);
1609 MessageDialog msg (*editor,
1611 JACK has either been shutdown or it\n\
1612 disconnected Ardour because Ardour\n\
1613 was not fast enough. You can save the\n\
1614 session and/or try to reconnect to JACK ."));
1619 ARDOUR_UI::do_engine_start ()
1627 error << _("Unable to start the session running")
1637 ARDOUR_UI::setup_theme ()
1639 theme_manager->setup_theme();
1643 ARDOUR_UI::update_clocks ()
1645 if (!editor || !editor->dragging_playhead()) {
1646 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1651 ARDOUR_UI::start_clocking ()
1653 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1657 ARDOUR_UI::stop_clocking ()
1659 clock_signal_connection.disconnect ();
1663 ARDOUR_UI::toggle_clocking ()
1666 if (clock_button.get_active()) {
1675 ARDOUR_UI::_blink (void *arg)
1678 ((ARDOUR_UI *) arg)->blink ();
1685 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1689 ARDOUR_UI::start_blinking ()
1691 /* Start the blink signal. Everybody with a blinking widget
1692 uses Blink to drive the widget's state.
1695 if (blink_timeout_tag < 0) {
1697 blink_timeout_tag = g_timeout_add (240, _blink, this);
1702 ARDOUR_UI::stop_blinking ()
1704 if (blink_timeout_tag >= 0) {
1705 g_source_remove (blink_timeout_tag);
1706 blink_timeout_tag = -1;
1711 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1717 if (io.n_inputs() == 0) {
1722 /* XXX we're not handling multiple ports yet. */
1724 const char **connections = io.input(0)->get_connections();
1726 if (connections == 0 || connections[0] == '\0') {
1729 buf = connections[0];
1736 if (io.n_outputs() == 0) {
1741 /* XXX we're not handling multiple ports yet. */
1743 const char **connections = io.output(0)->get_connections();
1745 if (connections == 0 || connections[0] == '\0') {
1748 buf = connections[0];
1755 /** Ask the user for the name of a new shapshot and then take it.
1758 ARDOUR_UI::snapshot_session ()
1760 ArdourPrompter prompter (true);
1764 struct tm local_time;
1767 localtime_r (&n, &local_time);
1768 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1770 prompter.set_name ("Prompter");
1771 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1772 prompter.set_prompt (_("Name of New Snapshot"));
1773 prompter.set_initial_text (timebuf);
1775 switch (prompter.run()) {
1776 case RESPONSE_ACCEPT:
1777 prompter.get_result (snapname);
1778 if (snapname.length()){
1779 save_state (snapname);
1789 ARDOUR_UI::save_state (const string & name)
1791 (void) save_state_canfail (name);
1795 ARDOUR_UI::save_state_canfail (string name)
1800 if (name.length() == 0) {
1801 name = session->snap_name();
1804 if ((ret = session->save_state (name)) != 0) {
1808 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1813 ARDOUR_UI::restore_state (string name)
1816 if (name.length() == 0) {
1817 name = session->name();
1819 session->restore_state (name);
1824 ARDOUR_UI::primary_clock_value_changed ()
1827 session->request_locate (primary_clock.current_time ());
1832 ARDOUR_UI::secondary_clock_value_changed ()
1835 session->request_locate (secondary_clock.current_time ());
1840 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1842 if (session && dstream && dstream->record_enabled()) {
1844 Session::RecordState rs;
1846 rs = session->record_status ();
1849 case Session::Disabled:
1850 case Session::Enabled:
1851 if (w->get_state() != STATE_SELECTED) {
1852 w->set_state (STATE_SELECTED);
1856 case Session::Recording:
1857 if (w->get_state() != STATE_ACTIVE) {
1858 w->set_state (STATE_ACTIVE);
1864 if (w->get_state() != STATE_NORMAL) {
1865 w->set_state (STATE_NORMAL);
1871 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1877 switch (session->record_status()) {
1878 case Session::Enabled:
1880 rec_button.set_visual_state (2);
1882 rec_button.set_visual_state (0);
1886 case Session::Recording:
1887 rec_button.set_visual_state (1);
1891 rec_button.set_visual_state (0);
1897 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1905 ARDOUR_UI::save_template ()
1908 ArdourPrompter prompter (true);
1911 if (!check_audioengine()) {
1915 prompter.set_name (X_("Prompter"));
1916 prompter.set_prompt (_("Name for mix template:"));
1917 prompter.set_initial_text(session->name() + _("-template"));
1918 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1920 switch (prompter.run()) {
1921 case RESPONSE_ACCEPT:
1922 prompter.get_result (name);
1924 if (name.length()) {
1925 session->save_template (name);
1935 ARDOUR_UI::new_session (Glib::ustring predetermined_path, bool have_engine)
1937 string session_name;
1938 string session_path;
1940 int response = Gtk::RESPONSE_NONE;
1942 new_session_dialog->set_modal(true);
1943 new_session_dialog->set_name (predetermined_path);
1944 new_session_dialog->reset_recent();
1945 new_session_dialog->show();
1946 new_session_dialog->set_current_page (0);
1950 new_session_dialog->set_have_engine (have_engine);
1952 response = new_session_dialog->run ();
1954 _session_is_new = false;
1956 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1961 new_session_dialog->hide ();
1964 } else if (response == Gtk::RESPONSE_NONE) {
1966 /* Clear was pressed */
1967 new_session_dialog->reset();
1971 /* first things first ... we need an audio engine running */
1974 if (start_backend_audio ()) {
1975 new_session_dialog->hide ();
1983 /* now handle possible affirmative responses */
1985 if (response == Gtk::RESPONSE_YES) {
1987 /* YES == OPEN from the open session tab */
1989 session_name = new_session_dialog->session_name();
1991 if (session_name.empty()) {
1992 response = Gtk::RESPONSE_NONE;
1996 if (session_name[0] == '/' ||
1997 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1998 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1999 load_session (Glib::path_get_dirname (session_name), session_name);
2001 session_path = new_session_dialog->session_folder();
2002 load_session (session_path, session_name);
2005 } else if (response == Gtk::RESPONSE_OK) {
2007 /* OK == OPEN from new session tab */
2009 session_name = new_session_dialog->session_name();
2011 if (new_session_dialog->get_current_page() == 1) {
2013 if (session_name.empty()) {
2014 response = Gtk::RESPONSE_NONE;
2018 if (session_name[0] == '/' ||
2019 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2020 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2021 load_session (Glib::path_get_dirname (session_name), session_name);
2023 session_path = new_session_dialog->session_folder();
2024 load_session (session_path, session_name);
2029 if (session_name.empty()) {
2030 response = Gtk::RESPONSE_NONE;
2034 /* handle what appear to be paths rather than just a name */
2036 if (session_name[0] == '/' ||
2037 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2038 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2040 session_path = Glib::path_get_dirname (session_name);
2041 session_name = Glib::path_get_basename (session_name);
2045 session_path = new_session_dialog->session_folder();
2049 //XXX This is needed because session constructor wants a
2050 //non-existant path. hopefully this will be fixed at some point.
2052 session_path = Glib::build_filename (session_path, session_name);
2054 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2056 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2058 MessageDialog msg (str,
2060 Gtk::MESSAGE_WARNING,
2061 Gtk::BUTTONS_YES_NO,
2065 msg.set_name (X_("CleanupDialog"));
2066 msg.set_wmclass (X_("existing_session"), "Ardour");
2067 msg.set_position (Gtk::WIN_POS_MOUSE);
2069 switch (msg.run()) {
2071 load_session (session_path, session_name);
2075 response = RESPONSE_NONE;
2076 new_session_dialog->reset ();
2081 _session_is_new = true;
2083 std::string template_name = new_session_dialog->session_template_name();
2085 if (new_session_dialog->use_session_template()) {
2087 load_session (session_path, session_name, &template_name);
2093 AutoConnectOption iconnect;
2094 AutoConnectOption oconnect;
2098 if (Profile->get_sae()) {
2102 iconnect = AutoConnectPhysical;
2103 oconnect = AutoConnectMaster;
2104 nphysin = 0; // use all available
2105 nphysout = 0; // use all available
2109 /* get settings from advanced section of NSD */
2111 if (new_session_dialog->create_control_bus()) {
2112 cchns = (uint32_t) new_session_dialog->control_channel_count();
2117 if (new_session_dialog->create_master_bus()) {
2118 mchns = (uint32_t) new_session_dialog->master_channel_count();
2123 if (new_session_dialog->connect_inputs()) {
2124 iconnect = AutoConnectPhysical;
2126 iconnect = AutoConnectOption (0);
2129 /// @todo some minor tweaks.
2131 if (new_session_dialog->connect_outs_to_master()) {
2132 oconnect = AutoConnectMaster;
2133 } else if (new_session_dialog->connect_outs_to_physical()) {
2134 oconnect = AutoConnectPhysical;
2136 oconnect = AutoConnectOption (0);
2139 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2140 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2143 if (build_session (session_path,
2151 engine->frame_rate() * 60 * 5)) {
2153 response = Gtk::RESPONSE_NONE;
2154 new_session_dialog->reset ();
2161 } while (response == Gtk::RESPONSE_NONE);
2165 new_session_dialog->get_window()->set_cursor();
2166 new_session_dialog->hide();
2171 ARDOUR_UI::close_session()
2173 if (!check_audioengine()) {
2178 new_session ("", true);
2182 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2184 Session *new_session;
2186 session_loaded = false;
2188 if (!check_audioengine()) {
2192 x = unload_session ();
2200 /* if it already exists, we must have write access */
2202 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2203 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2204 "This prevents the session from being loaded."));
2210 new_session = new Session (*engine, path, snap_name, mix_template);
2215 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2219 connect_to_session (new_session);
2221 Config->set_current_owner (ConfigVariableBase::Interface);
2223 session_loaded = true;
2225 goto_editor_window ();
2228 session->set_clean ();
2231 editor->edit_cursor_position (true);
2236 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2237 uint32_t control_channels,
2238 uint32_t master_channels,
2239 AutoConnectOption input_connect,
2240 AutoConnectOption output_connect,
2243 nframes_t initial_length)
2245 Session *new_session;
2248 if (!check_audioengine()) {
2252 session_loaded = false;
2254 x = unload_session ();
2262 _session_is_new = true;
2265 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2266 control_channels, master_channels, nphysin, nphysout, initial_length);
2271 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2276 connect_to_session (new_session);
2278 session_loaded = true;
2286 editor->show_window ();
2297 ARDOUR_UI::show_splash ()
2300 about = new About();
2301 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2308 ARDOUR_UI::about_signal_response(int response)
2314 ARDOUR_UI::hide_splash ()
2317 about->get_window()->set_cursor ();
2323 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2327 removed = rep.paths.size();
2330 MessageDialog msgd (*editor,
2331 _("No audio files were ready for cleanup"),
2334 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2335 msgd.set_secondary_text (_("If this seems suprising, \n\
2336 check for any existing snapshots.\n\
2337 These may still include regions that\n\
2338 require some unused files to continue to exist."));
2344 ArdourDialog results (_("ardour: cleanup"), true, false);
2346 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2347 CleanupResultsModelColumns() {
2351 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2352 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2356 CleanupResultsModelColumns results_columns;
2357 Glib::RefPtr<Gtk::ListStore> results_model;
2358 Gtk::TreeView results_display;
2360 results_model = ListStore::create (results_columns);
2361 results_display.set_model (results_model);
2362 results_display.append_column (list_title, results_columns.visible_name);
2364 results_display.set_name ("CleanupResultsList");
2365 results_display.set_headers_visible (true);
2366 results_display.set_headers_clickable (false);
2367 results_display.set_reorderable (false);
2369 Gtk::ScrolledWindow list_scroller;
2372 Gtk::HBox dhbox; // the hbox for the image and text
2373 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2374 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2376 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2378 if (rep.space < 1048576.0f) {
2380 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2382 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2386 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2388 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2392 dhbox.pack_start (*dimage, true, false, 5);
2393 dhbox.pack_start (txt, true, false, 5);
2395 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2396 TreeModel::Row row = *(results_model->append());
2397 row[results_columns.visible_name] = *i;
2398 row[results_columns.fullpath] = *i;
2401 list_scroller.add (results_display);
2402 list_scroller.set_size_request (-1, 150);
2403 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2405 dvbox.pack_start (dhbox, true, false, 5);
2406 dvbox.pack_start (list_scroller, true, false, 5);
2407 ddhbox.pack_start (dvbox, true, false, 5);
2409 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2410 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2411 results.set_default_response (RESPONSE_CLOSE);
2412 results.set_position (Gtk::WIN_POS_MOUSE);
2413 results.show_all_children ();
2414 results.set_resizable (false);
2421 ARDOUR_UI::cleanup ()
2424 /* shouldn't happen: menu item is insensitive */
2429 MessageDialog checker (_("Are you sure you want to cleanup?"),
2431 Gtk::MESSAGE_QUESTION,
2432 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2434 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2435 ALL undo/redo information will be lost if you cleanup.\n\
2436 After cleanup, unused audio files will be moved to a \
2437 \"dead sounds\" location."));
2439 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2440 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2441 checker.set_default_response (RESPONSE_CANCEL);
2443 checker.set_name (_("CleanupDialog"));
2444 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2445 checker.set_position (Gtk::WIN_POS_MOUSE);
2447 switch (checker.run()) {
2448 case RESPONSE_ACCEPT:
2454 Session::cleanup_report rep;
2456 editor->prepare_for_cleanup ();
2458 /* do not allow flush until a session is reloaded */
2460 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2462 act->set_sensitive (false);
2465 if (session->cleanup_sources (rep)) {
2470 display_cleanup_results (rep,
2473 The following %1 %2 not in use and \n\
2474 have been moved to:\n\
2476 Flushing the wastebasket will \n\
2477 release an additional\n\
2478 %4 %5bytes of disk space.\n"
2486 ARDOUR_UI::flush_trash ()
2489 /* shouldn't happen: menu item is insensitive */
2493 Session::cleanup_report rep;
2495 if (session->cleanup_trash_sources (rep)) {
2499 display_cleanup_results (rep,
2501 _("The following %1 %2 deleted from\n\
2503 releasing %4 %5bytes of disk space"));
2507 ARDOUR_UI::add_route (Gtk::Window* float_window)
2515 if (add_route_dialog == 0) {
2516 add_route_dialog = new AddRouteDialog;
2518 add_route_dialog->set_transient_for (*float_window);
2522 if (add_route_dialog->is_visible()) {
2523 /* we're already doing this */
2527 ResponseType r = (ResponseType) add_route_dialog->run ();
2529 add_route_dialog->hide();
2532 case RESPONSE_ACCEPT:
2539 if ((count = add_route_dialog->count()) <= 0) {
2543 uint32_t input_chan = add_route_dialog->channels ();
2544 uint32_t output_chan;
2545 string name_template = add_route_dialog->name_template ();
2546 bool track = add_route_dialog->track ();
2548 AutoConnectOption oac = Config->get_output_auto_connect();
2550 if (oac & AutoConnectMaster) {
2551 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2553 output_chan = input_chan;
2556 /* XXX do something with name template */
2559 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2561 session_add_audio_bus (input_chan, output_chan, count);
2566 ARDOUR_UI::mixer_settings () const
2571 node = session->instant_xml(X_("Mixer"), session->path());
2573 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2577 node = new XMLNode (X_("Mixer"));
2584 ARDOUR_UI::editor_settings () const
2589 node = session->instant_xml(X_("Editor"), session->path());
2591 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2595 node = new XMLNode (X_("Editor"));
2601 ARDOUR_UI::keyboard_settings () const
2605 node = Config->extra_xml(X_("Keyboard"));
2608 node = new XMLNode (X_("Keyboard"));
2614 ARDOUR_UI::halt_on_xrun_message ()
2616 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2618 MessageDialog msg (*editor,
2619 _("Recording was stopped because your system could not keep up."));
2624 ARDOUR_UI::disk_overrun_handler ()
2626 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2628 if (!have_disk_speed_dialog_displayed) {
2629 have_disk_speed_dialog_displayed = true;
2630 MessageDialog* msg = new MessageDialog (*editor, _("\
2631 The disk system on your computer\n\
2632 was not able to keep up with Ardour.\n\
2634 Specifically, it failed to write data to disk\n\
2635 quickly enough to keep up with recording.\n"));
2636 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2642 ARDOUR_UI::disk_underrun_handler ()
2644 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2646 if (!have_disk_speed_dialog_displayed) {
2647 have_disk_speed_dialog_displayed = true;
2648 MessageDialog* msg = new MessageDialog (*editor,
2649 _("The disk system on your computer\n\
2650 was not able to keep up with Ardour.\n\
2652 Specifically, it failed to read data from disk\n\
2653 quickly enough to keep up with playback.\n"));
2654 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2660 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2662 have_disk_speed_dialog_displayed = false;
2667 ARDOUR_UI::pending_state_dialog ()
2669 ArdourDialog dialog ("pending state dialog");
2671 This session appears to have been in\n\
2672 middle of recording when ardour or\n\
2673 the computer was shutdown.\n\
2675 Ardour can recover any captured audio for\n\
2676 you, or it can ignore it. Please decide\n\
2677 what you would like to do.\n"));
2679 dialog.get_vbox()->pack_start (message);
2680 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2681 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2683 dialog.set_position (WIN_POS_CENTER);
2686 switch (dialog.run ()) {
2687 case RESPONSE_ACCEPT:
2695 ARDOUR_UI::disconnect_from_jack ()
2698 if( engine->disconnect_from_jack ()) {
2699 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2703 update_sample_rate (0);
2708 ARDOUR_UI::reconnect_to_jack ()
2711 if (engine->reconnect_to_jack ()) {
2712 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2716 update_sample_rate (0);
2721 ARDOUR_UI::cmdline_new_session (string path)
2723 if (path[0] != '/') {
2724 char buf[PATH_MAX+1];
2727 getcwd (buf, sizeof (buf));
2736 _will_create_new_session_automatically = false; /* done it */
2737 return FALSE; /* don't call it again */
2741 ARDOUR_UI::use_config ()
2743 Glib::RefPtr<Action> act;
2745 switch (Config->get_native_file_data_format ()) {
2747 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2750 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2753 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2758 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2759 ract->set_active ();
2762 switch (Config->get_native_file_header_format ()) {
2764 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2767 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2770 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2773 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2776 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2779 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2782 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2787 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2788 ract->set_active ();
2791 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2793 set_transport_controllable_state (*node);
2798 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2800 if (Config->get_primary_clock_delta_edit_cursor()) {
2801 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2803 primary_clock.set (pos, 0, true);
2806 if (Config->get_secondary_clock_delta_edit_cursor()) {
2807 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2809 secondary_clock.set (pos);
2812 if (big_clock_window) {
2813 big_clock.set (pos);
2818 ARDOUR_UI::record_state_changed ()
2820 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2822 if (!session || !big_clock_window) {
2823 /* why bother - the clock isn't visible */
2827 switch (session->record_status()) {
2828 case Session::Recording:
2829 big_clock.set_widget_name ("BigClockRecording");
2832 big_clock.set_widget_name ("BigClockNonRecording");
2838 ARDOUR_UI::set_keybindings_path (string path)
2840 keybindings_path = path;
2844 ARDOUR_UI::save_keybindings ()
2846 if (can_save_keybindings) {
2847 AccelMap::save (user_keybindings_path);
2852 ARDOUR_UI::first_idle ()
2855 session->allow_auto_play (true);
2857 can_save_keybindings = true;
2862 ARDOUR_UI::store_clock_modes ()
2864 XMLNode* node = new XMLNode(X_("ClockModes"));
2866 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2867 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2870 session->add_extra_xml (*node);
2871 session->set_dirty ();
2876 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2877 : Controllable (name), ui (u), type(tp)
2883 ARDOUR_UI::TransportControllable::set_value (float val)
2885 if (type == ShuttleControl) {
2892 fract = -((0.5f - val)/0.5f);
2894 fract = ((val - 0.5f)/0.5f);
2898 ui.set_shuttle_fract (fract);
2903 /* do nothing: these are radio-style actions */
2911 action = X_("Roll");
2914 action = X_("Stop");
2917 action = X_("Goto Start");
2920 action = X_("Goto End");
2923 action = X_("Loop");
2926 action = X_("Play Selection");
2929 action = X_("Record");
2939 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2947 ARDOUR_UI::TransportControllable::get_value (void) const
2966 case ShuttleControl:
2976 ARDOUR_UI::TransportControllable::set_id (const string& str)
2982 ARDOUR_UI::setup_profile ()
2984 if (gdk_screen_width() < 1200) {
2985 Profile->set_small_screen ();
2988 if (getenv ("ARDOUR_SAE")) {
2989 Profile->set_sae ();
2990 Profile->set_single_package ();
2995 ARDOUR_UI::audioengine_setup ()