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();
169 _session_is_new = false;
170 big_clock_window = 0;
171 session_selector_window = 0;
172 new_session_dialog = 0;
173 last_key_press_time = 0;
174 connection_editor = 0;
175 add_route_dialog = 0;
179 open_session_selector = 0;
180 have_configure_timeout = false;
181 have_disk_speed_dialog_displayed = false;
182 _will_create_new_session_automatically = false;
183 session_loaded = false;
184 last_speed_displayed = -1.0f;
186 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
187 /* all changes go to the user directory */
188 user_keybindings_path = get_user_ardour_path ();
189 user_keybindings_path += '/';
190 user_keybindings_path += "ardour.bindings";
192 can_save_keybindings = false;
194 last_configure_time.tv_sec = 0;
195 last_configure_time.tv_usec = 0;
197 shuttle_grabbed = false;
199 shuttle_max_speed = 8.0f;
201 shuttle_style_menu = 0;
202 shuttle_unit_menu = 0;
204 gettimeofday (&last_peak_grab, 0);
205 gettimeofday (&last_shuttle_request, 0);
207 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
208 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
210 /* handle pending state with a dialog */
212 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
214 /* lets get this party started */
217 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
218 setup_gtk_ardour_enums ();
219 Config->set_current_owner (ConfigVariableBase::Interface);
222 } catch (failed_constructor& err) {
223 error << _("could not initialize Ardour.") << endmsg;
228 /* we like keyboards */
230 keyboard = new Keyboard;
232 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
233 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
237 ARDOUR_UI::start_backend_audio ()
239 if (new_session_dialog->engine_control.start_engine ()) {
247 ARDOUR_UI::create_engine ()
249 // this gets called every time by new_session()
256 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
257 } catch (AudioEngine::NoBackendAvailable& err) {
258 backend_audio_error ();
259 error << string_compose (_("Could not connect to JACK server as \"%1\""), ARDOUR_COMMAND_LINE::jack_client_name) << endmsg;
263 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
264 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
265 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
266 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
272 ARDOUR_UI::post_engine ()
274 /* Things to be done once we create the AudioEngine
277 check_memory_locking();
279 ActionManager::init ();
282 if (setup_windows ()) {
283 throw failed_constructor ();
286 /* this is the first point at which all the keybindings are available */
288 if (ARDOUR_COMMAND_LINE::show_key_actions) {
289 vector<string> names;
290 vector<string> paths;
292 vector<AccelKey> bindings;
294 ActionManager::get_all_actions (names, paths, keys, bindings);
296 vector<string>::iterator n;
297 vector<string>::iterator k;
298 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
299 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
305 blink_timeout_tag = -1;
307 /* the global configuration object is now valid */
311 /* this being a GUI and all, we want peakfiles */
313 AudioFileSource::set_build_peakfiles (true);
314 AudioFileSource::set_build_missing_peakfiles (true);
316 /* set default clock modes */
318 primary_clock.set_mode (AudioClock::SMPTE);
319 secondary_clock.set_mode (AudioClock::BBT);
321 /* start the time-of-day-clock */
323 update_wall_clock ();
324 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
326 update_disk_space ();
328 update_sample_rate (engine->frame_rate());
330 /* now start and maybe save state */
332 if (do_engine_start () == 0) {
333 if (session && _session_is_new) {
334 /* we need to retain initial visual
335 settings for a new session
337 session->save_state ("");
342 ARDOUR_UI::~ARDOUR_UI ()
344 save_ardour_state ();
358 if (add_route_dialog) {
359 delete add_route_dialog;
362 if (new_session_dialog) {
363 delete new_session_dialog;
368 ARDOUR_UI::configure_timeout ()
373 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
374 /* no configure events yet */
378 gettimeofday (&now, 0);
379 timersub (&now, &last_configure_time, &diff);
381 /* force a gap of 0.5 seconds since the last configure event
384 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
387 have_configure_timeout = false;
388 save_ardour_state ();
394 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
396 if (have_configure_timeout) {
397 gettimeofday (&last_configure_time, 0);
399 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
400 have_configure_timeout = true;
407 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
409 const XMLProperty* prop;
411 if ((prop = node.property ("roll")) != 0) {
412 roll_controllable.set_id (prop->value());
414 if ((prop = node.property ("stop")) != 0) {
415 stop_controllable.set_id (prop->value());
417 if ((prop = node.property ("goto_start")) != 0) {
418 goto_start_controllable.set_id (prop->value());
420 if ((prop = node.property ("goto_end")) != 0) {
421 goto_end_controllable.set_id (prop->value());
423 if ((prop = node.property ("auto_loop")) != 0) {
424 auto_loop_controllable.set_id (prop->value());
426 if ((prop = node.property ("play_selection")) != 0) {
427 play_selection_controllable.set_id (prop->value());
429 if ((prop = node.property ("rec")) != 0) {
430 rec_controllable.set_id (prop->value());
432 if ((prop = node.property ("shuttle")) != 0) {
433 shuttle_controllable.set_id (prop->value());
438 ARDOUR_UI::get_transport_controllable_state ()
440 XMLNode* node = new XMLNode(X_("TransportControllables"));
443 roll_controllable.id().print (buf, sizeof (buf));
444 node->add_property (X_("roll"), buf);
445 stop_controllable.id().print (buf, sizeof (buf));
446 node->add_property (X_("stop"), buf);
447 goto_start_controllable.id().print (buf, sizeof (buf));
448 node->add_property (X_("goto_start"), buf);
449 goto_end_controllable.id().print (buf, sizeof (buf));
450 node->add_property (X_("goto_end"), buf);
451 auto_loop_controllable.id().print (buf, sizeof (buf));
452 node->add_property (X_("auto_loop"), buf);
453 play_selection_controllable.id().print (buf, sizeof (buf));
454 node->add_property (X_("play_selection"), buf);
455 rec_controllable.id().print (buf, sizeof (buf));
456 node->add_property (X_("rec"), buf);
457 shuttle_controllable.id().print (buf, sizeof (buf));
458 node->add_property (X_("shuttle"), buf);
464 ARDOUR_UI::save_ardour_state ()
466 if (!keyboard || !mixer || !editor) {
470 /* XXX this is all a bit dubious. add_extra_xml() uses
471 a different lifetime model from add_instant_xml().
474 XMLNode* node = new XMLNode (keyboard->get_state());
475 Config->add_extra_xml (*node);
476 Config->add_extra_xml (get_transport_controllable_state());
477 Config->save_state();
479 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
480 XMLNode mnode(mixer->get_state());
483 session->add_instant_xml (enode, session->path());
484 session->add_instant_xml (mnode, session->path());
486 Config->add_instant_xml (enode, get_user_ardour_path());
487 Config->add_instant_xml (mnode, get_user_ardour_path());
494 ARDOUR_UI::autosave_session ()
496 if (!Config->get_periodic_safety_backups())
500 session->maybe_write_autosave();
507 ARDOUR_UI::update_autosave ()
509 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
511 if (session->dirty()) {
512 if (_autosave_connection.connected()) {
513 _autosave_connection.disconnect();
516 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
517 Config->get_periodic_safety_backup_interval() * 1000);
520 if (_autosave_connection.connected()) {
521 _autosave_connection.disconnect();
527 ARDOUR_UI::backend_audio_error ()
529 MessageDialog win (_("Ardour could not connect to JACK."),
532 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
533 win.set_secondary_text(_("There are several possible reasons:\n\
535 1) JACK is not running.\n\
536 2) JACK is running as another user, perhaps root.\n\
537 3) There is already another client called \"ardour\".\n\
539 Please consider the possibilities, and perhaps (re)start JACK."));
541 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
542 win.set_default_response (RESPONSE_CLOSE);
545 win.set_position (Gtk::WIN_POS_CENTER);
547 if (!ARDOUR_COMMAND_LINE::no_splash) {
551 /* we just don't care about the result, but we want to block */
557 ARDOUR_UI::startup ()
559 using namespace ARDOUR_COMMAND_LINE;
563 new_session_dialog = new NewSessionDialog();
565 /* If no session name is given: we're not loading a session yet, nor creating a new one */
567 if (session_name.length()) {
569 /* Load session or start the new session dialog */
571 if (Session::find_session (session_name, path, name, isnew)) {
572 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
576 if (!ARDOUR_COMMAND_LINE::new_session) {
578 /* Supposed to be loading an existing session, but the session doesn't exist */
581 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
582 "To create it from the command line, start ardour as \"ardour --new %1"), path)
588 new_session_dialog->set_session_name (name);
589 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
590 _session_is_new = isnew;
595 bool have_backend = EngineControl::engine_running();
597 bool load_needed = false;
601 /* backend audio is working */
603 if (session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
604 /* need NSD to get session name and other info */
612 /* no backend audio, must bring up NSD to check configuration */
619 if (!new_session (session_name,have_backend)) {
631 if (load_session (session_name, name)) {
640 ARDOUR_UI::no_memory_warning ()
642 XMLNode node (X_("no-memory-warning"));
643 Config->add_instant_xml (node, get_user_ardour_path());
647 ARDOUR_UI::check_memory_locking ()
650 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
654 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
656 if (engine->is_realtime() && memory_warning_node == 0) {
658 struct rlimit limits;
660 long pages, page_size;
662 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
665 ram = (int64_t) pages * (int64_t) page_size;
668 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
672 if (limits.rlim_cur != RLIM_INFINITY) {
674 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
677 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
678 "This might cause Ardour to run out of memory before your system "
679 "runs out of memory. \n\n"
680 "You can view the memory limit with 'ulimit -l', "
681 "and it is normally controlled by /etc/security/limits.conf"));
683 VBox* vbox = msg.get_vbox();
685 CheckButton cb (_("Do not show this window again"));
687 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
689 hbox.pack_start (cb, true, false);
690 vbox->pack_start (hbox);
693 editor->ensure_float (msg);
705 if (session && session->dirty()) {
706 switch (ask_about_saving_session(_("quit"))) {
711 /* use the default name */
712 if (save_state_canfail ("")) {
713 /* failed - don't quit */
714 MessageDialog msg (*editor,
716 Ardour was unable to save your session.\n\n\
717 If you still wish to quit, please use the\n\n\
718 \"Just quit\" option."));
729 session->set_deletion_in_progress ();
732 Config->save_state();
733 ARDOUR_UI::config()->save_state();
738 ARDOUR_UI::ask_about_saving_session (const string & what)
740 ArdourDialog window (_("ardour: save session?"));
741 Gtk::HBox dhbox; // the hbox for the image and text
742 Gtk::Label prompt_label;
743 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
747 msg = string_compose(_("Don't %1"), what);
748 window.add_button (msg, RESPONSE_REJECT);
749 msg = string_compose(_("Just %1"), what);
750 window.add_button (msg, RESPONSE_APPLY);
751 msg = string_compose(_("Save and %1"), what);
752 window.add_button (msg, RESPONSE_ACCEPT);
754 window.set_default_response (RESPONSE_ACCEPT);
756 Gtk::Button noquit_button (msg);
757 noquit_button.set_name ("EditorGTKButton");
762 if (session->snap_name() == session->name()) {
765 type = _("snapshot");
767 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?"),
768 type, session->snap_name());
770 prompt_label.set_text (prompt);
771 prompt_label.set_name (X_("PrompterLabel"));
772 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
774 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
776 dhbox.set_homogeneous (false);
777 dhbox.pack_start (*dimage, false, false, 5);
778 dhbox.pack_start (prompt_label, true, false, 5);
779 window.get_vbox()->pack_start (dhbox);
781 window.set_name (_("Prompter"));
782 window.set_position (Gtk::WIN_POS_MOUSE);
783 window.set_modal (true);
784 window.set_resizable (false);
787 save_the_session = 0;
789 window.set_keep_above (true);
792 ResponseType r = (ResponseType) window.run();
797 case RESPONSE_ACCEPT: // save and get out of here
799 case RESPONSE_APPLY: // get out of here
809 ARDOUR_UI::every_second ()
812 update_buffer_load ();
813 update_disk_space ();
818 ARDOUR_UI::every_point_one_seconds ()
820 update_speed_display ();
821 RapidScreenUpdate(); /* EMIT_SIGNAL */
826 ARDOUR_UI::every_point_zero_one_seconds ()
828 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
833 ARDOUR_UI::update_sample_rate (nframes_t ignored)
837 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
839 if (!engine->connected()) {
841 snprintf (buf, sizeof (buf), _("disconnected"));
845 nframes_t rate = engine->frame_rate();
847 if (fmod (rate, 1000.0) != 0.0) {
848 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
849 (float) rate/1000.0f,
850 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
852 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
854 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
858 sample_rate_label.set_text (buf);
862 ARDOUR_UI::update_cpu_load ()
865 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
866 cpu_load_label.set_text (buf);
870 ARDOUR_UI::update_buffer_load ()
875 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
876 session->playback_load(), session->capture_load());
877 buffer_load_label.set_text (buf);
879 buffer_load_label.set_text ("");
884 ARDOUR_UI::count_recenabled_streams (Route& route)
886 Track* track = dynamic_cast<Track*>(&route);
887 if (track && track->diskstream()->record_enabled()) {
888 rec_enabled_streams += track->n_inputs();
893 ARDOUR_UI::update_disk_space()
899 nframes_t frames = session->available_capture_duration();
902 if (frames == max_frames) {
903 strcpy (buf, _("Disk: 24hrs+"));
908 nframes_t fr = session->frame_rate();
910 rec_enabled_streams = 0;
911 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
913 if (rec_enabled_streams) {
914 frames /= rec_enabled_streams;
917 hrs = frames / (fr * 3600);
918 frames -= hrs * fr * 3600;
919 mins = frames / (fr * 60);
920 frames -= mins * fr * 60;
923 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
926 disk_space_label.set_text (buf);
930 ARDOUR_UI::update_wall_clock ()
937 tm_now = localtime (&now);
939 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
940 wall_clock_label.set_text (buf);
946 ARDOUR_UI::session_menu (GdkEventButton *ev)
948 session_popup_menu->popup (0, 0);
953 ARDOUR_UI::redisplay_recent_sessions ()
955 vector<string *> *sessions;
956 vector<string *>::iterator i;
957 RecentSessionsSorter cmp;
959 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
960 recent_session_model->clear ();
963 ARDOUR::read_recent_sessions (rs);
966 recent_session_display.set_model (recent_session_model);
970 /* sort them alphabetically */
971 sort (rs.begin(), rs.end(), cmp);
972 sessions = new vector<string*>;
974 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
975 sessions->push_back (new string ((*i).second));
978 for (i = sessions->begin(); i != sessions->end(); ++i) {
980 vector<string*>* states;
981 vector<const gchar*> item;
982 string fullpath = *(*i);
984 /* remove any trailing / */
986 if (fullpath[fullpath.length()-1] == '/') {
987 fullpath = fullpath.substr (0, fullpath.length()-1);
990 /* now get available states for this session */
992 if ((states = Session::possible_states (fullpath)) == 0) {
997 TreeModel::Row row = *(recent_session_model->append());
999 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1000 row[recent_session_columns.fullpath] = fullpath;
1002 if (states->size() > 1) {
1004 /* add the children */
1006 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1008 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1010 child_row[recent_session_columns.visible_name] = **i2;
1011 child_row[recent_session_columns.fullpath] = fullpath;
1020 recent_session_display.set_model (recent_session_model);
1025 ARDOUR_UI::build_session_selector ()
1027 session_selector_window = new ArdourDialog ("session selector");
1029 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1031 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1032 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1033 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1034 recent_session_model = TreeStore::create (recent_session_columns);
1035 recent_session_display.set_model (recent_session_model);
1036 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1037 recent_session_display.set_headers_visible (false);
1038 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1040 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1042 scroller->add (recent_session_display);
1043 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1045 session_selector_window->set_name ("SessionSelectorWindow");
1046 session_selector_window->set_size_request (200, 400);
1047 session_selector_window->get_vbox()->pack_start (*scroller);
1048 session_selector_window->show_all_children();
1052 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1054 session_selector_window->response (RESPONSE_ACCEPT);
1058 ARDOUR_UI::open_recent_session ()
1060 /* popup selector window */
1062 if (session_selector_window == 0) {
1063 build_session_selector ();
1066 redisplay_recent_sessions ();
1068 ResponseType r = (ResponseType) session_selector_window->run ();
1070 session_selector_window->hide();
1073 case RESPONSE_ACCEPT:
1079 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1081 if (i == recent_session_model->children().end()) {
1085 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1086 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1088 _session_is_new = false;
1090 load_session (path, state);
1094 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1096 struct stat statbuf;
1098 if (stat (info.filename.c_str(), &statbuf) != 0) {
1102 if (!S_ISDIR(statbuf.st_mode)) {
1108 string session_file = info.filename;
1109 session_file += '/';
1110 session_file += Glib::path_get_basename (info.filename);
1111 session_file += ".ardour";
1113 if (stat (session_file.c_str(), &statbuf) != 0) {
1117 return S_ISREG (statbuf.st_mode);
1121 ARDOUR_UI::check_audioengine ()
1124 if (!engine->connected()) {
1125 MessageDialog msg (_("Ardour is not connected to JACK\n"
1126 "You cannot open or close sessions in this condition"));
1137 ARDOUR_UI::open_session ()
1139 if (!check_audioengine()) {
1143 /* popup selector window */
1145 if (open_session_selector == 0) {
1147 /* ardour sessions are folders */
1149 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1150 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1151 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1153 FileFilter session_filter;
1154 session_filter.add_pattern ("*.ardour");
1155 session_filter.set_name (_("Ardour sessions"));
1156 open_session_selector->add_filter (session_filter);
1157 open_session_selector->set_filter (session_filter);
1160 int response = open_session_selector->run();
1161 open_session_selector->hide ();
1164 case RESPONSE_ACCEPT:
1167 open_session_selector->hide();
1171 open_session_selector->hide();
1172 string session_path = open_session_selector->get_filename();
1176 if (session_path.length() > 0) {
1177 if (Session::find_session (session_path, path, name, isnew) == 0) {
1178 _session_is_new = isnew;
1179 load_session (path, name);
1186 ARDOUR_UI::session_add_midi_track ()
1188 cerr << _("Patience is a virtue.\n");
1192 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1194 list<boost::shared_ptr<AudioTrack> > tracks;
1195 Session::RouteList routes;
1198 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1204 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1206 if (tracks.size() != how_many) {
1207 if (how_many == 1) {
1208 error << _("could not create a new audio track") << endmsg;
1210 error << string_compose (_("could only create %1 of %2 new audio %3"),
1211 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1217 routes = session->new_audio_route (input_channels, output_channels, how_many);
1219 if (routes.size() != how_many) {
1220 if (how_many == 1) {
1221 error << _("could not create a new audio track") << endmsg;
1223 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1229 if (need_control_room_outs) {
1235 route->set_stereo_control_outs (control_lr_channels);
1236 route->control_outs()->set_stereo_pan (pans, this);
1238 #endif /* CONTROLOUTS */
1242 cerr << "About to complain about JACK\n";
1243 MessageDialog msg (*editor,
1244 _("There are insufficient JACK ports available\n\
1245 to create a new track or bus.\n\
1246 You should save Ardour, exit and\n\
1247 restart JACK with more ports."));
1253 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1255 nframes_t _preroll = 0;
1258 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1259 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1261 if (new_position > _preroll) {
1262 new_position -= _preroll;
1267 session->request_locate (new_position);
1272 ARDOUR_UI::transport_goto_start ()
1275 session->goto_start();
1278 /* force displayed area in editor to start no matter
1279 what "follow playhead" setting is.
1283 editor->reset_x_origin (session->current_start_frame());
1289 ARDOUR_UI::transport_goto_zero ()
1292 session->request_locate (0);
1295 /* force displayed area in editor to start no matter
1296 what "follow playhead" setting is.
1300 editor->reset_x_origin (0);
1306 ARDOUR_UI::transport_goto_end ()
1309 nframes_t frame = session->current_end_frame();
1310 session->request_locate (frame);
1312 /* force displayed area in editor to start no matter
1313 what "follow playhead" setting is.
1317 editor->reset_x_origin (frame);
1323 ARDOUR_UI::transport_stop ()
1329 if (session->is_auditioning()) {
1330 session->cancel_audition ();
1334 if (session->get_play_loop ()) {
1335 session->request_play_loop (false);
1338 session->request_stop ();
1342 ARDOUR_UI::transport_stop_and_forget_capture ()
1345 session->request_stop (true);
1350 ARDOUR_UI::remove_last_capture()
1353 editor->remove_last_capture();
1358 ARDOUR_UI::transport_record ()
1361 switch (session->record_status()) {
1362 case Session::Disabled:
1363 if (session->ntracks() == 0) {
1364 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1368 session->maybe_enable_record ();
1370 case Session::Recording:
1371 case Session::Enabled:
1372 session->disable_record (false, true);
1378 ARDOUR_UI::transport_roll ()
1386 rolling = session->transport_rolling ();
1388 if (session->get_play_loop()) {
1389 session->request_play_loop (false);
1390 auto_loop_button.set_visual_state (1);
1391 roll_button.set_visual_state (1);
1392 } else if (session->get_play_range ()) {
1393 session->request_play_range (false);
1394 play_selection_button.set_visual_state (0);
1395 } else if (rolling) {
1396 session->request_locate (session->last_transport_start(), true);
1399 session->request_transport_speed (1.0f);
1403 ARDOUR_UI::transport_loop()
1406 if (session->get_play_loop()) {
1407 if (session->transport_rolling()) {
1408 Location * looploc = session->locations()->auto_loop_location();
1410 session->request_locate (looploc->start(), true);
1415 session->request_play_loop (true);
1421 ARDOUR_UI::transport_play_selection ()
1427 if (!session->get_play_range()) {
1428 session->request_stop ();
1431 editor->play_selection ();
1435 ARDOUR_UI::transport_rewind (int option)
1437 float current_transport_speed;
1440 current_transport_speed = session->transport_speed();
1442 if (current_transport_speed >= 0.0f) {
1445 session->request_transport_speed (-1.0f);
1448 session->request_transport_speed (-4.0f);
1451 session->request_transport_speed (-0.5f);
1456 session->request_transport_speed (current_transport_speed * 1.5f);
1462 ARDOUR_UI::transport_forward (int option)
1464 float current_transport_speed;
1467 current_transport_speed = session->transport_speed();
1469 if (current_transport_speed <= 0.0f) {
1472 session->request_transport_speed (1.0f);
1475 session->request_transport_speed (4.0f);
1478 session->request_transport_speed (0.5f);
1483 session->request_transport_speed (current_transport_speed * 1.5f);
1489 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1495 boost::shared_ptr<Route> r;
1497 if ((r = session->route_by_remote_id (dstream)) != 0) {
1501 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1502 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1511 ARDOUR_UI::queue_transport_change ()
1513 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1517 ARDOUR_UI::map_transport_state ()
1519 float sp = session->transport_speed();
1522 transport_rolling ();
1523 } else if (sp < 0.0f) {
1524 transport_rewinding ();
1525 } else if (sp > 0.0f) {
1526 transport_forwarding ();
1528 transport_stopped ();
1533 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1535 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1536 (int) adj.get_value()].c_str());
1540 ARDOUR_UI::engine_stopped ()
1542 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1543 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1544 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1548 ARDOUR_UI::engine_running ()
1550 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1551 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1552 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1554 Glib::RefPtr<Action> action;
1555 char* action_name = 0;
1557 switch (engine->frames_per_cycle()) {
1559 action_name = X_("JACKLatency32");
1562 action_name = X_("JACKLatency64");
1565 action_name = X_("JACKLatency128");
1568 action_name = X_("JACKLatency512");
1571 action_name = X_("JACKLatency1024");
1574 action_name = X_("JACKLatency2048");
1577 action_name = X_("JACKLatency4096");
1580 action_name = X_("JACKLatency8192");
1583 /* XXX can we do anything useful ? */
1589 action = ActionManager::get_action (X_("JACK"), action_name);
1592 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1593 ract->set_active ();
1599 ARDOUR_UI::engine_halted ()
1601 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1603 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1604 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1606 update_sample_rate (0);
1608 MessageDialog msg (*editor,
1610 JACK has either been shutdown or it\n\
1611 disconnected Ardour because Ardour\n\
1612 was not fast enough. You can save the\n\
1613 session and/or try to reconnect to JACK ."));
1618 ARDOUR_UI::do_engine_start ()
1626 error << _("Unable to start the session running")
1636 ARDOUR_UI::setup_theme ()
1638 theme_manager->setup_theme();
1642 ARDOUR_UI::update_clocks ()
1644 if (!editor || !editor->dragging_playhead()) {
1645 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1650 ARDOUR_UI::start_clocking ()
1652 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1656 ARDOUR_UI::stop_clocking ()
1658 clock_signal_connection.disconnect ();
1662 ARDOUR_UI::toggle_clocking ()
1665 if (clock_button.get_active()) {
1674 ARDOUR_UI::_blink (void *arg)
1677 ((ARDOUR_UI *) arg)->blink ();
1684 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1688 ARDOUR_UI::start_blinking ()
1690 /* Start the blink signal. Everybody with a blinking widget
1691 uses Blink to drive the widget's state.
1694 if (blink_timeout_tag < 0) {
1696 blink_timeout_tag = g_timeout_add (240, _blink, this);
1701 ARDOUR_UI::stop_blinking ()
1703 if (blink_timeout_tag >= 0) {
1704 g_source_remove (blink_timeout_tag);
1705 blink_timeout_tag = -1;
1710 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1716 if (io.n_inputs() == 0) {
1721 /* XXX we're not handling multiple ports yet. */
1723 const char **connections = io.input(0)->get_connections();
1725 if (connections == 0 || connections[0] == '\0') {
1728 buf = connections[0];
1735 if (io.n_outputs() == 0) {
1740 /* XXX we're not handling multiple ports yet. */
1742 const char **connections = io.output(0)->get_connections();
1744 if (connections == 0 || connections[0] == '\0') {
1747 buf = connections[0];
1754 /** Ask the user for the name of a new shapshot and then take it.
1757 ARDOUR_UI::snapshot_session ()
1759 ArdourPrompter prompter (true);
1763 struct tm local_time;
1766 localtime_r (&n, &local_time);
1767 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1769 prompter.set_name ("Prompter");
1770 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1771 prompter.set_prompt (_("Name of New Snapshot"));
1772 prompter.set_initial_text (timebuf);
1774 switch (prompter.run()) {
1775 case RESPONSE_ACCEPT:
1776 prompter.get_result (snapname);
1777 if (snapname.length()){
1778 save_state (snapname);
1788 ARDOUR_UI::save_state (const string & name)
1790 (void) save_state_canfail (name);
1794 ARDOUR_UI::save_state_canfail (string name)
1799 if (name.length() == 0) {
1800 name = session->snap_name();
1803 if ((ret = session->save_state (name)) != 0) {
1807 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1812 ARDOUR_UI::restore_state (string name)
1815 if (name.length() == 0) {
1816 name = session->name();
1818 session->restore_state (name);
1823 ARDOUR_UI::primary_clock_value_changed ()
1826 session->request_locate (primary_clock.current_time ());
1831 ARDOUR_UI::secondary_clock_value_changed ()
1834 session->request_locate (secondary_clock.current_time ());
1839 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1841 if (session && dstream && dstream->record_enabled()) {
1843 Session::RecordState rs;
1845 rs = session->record_status ();
1848 case Session::Disabled:
1849 case Session::Enabled:
1850 if (w->get_state() != STATE_SELECTED) {
1851 w->set_state (STATE_SELECTED);
1855 case Session::Recording:
1856 if (w->get_state() != STATE_ACTIVE) {
1857 w->set_state (STATE_ACTIVE);
1863 if (w->get_state() != STATE_NORMAL) {
1864 w->set_state (STATE_NORMAL);
1870 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1876 switch (session->record_status()) {
1877 case Session::Enabled:
1879 rec_button.set_visual_state (2);
1881 rec_button.set_visual_state (0);
1885 case Session::Recording:
1886 rec_button.set_visual_state (1);
1890 rec_button.set_visual_state (0);
1896 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1904 ARDOUR_UI::save_template ()
1907 ArdourPrompter prompter (true);
1910 if (!check_audioengine()) {
1914 prompter.set_name (X_("Prompter"));
1915 prompter.set_prompt (_("Name for mix template:"));
1916 prompter.set_initial_text(session->name() + _("-template"));
1917 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1919 switch (prompter.run()) {
1920 case RESPONSE_ACCEPT:
1921 prompter.get_result (name);
1923 if (name.length()) {
1924 session->save_template (name);
1934 ARDOUR_UI::new_session (Glib::ustring predetermined_path, bool have_engine)
1936 string session_name;
1937 string session_path;
1939 int response = Gtk::RESPONSE_NONE;
1941 new_session_dialog->set_modal(true);
1942 new_session_dialog->set_name (predetermined_path);
1943 new_session_dialog->reset_recent();
1944 new_session_dialog->show();
1945 new_session_dialog->set_current_page (0);
1949 new_session_dialog->set_have_engine (have_engine);
1951 response = new_session_dialog->run ();
1953 _session_is_new = false;
1955 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1960 new_session_dialog->hide ();
1963 } else if (response == Gtk::RESPONSE_NONE) {
1965 /* Clear was pressed */
1966 new_session_dialog->reset();
1970 /* first things first ... we need an audio engine running */
1973 if (start_backend_audio ()) {
1974 new_session_dialog->hide ();
1982 /* now handle possible affirmative responses */
1984 if (response == Gtk::RESPONSE_YES) {
1986 /* YES == OPEN from the open session tab */
1988 session_name = new_session_dialog->session_name();
1990 if (session_name.empty()) {
1991 response = Gtk::RESPONSE_NONE;
1995 if (session_name[0] == '/' ||
1996 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1997 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1998 load_session (Glib::path_get_dirname (session_name), session_name);
2000 session_path = new_session_dialog->session_folder();
2001 load_session (session_path, session_name);
2004 } else if (response == Gtk::RESPONSE_OK) {
2006 /* OK == OPEN from new session tab */
2008 session_name = new_session_dialog->session_name();
2010 if (new_session_dialog->get_current_page() == 1) {
2012 if (session_name.empty()) {
2013 response = Gtk::RESPONSE_NONE;
2017 if (session_name[0] == '/' ||
2018 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2019 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2020 load_session (Glib::path_get_dirname (session_name), session_name);
2022 session_path = new_session_dialog->session_folder();
2023 load_session (session_path, session_name);
2028 if (session_name.empty()) {
2029 response = Gtk::RESPONSE_NONE;
2033 /* handle what appear to be paths rather than just a name */
2035 if (session_name[0] == '/' ||
2036 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2037 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2039 session_path = Glib::path_get_dirname (session_name);
2040 session_name = Glib::path_get_basename (session_name);
2044 session_path = new_session_dialog->session_folder();
2048 //XXX This is needed because session constructor wants a
2049 //non-existant path. hopefully this will be fixed at some point.
2051 session_path = Glib::build_filename (session_path, session_name);
2053 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2055 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2057 MessageDialog msg (str,
2059 Gtk::MESSAGE_WARNING,
2060 Gtk::BUTTONS_YES_NO,
2064 msg.set_name (X_("CleanupDialog"));
2065 msg.set_wmclass (X_("existing_session"), "Ardour");
2066 msg.set_position (Gtk::WIN_POS_MOUSE);
2068 switch (msg.run()) {
2070 load_session (session_path, session_name);
2074 response = RESPONSE_NONE;
2075 new_session_dialog->reset ();
2080 _session_is_new = true;
2082 std::string template_name = new_session_dialog->session_template_name();
2084 if (new_session_dialog->use_session_template()) {
2086 load_session (session_path, session_name, &template_name);
2092 AutoConnectOption iconnect;
2093 AutoConnectOption oconnect;
2095 if (new_session_dialog->create_control_bus()) {
2096 cchns = (uint32_t) new_session_dialog->control_channel_count();
2101 if (new_session_dialog->create_master_bus()) {
2102 mchns = (uint32_t) new_session_dialog->master_channel_count();
2107 if (new_session_dialog->connect_inputs()) {
2108 iconnect = AutoConnectPhysical;
2110 iconnect = AutoConnectOption (0);
2113 /// @todo some minor tweaks.
2115 if (new_session_dialog->connect_outs_to_master()) {
2116 oconnect = AutoConnectMaster;
2117 } else if (new_session_dialog->connect_outs_to_physical()) {
2118 oconnect = AutoConnectPhysical;
2120 oconnect = AutoConnectOption (0);
2123 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2124 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2126 if (build_session (session_path,
2134 engine->frame_rate() * 60 * 5)) {
2136 response = Gtk::RESPONSE_NONE;
2137 new_session_dialog->reset ();
2144 } while (response == Gtk::RESPONSE_NONE);
2148 new_session_dialog->get_window()->set_cursor();
2149 new_session_dialog->hide();
2154 ARDOUR_UI::close_session()
2156 if (!check_audioengine()) {
2161 new_session ("", true);
2165 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2167 Session *new_session;
2169 session_loaded = false;
2171 if (!check_audioengine()) {
2175 x = unload_session ();
2183 /* if it already exists, we must have write access */
2185 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2186 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2187 "This prevents the session from being loaded."));
2193 new_session = new Session (*engine, path, snap_name, mix_template);
2198 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2202 connect_to_session (new_session);
2204 Config->set_current_owner (ConfigVariableBase::Interface);
2206 session_loaded = true;
2208 goto_editor_window ();
2211 session->set_clean ();
2214 editor->edit_cursor_position (true);
2219 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2220 uint32_t control_channels,
2221 uint32_t master_channels,
2222 AutoConnectOption input_connect,
2223 AutoConnectOption output_connect,
2226 nframes_t initial_length)
2228 Session *new_session;
2231 if (!check_audioengine()) {
2235 session_loaded = false;
2237 x = unload_session ();
2245 _session_is_new = true;
2248 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2249 control_channels, master_channels, nphysin, nphysout, initial_length);
2254 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2259 connect_to_session (new_session);
2261 session_loaded = true;
2269 editor->show_window ();
2280 ARDOUR_UI::show_splash ()
2283 about = new About();
2284 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2291 ARDOUR_UI::about_signal_response(int response)
2297 ARDOUR_UI::hide_splash ()
2300 about->get_window()->set_cursor ();
2306 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2310 removed = rep.paths.size();
2313 MessageDialog msgd (*editor,
2314 _("No audio files were ready for cleanup"),
2317 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2318 msgd.set_secondary_text (_("If this seems suprising, \n\
2319 check for any existing snapshots.\n\
2320 These may still include regions that\n\
2321 require some unused files to continue to exist."));
2327 ArdourDialog results (_("ardour: cleanup"), true, false);
2329 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2330 CleanupResultsModelColumns() {
2334 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2335 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2339 CleanupResultsModelColumns results_columns;
2340 Glib::RefPtr<Gtk::ListStore> results_model;
2341 Gtk::TreeView results_display;
2343 results_model = ListStore::create (results_columns);
2344 results_display.set_model (results_model);
2345 results_display.append_column (list_title, results_columns.visible_name);
2347 results_display.set_name ("CleanupResultsList");
2348 results_display.set_headers_visible (true);
2349 results_display.set_headers_clickable (false);
2350 results_display.set_reorderable (false);
2352 Gtk::ScrolledWindow list_scroller;
2355 Gtk::HBox dhbox; // the hbox for the image and text
2356 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2357 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2359 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2361 if (rep.space < 1048576.0f) {
2363 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2365 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2369 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2371 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2375 dhbox.pack_start (*dimage, true, false, 5);
2376 dhbox.pack_start (txt, true, false, 5);
2378 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2379 TreeModel::Row row = *(results_model->append());
2380 row[results_columns.visible_name] = *i;
2381 row[results_columns.fullpath] = *i;
2384 list_scroller.add (results_display);
2385 list_scroller.set_size_request (-1, 150);
2386 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2388 dvbox.pack_start (dhbox, true, false, 5);
2389 dvbox.pack_start (list_scroller, true, false, 5);
2390 ddhbox.pack_start (dvbox, true, false, 5);
2392 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2393 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2394 results.set_default_response (RESPONSE_CLOSE);
2395 results.set_position (Gtk::WIN_POS_MOUSE);
2396 results.show_all_children ();
2397 results.set_resizable (false);
2404 ARDOUR_UI::cleanup ()
2407 /* shouldn't happen: menu item is insensitive */
2412 MessageDialog checker (_("Are you sure you want to cleanup?"),
2414 Gtk::MESSAGE_QUESTION,
2415 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2417 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2418 ALL undo/redo information will be lost if you cleanup.\n\
2419 After cleanup, unused audio files will be moved to a \
2420 \"dead sounds\" location."));
2422 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2423 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2424 checker.set_default_response (RESPONSE_CANCEL);
2426 checker.set_name (_("CleanupDialog"));
2427 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2428 checker.set_position (Gtk::WIN_POS_MOUSE);
2430 switch (checker.run()) {
2431 case RESPONSE_ACCEPT:
2437 Session::cleanup_report rep;
2439 editor->prepare_for_cleanup ();
2441 /* do not allow flush until a session is reloaded */
2443 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2445 act->set_sensitive (false);
2448 if (session->cleanup_sources (rep)) {
2453 display_cleanup_results (rep,
2456 The following %1 %2 not in use and \n\
2457 have been moved to:\n\
2459 Flushing the wastebasket will \n\
2460 release an additional\n\
2461 %4 %5bytes of disk space.\n"
2469 ARDOUR_UI::flush_trash ()
2472 /* shouldn't happen: menu item is insensitive */
2476 Session::cleanup_report rep;
2478 if (session->cleanup_trash_sources (rep)) {
2482 display_cleanup_results (rep,
2484 _("The following %1 %2 deleted from\n\
2486 releasing %4 %5bytes of disk space"));
2490 ARDOUR_UI::add_route (Gtk::Window* float_window)
2498 if (add_route_dialog == 0) {
2499 add_route_dialog = new AddRouteDialog;
2501 add_route_dialog->set_transient_for (*float_window);
2505 if (add_route_dialog->is_visible()) {
2506 /* we're already doing this */
2510 ResponseType r = (ResponseType) add_route_dialog->run ();
2512 add_route_dialog->hide();
2515 case RESPONSE_ACCEPT:
2522 if ((count = add_route_dialog->count()) <= 0) {
2526 uint32_t input_chan = add_route_dialog->channels ();
2527 uint32_t output_chan;
2528 string name_template = add_route_dialog->name_template ();
2529 bool track = add_route_dialog->track ();
2531 AutoConnectOption oac = Config->get_output_auto_connect();
2533 if (oac & AutoConnectMaster) {
2534 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2536 output_chan = input_chan;
2539 /* XXX do something with name template */
2542 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2544 session_add_audio_bus (input_chan, output_chan, count);
2549 ARDOUR_UI::mixer_settings () const
2554 node = session->instant_xml(X_("Mixer"), session->path());
2556 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2560 node = new XMLNode (X_("Mixer"));
2567 ARDOUR_UI::editor_settings () const
2572 node = session->instant_xml(X_("Editor"), session->path());
2574 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2578 node = new XMLNode (X_("Editor"));
2584 ARDOUR_UI::keyboard_settings () const
2588 node = Config->extra_xml(X_("Keyboard"));
2591 node = new XMLNode (X_("Keyboard"));
2597 ARDOUR_UI::halt_on_xrun_message ()
2599 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2601 MessageDialog msg (*editor,
2602 _("Recording was stopped because your system could not keep up."));
2607 ARDOUR_UI::disk_overrun_handler ()
2609 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2611 if (!have_disk_speed_dialog_displayed) {
2612 have_disk_speed_dialog_displayed = true;
2613 MessageDialog* msg = new MessageDialog (*editor, _("\
2614 The disk system on your computer\n\
2615 was not able to keep up with Ardour.\n\
2617 Specifically, it failed to write data to disk\n\
2618 quickly enough to keep up with recording.\n"));
2619 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2625 ARDOUR_UI::disk_underrun_handler ()
2627 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2629 if (!have_disk_speed_dialog_displayed) {
2630 have_disk_speed_dialog_displayed = true;
2631 MessageDialog* msg = new MessageDialog (*editor,
2632 _("The disk system on your computer\n\
2633 was not able to keep up with Ardour.\n\
2635 Specifically, it failed to read data from disk\n\
2636 quickly enough to keep up with playback.\n"));
2637 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2643 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2645 have_disk_speed_dialog_displayed = false;
2650 ARDOUR_UI::pending_state_dialog ()
2652 ArdourDialog dialog ("pending state dialog");
2654 This session appears to have been in\n\
2655 middle of recording when ardour or\n\
2656 the computer was shutdown.\n\
2658 Ardour can recover any captured audio for\n\
2659 you, or it can ignore it. Please decide\n\
2660 what you would like to do.\n"));
2662 dialog.get_vbox()->pack_start (message);
2663 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2664 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2666 dialog.set_position (WIN_POS_CENTER);
2669 switch (dialog.run ()) {
2670 case RESPONSE_ACCEPT:
2678 ARDOUR_UI::disconnect_from_jack ()
2681 if( engine->disconnect_from_jack ()) {
2682 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2686 update_sample_rate (0);
2691 ARDOUR_UI::reconnect_to_jack ()
2694 if (engine->reconnect_to_jack ()) {
2695 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2699 update_sample_rate (0);
2704 ARDOUR_UI::cmdline_new_session (string path)
2706 if (path[0] != '/') {
2707 char buf[PATH_MAX+1];
2710 getcwd (buf, sizeof (buf));
2719 _will_create_new_session_automatically = false; /* done it */
2720 return FALSE; /* don't call it again */
2724 ARDOUR_UI::use_config ()
2726 Glib::RefPtr<Action> act;
2728 switch (Config->get_native_file_data_format ()) {
2730 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2733 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2736 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2741 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2742 ract->set_active ();
2745 switch (Config->get_native_file_header_format ()) {
2747 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2750 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2753 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2756 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2759 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2762 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2765 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2770 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2771 ract->set_active ();
2774 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2776 set_transport_controllable_state (*node);
2781 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2783 if (Config->get_primary_clock_delta_edit_cursor()) {
2784 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2786 primary_clock.set (pos, 0, true);
2789 if (Config->get_secondary_clock_delta_edit_cursor()) {
2790 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2792 secondary_clock.set (pos);
2795 if (big_clock_window) {
2796 big_clock.set (pos);
2801 ARDOUR_UI::record_state_changed ()
2803 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2805 if (!session || !big_clock_window) {
2806 /* why bother - the clock isn't visible */
2810 switch (session->record_status()) {
2811 case Session::Recording:
2812 big_clock.set_widget_name ("BigClockRecording");
2815 big_clock.set_widget_name ("BigClockNonRecording");
2821 ARDOUR_UI::set_keybindings_path (string path)
2823 keybindings_path = path;
2827 ARDOUR_UI::save_keybindings ()
2829 if (can_save_keybindings) {
2830 AccelMap::save (user_keybindings_path);
2835 ARDOUR_UI::first_idle ()
2838 session->allow_auto_play (true);
2840 can_save_keybindings = true;
2845 ARDOUR_UI::store_clock_modes ()
2847 XMLNode* node = new XMLNode(X_("ClockModes"));
2849 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2850 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2853 session->add_extra_xml (*node);
2854 session->set_dirty ();
2859 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2860 : Controllable (name), ui (u), type(tp)
2866 ARDOUR_UI::TransportControllable::set_value (float val)
2868 if (type == ShuttleControl) {
2875 fract = -((0.5f - val)/0.5f);
2877 fract = ((val - 0.5f)/0.5f);
2881 ui.set_shuttle_fract (fract);
2886 /* do nothing: these are radio-style actions */
2894 action = X_("Roll");
2897 action = X_("Stop");
2900 action = X_("Goto Start");
2903 action = X_("Goto End");
2906 action = X_("Loop");
2909 action = X_("Play Selection");
2912 action = X_("Record");
2922 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2930 ARDOUR_UI::TransportControllable::get_value (void) const
2949 case ShuttleControl:
2959 ARDOUR_UI::TransportControllable::set_id (const string& str)
2965 ARDOUR_UI::setup_profile ()
2967 if (gdk_screen_width() < 1200) {
2968 Profile->set_small_screen ();
2971 if (getenv ("ARDOUR_SAE")) {
2972 Profile->set_sae ();
2977 ARDOUR_UI::audioengine_setup ()