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_utils.h>
61 #include <ardour/port.h>
62 #include <ardour/audioengine.h>
63 #include <ardour/playlist.h>
64 #include <ardour/utils.h>
65 #include <ardour/audio_diskstream.h>
66 #include <ardour/audiofilesource.h>
67 #include <ardour/recent_sessions.h>
68 #include <ardour/port.h>
69 #include <ardour/audio_track.h>
70 #include <ardour/midi_track.h>
71 #include <ardour/filesystem_paths.h>
74 #include "ardour_ui.h"
75 #include "public_editor.h"
76 #include "audio_clock.h"
81 #include "add_route_dialog.h"
82 #include "new_session_dialog.h"
85 #include "gui_thread.h"
86 #include "theme_manager.h"
91 using namespace ARDOUR;
93 using namespace Gtkmm2ext;
97 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
98 UIConfiguration *ARDOUR_UI::ui_config = 0;
100 sigc::signal<void,bool> ARDOUR_UI::Blink;
101 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
102 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
103 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
105 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
107 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
109 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
110 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
111 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
112 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
116 adjuster_table (3, 3),
120 preroll_button (_("pre\nroll")),
121 postroll_button (_("post\nroll")),
125 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
129 roll_controllable ("transport roll", *this, TransportControllable::Roll),
130 stop_controllable ("transport stop", *this, TransportControllable::Stop),
131 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
132 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
133 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
134 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
135 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
136 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
137 shuttle_controller_binding_proxy (shuttle_controllable),
139 roll_button (roll_controllable),
140 stop_button (stop_controllable),
141 goto_start_button (goto_start_controllable),
142 goto_end_button (goto_end_controllable),
143 auto_loop_button (auto_loop_controllable),
144 play_selection_button (play_selection_controllable),
145 rec_button (rec_controllable),
147 shuttle_units_button (_("% ")),
149 punch_in_button (_("Punch In")),
150 punch_out_button (_("Punch Out")),
151 auto_return_button (_("Auto Return")),
152 auto_play_button (_("Auto Play")),
153 auto_input_button (_("Auto Input")),
154 click_button (_("Click")),
155 time_master_button (_("time\nmaster")),
157 auditioning_alert_button (_("AUDITION")),
158 solo_alert_button (_("SOLO")),
161 using namespace Gtk::Menu_Helpers;
167 if (theArdourUI == 0) {
171 ui_config = new UIConfiguration();
172 theme_manager = new ThemeManager();
177 _session_is_new = false;
178 big_clock_window = 0;
179 session_selector_window = 0;
180 last_key_press_time = 0;
181 connection_editor = 0;
182 add_route_dialog = 0;
186 open_session_selector = 0;
187 have_configure_timeout = false;
188 have_disk_speed_dialog_displayed = false;
189 session_loaded = false;
190 last_speed_displayed = -1.0f;
193 sys::path key_bindings_file;
195 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
196 "ardour.bindings", key_bindings_file);
198 keybindings_path = key_bindings_file.to_string();
200 /* store all bindings changes in per-user file, no matter where they were loaded from */
201 user_keybindings_path = user_config_directory().to_string ();
202 user_keybindings_path += '/';
203 user_keybindings_path += "ardour.bindings";
205 can_save_keybindings = false;
207 last_configure_time.tv_sec = 0;
208 last_configure_time.tv_usec = 0;
210 shuttle_grabbed = false;
212 shuttle_max_speed = 8.0f;
214 shuttle_style_menu = 0;
215 shuttle_unit_menu = 0;
217 gettimeofday (&last_peak_grab, 0);
218 gettimeofday (&last_shuttle_request, 0);
220 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
221 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
223 /* handle pending state with a dialog */
225 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
227 /* have to wait for AudioEngine and Configuration before proceeding */
231 ARDOUR_UI::set_engine (AudioEngine& e)
235 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
236 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
237 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
238 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
240 ActionManager::init ();
241 new_session_dialog = new NewSessionDialog();
245 keyboard = new Keyboard;
247 if (setup_windows ()) {
248 throw failed_constructor ();
251 if (GTK_ARDOUR::show_key_actions) {
252 vector<string> names;
253 vector<string> paths;
255 vector<AccelKey> bindings;
257 ActionManager::get_all_actions (names, paths, keys, bindings);
259 vector<string>::iterator n;
260 vector<string>::iterator k;
261 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
262 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
268 /* start with timecode, metering enabled
271 blink_timeout_tag = -1;
273 /* the global configuration object is now valid */
277 /* this being a GUI and all, we want peakfiles */
279 AudioFileSource::set_build_peakfiles (true);
280 AudioFileSource::set_build_missing_peakfiles (true);
282 /* set default clock modes */
284 primary_clock.set_mode (AudioClock::SMPTE);
285 secondary_clock.set_mode (AudioClock::BBT);
287 /* start the time-of-day-clock */
289 update_wall_clock ();
290 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
292 update_disk_space ();
294 update_sample_rate (engine->frame_rate());
296 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
297 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
300 ARDOUR_UI::~ARDOUR_UI ()
302 save_ardour_state ();
316 if (add_route_dialog) {
317 delete add_route_dialog;
322 ARDOUR_UI::configure_timeout ()
327 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
328 /* no configure events yet */
332 gettimeofday (&now, 0);
333 timersub (&now, &last_configure_time, &diff);
335 /* force a gap of 0.5 seconds since the last configure event
338 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
341 have_configure_timeout = false;
342 save_ardour_state ();
348 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
350 if (have_configure_timeout) {
351 gettimeofday (&last_configure_time, 0);
353 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
354 have_configure_timeout = true;
361 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
363 const XMLProperty* prop;
365 if ((prop = node.property ("roll")) != 0) {
366 roll_controllable.set_id (prop->value());
368 if ((prop = node.property ("stop")) != 0) {
369 stop_controllable.set_id (prop->value());
371 if ((prop = node.property ("goto_start")) != 0) {
372 goto_start_controllable.set_id (prop->value());
374 if ((prop = node.property ("goto_end")) != 0) {
375 goto_end_controllable.set_id (prop->value());
377 if ((prop = node.property ("auto_loop")) != 0) {
378 auto_loop_controllable.set_id (prop->value());
380 if ((prop = node.property ("play_selection")) != 0) {
381 play_selection_controllable.set_id (prop->value());
383 if ((prop = node.property ("rec")) != 0) {
384 rec_controllable.set_id (prop->value());
386 if ((prop = node.property ("shuttle")) != 0) {
387 shuttle_controllable.set_id (prop->value());
392 ARDOUR_UI::get_transport_controllable_state ()
394 XMLNode* node = new XMLNode(X_("TransportControllables"));
397 roll_controllable.id().print (buf, sizeof (buf));
398 node->add_property (X_("roll"), buf);
399 stop_controllable.id().print (buf, sizeof (buf));
400 node->add_property (X_("stop"), buf);
401 goto_start_controllable.id().print (buf, sizeof (buf));
402 node->add_property (X_("goto_start"), buf);
403 goto_end_controllable.id().print (buf, sizeof (buf));
404 node->add_property (X_("goto_end"), buf);
405 auto_loop_controllable.id().print (buf, sizeof (buf));
406 node->add_property (X_("auto_loop"), buf);
407 play_selection_controllable.id().print (buf, sizeof (buf));
408 node->add_property (X_("play_selection"), buf);
409 rec_controllable.id().print (buf, sizeof (buf));
410 node->add_property (X_("rec"), buf);
411 shuttle_controllable.id().print (buf, sizeof (buf));
412 node->add_property (X_("shuttle"), buf);
418 ARDOUR_UI::save_ardour_state ()
420 if (!keyboard || !mixer || !editor) {
424 /* XXX this is all a bit dubious. add_extra_xml() uses
425 a different lifetime model from add_instant_xml().
428 XMLNode* node = new XMLNode (keyboard->get_state());
429 Config->add_extra_xml (*node);
430 Config->add_extra_xml (get_transport_controllable_state());
431 Config->save_state();
433 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
434 XMLNode mnode(mixer->get_state());
437 session->add_instant_xml (enode);
438 session->add_instant_xml (mnode);
440 Config->add_instant_xml (enode);
441 Config->add_instant_xml (mnode);
448 ARDOUR_UI::autosave_session ()
450 if (!Config->get_periodic_safety_backups())
454 session->maybe_write_autosave();
461 ARDOUR_UI::update_autosave ()
463 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
465 if (session->dirty()) {
466 if (_autosave_connection.connected()) {
467 _autosave_connection.disconnect();
470 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
471 Config->get_periodic_safety_backup_interval() * 1000);
474 if (_autosave_connection.connected()) {
475 _autosave_connection.disconnect();
481 ARDOUR_UI::startup ()
483 check_memory_locking();
487 ARDOUR_UI::no_memory_warning ()
489 XMLNode node (X_("no-memory-warning"));
490 Config->add_instant_xml (node);
494 ARDOUR_UI::check_memory_locking ()
497 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
501 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
503 if (engine->is_realtime() && memory_warning_node == 0) {
505 struct rlimit limits;
507 long pages, page_size;
509 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
512 ram = (int64_t) pages * (int64_t) page_size;
515 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
519 if (limits.rlim_cur != RLIM_INFINITY) {
521 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
524 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
525 "This might cause Ardour to run out of memory before your system "
526 "runs out of memory. \n\n"
527 "You can view the memory limit with 'ulimit -l', "
528 "and it is normally controlled by /etc/security/limits.conf"));
530 VBox* vbox = msg.get_vbox();
532 CheckButton cb (_("Do not show this window again"));
534 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
536 hbox.pack_start (cb, true, false);
537 vbox->pack_start (hbox);
542 editor->ensure_float (msg);
554 if (session && session->dirty()) {
555 switch (ask_about_saving_session(_("quit"))) {
560 /* use the default name */
561 if (save_state_canfail ("")) {
562 /* failed - don't quit */
563 MessageDialog msg (*editor,
565 Ardour was unable to save your session.\n\n\
566 If you still wish to quit, please use the\n\n\
567 \"Just quit\" option."));
578 session->set_deletion_in_progress ();
581 Config->save_state();
582 ARDOUR_UI::config()->save_state();
587 ARDOUR_UI::ask_about_saving_session (const string & what)
589 ArdourDialog window (_("ardour: save session?"));
590 Gtk::HBox dhbox; // the hbox for the image and text
591 Gtk::Label prompt_label;
592 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
596 msg = string_compose(_("Don't %1"), what);
597 window.add_button (msg, RESPONSE_REJECT);
598 msg = string_compose(_("Just %1"), what);
599 window.add_button (msg, RESPONSE_APPLY);
600 msg = string_compose(_("Save and %1"), what);
601 window.add_button (msg, RESPONSE_ACCEPT);
603 window.set_default_response (RESPONSE_ACCEPT);
605 Gtk::Button noquit_button (msg);
606 noquit_button.set_name ("EditorGTKButton");
611 if (session->snap_name() == session->name()) {
614 type = _("snapshot");
616 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?"),
617 type, session->snap_name());
619 prompt_label.set_text (prompt);
620 prompt_label.set_name (X_("PrompterLabel"));
621 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
623 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
625 dhbox.set_homogeneous (false);
626 dhbox.pack_start (*dimage, false, false, 5);
627 dhbox.pack_start (prompt_label, true, false, 5);
628 window.get_vbox()->pack_start (dhbox);
630 window.set_name (_("Prompter"));
631 window.set_position (Gtk::WIN_POS_MOUSE);
632 window.set_modal (true);
633 window.set_resizable (false);
640 save_the_session = 0;
642 window.set_keep_above (true);
645 ResponseType r = (ResponseType) window.run();
650 case RESPONSE_ACCEPT: // save and get out of here
652 case RESPONSE_APPLY: // get out of here
662 ARDOUR_UI::every_second ()
665 update_buffer_load ();
666 update_disk_space ();
671 ARDOUR_UI::every_point_one_seconds ()
673 update_speed_display ();
674 RapidScreenUpdate(); /* EMIT_SIGNAL */
679 ARDOUR_UI::every_point_zero_one_seconds ()
681 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
686 ARDOUR_UI::update_sample_rate (nframes_t ignored)
690 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
692 if (!engine->connected()) {
694 snprintf (buf, sizeof (buf), _("disconnected"));
698 nframes_t rate = engine->frame_rate();
700 if (fmod (rate, 1000.0) != 0.0) {
701 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
702 (float) rate/1000.0f,
703 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
705 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
707 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
711 sample_rate_label.set_text (buf);
715 ARDOUR_UI::update_cpu_load ()
718 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
719 cpu_load_label.set_text (buf);
723 ARDOUR_UI::update_buffer_load ()
728 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
729 session->playback_load(), session->capture_load());
730 buffer_load_label.set_text (buf);
732 buffer_load_label.set_text ("");
737 ARDOUR_UI::count_recenabled_streams (Route& route)
739 Track* track = dynamic_cast<Track*>(&route);
740 if (track && track->diskstream()->record_enabled()) {
741 rec_enabled_streams += track->n_inputs().n_total();
746 ARDOUR_UI::update_disk_space()
752 nframes_t frames = session->available_capture_duration();
755 if (frames == max_frames) {
756 strcpy (buf, _("Disk: 24hrs+"));
761 nframes_t fr = session->frame_rate();
763 rec_enabled_streams = 0;
764 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
766 if (rec_enabled_streams) {
767 frames /= rec_enabled_streams;
770 hrs = frames / (fr * 3600);
771 frames -= hrs * fr * 3600;
772 mins = frames / (fr * 60);
773 frames -= mins * fr * 60;
776 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
779 disk_space_label.set_text (buf);
783 ARDOUR_UI::update_wall_clock ()
790 tm_now = localtime (&now);
792 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
793 wall_clock_label.set_text (buf);
799 ARDOUR_UI::session_menu (GdkEventButton *ev)
801 session_popup_menu->popup (0, 0);
806 ARDOUR_UI::redisplay_recent_sessions ()
808 vector<string *> *sessions;
809 vector<string *>::iterator i;
810 RecentSessionsSorter cmp;
812 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
813 recent_session_model->clear ();
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);
825 sessions = new vector<string*>;
827 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
828 sessions->push_back (new string ((*i).second));
831 for (i = sessions->begin(); i != sessions->end(); ++i) {
833 vector<string*>* states;
834 vector<const gchar*> item;
835 string fullpath = *(*i);
837 /* remove any trailing / */
839 if (fullpath[fullpath.length()-1] == '/') {
840 fullpath = fullpath.substr (0, fullpath.length()-1);
843 /* now get available states for this session */
845 if ((states = Session::possible_states (fullpath)) == 0) {
850 TreeModel::Row row = *(recent_session_model->append());
852 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
853 row[recent_session_columns.fullpath] = fullpath;
855 if (states->size() > 1) {
857 /* add the children */
859 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
861 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;
873 recent_session_display.set_model (recent_session_model);
878 ARDOUR_UI::build_session_selector ()
880 session_selector_window = new ArdourDialog ("session selector");
882 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
884 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
885 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
886 session_selector_window->set_default_response (RESPONSE_ACCEPT);
887 recent_session_model = TreeStore::create (recent_session_columns);
888 recent_session_display.set_model (recent_session_model);
889 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
890 recent_session_display.set_headers_visible (false);
891 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
893 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
895 scroller->add (recent_session_display);
896 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
898 session_selector_window->set_name ("SessionSelectorWindow");
899 session_selector_window->set_size_request (200, 400);
900 session_selector_window->get_vbox()->pack_start (*scroller);
902 recent_session_display.show();
904 //session_selector_window->get_vbox()->show();
908 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
910 session_selector_window->response (RESPONSE_ACCEPT);
914 ARDOUR_UI::open_recent_session ()
916 /* popup selector window */
918 if (session_selector_window == 0) {
919 build_session_selector ();
922 redisplay_recent_sessions ();
924 ResponseType r = (ResponseType) session_selector_window->run ();
926 session_selector_window->hide();
929 case RESPONSE_ACCEPT:
935 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
937 if (i == recent_session_model->children().end()) {
941 Glib::ustring path = (*i)[recent_session_columns.fullpath];
942 Glib::ustring state = (*i)[recent_session_columns.visible_name];
944 _session_is_new = false;
946 load_session (path, state);
950 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
954 if (stat (info.filename.c_str(), &statbuf) != 0) {
958 if (!S_ISDIR(statbuf.st_mode)) {
964 string session_file = info.filename;
966 session_file += Glib::path_get_basename (info.filename);
967 session_file += ".ardour";
969 if (stat (session_file.c_str(), &statbuf) != 0) {
973 return S_ISREG (statbuf.st_mode);
977 ARDOUR_UI::check_audioengine ()
980 if (!engine->connected()) {
981 MessageDialog msg (_("Ardour is not connected to JACK\n"
982 "You cannot open or close sessions in this condition"));
993 ARDOUR_UI::open_session ()
995 if (!check_audioengine()) {
1000 /* popup selector window */
1002 if (open_session_selector == 0) {
1004 /* ardour sessions are folders */
1006 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1007 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1008 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1010 FileFilter session_filter;
1011 session_filter.add_pattern ("*.ardour");
1012 session_filter.set_name (_("Ardour sessions"));
1013 open_session_selector->add_filter (session_filter);
1014 open_session_selector->set_filter (session_filter);
1017 int response = open_session_selector->run();
1018 open_session_selector->hide ();
1021 case RESPONSE_ACCEPT:
1024 open_session_selector->hide();
1028 open_session_selector->hide();
1029 string session_path = open_session_selector->get_filename();
1033 if (session_path.length() > 0) {
1034 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1035 _session_is_new = isnew;
1036 load_session (path, name);
1043 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1045 list<boost::shared_ptr<MidiTrack> > tracks;
1048 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1055 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1057 if (tracks.size() != how_many) {
1058 if (how_many == 1) {
1059 error << _("could not create a new midi track") << endmsg;
1061 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1065 if ((route = session->new_midi_route ()) == 0) {
1066 error << _("could not create new midi bus") << endmsg;
1072 MessageDialog msg (*editor,
1073 _("There are insufficient JACK ports available\n\
1074 to create a new track or bus.\n\
1075 You should save Ardour, exit and\n\
1076 restart JACK with more ports."));
1083 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1085 list<boost::shared_ptr<AudioTrack> > tracks;
1086 Session::RouteList routes;
1089 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1095 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1097 if (tracks.size() != how_many) {
1098 if (how_many == 1) {
1099 error << _("could not create a new audio track") << endmsg;
1101 error << string_compose (_("could only create %1 of %2 new audio %3"),
1102 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1108 routes = session->new_audio_route (input_channels, output_channels, how_many);
1110 if (routes.size() != how_many) {
1111 if (how_many == 1) {
1112 error << _("could not create a new audio track") << endmsg;
1114 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1120 if (need_control_room_outs) {
1126 route->set_stereo_control_outs (control_lr_channels);
1127 route->control_outs()->set_stereo_pan (pans, this);
1129 #endif /* CONTROLOUTS */
1133 cerr << "About to complain about JACK\n";
1134 MessageDialog msg (*editor,
1135 _("There are insufficient JACK ports available\n\
1136 to create a new track or bus.\n\
1137 You should save Ardour, exit and\n\
1138 restart JACK with more ports."));
1144 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1146 nframes_t _preroll = 0;
1149 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1150 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1152 if (new_position > _preroll) {
1153 new_position -= _preroll;
1158 session->request_locate (new_position);
1163 ARDOUR_UI::transport_goto_start ()
1166 session->goto_start();
1169 /* force displayed area in editor to start no matter
1170 what "follow playhead" setting is.
1174 editor->reset_x_origin (session->current_start_frame());
1180 ARDOUR_UI::transport_goto_zero ()
1183 session->request_locate (0);
1186 /* force displayed area in editor to start no matter
1187 what "follow playhead" setting is.
1191 editor->reset_x_origin (0);
1197 ARDOUR_UI::transport_goto_end ()
1200 nframes_t frame = session->current_end_frame();
1201 session->request_locate (frame);
1203 /* force displayed area in editor to start no matter
1204 what "follow playhead" setting is.
1208 editor->reset_x_origin (frame);
1214 ARDOUR_UI::transport_stop ()
1220 if (session->is_auditioning()) {
1221 session->cancel_audition ();
1225 if (session->get_play_loop ()) {
1226 session->request_play_loop (false);
1229 session->request_stop ();
1233 ARDOUR_UI::transport_stop_and_forget_capture ()
1236 session->request_stop (true);
1241 ARDOUR_UI::remove_last_capture()
1244 editor->remove_last_capture();
1249 ARDOUR_UI::transport_record ()
1252 switch (session->record_status()) {
1253 case Session::Disabled:
1254 if (session->ntracks() == 0) {
1255 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1259 session->maybe_enable_record ();
1261 case Session::Recording:
1262 case Session::Enabled:
1263 session->disable_record (false, true);
1269 ARDOUR_UI::transport_roll ()
1277 rolling = session->transport_rolling ();
1279 if (session->get_play_loop()) {
1280 session->request_play_loop (false);
1281 auto_loop_button.set_visual_state (1);
1282 roll_button.set_visual_state (1);
1283 } else if (session->get_play_range ()) {
1284 session->request_play_range (false);
1285 play_selection_button.set_visual_state (0);
1286 } else if (rolling) {
1287 session->request_locate (session->last_transport_start(), true);
1290 session->request_transport_speed (1.0f);
1294 ARDOUR_UI::transport_loop()
1297 if (session->get_play_loop()) {
1298 if (session->transport_rolling()) {
1299 Location * looploc = session->locations()->auto_loop_location();
1301 session->request_locate (looploc->start(), true);
1306 session->request_play_loop (true);
1312 ARDOUR_UI::transport_play_selection ()
1318 if (!session->get_play_range()) {
1319 session->request_stop ();
1322 editor->play_selection ();
1326 ARDOUR_UI::transport_rewind (int option)
1328 float current_transport_speed;
1331 current_transport_speed = session->transport_speed();
1333 if (current_transport_speed >= 0.0f) {
1336 session->request_transport_speed (-1.0f);
1339 session->request_transport_speed (-4.0f);
1342 session->request_transport_speed (-0.5f);
1347 session->request_transport_speed (current_transport_speed * 1.5f);
1353 ARDOUR_UI::transport_forward (int option)
1355 float current_transport_speed;
1358 current_transport_speed = session->transport_speed();
1360 if (current_transport_speed <= 0.0f) {
1363 session->request_transport_speed (1.0f);
1366 session->request_transport_speed (4.0f);
1369 session->request_transport_speed (0.5f);
1374 session->request_transport_speed (current_transport_speed * 1.5f);
1380 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1386 boost::shared_ptr<Route> r;
1388 if ((r = session->route_by_remote_id (dstream)) != 0) {
1392 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1393 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1402 ARDOUR_UI::queue_transport_change ()
1404 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1408 ARDOUR_UI::map_transport_state ()
1410 float sp = session->transport_speed();
1413 transport_rolling ();
1414 } else if (sp < 0.0f) {
1415 transport_rewinding ();
1416 } else if (sp > 0.0f) {
1417 transport_forwarding ();
1419 transport_stopped ();
1424 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1426 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1427 (int) adj.get_value()].c_str());
1431 ARDOUR_UI::engine_stopped ()
1433 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1434 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1435 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1439 ARDOUR_UI::engine_running ()
1441 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1442 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1443 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1445 Glib::RefPtr<Action> action;
1446 char* action_name = 0;
1448 switch (engine->frames_per_cycle()) {
1450 action_name = X_("JACKLatency32");
1453 action_name = X_("JACKLatency64");
1456 action_name = X_("JACKLatency128");
1459 action_name = X_("JACKLatency512");
1462 action_name = X_("JACKLatency1024");
1465 action_name = X_("JACKLatency2048");
1468 action_name = X_("JACKLatency4096");
1471 action_name = X_("JACKLatency8192");
1474 /* XXX can we do anything useful ? */
1480 action = ActionManager::get_action (X_("JACK"), action_name);
1483 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1484 ract->set_active ();
1490 ARDOUR_UI::engine_halted ()
1492 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1494 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1495 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1497 update_sample_rate (0);
1499 MessageDialog msg (*editor,
1501 JACK has either been shutdown or it\n\
1502 disconnected Ardour because Ardour\n\
1503 was not fast enough. You can save the\n\
1504 session and/or try to reconnect to JACK ."));
1509 ARDOUR_UI::do_engine_start ()
1517 error << _("Unable to start the session running")
1527 ARDOUR_UI::setup_theme ()
1529 theme_manager->setup_theme();
1533 ARDOUR_UI::start_engine ()
1535 if (do_engine_start () == 0) {
1536 if (session && _session_is_new) {
1537 /* we need to retain initial visual
1538 settings for a new session
1540 session->save_state ("");
1548 ARDOUR_UI::update_clocks ()
1550 if (!editor || !editor->dragging_playhead()) {
1551 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1556 ARDOUR_UI::start_clocking ()
1558 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1562 ARDOUR_UI::stop_clocking ()
1564 clock_signal_connection.disconnect ();
1568 ARDOUR_UI::toggle_clocking ()
1571 if (clock_button.get_active()) {
1580 ARDOUR_UI::_blink (void *arg)
1583 ((ARDOUR_UI *) arg)->blink ();
1590 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1594 ARDOUR_UI::start_blinking ()
1596 /* Start the blink signal. Everybody with a blinking widget
1597 uses Blink to drive the widget's state.
1600 if (blink_timeout_tag < 0) {
1602 blink_timeout_tag = g_timeout_add (240, _blink, this);
1607 ARDOUR_UI::stop_blinking ()
1609 if (blink_timeout_tag >= 0) {
1610 g_source_remove (blink_timeout_tag);
1611 blink_timeout_tag = -1;
1616 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1622 if (io.n_inputs().n_total() == 0) {
1627 /* XXX we're not handling multiple ports yet. */
1629 const char **connections = io.input(0)->get_connections();
1631 if (connections == 0 || connections[0] == '\0') {
1634 buf = connections[0];
1641 if (io.n_outputs().n_total() == 0) {
1646 /* XXX we're not handling multiple ports yet. */
1648 const char **connections = io.output(0)->get_connections();
1650 if (connections == 0 || connections[0] == '\0') {
1653 buf = connections[0];
1660 /** Ask the user for the name of a new shapshot and then take it.
1663 ARDOUR_UI::snapshot_session ()
1665 ArdourPrompter prompter (true);
1669 struct tm local_time;
1672 localtime_r (&n, &local_time);
1673 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1675 prompter.set_name ("Prompter");
1676 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1677 prompter.set_prompt (_("Name of New Snapshot"));
1678 prompter.set_initial_text (timebuf);
1680 switch (prompter.run()) {
1681 case RESPONSE_ACCEPT:
1682 prompter.get_result (snapname);
1683 if (snapname.length()){
1684 save_state (snapname);
1694 ARDOUR_UI::save_state (const string & name)
1696 (void) save_state_canfail (name);
1700 ARDOUR_UI::save_state_canfail (string name)
1705 if (name.length() == 0) {
1706 name = session->snap_name();
1709 if ((ret = session->save_state (name)) != 0) {
1713 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1718 ARDOUR_UI::restore_state (string name)
1721 if (name.length() == 0) {
1722 name = session->name();
1724 session->restore_state (name);
1729 ARDOUR_UI::primary_clock_value_changed ()
1732 session->request_locate (primary_clock.current_time ());
1737 ARDOUR_UI::secondary_clock_value_changed ()
1740 session->request_locate (secondary_clock.current_time ());
1745 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1747 if (session && dstream && dstream->record_enabled()) {
1749 Session::RecordState rs;
1751 rs = session->record_status ();
1754 case Session::Disabled:
1755 case Session::Enabled:
1756 if (w->get_state() != STATE_SELECTED) {
1757 w->set_state (STATE_SELECTED);
1761 case Session::Recording:
1762 if (w->get_state() != STATE_ACTIVE) {
1763 w->set_state (STATE_ACTIVE);
1769 if (w->get_state() != STATE_NORMAL) {
1770 w->set_state (STATE_NORMAL);
1776 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1782 switch (session->record_status()) {
1783 case Session::Enabled:
1785 rec_button.set_visual_state (2);
1787 rec_button.set_visual_state (0);
1791 case Session::Recording:
1792 rec_button.set_visual_state (1);
1796 rec_button.set_visual_state (0);
1802 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1810 ARDOUR_UI::save_template ()
1813 ArdourPrompter prompter (true);
1816 prompter.set_name (X_("Prompter"));
1817 prompter.set_prompt (_("Name for mix template:"));
1818 prompter.set_initial_text(session->name() + _("-template"));
1819 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1821 switch (prompter.run()) {
1822 case RESPONSE_ACCEPT:
1823 prompter.get_result (name);
1825 if (name.length()) {
1826 session->save_template (name);
1836 ARDOUR_UI::new_session (std::string predetermined_path)
1838 string session_name;
1839 string session_path;
1841 if (!check_audioengine()) {
1845 int response = Gtk::RESPONSE_NONE;
1847 new_session_dialog->set_modal(true);
1848 new_session_dialog->set_name (predetermined_path);
1849 new_session_dialog->reset_recent();
1850 new_session_dialog->show();
1851 new_session_dialog->set_current_page (0);
1854 response = new_session_dialog->run ();
1856 if (!check_audioengine()) {
1857 new_session_dialog->hide ();
1861 _session_is_new = false;
1863 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1868 new_session_dialog->hide ();
1871 } else if (response == Gtk::RESPONSE_NONE) {
1873 /* Clear was pressed */
1874 new_session_dialog->reset();
1876 } else if (response == Gtk::RESPONSE_YES) {
1878 /* YES == OPEN, but there's no enum for that */
1880 session_name = new_session_dialog->session_name();
1882 if (session_name.empty()) {
1883 response = Gtk::RESPONSE_NONE;
1887 if (session_name[0] == '/' ||
1888 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1889 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1890 load_session (Glib::path_get_dirname (session_name), session_name);
1892 session_path = new_session_dialog->session_folder();
1893 load_session (session_path, session_name);
1896 } else if (response == Gtk::RESPONSE_OK) {
1898 session_name = new_session_dialog->session_name();
1900 if (!new_session_dialog->on_new_session_page ()) {
1902 /* XXX this is a bit of a hack..
1903 i really want the new sesion dialog to return RESPONSE_YES
1904 if we're on page 1 (the load page)
1905 Unfortunately i can't see how atm..
1908 if (session_name.empty()) {
1909 response = Gtk::RESPONSE_NONE;
1913 if (session_name[0] == '/' ||
1914 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1915 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1916 load_session (Glib::path_get_dirname (session_name), session_name);
1918 session_path = new_session_dialog->session_folder();
1919 load_session (session_path, session_name);
1924 if (session_name.empty()) {
1925 response = Gtk::RESPONSE_NONE;
1929 if (session_name[0] == '/' ||
1930 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1931 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1933 session_path = Glib::path_get_dirname (session_name);
1934 session_name = Glib::path_get_basename (session_name);
1938 session_path = new_session_dialog->session_folder();
1942 //XXX This is needed because session constructor wants a
1943 //non-existant path. hopefully this will be fixed at some point.
1945 session_path = Glib::build_filename (session_path, session_name);
1947 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1949 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1951 MessageDialog msg (str,
1953 Gtk::MESSAGE_WARNING,
1954 Gtk::BUTTONS_YES_NO,
1958 msg.set_name (X_("CleanupDialog"));
1959 msg.set_wmclass (X_("existing_session"), "Ardour");
1960 msg.set_position (Gtk::WIN_POS_MOUSE);
1962 switch (msg.run()) {
1964 load_session (session_path, session_name);
1968 response = RESPONSE_NONE;
1969 new_session_dialog->reset ();
1974 _session_is_new = true;
1976 std::string template_name = new_session_dialog->session_template_name();
1978 if (new_session_dialog->use_session_template()) {
1980 load_session (session_path, session_name, &template_name);
1986 AutoConnectOption iconnect;
1987 AutoConnectOption oconnect;
1989 if (new_session_dialog->create_control_bus()) {
1990 cchns = (uint32_t) new_session_dialog->control_channel_count();
1995 if (new_session_dialog->create_master_bus()) {
1996 mchns = (uint32_t) new_session_dialog->master_channel_count();
2001 if (new_session_dialog->connect_inputs()) {
2002 iconnect = AutoConnectPhysical;
2004 iconnect = AutoConnectOption (0);
2007 /// @todo some minor tweaks.
2009 if (new_session_dialog->connect_outs_to_master()) {
2010 oconnect = AutoConnectMaster;
2011 } else if (new_session_dialog->connect_outs_to_physical()) {
2012 oconnect = AutoConnectPhysical;
2014 oconnect = AutoConnectOption (0);
2017 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2018 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2020 if (!build_session (session_path,
2028 engine->frame_rate() * 60 * 5)) {
2030 response = Gtk::RESPONSE_NONE;
2031 new_session_dialog->reset ();
2038 } while (response == Gtk::RESPONSE_NONE);
2042 new_session_dialog->get_window()->set_cursor();
2043 new_session_dialog->hide();
2048 ARDOUR_UI::close_session()
2050 if (!check_audioengine()) {
2059 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2061 Session *new_session;
2062 session_loaded = false;
2064 if (!check_audioengine()) {
2068 if(!unload_session ()) return -1;
2070 /* if it already exists, we must have write access */
2072 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2073 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2074 "This prevents the session from being loaded."));
2080 new_session = new Session (*engine, path, snap_name, mix_template);
2085 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2089 connect_to_session (new_session);
2091 Config->set_current_owner (ConfigVariableBase::Interface);
2093 session_loaded = true;
2095 goto_editor_window ();
2098 session->set_clean ();
2101 editor->edit_cursor_position (true);
2106 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2107 uint32_t control_channels,
2108 uint32_t master_channels,
2109 AutoConnectOption input_connect,
2110 AutoConnectOption output_connect,
2113 nframes_t initial_length)
2115 Session *new_session;
2117 if (!check_audioengine()) {
2121 session_loaded = false;
2123 if (!unload_session ()) return false;
2125 _session_is_new = true;
2128 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2129 control_channels, master_channels, nphysin, nphysout, initial_length);
2134 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2139 connect_to_session (new_session);
2141 session_loaded = true;
2149 editor->show_window ();
2160 ARDOUR_UI::show_splash ()
2163 about = new About();
2164 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2171 ARDOUR_UI::about_signal_response(int response)
2177 ARDOUR_UI::hide_splash ()
2180 about->get_window()->set_cursor ();
2186 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2190 removed = rep.paths.size();
2193 MessageDialog msgd (*editor,
2194 _("No audio files were ready for cleanup"),
2197 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2198 msgd.set_secondary_text (_("If this seems suprising, \n\
2199 check for any existing snapshots.\n\
2200 These may still include regions that\n\
2201 require some unused files to continue to exist."));
2207 ArdourDialog results (_("ardour: cleanup"), true, false);
2209 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2210 CleanupResultsModelColumns() {
2214 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2215 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2219 CleanupResultsModelColumns results_columns;
2220 Glib::RefPtr<Gtk::ListStore> results_model;
2221 Gtk::TreeView results_display;
2223 results_model = ListStore::create (results_columns);
2224 results_display.set_model (results_model);
2225 results_display.append_column (list_title, results_columns.visible_name);
2227 results_display.set_name ("CleanupResultsList");
2228 results_display.set_headers_visible (true);
2229 results_display.set_headers_clickable (false);
2230 results_display.set_reorderable (false);
2232 Gtk::ScrolledWindow list_scroller;
2235 Gtk::HBox dhbox; // the hbox for the image and text
2236 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2237 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2239 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2241 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2243 if (rep.space < 1048576.0f) {
2245 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2247 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2251 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2253 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2257 dhbox.pack_start (*dimage, true, false, 5);
2258 dhbox.pack_start (txt, true, false, 5);
2260 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2261 TreeModel::Row row = *(results_model->append());
2262 row[results_columns.visible_name] = *i;
2263 row[results_columns.fullpath] = *i;
2266 list_scroller.add (results_display);
2267 list_scroller.set_size_request (-1, 150);
2268 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2270 dvbox.pack_start (dhbox, true, false, 5);
2271 dvbox.pack_start (list_scroller, true, false, 5);
2272 ddhbox.pack_start (dvbox, true, false, 5);
2274 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2275 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2276 results.set_default_response (RESPONSE_CLOSE);
2277 results.set_position (Gtk::WIN_POS_MOUSE);
2279 results_display.show();
2280 list_scroller.show();
2287 //results.get_vbox()->show();
2288 results.set_resizable (false);
2295 ARDOUR_UI::cleanup ()
2298 /* shouldn't happen: menu item is insensitive */
2303 MessageDialog checker (_("Are you sure you want to cleanup?"),
2305 Gtk::MESSAGE_QUESTION,
2306 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2308 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2309 ALL undo/redo information will be lost if you cleanup.\n\
2310 After cleanup, unused audio files will be moved to a \
2311 \"dead sounds\" location."));
2313 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2314 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2315 checker.set_default_response (RESPONSE_CANCEL);
2317 checker.set_name (_("CleanupDialog"));
2318 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2319 checker.set_position (Gtk::WIN_POS_MOUSE);
2321 switch (checker.run()) {
2322 case RESPONSE_ACCEPT:
2328 Session::cleanup_report rep;
2330 editor->prepare_for_cleanup ();
2332 /* do not allow flush until a session is reloaded */
2334 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2336 act->set_sensitive (false);
2339 if (session->cleanup_sources (rep)) {
2344 display_cleanup_results (rep,
2347 The following %1 %2 not in use and \n\
2348 have been moved to:\n\
2350 Flushing the wastebasket will \n\
2351 release an additional\n\
2352 %4 %5bytes of disk space.\n"
2360 ARDOUR_UI::flush_trash ()
2363 /* shouldn't happen: menu item is insensitive */
2367 Session::cleanup_report rep;
2369 if (session->cleanup_trash_sources (rep)) {
2373 display_cleanup_results (rep,
2375 _("The following %1 %2 deleted from\n\
2377 releasing %4 %5bytes of disk space"));
2381 ARDOUR_UI::add_route (Gtk::Window* float_window)
2389 if (add_route_dialog == 0) {
2390 add_route_dialog = new AddRouteDialog;
2392 add_route_dialog->set_transient_for (*float_window);
2396 if (add_route_dialog->is_visible()) {
2397 /* we're already doing this */
2401 ResponseType r = (ResponseType) add_route_dialog->run ();
2403 add_route_dialog->hide();
2406 case RESPONSE_ACCEPT:
2413 if ((count = add_route_dialog->count()) <= 0) {
2417 uint32_t input_chan = add_route_dialog->channels ();
2418 uint32_t output_chan;
2419 string name_template = add_route_dialog->name_template ();
2420 bool track = add_route_dialog->track ();
2422 AutoConnectOption oac = Config->get_output_auto_connect();
2424 if (oac & AutoConnectMaster) {
2425 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2427 output_chan = input_chan;
2430 /* XXX do something with name template */
2432 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2434 session_add_midi_track(count);
2436 MessageDialog msg (*editor,
2437 _("Sorry, MIDI Busses are not supported at this time."));
2439 //session_add_midi_bus();
2443 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2445 session_add_audio_bus (input_chan, output_chan, count);
2451 ARDOUR_UI::mixer_settings () const
2456 node = session->instant_xml(X_("Mixer"));
2458 node = Config->instant_xml(X_("Mixer"));
2462 node = new XMLNode (X_("Mixer"));
2469 ARDOUR_UI::editor_settings () const
2474 node = session->instant_xml(X_("Editor"));
2476 node = Config->instant_xml(X_("Editor"));
2480 node = new XMLNode (X_("Editor"));
2486 ARDOUR_UI::keyboard_settings () const
2490 node = Config->extra_xml(X_("Keyboard"));
2493 node = new XMLNode (X_("Keyboard"));
2499 ARDOUR_UI::halt_on_xrun_message ()
2501 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2503 MessageDialog msg (*editor,
2504 _("Recording was stopped because your system could not keep up."));
2509 ARDOUR_UI::disk_overrun_handler ()
2511 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2513 if (!have_disk_speed_dialog_displayed) {
2514 have_disk_speed_dialog_displayed = true;
2515 MessageDialog* msg = new MessageDialog (*editor, _("\
2516 The disk system on your computer\n\
2517 was not able to keep up with Ardour.\n\
2519 Specifically, it failed to write data to disk\n\
2520 quickly enough to keep up with recording.\n"));
2521 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2527 ARDOUR_UI::disk_underrun_handler ()
2529 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2531 if (!have_disk_speed_dialog_displayed) {
2532 have_disk_speed_dialog_displayed = true;
2533 MessageDialog* msg = new MessageDialog (*editor,
2534 _("The disk system on your computer\n\
2535 was not able to keep up with Ardour.\n\
2537 Specifically, it failed to read data from disk\n\
2538 quickly enough to keep up with playback.\n"));
2539 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2545 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2547 have_disk_speed_dialog_displayed = false;
2552 ARDOUR_UI::pending_state_dialog ()
2554 ArdourDialog dialog ("pending state dialog");
2556 This session appears to have been in\n\
2557 middle of recording when ardour or\n\
2558 the computer was shutdown.\n\
2560 Ardour can recover any captured audio for\n\
2561 you, or it can ignore it. Please decide\n\
2562 what you would like to do.\n"));
2564 dialog.get_vbox()->pack_start (message);
2565 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2566 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2568 dialog.set_position (WIN_POS_CENTER);
2570 //dialog.get_vbox()->show();
2572 switch (dialog.run ()) {
2573 case RESPONSE_ACCEPT:
2581 ARDOUR_UI::disconnect_from_jack ()
2584 if( engine->disconnect_from_jack ()) {
2585 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2589 update_sample_rate (0);
2594 ARDOUR_UI::reconnect_to_jack ()
2597 if (engine->reconnect_to_jack ()) {
2598 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2602 update_sample_rate (0);
2607 ARDOUR_UI::cmdline_new_session (string path)
2609 if (path[0] != '/') {
2610 char buf[PATH_MAX+1];
2613 getcwd (buf, sizeof (buf));
2622 return FALSE; /* don't call it again */
2626 ARDOUR_UI::use_config ()
2628 Glib::RefPtr<Action> act;
2630 switch (Config->get_native_file_data_format ()) {
2632 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2635 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2638 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2643 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2644 ract->set_active ();
2647 switch (Config->get_native_file_header_format ()) {
2649 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2652 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2655 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2658 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2661 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2664 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2667 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2672 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2673 ract->set_active ();
2676 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2678 set_transport_controllable_state (*node);
2683 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2685 if (Config->get_primary_clock_delta_edit_cursor()) {
2686 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
2688 primary_clock.set (pos, 0, true);
2691 if (Config->get_secondary_clock_delta_edit_cursor()) {
2692 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
2694 secondary_clock.set (pos);
2697 if (big_clock_window) {
2698 big_clock.set (pos);
2703 ARDOUR_UI::record_state_changed ()
2705 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2707 if (!session || !big_clock_window) {
2708 /* why bother - the clock isn't visible */
2712 switch (session->record_status()) {
2713 case Session::Recording:
2714 big_clock.set_widget_name ("BigClockRecording");
2717 big_clock.set_widget_name ("BigClockNonRecording");
2723 ARDOUR_UI::set_keybindings_path (string path)
2725 keybindings_path = path;
2729 ARDOUR_UI::save_keybindings ()
2731 if (can_save_keybindings) {
2732 AccelMap::save (user_keybindings_path);
2737 ARDOUR_UI::first_idle ()
2740 session->allow_auto_play (true);
2742 can_save_keybindings = true;
2747 ARDOUR_UI::store_clock_modes ()
2749 XMLNode* node = new XMLNode(X_("ClockModes"));
2751 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2752 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2755 session->add_extra_xml (*node);
2756 session->set_dirty ();
2761 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2762 : Controllable (name), ui (u), type(tp)
2768 ARDOUR_UI::TransportControllable::set_value (float val)
2770 if (type == ShuttleControl) {
2777 fract = -((0.5f - val)/0.5f);
2779 fract = ((val - 0.5f)/0.5f);
2783 ui.set_shuttle_fract (fract);
2788 /* do nothing: these are radio-style actions */
2796 action = X_("Roll");
2799 action = X_("Stop");
2802 action = X_("Goto Start");
2805 action = X_("Goto End");
2808 action = X_("Loop");
2811 action = X_("Play Selection");
2814 action = X_("Record");
2824 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2832 ARDOUR_UI::TransportControllable::get_value (void) const
2851 case ShuttleControl:
2861 ARDOUR_UI::TransportControllable::set_id (const string& str)
2867 ARDOUR_UI::setup_profile ()
2869 if (gdk_screen_width() < 1200) {
2870 Profile->set_small_screen ();
2875 ARDOUR_UI::disable_all_plugins ()
2881 // session->begin_reversible_command (_("Disable all plugins"));
2883 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2885 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2886 // XMLNode& before = (*i)->get_redirect_state ();
2887 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
2888 (*i)->disable_plugins ();
2889 // XMLNode& after = (*i)->get_redirect_state ();
2890 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
2894 // session->commit_reversible_command ();
2898 ARDOUR_UI::ab_all_plugins ()
2904 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2906 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2907 (*i)->ab_plugins (ab_direction);
2910 ab_direction = !ab_direction;