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.
20 #define __STDC_FORMAT_MACROS 1
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
39 #include <pbd/compose.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/memento_command.h>
43 #include <pbd/file_utils.h>
45 #include <gtkmm2ext/gtk_ui.h>
46 #include <gtkmm2ext/utils.h>
47 #include <gtkmm2ext/click_box.h>
48 #include <gtkmm2ext/fastmeter.h>
49 #include <gtkmm2ext/stop_signal.h>
50 #include <gtkmm2ext/popup.h>
51 #include <gtkmm2ext/window_title.h>
53 #include <midi++/port.h>
54 #include <midi++/mmc.h>
56 #include <ardour/ardour.h>
57 #include <ardour/profile.h>
58 #include <ardour/session_directory.h>
59 #include <ardour/session_route.h>
60 #include <ardour/session_state_utils.h>
61 #include <ardour/session_utils.h>
62 #include <ardour/port.h>
63 #include <ardour/audioengine.h>
64 #include <ardour/playlist.h>
65 #include <ardour/utils.h>
66 #include <ardour/audio_diskstream.h>
67 #include <ardour/audiofilesource.h>
68 #include <ardour/recent_sessions.h>
69 #include <ardour/port.h>
70 #include <ardour/audio_track.h>
71 #include <ardour/midi_track.h>
72 #include <ardour/filesystem_paths.h>
75 #include "ardour_ui.h"
76 #include "public_editor.h"
77 #include "audio_clock.h"
82 #include "add_route_dialog.h"
83 #include "new_session_dialog.h"
86 #include "gui_thread.h"
87 #include "theme_manager.h"
92 using namespace ARDOUR;
94 using namespace Gtkmm2ext;
98 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
99 UIConfiguration *ARDOUR_UI::ui_config = 0;
101 sigc::signal<void,bool> ARDOUR_UI::Blink;
102 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
103 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
104 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
106 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
108 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
110 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
111 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
112 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
113 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
117 adjuster_table (3, 3),
121 preroll_button (_("pre\nroll")),
122 postroll_button (_("post\nroll")),
126 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
130 roll_controllable ("transport roll", *this, TransportControllable::Roll),
131 stop_controllable ("transport stop", *this, TransportControllable::Stop),
132 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
133 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
134 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
135 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
136 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
137 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
138 shuttle_controller_binding_proxy (shuttle_controllable),
140 roll_button (roll_controllable),
141 stop_button (stop_controllable),
142 goto_start_button (goto_start_controllable),
143 goto_end_button (goto_end_controllable),
144 auto_loop_button (auto_loop_controllable),
145 play_selection_button (play_selection_controllable),
146 rec_button (rec_controllable),
148 shuttle_units_button (_("% ")),
150 punch_in_button (_("Punch In")),
151 punch_out_button (_("Punch Out")),
152 auto_return_button (_("Auto Return")),
153 auto_play_button (_("Auto Play")),
154 auto_input_button (_("Auto Input")),
155 click_button (_("Click")),
156 time_master_button (_("time\nmaster")),
158 auditioning_alert_button (_("AUDITION")),
159 solo_alert_button (_("SOLO")),
162 using namespace Gtk::Menu_Helpers;
168 if (theArdourUI == 0) {
172 ui_config = new UIConfiguration();
173 theme_manager = new ThemeManager();
178 _session_is_new = false;
179 big_clock_window = 0;
180 session_selector_window = 0;
181 last_key_press_time = 0;
182 connection_editor = 0;
183 add_route_dialog = 0;
187 open_session_selector = 0;
188 have_configure_timeout = false;
189 have_disk_speed_dialog_displayed = false;
190 session_loaded = false;
191 last_speed_displayed = -1.0f;
194 sys::path key_bindings_file;
196 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
197 "ardour.bindings", key_bindings_file);
199 keybindings_path = key_bindings_file.to_string();
201 /* store all bindings changes in per-user file, no matter where they were loaded from */
202 user_keybindings_path = user_config_directory().to_string ();
203 user_keybindings_path += '/';
204 user_keybindings_path += "ardour.bindings";
206 can_save_keybindings = false;
208 last_configure_time.tv_sec = 0;
209 last_configure_time.tv_usec = 0;
211 shuttle_grabbed = false;
213 shuttle_max_speed = 8.0f;
215 shuttle_style_menu = 0;
216 shuttle_unit_menu = 0;
218 gettimeofday (&last_peak_grab, 0);
219 gettimeofday (&last_shuttle_request, 0);
221 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
222 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
224 /* handle pending state with a dialog */
226 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
228 /* have to wait for AudioEngine and Configuration before proceeding */
232 ARDOUR_UI::set_engine (AudioEngine& e)
236 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
237 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
238 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
239 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
241 ActionManager::init ();
242 new_session_dialog = new NewSessionDialog();
246 keyboard = new Keyboard;
248 if (setup_windows ()) {
249 throw failed_constructor ();
252 if (GTK_ARDOUR::show_key_actions) {
253 vector<string> names;
254 vector<string> paths;
256 vector<AccelKey> bindings;
258 ActionManager::get_all_actions (names, paths, keys, bindings);
260 vector<string>::iterator n;
261 vector<string>::iterator k;
262 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
263 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
269 /* start with timecode, metering enabled
272 blink_timeout_tag = -1;
274 /* the global configuration object is now valid */
278 /* this being a GUI and all, we want peakfiles */
280 AudioFileSource::set_build_peakfiles (true);
281 AudioFileSource::set_build_missing_peakfiles (true);
283 /* set default clock modes */
285 primary_clock.set_mode (AudioClock::SMPTE);
286 secondary_clock.set_mode (AudioClock::BBT);
288 /* start the time-of-day-clock */
290 update_wall_clock ();
291 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
293 update_disk_space ();
295 update_sample_rate (engine->frame_rate());
297 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
298 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
301 ARDOUR_UI::~ARDOUR_UI ()
303 save_ardour_state ();
317 if (add_route_dialog) {
318 delete add_route_dialog;
323 ARDOUR_UI::configure_timeout ()
328 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
329 /* no configure events yet */
333 gettimeofday (&now, 0);
334 timersub (&now, &last_configure_time, &diff);
336 /* force a gap of 0.5 seconds since the last configure event
339 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
342 have_configure_timeout = false;
343 save_ardour_state ();
349 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
351 if (have_configure_timeout) {
352 gettimeofday (&last_configure_time, 0);
354 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
355 have_configure_timeout = true;
362 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
364 const XMLProperty* prop;
366 if ((prop = node.property ("roll")) != 0) {
367 roll_controllable.set_id (prop->value());
369 if ((prop = node.property ("stop")) != 0) {
370 stop_controllable.set_id (prop->value());
372 if ((prop = node.property ("goto_start")) != 0) {
373 goto_start_controllable.set_id (prop->value());
375 if ((prop = node.property ("goto_end")) != 0) {
376 goto_end_controllable.set_id (prop->value());
378 if ((prop = node.property ("auto_loop")) != 0) {
379 auto_loop_controllable.set_id (prop->value());
381 if ((prop = node.property ("play_selection")) != 0) {
382 play_selection_controllable.set_id (prop->value());
384 if ((prop = node.property ("rec")) != 0) {
385 rec_controllable.set_id (prop->value());
387 if ((prop = node.property ("shuttle")) != 0) {
388 shuttle_controllable.set_id (prop->value());
393 ARDOUR_UI::get_transport_controllable_state ()
395 XMLNode* node = new XMLNode(X_("TransportControllables"));
398 roll_controllable.id().print (buf, sizeof (buf));
399 node->add_property (X_("roll"), buf);
400 stop_controllable.id().print (buf, sizeof (buf));
401 node->add_property (X_("stop"), buf);
402 goto_start_controllable.id().print (buf, sizeof (buf));
403 node->add_property (X_("goto_start"), buf);
404 goto_end_controllable.id().print (buf, sizeof (buf));
405 node->add_property (X_("goto_end"), buf);
406 auto_loop_controllable.id().print (buf, sizeof (buf));
407 node->add_property (X_("auto_loop"), buf);
408 play_selection_controllable.id().print (buf, sizeof (buf));
409 node->add_property (X_("play_selection"), buf);
410 rec_controllable.id().print (buf, sizeof (buf));
411 node->add_property (X_("rec"), buf);
412 shuttle_controllable.id().print (buf, sizeof (buf));
413 node->add_property (X_("shuttle"), buf);
419 ARDOUR_UI::save_ardour_state ()
421 if (!keyboard || !mixer || !editor) {
425 /* XXX this is all a bit dubious. add_extra_xml() uses
426 a different lifetime model from add_instant_xml().
429 XMLNode* node = new XMLNode (keyboard->get_state());
430 Config->add_extra_xml (*node);
431 Config->add_extra_xml (get_transport_controllable_state());
432 Config->save_state();
434 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
435 XMLNode mnode(mixer->get_state());
438 session->add_instant_xml (enode);
439 session->add_instant_xml (mnode);
441 Config->add_instant_xml (enode);
442 Config->add_instant_xml (mnode);
449 ARDOUR_UI::autosave_session ()
451 if (!Config->get_periodic_safety_backups())
455 session->maybe_write_autosave();
462 ARDOUR_UI::update_autosave ()
464 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
466 if (session->dirty()) {
467 if (_autosave_connection.connected()) {
468 _autosave_connection.disconnect();
471 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
472 Config->get_periodic_safety_backup_interval() * 1000);
475 if (_autosave_connection.connected()) {
476 _autosave_connection.disconnect();
482 ARDOUR_UI::startup ()
484 check_memory_locking();
488 ARDOUR_UI::no_memory_warning ()
490 XMLNode node (X_("no-memory-warning"));
491 Config->add_instant_xml (node);
495 ARDOUR_UI::check_memory_locking ()
498 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
502 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
504 if (engine->is_realtime() && memory_warning_node == 0) {
506 struct rlimit limits;
508 long pages, page_size;
510 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
513 ram = (int64_t) pages * (int64_t) page_size;
516 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
520 if (limits.rlim_cur != RLIM_INFINITY) {
522 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
525 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
526 "This might cause Ardour to run out of memory before your system "
527 "runs out of memory. \n\n"
528 "You can view the memory limit with 'ulimit -l', "
529 "and it is normally controlled by /etc/security/limits.conf"));
531 VBox* vbox = msg.get_vbox();
533 CheckButton cb (_("Do not show this window again"));
535 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
537 hbox.pack_start (cb, true, false);
538 vbox->pack_start (hbox);
543 editor->ensure_float (msg);
555 if (session && session->dirty()) {
556 switch (ask_about_saving_session(_("quit"))) {
561 /* use the default name */
562 if (save_state_canfail ("")) {
563 /* failed - don't quit */
564 MessageDialog msg (*editor,
566 Ardour was unable to save your session.\n\n\
567 If you still wish to quit, please use the\n\n\
568 \"Just quit\" option."));
579 session->set_deletion_in_progress ();
582 Config->save_state();
583 ARDOUR_UI::config()->save_state();
588 ARDOUR_UI::ask_about_saving_session (const string & what)
590 ArdourDialog window (_("ardour: save session?"));
591 Gtk::HBox dhbox; // the hbox for the image and text
592 Gtk::Label prompt_label;
593 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
597 msg = string_compose(_("Don't %1"), what);
598 window.add_button (msg, RESPONSE_REJECT);
599 msg = string_compose(_("Just %1"), what);
600 window.add_button (msg, RESPONSE_APPLY);
601 msg = string_compose(_("Save and %1"), what);
602 window.add_button (msg, RESPONSE_ACCEPT);
604 window.set_default_response (RESPONSE_ACCEPT);
606 Gtk::Button noquit_button (msg);
607 noquit_button.set_name ("EditorGTKButton");
612 if (session->snap_name() == session->name()) {
615 type = _("snapshot");
617 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?"),
618 type, session->snap_name());
620 prompt_label.set_text (prompt);
621 prompt_label.set_name (X_("PrompterLabel"));
622 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
624 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
626 dhbox.set_homogeneous (false);
627 dhbox.pack_start (*dimage, false, false, 5);
628 dhbox.pack_start (prompt_label, true, false, 5);
629 window.get_vbox()->pack_start (dhbox);
631 window.set_name (_("Prompter"));
632 window.set_position (Gtk::WIN_POS_MOUSE);
633 window.set_modal (true);
634 window.set_resizable (false);
641 save_the_session = 0;
643 window.set_keep_above (true);
646 ResponseType r = (ResponseType) window.run();
651 case RESPONSE_ACCEPT: // save and get out of here
653 case RESPONSE_APPLY: // get out of here
663 ARDOUR_UI::every_second ()
666 update_buffer_load ();
667 update_disk_space ();
672 ARDOUR_UI::every_point_one_seconds ()
674 update_speed_display ();
675 RapidScreenUpdate(); /* EMIT_SIGNAL */
680 ARDOUR_UI::every_point_zero_one_seconds ()
682 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
687 ARDOUR_UI::update_sample_rate (nframes_t ignored)
691 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
693 if (!engine->connected()) {
695 snprintf (buf, sizeof (buf), _("disconnected"));
699 nframes_t rate = engine->frame_rate();
701 if (fmod (rate, 1000.0) != 0.0) {
702 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
703 (float) rate/1000.0f,
704 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
706 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
708 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
712 sample_rate_label.set_text (buf);
716 ARDOUR_UI::update_cpu_load ()
719 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
720 cpu_load_label.set_text (buf);
724 ARDOUR_UI::update_buffer_load ()
729 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
730 session->playback_load(), session->capture_load());
731 buffer_load_label.set_text (buf);
733 buffer_load_label.set_text ("");
738 ARDOUR_UI::count_recenabled_streams (Route& route)
740 Track* track = dynamic_cast<Track*>(&route);
741 if (track && track->diskstream()->record_enabled()) {
742 rec_enabled_streams += track->n_inputs().n_total();
747 ARDOUR_UI::update_disk_space()
753 nframes_t frames = session->available_capture_duration();
756 if (frames == max_frames) {
757 strcpy (buf, _("Disk: 24hrs+"));
762 nframes_t fr = session->frame_rate();
764 rec_enabled_streams = 0;
765 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
767 if (rec_enabled_streams) {
768 frames /= rec_enabled_streams;
771 hrs = frames / (fr * 3600);
772 frames -= hrs * fr * 3600;
773 mins = frames / (fr * 60);
774 frames -= mins * fr * 60;
777 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
780 disk_space_label.set_text (buf);
784 ARDOUR_UI::update_wall_clock ()
791 tm_now = localtime (&now);
793 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
794 wall_clock_label.set_text (buf);
800 ARDOUR_UI::session_menu (GdkEventButton *ev)
802 session_popup_menu->popup (0, 0);
807 ARDOUR_UI::redisplay_recent_sessions ()
809 std::vector<sys::path> session_directories;
810 RecentSessionsSorter cmp;
812 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
813 recent_session_model->clear ();
815 ARDOUR::RecentSessions rs;
816 ARDOUR::read_recent_sessions (rs);
819 recent_session_display.set_model (recent_session_model);
823 // sort them alphabetically
824 sort (rs.begin(), rs.end(), cmp);
826 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
827 session_directories.push_back ((*i).second);
830 for (vector<sys::path>::const_iterator i = session_directories.begin();
831 i != session_directories.end(); ++i)
833 std::vector<sys::path> state_file_paths;
835 // now get available states for this session
837 get_state_files_in_directory (*i, state_file_paths);
839 if (state_file_paths.empty()) {
844 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
846 Gtk::TreeModel::Row row = *(recent_session_model->append());
848 const string fullpath = (*i).to_string();
850 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
851 row[recent_session_columns.fullpath] = fullpath;
853 if (state_file_names.size() > 1) {
857 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
858 i2 != state_file_names.end(); ++i2)
861 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
863 child_row[recent_session_columns.visible_name] = *i2;
864 child_row[recent_session_columns.fullpath] = fullpath;
869 recent_session_display.set_model (recent_session_model);
873 ARDOUR_UI::build_session_selector ()
875 session_selector_window = new ArdourDialog ("session selector");
877 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
879 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
880 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
881 session_selector_window->set_default_response (RESPONSE_ACCEPT);
882 recent_session_model = TreeStore::create (recent_session_columns);
883 recent_session_display.set_model (recent_session_model);
884 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
885 recent_session_display.set_headers_visible (false);
886 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
888 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
890 scroller->add (recent_session_display);
891 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
893 session_selector_window->set_name ("SessionSelectorWindow");
894 session_selector_window->set_size_request (200, 400);
895 session_selector_window->get_vbox()->pack_start (*scroller);
897 recent_session_display.show();
899 //session_selector_window->get_vbox()->show();
903 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
905 session_selector_window->response (RESPONSE_ACCEPT);
909 ARDOUR_UI::open_recent_session ()
911 /* popup selector window */
913 if (session_selector_window == 0) {
914 build_session_selector ();
917 redisplay_recent_sessions ();
919 ResponseType r = (ResponseType) session_selector_window->run ();
921 session_selector_window->hide();
924 case RESPONSE_ACCEPT:
930 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
932 if (i == recent_session_model->children().end()) {
936 Glib::ustring path = (*i)[recent_session_columns.fullpath];
937 Glib::ustring state = (*i)[recent_session_columns.visible_name];
939 _session_is_new = false;
941 load_session (path, state);
945 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
949 if (stat (info.filename.c_str(), &statbuf) != 0) {
953 if (!S_ISDIR(statbuf.st_mode)) {
959 string session_file = info.filename;
961 session_file += Glib::path_get_basename (info.filename);
962 session_file += ".ardour";
964 if (stat (session_file.c_str(), &statbuf) != 0) {
968 return S_ISREG (statbuf.st_mode);
972 ARDOUR_UI::check_audioengine ()
975 if (!engine->connected()) {
976 MessageDialog msg (_("Ardour is not connected to JACK\n"
977 "You cannot open or close sessions in this condition"));
988 ARDOUR_UI::open_session ()
990 if (!check_audioengine()) {
995 /* popup selector window */
997 if (open_session_selector == 0) {
999 /* ardour sessions are folders */
1001 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1002 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1003 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1005 FileFilter session_filter;
1006 session_filter.add_pattern ("*.ardour");
1007 session_filter.set_name (_("Ardour sessions"));
1008 open_session_selector->add_filter (session_filter);
1009 open_session_selector->set_filter (session_filter);
1012 int response = open_session_selector->run();
1013 open_session_selector->hide ();
1016 case RESPONSE_ACCEPT:
1019 open_session_selector->hide();
1023 open_session_selector->hide();
1024 string session_path = open_session_selector->get_filename();
1028 if (session_path.length() > 0) {
1029 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1030 _session_is_new = isnew;
1031 load_session (path, name);
1038 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1040 list<boost::shared_ptr<MidiTrack> > tracks;
1043 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1050 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1052 if (tracks.size() != how_many) {
1053 if (how_many == 1) {
1054 error << _("could not create a new midi track") << endmsg;
1056 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1060 if ((route = session->new_midi_route ()) == 0) {
1061 error << _("could not create new midi bus") << endmsg;
1067 MessageDialog msg (*editor,
1068 _("There are insufficient JACK ports available\n\
1069 to create a new track or bus.\n\
1070 You should save Ardour, exit and\n\
1071 restart JACK with more ports."));
1078 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1080 list<boost::shared_ptr<AudioTrack> > tracks;
1081 Session::RouteList routes;
1084 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1090 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1092 if (tracks.size() != how_many) {
1093 if (how_many == 1) {
1094 error << _("could not create a new audio track") << endmsg;
1096 error << string_compose (_("could only create %1 of %2 new audio %3"),
1097 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1103 routes = session->new_audio_route (input_channels, output_channels, how_many);
1105 if (routes.size() != how_many) {
1106 if (how_many == 1) {
1107 error << _("could not create a new audio track") << endmsg;
1109 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1115 if (need_control_room_outs) {
1121 route->set_stereo_control_outs (control_lr_channels);
1122 route->control_outs()->set_stereo_pan (pans, this);
1124 #endif /* CONTROLOUTS */
1128 cerr << "About to complain about JACK\n";
1129 MessageDialog msg (*editor,
1130 _("There are insufficient JACK ports available\n\
1131 to create a new track or bus.\n\
1132 You should save Ardour, exit and\n\
1133 restart JACK with more ports."));
1139 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1141 nframes_t _preroll = 0;
1144 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1145 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1147 if (new_position > _preroll) {
1148 new_position -= _preroll;
1153 session->request_locate (new_position);
1158 ARDOUR_UI::transport_goto_start ()
1161 session->goto_start();
1164 /* force displayed area in editor to start no matter
1165 what "follow playhead" setting is.
1169 editor->reset_x_origin (session->current_start_frame());
1175 ARDOUR_UI::transport_goto_zero ()
1178 session->request_locate (0);
1181 /* force displayed area in editor to start no matter
1182 what "follow playhead" setting is.
1186 editor->reset_x_origin (0);
1192 ARDOUR_UI::transport_goto_end ()
1195 nframes_t frame = session->current_end_frame();
1196 session->request_locate (frame);
1198 /* force displayed area in editor to start no matter
1199 what "follow playhead" setting is.
1203 editor->reset_x_origin (frame);
1209 ARDOUR_UI::transport_stop ()
1215 if (session->is_auditioning()) {
1216 session->cancel_audition ();
1220 if (session->get_play_loop ()) {
1221 session->request_play_loop (false);
1224 session->request_stop ();
1228 ARDOUR_UI::transport_stop_and_forget_capture ()
1231 session->request_stop (true);
1236 ARDOUR_UI::remove_last_capture()
1239 editor->remove_last_capture();
1244 ARDOUR_UI::transport_record ()
1247 switch (session->record_status()) {
1248 case Session::Disabled:
1249 if (session->ntracks() == 0) {
1250 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1254 session->maybe_enable_record ();
1256 case Session::Recording:
1257 case Session::Enabled:
1258 session->disable_record (false, true);
1264 ARDOUR_UI::transport_roll ()
1272 rolling = session->transport_rolling ();
1274 if (session->get_play_loop()) {
1275 session->request_play_loop (false);
1276 auto_loop_button.set_visual_state (1);
1277 roll_button.set_visual_state (1);
1278 } else if (session->get_play_range ()) {
1279 session->request_play_range (false);
1280 play_selection_button.set_visual_state (0);
1281 } else if (rolling) {
1282 session->request_locate (session->last_transport_start(), true);
1285 session->request_transport_speed (1.0f);
1289 ARDOUR_UI::transport_loop()
1292 if (session->get_play_loop()) {
1293 if (session->transport_rolling()) {
1294 Location * looploc = session->locations()->auto_loop_location();
1296 session->request_locate (looploc->start(), true);
1301 session->request_play_loop (true);
1307 ARDOUR_UI::transport_play_selection ()
1313 if (!session->get_play_range()) {
1314 session->request_stop ();
1317 editor->play_selection ();
1321 ARDOUR_UI::transport_rewind (int option)
1323 float current_transport_speed;
1326 current_transport_speed = session->transport_speed();
1328 if (current_transport_speed >= 0.0f) {
1331 session->request_transport_speed (-1.0f);
1334 session->request_transport_speed (-4.0f);
1337 session->request_transport_speed (-0.5f);
1342 session->request_transport_speed (current_transport_speed * 1.5f);
1348 ARDOUR_UI::transport_forward (int option)
1350 float current_transport_speed;
1353 current_transport_speed = session->transport_speed();
1355 if (current_transport_speed <= 0.0f) {
1358 session->request_transport_speed (1.0f);
1361 session->request_transport_speed (4.0f);
1364 session->request_transport_speed (0.5f);
1369 session->request_transport_speed (current_transport_speed * 1.5f);
1375 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1381 boost::shared_ptr<Route> r;
1383 if ((r = session->route_by_remote_id (dstream)) != 0) {
1387 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1388 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1397 ARDOUR_UI::queue_transport_change ()
1399 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1403 ARDOUR_UI::map_transport_state ()
1405 float sp = session->transport_speed();
1408 transport_rolling ();
1409 } else if (sp < 0.0f) {
1410 transport_rewinding ();
1411 } else if (sp > 0.0f) {
1412 transport_forwarding ();
1414 transport_stopped ();
1419 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1421 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1422 (int) adj.get_value()].c_str());
1426 ARDOUR_UI::engine_stopped ()
1428 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1429 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1430 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1434 ARDOUR_UI::engine_running ()
1436 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1437 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1438 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1440 Glib::RefPtr<Action> action;
1441 char* action_name = 0;
1443 switch (engine->frames_per_cycle()) {
1445 action_name = X_("JACKLatency32");
1448 action_name = X_("JACKLatency64");
1451 action_name = X_("JACKLatency128");
1454 action_name = X_("JACKLatency512");
1457 action_name = X_("JACKLatency1024");
1460 action_name = X_("JACKLatency2048");
1463 action_name = X_("JACKLatency4096");
1466 action_name = X_("JACKLatency8192");
1469 /* XXX can we do anything useful ? */
1475 action = ActionManager::get_action (X_("JACK"), action_name);
1478 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1479 ract->set_active ();
1485 ARDOUR_UI::engine_halted ()
1487 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1489 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1490 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1492 update_sample_rate (0);
1494 MessageDialog msg (*editor,
1496 JACK has either been shutdown or it\n\
1497 disconnected Ardour because Ardour\n\
1498 was not fast enough. You can save the\n\
1499 session and/or try to reconnect to JACK ."));
1504 ARDOUR_UI::do_engine_start ()
1512 error << _("Unable to start the session running")
1522 ARDOUR_UI::setup_theme ()
1524 theme_manager->setup_theme();
1528 ARDOUR_UI::start_engine ()
1530 if (do_engine_start () == 0) {
1531 if (session && _session_is_new) {
1532 /* we need to retain initial visual
1533 settings for a new session
1535 session->save_state ("");
1543 ARDOUR_UI::update_clocks ()
1545 if (!editor || !editor->dragging_playhead()) {
1546 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1551 ARDOUR_UI::start_clocking ()
1553 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1557 ARDOUR_UI::stop_clocking ()
1559 clock_signal_connection.disconnect ();
1563 ARDOUR_UI::toggle_clocking ()
1566 if (clock_button.get_active()) {
1575 ARDOUR_UI::_blink (void *arg)
1578 ((ARDOUR_UI *) arg)->blink ();
1585 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1589 ARDOUR_UI::start_blinking ()
1591 /* Start the blink signal. Everybody with a blinking widget
1592 uses Blink to drive the widget's state.
1595 if (blink_timeout_tag < 0) {
1597 blink_timeout_tag = g_timeout_add (240, _blink, this);
1602 ARDOUR_UI::stop_blinking ()
1604 if (blink_timeout_tag >= 0) {
1605 g_source_remove (blink_timeout_tag);
1606 blink_timeout_tag = -1;
1611 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1617 if (io.n_inputs().n_total() == 0) {
1622 /* XXX we're not handling multiple ports yet. */
1624 const char **connections = io.input(0)->get_connections();
1626 if (connections == 0 || connections[0] == '\0') {
1629 buf = connections[0];
1636 if (io.n_outputs().n_total() == 0) {
1641 /* XXX we're not handling multiple ports yet. */
1643 const char **connections = io.output(0)->get_connections();
1645 if (connections == 0 || connections[0] == '\0') {
1648 buf = connections[0];
1655 /** Ask the user for the name of a new shapshot and then take it.
1658 ARDOUR_UI::snapshot_session ()
1660 ArdourPrompter prompter (true);
1664 struct tm local_time;
1667 localtime_r (&n, &local_time);
1668 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1670 prompter.set_name ("Prompter");
1671 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1672 prompter.set_prompt (_("Name of New Snapshot"));
1673 prompter.set_initial_text (timebuf);
1675 switch (prompter.run()) {
1676 case RESPONSE_ACCEPT:
1677 prompter.get_result (snapname);
1678 if (snapname.length()){
1679 save_state (snapname);
1689 ARDOUR_UI::save_state (const string & name)
1691 (void) save_state_canfail (name);
1695 ARDOUR_UI::save_state_canfail (string name)
1700 if (name.length() == 0) {
1701 name = session->snap_name();
1704 if ((ret = session->save_state (name)) != 0) {
1708 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1713 ARDOUR_UI::restore_state (string name)
1716 if (name.length() == 0) {
1717 name = session->name();
1719 session->restore_state (name);
1724 ARDOUR_UI::primary_clock_value_changed ()
1727 session->request_locate (primary_clock.current_time ());
1732 ARDOUR_UI::secondary_clock_value_changed ()
1735 session->request_locate (secondary_clock.current_time ());
1740 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1742 if (session && dstream && dstream->record_enabled()) {
1744 Session::RecordState rs;
1746 rs = session->record_status ();
1749 case Session::Disabled:
1750 case Session::Enabled:
1751 if (w->get_state() != STATE_SELECTED) {
1752 w->set_state (STATE_SELECTED);
1756 case Session::Recording:
1757 if (w->get_state() != STATE_ACTIVE) {
1758 w->set_state (STATE_ACTIVE);
1764 if (w->get_state() != STATE_NORMAL) {
1765 w->set_state (STATE_NORMAL);
1771 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1777 switch (session->record_status()) {
1778 case Session::Enabled:
1780 rec_button.set_visual_state (2);
1782 rec_button.set_visual_state (0);
1786 case Session::Recording:
1787 rec_button.set_visual_state (1);
1791 rec_button.set_visual_state (0);
1797 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1805 ARDOUR_UI::save_template ()
1808 ArdourPrompter prompter (true);
1811 if (!check_audioengine()) {
1815 prompter.set_name (X_("Prompter"));
1816 prompter.set_prompt (_("Name for mix template:"));
1817 prompter.set_initial_text(session->name() + _("-template"));
1818 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1820 switch (prompter.run()) {
1821 case RESPONSE_ACCEPT:
1822 prompter.get_result (name);
1824 if (name.length()) {
1825 session->save_template (name);
1835 ARDOUR_UI::new_session (std::string predetermined_path)
1837 string session_name;
1838 string session_path;
1840 if (!check_audioengine()) {
1844 int response = Gtk::RESPONSE_NONE;
1846 new_session_dialog->set_modal(true);
1847 new_session_dialog->set_name (predetermined_path);
1848 new_session_dialog->reset_recent();
1849 new_session_dialog->show();
1850 new_session_dialog->set_current_page (0);
1853 response = new_session_dialog->run ();
1855 if (!check_audioengine()) {
1856 new_session_dialog->hide ();
1860 _session_is_new = false;
1862 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1867 new_session_dialog->hide ();
1870 } else if (response == Gtk::RESPONSE_NONE) {
1872 /* Clear was pressed */
1873 new_session_dialog->reset();
1875 } else if (response == Gtk::RESPONSE_YES) {
1877 /* YES == OPEN, but there's no enum for that */
1879 session_name = new_session_dialog->session_name();
1881 if (session_name.empty()) {
1882 response = Gtk::RESPONSE_NONE;
1886 if (session_name[0] == '/' ||
1887 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1888 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1889 load_session (Glib::path_get_dirname (session_name), session_name);
1891 session_path = new_session_dialog->session_folder();
1892 load_session (session_path, session_name);
1895 } else if (response == Gtk::RESPONSE_OK) {
1897 session_name = new_session_dialog->session_name();
1899 if (!new_session_dialog->on_new_session_page ()) {
1901 /* XXX this is a bit of a hack..
1902 i really want the new sesion dialog to return RESPONSE_YES
1903 if we're on page 1 (the load page)
1904 Unfortunately i can't see how atm..
1907 if (session_name.empty()) {
1908 response = Gtk::RESPONSE_NONE;
1912 if (session_name[0] == '/' ||
1913 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1914 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1915 load_session (Glib::path_get_dirname (session_name), session_name);
1917 session_path = new_session_dialog->session_folder();
1918 load_session (session_path, session_name);
1923 if (session_name.empty()) {
1924 response = Gtk::RESPONSE_NONE;
1928 if (session_name[0] == '/' ||
1929 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1930 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1932 session_path = Glib::path_get_dirname (session_name);
1933 session_name = Glib::path_get_basename (session_name);
1937 session_path = new_session_dialog->session_folder();
1941 //XXX This is needed because session constructor wants a
1942 //non-existant path. hopefully this will be fixed at some point.
1944 session_path = Glib::build_filename (session_path, session_name);
1946 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1948 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1950 MessageDialog msg (str,
1952 Gtk::MESSAGE_WARNING,
1953 Gtk::BUTTONS_YES_NO,
1957 msg.set_name (X_("CleanupDialog"));
1958 msg.set_wmclass (X_("existing_session"), "Ardour");
1959 msg.set_position (Gtk::WIN_POS_MOUSE);
1961 switch (msg.run()) {
1963 load_session (session_path, session_name);
1967 response = RESPONSE_NONE;
1968 new_session_dialog->reset ();
1973 _session_is_new = true;
1975 std::string template_name = new_session_dialog->session_template_name();
1977 if (new_session_dialog->use_session_template()) {
1979 load_session (session_path, session_name, &template_name);
1985 AutoConnectOption iconnect;
1986 AutoConnectOption oconnect;
1988 if (new_session_dialog->create_control_bus()) {
1989 cchns = (uint32_t) new_session_dialog->control_channel_count();
1994 if (new_session_dialog->create_master_bus()) {
1995 mchns = (uint32_t) new_session_dialog->master_channel_count();
2000 if (new_session_dialog->connect_inputs()) {
2001 iconnect = AutoConnectPhysical;
2003 iconnect = AutoConnectOption (0);
2006 /// @todo some minor tweaks.
2008 if (new_session_dialog->connect_outs_to_master()) {
2009 oconnect = AutoConnectMaster;
2010 } else if (new_session_dialog->connect_outs_to_physical()) {
2011 oconnect = AutoConnectPhysical;
2013 oconnect = AutoConnectOption (0);
2016 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2017 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2019 if (!build_session (session_path,
2027 engine->frame_rate() * 60 * 5)) {
2029 response = Gtk::RESPONSE_NONE;
2030 new_session_dialog->reset ();
2037 } while (response == Gtk::RESPONSE_NONE);
2041 new_session_dialog->get_window()->set_cursor();
2042 new_session_dialog->hide();
2047 ARDOUR_UI::close_session()
2049 if (!check_audioengine()) {
2058 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2060 Session *new_session;
2061 session_loaded = false;
2063 if (!check_audioengine()) {
2067 if(!unload_session ()) return -1;
2069 /* if it already exists, we must have write access */
2071 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2072 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2073 "This prevents the session from being loaded."));
2079 new_session = new Session (*engine, path, snap_name, mix_template);
2084 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2088 connect_to_session (new_session);
2090 Config->set_current_owner (ConfigVariableBase::Interface);
2092 session_loaded = true;
2094 goto_editor_window ();
2097 session->set_clean ();
2100 editor->edit_cursor_position (true);
2105 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2106 uint32_t control_channels,
2107 uint32_t master_channels,
2108 AutoConnectOption input_connect,
2109 AutoConnectOption output_connect,
2112 nframes_t initial_length)
2114 Session *new_session;
2116 if (!check_audioengine()) {
2120 session_loaded = false;
2122 if (!unload_session ()) return false;
2124 _session_is_new = true;
2127 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2128 control_channels, master_channels, nphysin, nphysout, initial_length);
2133 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2138 connect_to_session (new_session);
2140 session_loaded = true;
2148 editor->show_window ();
2159 ARDOUR_UI::show_splash ()
2162 about = new About();
2163 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2170 ARDOUR_UI::about_signal_response(int response)
2176 ARDOUR_UI::hide_splash ()
2179 about->get_window()->set_cursor ();
2185 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2189 removed = rep.paths.size();
2192 MessageDialog msgd (*editor,
2193 _("No audio files were ready for cleanup"),
2196 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2197 msgd.set_secondary_text (_("If this seems suprising, \n\
2198 check for any existing snapshots.\n\
2199 These may still include regions that\n\
2200 require some unused files to continue to exist."));
2206 ArdourDialog results (_("ardour: cleanup"), true, false);
2208 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2209 CleanupResultsModelColumns() {
2213 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2214 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2218 CleanupResultsModelColumns results_columns;
2219 Glib::RefPtr<Gtk::ListStore> results_model;
2220 Gtk::TreeView results_display;
2222 results_model = ListStore::create (results_columns);
2223 results_display.set_model (results_model);
2224 results_display.append_column (list_title, results_columns.visible_name);
2226 results_display.set_name ("CleanupResultsList");
2227 results_display.set_headers_visible (true);
2228 results_display.set_headers_clickable (false);
2229 results_display.set_reorderable (false);
2231 Gtk::ScrolledWindow list_scroller;
2234 Gtk::HBox dhbox; // the hbox for the image and text
2235 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2236 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2238 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2240 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2242 if (rep.space < 1048576.0f) {
2244 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2246 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2250 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2252 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2256 dhbox.pack_start (*dimage, true, false, 5);
2257 dhbox.pack_start (txt, true, false, 5);
2259 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2260 TreeModel::Row row = *(results_model->append());
2261 row[results_columns.visible_name] = *i;
2262 row[results_columns.fullpath] = *i;
2265 list_scroller.add (results_display);
2266 list_scroller.set_size_request (-1, 150);
2267 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2269 dvbox.pack_start (dhbox, true, false, 5);
2270 dvbox.pack_start (list_scroller, true, false, 5);
2271 ddhbox.pack_start (dvbox, true, false, 5);
2273 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2274 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2275 results.set_default_response (RESPONSE_CLOSE);
2276 results.set_position (Gtk::WIN_POS_MOUSE);
2278 results_display.show();
2279 list_scroller.show();
2286 //results.get_vbox()->show();
2287 results.set_resizable (false);
2294 ARDOUR_UI::cleanup ()
2297 /* shouldn't happen: menu item is insensitive */
2302 MessageDialog checker (_("Are you sure you want to cleanup?"),
2304 Gtk::MESSAGE_QUESTION,
2305 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2307 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2308 ALL undo/redo information will be lost if you cleanup.\n\
2309 After cleanup, unused audio files will be moved to a \
2310 \"dead sounds\" location."));
2312 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2313 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2314 checker.set_default_response (RESPONSE_CANCEL);
2316 checker.set_name (_("CleanupDialog"));
2317 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2318 checker.set_position (Gtk::WIN_POS_MOUSE);
2320 switch (checker.run()) {
2321 case RESPONSE_ACCEPT:
2327 Session::cleanup_report rep;
2329 editor->prepare_for_cleanup ();
2331 /* do not allow flush until a session is reloaded */
2333 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2335 act->set_sensitive (false);
2338 if (session->cleanup_sources (rep)) {
2343 display_cleanup_results (rep,
2346 The following %1 %2 not in use and \n\
2347 have been moved to:\n\
2349 Flushing the wastebasket will \n\
2350 release an additional\n\
2351 %4 %5bytes of disk space.\n"
2359 ARDOUR_UI::flush_trash ()
2362 /* shouldn't happen: menu item is insensitive */
2366 Session::cleanup_report rep;
2368 if (session->cleanup_trash_sources (rep)) {
2372 display_cleanup_results (rep,
2374 _("The following %1 %2 deleted from\n\
2376 releasing %4 %5bytes of disk space"));
2380 ARDOUR_UI::add_route (Gtk::Window* float_window)
2388 if (add_route_dialog == 0) {
2389 add_route_dialog = new AddRouteDialog;
2391 add_route_dialog->set_transient_for (*float_window);
2395 if (add_route_dialog->is_visible()) {
2396 /* we're already doing this */
2400 ResponseType r = (ResponseType) add_route_dialog->run ();
2402 add_route_dialog->hide();
2405 case RESPONSE_ACCEPT:
2412 if ((count = add_route_dialog->count()) <= 0) {
2416 uint32_t input_chan = add_route_dialog->channels ();
2417 uint32_t output_chan;
2418 string name_template = add_route_dialog->name_template ();
2419 bool track = add_route_dialog->track ();
2421 AutoConnectOption oac = Config->get_output_auto_connect();
2423 if (oac & AutoConnectMaster) {
2424 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2426 output_chan = input_chan;
2429 /* XXX do something with name template */
2431 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2433 session_add_midi_track(count);
2435 MessageDialog msg (*editor,
2436 _("Sorry, MIDI Busses are not supported at this time."));
2438 //session_add_midi_bus();
2442 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2444 session_add_audio_bus (input_chan, output_chan, count);
2450 ARDOUR_UI::mixer_settings () const
2455 node = session->instant_xml(X_("Mixer"));
2457 node = Config->instant_xml(X_("Mixer"));
2461 node = new XMLNode (X_("Mixer"));
2468 ARDOUR_UI::editor_settings () const
2473 node = session->instant_xml(X_("Editor"));
2475 node = Config->instant_xml(X_("Editor"));
2479 node = new XMLNode (X_("Editor"));
2485 ARDOUR_UI::keyboard_settings () const
2489 node = Config->extra_xml(X_("Keyboard"));
2492 node = new XMLNode (X_("Keyboard"));
2498 ARDOUR_UI::halt_on_xrun_message ()
2500 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2502 MessageDialog msg (*editor,
2503 _("Recording was stopped because your system could not keep up."));
2508 ARDOUR_UI::disk_overrun_handler ()
2510 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2512 if (!have_disk_speed_dialog_displayed) {
2513 have_disk_speed_dialog_displayed = true;
2514 MessageDialog* msg = new MessageDialog (*editor, _("\
2515 The disk system on your computer\n\
2516 was not able to keep up with Ardour.\n\
2518 Specifically, it failed to write data to disk\n\
2519 quickly enough to keep up with recording.\n"));
2520 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2526 ARDOUR_UI::disk_underrun_handler ()
2528 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2530 if (!have_disk_speed_dialog_displayed) {
2531 have_disk_speed_dialog_displayed = true;
2532 MessageDialog* msg = new MessageDialog (*editor,
2533 _("The disk system on your computer\n\
2534 was not able to keep up with Ardour.\n\
2536 Specifically, it failed to read data from disk\n\
2537 quickly enough to keep up with playback.\n"));
2538 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2544 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2546 have_disk_speed_dialog_displayed = false;
2551 ARDOUR_UI::pending_state_dialog ()
2553 ArdourDialog dialog ("pending state dialog");
2555 This session appears to have been in\n\
2556 middle of recording when ardour or\n\
2557 the computer was shutdown.\n\
2559 Ardour can recover any captured audio for\n\
2560 you, or it can ignore it. Please decide\n\
2561 what you would like to do.\n"));
2563 dialog.get_vbox()->pack_start (message);
2564 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2565 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2567 dialog.set_position (WIN_POS_CENTER);
2569 //dialog.get_vbox()->show();
2571 switch (dialog.run ()) {
2572 case RESPONSE_ACCEPT:
2580 ARDOUR_UI::disconnect_from_jack ()
2583 if( engine->disconnect_from_jack ()) {
2584 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2588 update_sample_rate (0);
2593 ARDOUR_UI::reconnect_to_jack ()
2596 if (engine->reconnect_to_jack ()) {
2597 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2601 update_sample_rate (0);
2606 ARDOUR_UI::cmdline_new_session (string path)
2608 if (path[0] != '/') {
2609 char buf[PATH_MAX+1];
2612 getcwd (buf, sizeof (buf));
2621 return FALSE; /* don't call it again */
2625 ARDOUR_UI::use_config ()
2627 Glib::RefPtr<Action> act;
2629 switch (Config->get_native_file_data_format ()) {
2631 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2634 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2637 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2642 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2643 ract->set_active ();
2646 switch (Config->get_native_file_header_format ()) {
2648 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2651 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2654 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2657 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2660 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2663 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2666 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2671 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2672 ract->set_active ();
2675 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2677 set_transport_controllable_state (*node);
2682 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2684 if (Config->get_primary_clock_delta_edit_cursor()) {
2685 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
2687 primary_clock.set (pos, 0, true);
2690 if (Config->get_secondary_clock_delta_edit_cursor()) {
2691 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
2693 secondary_clock.set (pos);
2696 if (big_clock_window) {
2697 big_clock.set (pos);
2702 ARDOUR_UI::record_state_changed ()
2704 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2706 if (!session || !big_clock_window) {
2707 /* why bother - the clock isn't visible */
2711 switch (session->record_status()) {
2712 case Session::Recording:
2713 big_clock.set_widget_name ("BigClockRecording");
2716 big_clock.set_widget_name ("BigClockNonRecording");
2722 ARDOUR_UI::set_keybindings_path (string path)
2724 keybindings_path = path;
2728 ARDOUR_UI::save_keybindings ()
2730 if (can_save_keybindings) {
2731 AccelMap::save (user_keybindings_path);
2736 ARDOUR_UI::first_idle ()
2739 session->allow_auto_play (true);
2741 can_save_keybindings = true;
2746 ARDOUR_UI::store_clock_modes ()
2748 XMLNode* node = new XMLNode(X_("ClockModes"));
2750 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2751 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2754 session->add_extra_xml (*node);
2755 session->set_dirty ();
2760 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2761 : Controllable (name), ui (u), type(tp)
2767 ARDOUR_UI::TransportControllable::set_value (float val)
2769 if (type == ShuttleControl) {
2776 fract = -((0.5f - val)/0.5f);
2778 fract = ((val - 0.5f)/0.5f);
2782 ui.set_shuttle_fract (fract);
2787 /* do nothing: these are radio-style actions */
2795 action = X_("Roll");
2798 action = X_("Stop");
2801 action = X_("Goto Start");
2804 action = X_("Goto End");
2807 action = X_("Loop");
2810 action = X_("Play Selection");
2813 action = X_("Record");
2823 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2831 ARDOUR_UI::TransportControllable::get_value (void) const
2850 case ShuttleControl:
2860 ARDOUR_UI::TransportControllable::set_id (const string& str)
2866 ARDOUR_UI::setup_profile ()
2868 if (gdk_screen_width() < 1200) {
2869 Profile->set_small_screen ();
2874 ARDOUR_UI::disable_all_plugins ()
2880 // session->begin_reversible_command (_("Disable all plugins"));
2882 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2884 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2885 // XMLNode& before = (*i)->get_redirect_state ();
2886 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
2887 (*i)->disable_plugins ();
2888 // XMLNode& after = (*i)->get_redirect_state ();
2889 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
2893 // session->commit_reversible_command ();
2897 ARDOUR_UI::ab_all_plugins ()
2903 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2905 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2906 (*i)->ab_plugins (ab_direction);
2909 ab_direction = !ab_direction;