2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/compose.h>
37 #include <pbd/pathscanner.h>
38 #include <pbd/failed_constructor.h>
39 #include <pbd/enumwriter.h>
40 #include <pbd/stacktrace.h>
41 #include <gtkmm2ext/gtk_ui.h>
42 #include <gtkmm2ext/utils.h>
43 #include <gtkmm2ext/click_box.h>
44 #include <gtkmm2ext/fastmeter.h>
45 #include <gtkmm2ext/stop_signal.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/window_title.h>
49 #include <midi++/port.h>
50 #include <midi++/mmc.h>
52 #include <ardour/ardour.h>
53 #include <ardour/profile.h>
54 #include <ardour/session_route.h>
55 #include <ardour/port.h>
56 #include <ardour/audioengine.h>
57 #include <ardour/playlist.h>
58 #include <ardour/utils.h>
59 #include <ardour/audio_diskstream.h>
60 #include <ardour/audiofilesource.h>
61 #include <ardour/recent_sessions.h>
62 #include <ardour/port.h>
63 #include <ardour/audio_track.h>
66 #include "ardour_ui.h"
67 #include "public_editor.h"
68 #include "audio_clock.h"
73 #include "add_route_dialog.h"
74 #include "new_session_dialog.h"
77 #include "gui_thread.h"
78 #include "color_manager.h"
82 using namespace ARDOUR;
84 using namespace Gtkmm2ext;
88 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
90 sigc::signal<void,bool> ARDOUR_UI::Blink;
91 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
92 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
93 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
95 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
97 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp, rcfile),
99 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
100 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
101 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
102 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
106 adjuster_table (3, 3),
110 preroll_button (_("pre\nroll")),
111 postroll_button (_("post\nroll")),
115 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
119 roll_controllable ("transport roll", *this, TransportControllable::Roll),
120 stop_controllable ("transport stop", *this, TransportControllable::Stop),
121 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
122 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
123 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
124 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
125 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
126 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
127 shuttle_controller_binding_proxy (shuttle_controllable),
129 roll_button (roll_controllable),
130 stop_button (stop_controllable),
131 goto_start_button (goto_start_controllable),
132 goto_end_button (goto_end_controllable),
133 auto_loop_button (auto_loop_controllable),
134 play_selection_button (play_selection_controllable),
135 rec_button (rec_controllable),
137 shuttle_units_button (_("% ")),
139 punch_in_button (_("Punch In")),
140 punch_out_button (_("Punch Out")),
141 auto_return_button (_("Auto Return")),
142 auto_play_button (_("Auto Play")),
143 auto_input_button (_("Auto Input")),
144 click_button (_("Click")),
145 time_master_button (_("time\nmaster")),
147 auditioning_alert_button (_("AUDITION")),
148 solo_alert_button (_("SOLO")),
151 using namespace Gtk::Menu_Helpers;
157 if (theArdourUI == 0) {
163 color_manager = new ColorManager();
165 std::string color_file = ARDOUR::find_config_file("ardour.colors");
167 color_manager->load (color_file);
172 _session_is_new = false;
173 big_clock_window = 0;
174 session_selector_window = 0;
175 last_key_press_time = 0;
176 connection_editor = 0;
177 add_route_dialog = 0;
181 open_session_selector = 0;
182 have_configure_timeout = false;
183 have_disk_speed_dialog_displayed = false;
184 _will_create_new_session_automatically = false;
185 session_loaded = false;
186 last_speed_displayed = -1.0f;
187 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
189 can_save_keybindings = false;
191 last_configure_time.tv_sec = 0;
192 last_configure_time.tv_usec = 0;
194 shuttle_grabbed = false;
196 shuttle_max_speed = 8.0f;
198 shuttle_style_menu = 0;
199 shuttle_unit_menu = 0;
201 gettimeofday (&last_peak_grab, 0);
202 gettimeofday (&last_shuttle_request, 0);
204 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
205 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
207 /* handle pending state with a dialog */
209 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
211 /* have to wait for AudioEngine and Configuration before proceeding */
215 ARDOUR_UI::set_engine (AudioEngine& e)
219 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
220 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
221 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
222 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
224 ActionManager::init ();
225 new_session_dialog = new NewSessionDialog();
229 keyboard = new Keyboard;
231 if (setup_windows ()) {
232 throw failed_constructor ();
235 if (GTK_ARDOUR::show_key_actions) {
236 vector<string> names;
237 vector<string> paths;
239 vector<AccelKey> bindings;
241 ActionManager::get_all_actions (names, paths, keys, bindings);
243 vector<string>::iterator n;
244 vector<string>::iterator k;
245 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
246 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
252 /* start with timecode, metering enabled
255 blink_timeout_tag = -1;
257 /* the global configuration object is now valid */
261 /* this being a GUI and all, we want peakfiles */
263 AudioFileSource::set_build_peakfiles (true);
264 AudioFileSource::set_build_missing_peakfiles (true);
266 /* set default clock modes */
268 primary_clock.set_mode (AudioClock::SMPTE);
269 secondary_clock.set_mode (AudioClock::BBT);
271 /* start the time-of-day-clock */
273 update_wall_clock ();
274 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
276 update_disk_space ();
278 update_sample_rate (engine->frame_rate());
280 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
281 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
284 ARDOUR_UI::~ARDOUR_UI ()
286 save_ardour_state ();
300 if (add_route_dialog) {
301 delete add_route_dialog;
306 ARDOUR_UI::configure_timeout ()
311 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
312 /* no configure events yet */
316 gettimeofday (&now, 0);
317 timersub (&now, &last_configure_time, &diff);
319 /* force a gap of 0.5 seconds since the last configure event
322 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
325 have_configure_timeout = false;
326 save_ardour_state ();
332 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
334 if (have_configure_timeout) {
335 gettimeofday (&last_configure_time, 0);
337 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
338 have_configure_timeout = true;
345 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
347 const XMLProperty* prop;
349 if ((prop = node.property ("roll")) != 0) {
350 roll_controllable.set_id (prop->value());
352 if ((prop = node.property ("stop")) != 0) {
353 stop_controllable.set_id (prop->value());
355 if ((prop = node.property ("goto_start")) != 0) {
356 goto_start_controllable.set_id (prop->value());
358 if ((prop = node.property ("goto_end")) != 0) {
359 goto_end_controllable.set_id (prop->value());
361 if ((prop = node.property ("auto_loop")) != 0) {
362 auto_loop_controllable.set_id (prop->value());
364 if ((prop = node.property ("play_selection")) != 0) {
365 play_selection_controllable.set_id (prop->value());
367 if ((prop = node.property ("rec")) != 0) {
368 rec_controllable.set_id (prop->value());
370 if ((prop = node.property ("shuttle")) != 0) {
371 shuttle_controllable.set_id (prop->value());
376 ARDOUR_UI::get_transport_controllable_state ()
378 XMLNode* node = new XMLNode(X_("TransportControllables"));
381 roll_controllable.id().print (buf, sizeof (buf));
382 node->add_property (X_("roll"), buf);
383 stop_controllable.id().print (buf, sizeof (buf));
384 node->add_property (X_("stop"), buf);
385 goto_start_controllable.id().print (buf, sizeof (buf));
386 node->add_property (X_("goto_start"), buf);
387 goto_end_controllable.id().print (buf, sizeof (buf));
388 node->add_property (X_("goto_end"), buf);
389 auto_loop_controllable.id().print (buf, sizeof (buf));
390 node->add_property (X_("auto_loop"), buf);
391 play_selection_controllable.id().print (buf, sizeof (buf));
392 node->add_property (X_("play_selection"), buf);
393 rec_controllable.id().print (buf, sizeof (buf));
394 node->add_property (X_("rec"), buf);
395 shuttle_controllable.id().print (buf, sizeof (buf));
396 node->add_property (X_("shuttle"), buf);
402 ARDOUR_UI::save_ardour_state ()
404 if (!keyboard || !mixer || !editor) {
408 /* XXX this is all a bit dubious. add_extra_xml() uses
409 a different lifetime model from add_instant_xml().
412 XMLNode* node = new XMLNode (keyboard->get_state());
413 Config->add_extra_xml (*node);
414 Config->add_extra_xml (get_transport_controllable_state());
415 Config->save_state();
417 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
418 XMLNode mnode(mixer->get_state());
421 session->add_instant_xml (enode, session->path());
422 session->add_instant_xml (mnode, session->path());
424 Config->add_instant_xml (enode, get_user_ardour_path());
425 Config->add_instant_xml (mnode, get_user_ardour_path());
432 ARDOUR_UI::autosave_session ()
434 if (!Config->get_periodic_safety_backups())
438 session->maybe_write_autosave();
445 ARDOUR_UI::update_autosave ()
447 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
449 if (session->dirty()) {
450 if (_autosave_connection.connected()) {
451 _autosave_connection.disconnect();
454 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
455 Config->get_periodic_safety_backup_interval() * 1000);
458 if (_autosave_connection.connected()) {
459 _autosave_connection.disconnect();
465 ARDOUR_UI::startup ()
467 check_memory_locking();
471 ARDOUR_UI::no_memory_warning ()
473 XMLNode node (X_("no-memory-warning"));
474 Config->add_instant_xml (node, get_user_ardour_path());
478 ARDOUR_UI::check_memory_locking ()
481 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
485 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
487 if (engine->is_realtime() && memory_warning_node == 0) {
489 struct rlimit limits;
491 long pages, page_size;
493 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
496 ram = (int64_t) pages * (int64_t) page_size;
499 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
503 if (limits.rlim_cur != RLIM_INFINITY) {
505 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
508 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
509 "This might cause Ardour to run out of memory before your system "
510 "runs out of memory. \n\n"
511 "You can view the memory limit with 'ulimit -l', "
512 "and it is normally controlled by /etc/security/limits.conf"));
514 VBox* vbox = msg.get_vbox();
516 CheckButton cb (_("Do not show this window again"));
518 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
520 hbox.pack_start (cb, true, false);
521 vbox->pack_start (hbox);
524 editor->ensure_float (msg);
536 if (session && session->dirty()) {
537 switch (ask_about_saving_session(_("quit"))) {
542 /* use the default name */
543 if (save_state_canfail ("")) {
544 /* failed - don't quit */
545 MessageDialog msg (*editor,
547 Ardour was unable to save your session.\n\n\
548 If you still wish to quit, please use the\n\n\
549 \"Just quit\" option."));
560 session->set_deletion_in_progress ();
563 Config->save_state();
568 ARDOUR_UI::ask_about_saving_session (const string & what)
570 ArdourDialog window (_("ardour: save session?"));
571 Gtk::HBox dhbox; // the hbox for the image and text
572 Gtk::Label prompt_label;
573 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
577 msg = string_compose(_("Don't %1"), what);
578 window.add_button (msg, RESPONSE_REJECT);
579 msg = string_compose(_("Just %1"), what);
580 window.add_button (msg, RESPONSE_APPLY);
581 msg = string_compose(_("Save and %1"), what);
582 window.add_button (msg, RESPONSE_ACCEPT);
584 window.set_default_response (RESPONSE_ACCEPT);
586 Gtk::Button noquit_button (msg);
587 noquit_button.set_name ("EditorGTKButton");
592 if (session->snap_name() == session->name()) {
595 type = _("snapshot");
597 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?"),
598 type, session->snap_name());
600 prompt_label.set_text (prompt);
601 prompt_label.set_name (X_("PrompterLabel"));
602 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
604 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
606 dhbox.set_homogeneous (false);
607 dhbox.pack_start (*dimage, false, false, 5);
608 dhbox.pack_start (prompt_label, true, false, 5);
609 window.get_vbox()->pack_start (dhbox);
611 window.set_name (_("Prompter"));
612 window.set_position (Gtk::WIN_POS_MOUSE);
613 window.set_modal (true);
614 window.set_resizable (false);
617 save_the_session = 0;
619 window.set_keep_above (true);
622 ResponseType r = (ResponseType) window.run();
627 case RESPONSE_ACCEPT: // save and get out of here
629 case RESPONSE_APPLY: // get out of here
639 ARDOUR_UI::every_second ()
642 update_buffer_load ();
643 update_disk_space ();
648 ARDOUR_UI::every_point_one_seconds ()
650 update_speed_display ();
651 RapidScreenUpdate(); /* EMIT_SIGNAL */
656 ARDOUR_UI::every_point_zero_one_seconds ()
658 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
663 ARDOUR_UI::update_sample_rate (nframes_t ignored)
667 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
669 if (!engine->connected()) {
671 snprintf (buf, sizeof (buf), _("disconnected"));
675 nframes_t rate = engine->frame_rate();
677 if (fmod (rate, 1000.0) != 0.0) {
678 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
679 (float) rate/1000.0f,
680 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
682 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
684 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
688 sample_rate_label.set_text (buf);
692 ARDOUR_UI::update_cpu_load ()
695 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
696 cpu_load_label.set_text (buf);
700 ARDOUR_UI::update_buffer_load ()
705 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
706 session->playback_load(), session->capture_load());
707 buffer_load_label.set_text (buf);
709 buffer_load_label.set_text ("");
714 ARDOUR_UI::count_recenabled_streams (Route& route)
716 Track* track = dynamic_cast<Track*>(&route);
717 if (track && track->diskstream()->record_enabled()) {
718 rec_enabled_streams += track->n_inputs();
723 ARDOUR_UI::update_disk_space()
729 nframes_t frames = session->available_capture_duration();
732 if (frames == max_frames) {
733 strcpy (buf, _("Disk: 24hrs+"));
738 nframes_t fr = session->frame_rate();
740 rec_enabled_streams = 0;
741 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
743 if (rec_enabled_streams) {
744 frames /= rec_enabled_streams;
747 hrs = frames / (fr * 3600);
748 frames -= hrs * fr * 3600;
749 mins = frames / (fr * 60);
750 frames -= mins * fr * 60;
753 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
756 disk_space_label.set_text (buf);
760 ARDOUR_UI::update_wall_clock ()
767 tm_now = localtime (&now);
769 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
770 wall_clock_label.set_text (buf);
776 ARDOUR_UI::session_menu (GdkEventButton *ev)
778 session_popup_menu->popup (0, 0);
783 ARDOUR_UI::redisplay_recent_sessions ()
785 vector<string *> *sessions;
786 vector<string *>::iterator i;
787 RecentSessionsSorter cmp;
789 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
790 recent_session_model->clear ();
793 ARDOUR::read_recent_sessions (rs);
796 recent_session_display.set_model (recent_session_model);
800 /* sort them alphabetically */
801 sort (rs.begin(), rs.end(), cmp);
802 sessions = new vector<string*>;
804 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
805 sessions->push_back (new string ((*i).second));
808 for (i = sessions->begin(); i != sessions->end(); ++i) {
810 vector<string*>* states;
811 vector<const gchar*> item;
812 string fullpath = *(*i);
814 /* remove any trailing / */
816 if (fullpath[fullpath.length()-1] == '/') {
817 fullpath = fullpath.substr (0, fullpath.length()-1);
820 /* now get available states for this session */
822 if ((states = Session::possible_states (fullpath)) == 0) {
827 TreeModel::Row row = *(recent_session_model->append());
829 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
830 row[recent_session_columns.fullpath] = fullpath;
832 if (states->size() > 1) {
834 /* add the children */
836 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
838 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
840 child_row[recent_session_columns.visible_name] = **i2;
841 child_row[recent_session_columns.fullpath] = fullpath;
850 recent_session_display.set_model (recent_session_model);
855 ARDOUR_UI::build_session_selector ()
857 session_selector_window = new ArdourDialog ("session selector");
859 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
861 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
862 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
863 session_selector_window->set_default_response (RESPONSE_ACCEPT);
864 recent_session_model = TreeStore::create (recent_session_columns);
865 recent_session_display.set_model (recent_session_model);
866 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
867 recent_session_display.set_headers_visible (false);
868 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
870 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
872 scroller->add (recent_session_display);
873 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
875 session_selector_window->set_name ("SessionSelectorWindow");
876 session_selector_window->set_size_request (200, 400);
877 session_selector_window->get_vbox()->pack_start (*scroller);
878 session_selector_window->show_all_children();
882 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
884 session_selector_window->response (RESPONSE_ACCEPT);
888 ARDOUR_UI::open_recent_session ()
890 /* popup selector window */
892 if (session_selector_window == 0) {
893 build_session_selector ();
896 redisplay_recent_sessions ();
898 ResponseType r = (ResponseType) session_selector_window->run ();
900 session_selector_window->hide();
903 case RESPONSE_ACCEPT:
909 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
911 if (i == recent_session_model->children().end()) {
915 Glib::ustring path = (*i)[recent_session_columns.fullpath];
916 Glib::ustring state = (*i)[recent_session_columns.visible_name];
918 _session_is_new = false;
920 load_session (path, state);
924 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
928 if (stat (info.filename.c_str(), &statbuf) != 0) {
932 if (!S_ISDIR(statbuf.st_mode)) {
938 string session_file = info.filename;
940 session_file += Glib::path_get_basename (info.filename);
941 session_file += ".ardour";
943 if (stat (session_file.c_str(), &statbuf) != 0) {
947 return S_ISREG (statbuf.st_mode);
951 ARDOUR_UI::check_audioengine ()
954 if (!engine->connected()) {
955 MessageDialog msg (_("Ardour is not connected to JACK\n"
956 "You cannot open or close sessions in this condition"));
967 ARDOUR_UI::open_session ()
969 if (!check_audioengine()) {
974 /* popup selector window */
976 if (open_session_selector == 0) {
978 /* ardour sessions are folders */
980 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
981 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
982 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
984 FileFilter session_filter;
985 session_filter.add_pattern ("*.ardour");
986 session_filter.set_name (_("Ardour sessions"));
987 open_session_selector->add_filter (session_filter);
988 open_session_selector->set_filter (session_filter);
991 int response = open_session_selector->run();
992 open_session_selector->hide ();
995 case RESPONSE_ACCEPT:
998 open_session_selector->hide();
1002 open_session_selector->hide();
1003 string session_path = open_session_selector->get_filename();
1007 if (session_path.length() > 0) {
1008 if (Session::find_session (session_path, path, name, isnew) == 0) {
1009 _session_is_new = isnew;
1010 load_session (path, name);
1017 ARDOUR_UI::session_add_midi_track ()
1019 cerr << _("Patience is a virtue.\n");
1023 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1025 list<boost::shared_ptr<AudioTrack> > tracks;
1026 Session::RouteList routes;
1029 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1035 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1037 if (tracks.size() != how_many) {
1038 if (how_many == 1) {
1039 error << _("could not create a new audio track") << endmsg;
1041 error << string_compose (_("could only create %1 of %2 new audio %3"),
1042 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1048 routes = session->new_audio_route (input_channels, output_channels, how_many);
1050 if (routes.size() != how_many) {
1051 if (how_many == 1) {
1052 error << _("could not create a new audio track") << endmsg;
1054 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1060 if (need_control_room_outs) {
1066 route->set_stereo_control_outs (control_lr_channels);
1067 route->control_outs()->set_stereo_pan (pans, this);
1069 #endif /* CONTROLOUTS */
1073 cerr << "About to complain about JACK\n";
1074 MessageDialog msg (*editor,
1075 _("There are insufficient JACK ports available\n\
1076 to create a new track or bus.\n\
1077 You should save Ardour, exit and\n\
1078 restart JACK with more ports."));
1084 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1086 nframes_t _preroll = 0;
1089 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1090 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1092 if (new_position > _preroll) {
1093 new_position -= _preroll;
1098 session->request_locate (new_position);
1103 ARDOUR_UI::transport_goto_start ()
1106 session->goto_start();
1109 /* force displayed area in editor to start no matter
1110 what "follow playhead" setting is.
1114 editor->reset_x_origin (session->current_start_frame());
1120 ARDOUR_UI::transport_goto_zero ()
1123 session->request_locate (0);
1126 /* force displayed area in editor to start no matter
1127 what "follow playhead" setting is.
1131 editor->reset_x_origin (0);
1137 ARDOUR_UI::transport_goto_end ()
1140 nframes_t frame = session->current_end_frame();
1141 session->request_locate (frame);
1143 /* force displayed area in editor to start no matter
1144 what "follow playhead" setting is.
1148 editor->reset_x_origin (frame);
1154 ARDOUR_UI::transport_stop ()
1160 if (session->is_auditioning()) {
1161 session->cancel_audition ();
1165 if (session->get_play_loop ()) {
1166 session->request_play_loop (false);
1169 session->request_stop ();
1173 ARDOUR_UI::transport_stop_and_forget_capture ()
1176 session->request_stop (true);
1181 ARDOUR_UI::remove_last_capture()
1184 editor->remove_last_capture();
1189 ARDOUR_UI::transport_record ()
1192 switch (session->record_status()) {
1193 case Session::Disabled:
1194 if (session->ntracks() == 0) {
1195 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1199 session->maybe_enable_record ();
1201 case Session::Recording:
1202 case Session::Enabled:
1203 session->disable_record (true);
1209 ARDOUR_UI::transport_roll ()
1217 rolling = session->transport_rolling ();
1219 if (session->get_play_loop()) {
1220 session->request_play_loop (false);
1221 auto_loop_button.set_visual_state (1);
1222 roll_button.set_visual_state (1);
1223 } else if (session->get_play_range ()) {
1224 session->request_play_range (false);
1225 play_selection_button.set_visual_state (0);
1226 } else if (rolling) {
1227 session->request_locate (session->last_transport_start(), true);
1230 session->request_transport_speed (1.0f);
1234 ARDOUR_UI::transport_loop()
1237 if (session->get_play_loop()) {
1238 if (session->transport_rolling()) {
1239 Location * looploc = session->locations()->auto_loop_location();
1241 session->request_locate (looploc->start(), true);
1246 session->request_play_loop (true);
1252 ARDOUR_UI::transport_play_selection ()
1258 if (!session->get_play_range()) {
1259 session->request_stop ();
1262 editor->play_selection ();
1266 ARDOUR_UI::transport_rewind (int option)
1268 float current_transport_speed;
1271 current_transport_speed = session->transport_speed();
1273 if (current_transport_speed >= 0.0f) {
1276 session->request_transport_speed (-1.0f);
1279 session->request_transport_speed (-4.0f);
1282 session->request_transport_speed (-0.5f);
1287 session->request_transport_speed (current_transport_speed * 1.5f);
1293 ARDOUR_UI::transport_forward (int option)
1295 float current_transport_speed;
1298 current_transport_speed = session->transport_speed();
1300 if (current_transport_speed <= 0.0f) {
1303 session->request_transport_speed (1.0f);
1306 session->request_transport_speed (4.0f);
1309 session->request_transport_speed (0.5f);
1314 session->request_transport_speed (current_transport_speed * 1.5f);
1320 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1326 boost::shared_ptr<Route> r;
1328 if ((r = session->route_by_remote_id (dstream)) != 0) {
1332 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1333 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1342 ARDOUR_UI::queue_transport_change ()
1344 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1348 ARDOUR_UI::map_transport_state ()
1350 float sp = session->transport_speed();
1353 transport_rolling ();
1354 } else if (sp < 0.0f) {
1355 transport_rewinding ();
1356 } else if (sp > 0.0f) {
1357 transport_forwarding ();
1359 transport_stopped ();
1364 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1366 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1367 (int) adj.get_value()].c_str());
1371 ARDOUR_UI::engine_stopped ()
1373 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1374 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1375 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1379 ARDOUR_UI::engine_running ()
1381 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1382 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1383 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1385 Glib::RefPtr<Action> action;
1386 char* action_name = 0;
1388 switch (engine->frames_per_cycle()) {
1390 action_name = X_("JACKLatency32");
1393 action_name = X_("JACKLatency64");
1396 action_name = X_("JACKLatency128");
1399 action_name = X_("JACKLatency512");
1402 action_name = X_("JACKLatency1024");
1405 action_name = X_("JACKLatency2048");
1408 action_name = X_("JACKLatency4096");
1411 action_name = X_("JACKLatency8192");
1414 /* XXX can we do anything useful ? */
1420 action = ActionManager::get_action (X_("JACK"), action_name);
1423 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1424 ract->set_active ();
1430 ARDOUR_UI::engine_halted ()
1432 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1434 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1435 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1437 update_sample_rate (0);
1439 MessageDialog msg (*editor,
1441 JACK has either been shutdown or it\n\
1442 disconnected Ardour because Ardour\n\
1443 was not fast enough. You can save the\n\
1444 session and/or try to reconnect to JACK ."));
1449 ARDOUR_UI::do_engine_start ()
1457 error << _("Unable to start the session running")
1467 ARDOUR_UI::start_engine ()
1469 if (do_engine_start () == 0) {
1470 if (session && _session_is_new) {
1471 /* we need to retain initial visual
1472 settings for a new session
1474 session->save_state ("");
1482 ARDOUR_UI::update_clocks ()
1484 if (!editor || !editor->dragging_playhead()) {
1485 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1490 ARDOUR_UI::start_clocking ()
1492 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1496 ARDOUR_UI::stop_clocking ()
1498 clock_signal_connection.disconnect ();
1502 ARDOUR_UI::toggle_clocking ()
1505 if (clock_button.get_active()) {
1514 ARDOUR_UI::_blink (void *arg)
1517 ((ARDOUR_UI *) arg)->blink ();
1524 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1528 ARDOUR_UI::start_blinking ()
1530 /* Start the blink signal. Everybody with a blinking widget
1531 uses Blink to drive the widget's state.
1534 if (blink_timeout_tag < 0) {
1536 blink_timeout_tag = g_timeout_add (240, _blink, this);
1541 ARDOUR_UI::stop_blinking ()
1543 if (blink_timeout_tag >= 0) {
1544 g_source_remove (blink_timeout_tag);
1545 blink_timeout_tag = -1;
1550 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1556 if (io.n_inputs() == 0) {
1561 /* XXX we're not handling multiple ports yet. */
1563 const char **connections = io.input(0)->get_connections();
1565 if (connections == 0 || connections[0] == '\0') {
1568 buf = connections[0];
1575 if (io.n_outputs() == 0) {
1580 /* XXX we're not handling multiple ports yet. */
1582 const char **connections = io.output(0)->get_connections();
1584 if (connections == 0 || connections[0] == '\0') {
1587 buf = connections[0];
1594 /** Ask the user for the name of a new shapshot and then take it.
1597 ARDOUR_UI::snapshot_session ()
1599 ArdourPrompter prompter (true);
1603 struct tm local_time;
1606 localtime_r (&n, &local_time);
1607 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1609 prompter.set_name ("Prompter");
1610 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1611 prompter.set_prompt (_("Name of New Snapshot"));
1612 prompter.set_initial_text (timebuf);
1614 switch (prompter.run()) {
1615 case RESPONSE_ACCEPT:
1616 prompter.get_result (snapname);
1617 if (snapname.length()){
1618 save_state (snapname);
1628 ARDOUR_UI::save_state (const string & name)
1630 (void) save_state_canfail (name);
1634 ARDOUR_UI::save_state_canfail (string name)
1639 if (name.length() == 0) {
1640 name = session->snap_name();
1643 if ((ret = session->save_state (name)) != 0) {
1647 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1652 ARDOUR_UI::restore_state (string name)
1655 if (name.length() == 0) {
1656 name = session->name();
1658 session->restore_state (name);
1663 ARDOUR_UI::primary_clock_value_changed ()
1666 session->request_locate (primary_clock.current_time ());
1671 ARDOUR_UI::secondary_clock_value_changed ()
1674 session->request_locate (secondary_clock.current_time ());
1679 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1681 if (session && dstream && dstream->record_enabled()) {
1683 Session::RecordState rs;
1685 rs = session->record_status ();
1688 case Session::Disabled:
1689 case Session::Enabled:
1690 if (w->get_state() != STATE_SELECTED) {
1691 w->set_state (STATE_SELECTED);
1695 case Session::Recording:
1696 if (w->get_state() != STATE_ACTIVE) {
1697 w->set_state (STATE_ACTIVE);
1703 if (w->get_state() != STATE_NORMAL) {
1704 w->set_state (STATE_NORMAL);
1710 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1716 switch (session->record_status()) {
1717 case Session::Enabled:
1719 rec_button.set_visual_state (2);
1721 rec_button.set_visual_state (0);
1725 case Session::Recording:
1726 rec_button.set_visual_state (1);
1730 rec_button.set_visual_state (0);
1736 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1744 ARDOUR_UI::save_template ()
1747 ArdourPrompter prompter (true);
1750 prompter.set_name (X_("Prompter"));
1751 prompter.set_prompt (_("Name for mix template:"));
1752 prompter.set_initial_text(session->name() + _("-template"));
1753 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1755 switch (prompter.run()) {
1756 case RESPONSE_ACCEPT:
1757 prompter.get_result (name);
1759 if (name.length()) {
1760 session->save_template (name);
1770 ARDOUR_UI::new_session (std::string predetermined_path)
1772 string session_name;
1773 string session_path;
1775 if (!check_audioengine()) {
1779 int response = Gtk::RESPONSE_NONE;
1781 new_session_dialog->set_modal(true);
1782 new_session_dialog->set_name (predetermined_path);
1783 new_session_dialog->reset_recent();
1784 new_session_dialog->show();
1785 new_session_dialog->set_current_page (0);
1788 response = new_session_dialog->run ();
1790 if (!check_audioengine()) {
1791 new_session_dialog->hide ();
1795 _session_is_new = false;
1797 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1802 new_session_dialog->hide ();
1805 } else if (response == Gtk::RESPONSE_NONE) {
1807 /* Clear was pressed */
1808 new_session_dialog->reset();
1810 } else if (response == Gtk::RESPONSE_YES) {
1812 /* YES == OPEN, but there's no enum for that */
1814 session_name = new_session_dialog->session_name();
1816 if (session_name.empty()) {
1817 response = Gtk::RESPONSE_NONE;
1821 if (session_name[0] == '/' ||
1822 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1823 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1824 load_session (Glib::path_get_dirname (session_name), session_name);
1826 session_path = new_session_dialog->session_folder();
1827 load_session (session_path, session_name);
1830 } else if (response == Gtk::RESPONSE_OK) {
1832 session_name = new_session_dialog->session_name();
1834 if (new_session_dialog->get_current_page() == 1) {
1836 /* XXX this is a bit of a hack..
1837 i really want the new sesion dialog to return RESPONSE_YES
1838 if we're on page 1 (the load page)
1839 Unfortunately i can't see how atm..
1842 if (session_name.empty()) {
1843 response = Gtk::RESPONSE_NONE;
1847 if (session_name[0] == '/' ||
1848 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1849 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1850 load_session (Glib::path_get_dirname (session_name), session_name);
1852 session_path = new_session_dialog->session_folder();
1853 load_session (session_path, session_name);
1858 if (session_name.empty()) {
1859 response = Gtk::RESPONSE_NONE;
1863 if (session_name[0] == '/' ||
1864 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1865 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1867 session_path = Glib::path_get_dirname (session_name);
1868 session_name = Glib::path_get_basename (session_name);
1872 session_path = new_session_dialog->session_folder();
1876 //XXX This is needed because session constructor wants a
1877 //non-existant path. hopefully this will be fixed at some point.
1879 session_path = Glib::build_filename (session_path, session_name);
1881 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1883 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1885 MessageDialog msg (str,
1887 Gtk::MESSAGE_WARNING,
1888 Gtk::BUTTONS_YES_NO,
1892 msg.set_name (X_("CleanupDialog"));
1893 msg.set_wmclass (X_("existing_session"), "Ardour");
1894 msg.set_position (Gtk::WIN_POS_MOUSE);
1896 switch (msg.run()) {
1898 load_session (session_path, session_name);
1902 response = RESPONSE_NONE;
1903 new_session_dialog->reset ();
1908 _session_is_new = true;
1910 std::string template_name = new_session_dialog->session_template_name();
1912 if (new_session_dialog->use_session_template()) {
1914 load_session (session_path, session_name, &template_name);
1920 AutoConnectOption iconnect;
1921 AutoConnectOption oconnect;
1923 if (new_session_dialog->create_control_bus()) {
1924 cchns = (uint32_t) new_session_dialog->control_channel_count();
1929 if (new_session_dialog->create_master_bus()) {
1930 mchns = (uint32_t) new_session_dialog->master_channel_count();
1935 if (new_session_dialog->connect_inputs()) {
1936 iconnect = AutoConnectPhysical;
1938 iconnect = AutoConnectOption (0);
1941 /// @todo some minor tweaks.
1943 if (new_session_dialog->connect_outs_to_master()) {
1944 oconnect = AutoConnectMaster;
1945 } else if (new_session_dialog->connect_outs_to_physical()) {
1946 oconnect = AutoConnectPhysical;
1948 oconnect = AutoConnectOption (0);
1951 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1952 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1954 if (build_session (session_path,
1962 engine->frame_rate() * 60 * 5)) {
1964 response = Gtk::RESPONSE_NONE;
1965 new_session_dialog->reset ();
1972 } while (response == Gtk::RESPONSE_NONE);
1976 new_session_dialog->get_window()->set_cursor();
1977 new_session_dialog->hide();
1982 ARDOUR_UI::close_session()
1984 if (!check_audioengine()) {
1993 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1995 Session *new_session;
1997 session_loaded = false;
1999 if (!check_audioengine()) {
2003 x = unload_session ();
2011 /* if it already exists, we must have write access */
2013 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2014 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2015 "This prevents the session from being loaded."));
2021 new_session = new Session (*engine, path, snap_name, mix_template);
2026 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2030 connect_to_session (new_session);
2032 Config->set_current_owner (ConfigVariableBase::Interface);
2034 session_loaded = true;
2036 goto_editor_window ();
2039 session->set_clean ();
2042 editor->edit_cursor_position (true);
2047 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2048 uint32_t control_channels,
2049 uint32_t master_channels,
2050 AutoConnectOption input_connect,
2051 AutoConnectOption output_connect,
2054 nframes_t initial_length)
2056 Session *new_session;
2059 if (!check_audioengine()) {
2063 session_loaded = false;
2065 x = unload_session ();
2073 _session_is_new = true;
2076 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2077 control_channels, master_channels, nphysin, nphysout, initial_length);
2082 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2087 connect_to_session (new_session);
2089 session_loaded = true;
2097 editor->show_window ();
2108 ARDOUR_UI::show_splash ()
2111 about = new About();
2112 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2119 ARDOUR_UI::about_signal_response(int response)
2125 ARDOUR_UI::hide_splash ()
2128 about->get_window()->set_cursor ();
2134 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2138 removed = rep.paths.size();
2141 MessageDialog msgd (*editor,
2142 _("No audio files were ready for cleanup"),
2145 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2146 msgd.set_secondary_text (_("If this seems suprising, \n\
2147 check for any existing snapshots.\n\
2148 These may still include regions that\n\
2149 require some unused files to continue to exist."));
2155 ArdourDialog results (_("ardour: cleanup"), true, false);
2157 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2158 CleanupResultsModelColumns() {
2162 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2163 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2167 CleanupResultsModelColumns results_columns;
2168 Glib::RefPtr<Gtk::ListStore> results_model;
2169 Gtk::TreeView results_display;
2171 results_model = ListStore::create (results_columns);
2172 results_display.set_model (results_model);
2173 results_display.append_column (list_title, results_columns.visible_name);
2175 results_display.set_name ("CleanupResultsList");
2176 results_display.set_headers_visible (true);
2177 results_display.set_headers_clickable (false);
2178 results_display.set_reorderable (false);
2180 Gtk::ScrolledWindow list_scroller;
2183 Gtk::HBox dhbox; // the hbox for the image and text
2184 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2185 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2187 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2189 if (rep.space < 1048576.0f) {
2191 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2193 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2197 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2199 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2203 dhbox.pack_start (*dimage, true, false, 5);
2204 dhbox.pack_start (txt, true, false, 5);
2206 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2207 TreeModel::Row row = *(results_model->append());
2208 row[results_columns.visible_name] = *i;
2209 row[results_columns.fullpath] = *i;
2212 list_scroller.add (results_display);
2213 list_scroller.set_size_request (-1, 150);
2214 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2216 dvbox.pack_start (dhbox, true, false, 5);
2217 dvbox.pack_start (list_scroller, true, false, 5);
2218 ddhbox.pack_start (dvbox, true, false, 5);
2220 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2221 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2222 results.set_default_response (RESPONSE_CLOSE);
2223 results.set_position (Gtk::WIN_POS_MOUSE);
2224 results.show_all_children ();
2225 results.set_resizable (false);
2232 ARDOUR_UI::cleanup ()
2235 /* shouldn't happen: menu item is insensitive */
2240 MessageDialog checker (_("Are you sure you want to cleanup?"),
2242 Gtk::MESSAGE_QUESTION,
2243 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2245 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2246 ALL undo/redo information will be lost if you cleanup.\n\
2247 After cleanup, unused audio files will be moved to a \
2248 \"dead sounds\" location."));
2250 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2251 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2252 checker.set_default_response (RESPONSE_CANCEL);
2254 checker.set_name (_("CleanupDialog"));
2255 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2256 checker.set_position (Gtk::WIN_POS_MOUSE);
2258 switch (checker.run()) {
2259 case RESPONSE_ACCEPT:
2265 Session::cleanup_report rep;
2267 editor->prepare_for_cleanup ();
2269 /* do not allow flush until a session is reloaded */
2271 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2273 act->set_sensitive (false);
2276 if (session->cleanup_sources (rep)) {
2281 display_cleanup_results (rep,
2284 The following %1 %2 not in use and \n\
2285 have been moved to:\n\
2287 Flushing the wastebasket will \n\
2288 release an additional\n\
2289 %4 %5bytes of disk space.\n"
2297 ARDOUR_UI::flush_trash ()
2300 /* shouldn't happen: menu item is insensitive */
2304 Session::cleanup_report rep;
2306 if (session->cleanup_trash_sources (rep)) {
2310 display_cleanup_results (rep,
2312 _("The following %1 %2 deleted from\n\
2314 releasing %4 %5bytes of disk space"));
2318 ARDOUR_UI::add_route (Gtk::Window* float_window)
2326 if (add_route_dialog == 0) {
2327 add_route_dialog = new AddRouteDialog;
2329 add_route_dialog->set_transient_for (*float_window);
2333 if (add_route_dialog->is_visible()) {
2334 /* we're already doing this */
2338 ResponseType r = (ResponseType) add_route_dialog->run ();
2340 add_route_dialog->hide();
2343 case RESPONSE_ACCEPT:
2350 if ((count = add_route_dialog->count()) <= 0) {
2354 uint32_t input_chan = add_route_dialog->channels ();
2355 uint32_t output_chan;
2356 string name_template = add_route_dialog->name_template ();
2357 bool track = add_route_dialog->track ();
2359 AutoConnectOption oac = Config->get_output_auto_connect();
2361 if (oac & AutoConnectMaster) {
2362 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2364 output_chan = input_chan;
2367 /* XXX do something with name template */
2370 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2372 session_add_audio_bus (input_chan, output_chan, count);
2377 ARDOUR_UI::mixer_settings () const
2382 node = session->instant_xml(X_("Mixer"), session->path());
2384 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2388 node = new XMLNode (X_("Mixer"));
2395 ARDOUR_UI::editor_settings () const
2400 node = session->instant_xml(X_("Editor"), session->path());
2402 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2406 node = new XMLNode (X_("Editor"));
2412 ARDOUR_UI::keyboard_settings () const
2416 node = Config->extra_xml(X_("Keyboard"));
2419 node = new XMLNode (X_("Keyboard"));
2425 ARDOUR_UI::halt_on_xrun_message ()
2427 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2429 MessageDialog msg (*editor,
2430 _("Recording was stopped because your system could not keep up."));
2435 ARDOUR_UI::disk_overrun_handler ()
2437 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2439 if (!have_disk_speed_dialog_displayed) {
2440 have_disk_speed_dialog_displayed = true;
2441 MessageDialog* msg = new MessageDialog (*editor, _("\
2442 The disk system on your computer\n\
2443 was not able to keep up with Ardour.\n\
2445 Specifically, it failed to write data to disk\n\
2446 quickly enough to keep up with recording.\n"));
2447 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2453 ARDOUR_UI::disk_underrun_handler ()
2455 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2457 if (!have_disk_speed_dialog_displayed) {
2458 have_disk_speed_dialog_displayed = true;
2459 MessageDialog* msg = new MessageDialog (*editor,
2460 _("The disk system on your computer\n\
2461 was not able to keep up with Ardour.\n\
2463 Specifically, it failed to read data from disk\n\
2464 quickly enough to keep up with playback.\n"));
2465 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2471 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2473 have_disk_speed_dialog_displayed = false;
2478 ARDOUR_UI::pending_state_dialog ()
2480 ArdourDialog dialog ("pending state dialog");
2482 This session appears to have been in\n\
2483 middle of recording when ardour or\n\
2484 the computer was shutdown.\n\
2486 Ardour can recover any captured audio for\n\
2487 you, or it can ignore it. Please decide\n\
2488 what you would like to do.\n"));
2490 dialog.get_vbox()->pack_start (message);
2491 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2492 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2494 dialog.set_position (WIN_POS_CENTER);
2497 switch (dialog.run ()) {
2498 case RESPONSE_ACCEPT:
2506 ARDOUR_UI::disconnect_from_jack ()
2509 if( engine->disconnect_from_jack ()) {
2510 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2514 update_sample_rate (0);
2519 ARDOUR_UI::reconnect_to_jack ()
2522 if (engine->reconnect_to_jack ()) {
2523 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2527 update_sample_rate (0);
2532 ARDOUR_UI::cmdline_new_session (string path)
2534 if (path[0] != '/') {
2535 char buf[PATH_MAX+1];
2538 getcwd (buf, sizeof (buf));
2547 _will_create_new_session_automatically = false; /* done it */
2548 return FALSE; /* don't call it again */
2552 ARDOUR_UI::use_config ()
2554 Glib::RefPtr<Action> act;
2556 switch (Config->get_native_file_data_format ()) {
2558 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2561 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2566 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2567 ract->set_active ();
2570 switch (Config->get_native_file_header_format ()) {
2572 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2575 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2578 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2581 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2584 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2587 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2590 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2595 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2596 ract->set_active ();
2599 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2601 set_transport_controllable_state (*node);
2606 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2608 primary_clock.set (pos);
2609 secondary_clock.set (pos);
2611 if (big_clock_window) {
2612 big_clock.set (pos);
2617 ARDOUR_UI::record_state_changed ()
2619 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2621 if (!session || !big_clock_window) {
2622 /* why bother - the clock isn't visible */
2626 switch (session->record_status()) {
2627 case Session::Recording:
2628 big_clock.set_widget_name ("BigClockRecording");
2631 big_clock.set_widget_name ("BigClockNonRecording");
2637 ARDOUR_UI::set_keybindings_path (string path)
2639 keybindings_path = path;
2643 ARDOUR_UI::save_keybindings ()
2645 if (can_save_keybindings) {
2646 AccelMap::save (keybindings_path);
2651 ARDOUR_UI::first_idle ()
2654 session->allow_auto_play (true);
2656 can_save_keybindings = true;
2661 ARDOUR_UI::store_clock_modes ()
2663 XMLNode* node = new XMLNode(X_("ClockModes"));
2665 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2666 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2669 session->add_extra_xml (*node);
2670 session->set_dirty ();
2675 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2676 : Controllable (name), ui (u), type(tp)
2682 ARDOUR_UI::TransportControllable::set_value (float val)
2684 if (type == ShuttleControl) {
2691 fract = -((0.5f - val)/0.5f);
2693 fract = ((val - 0.5f)/0.5f);
2697 ui.set_shuttle_fract (fract);
2702 /* do nothing: these are radio-style actions */
2710 action = X_("Roll");
2713 action = X_("Stop");
2716 action = X_("Goto Start");
2719 action = X_("Goto End");
2722 action = X_("Loop");
2725 action = X_("Play Selection");
2728 action = X_("Record");
2738 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2746 ARDOUR_UI::TransportControllable::get_value (void) const
2765 case ShuttleControl:
2775 ARDOUR_UI::TransportControllable::set_id (const string& str)
2781 ARDOUR_UI::setup_profile ()
2783 if (gdk_screen_width() < 1200) {
2784 Profile->set_small_screen ();