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>
48 #include <midi++/port.h>
49 #include <midi++/mmc.h>
51 #include <ardour/ardour.h>
52 #include <ardour/session_route.h>
53 #include <ardour/port.h>
54 #include <ardour/audioengine.h>
55 #include <ardour/playlist.h>
56 #include <ardour/utils.h>
57 #include <ardour/audio_diskstream.h>
58 #include <ardour/audiofilesource.h>
59 #include <ardour/recent_sessions.h>
60 #include <ardour/port.h>
61 #include <ardour/audio_track.h>
64 #include "ardour_ui.h"
65 #include "public_editor.h"
66 #include "audio_clock.h"
71 #include "add_route_dialog.h"
72 #include "new_session_dialog.h"
75 #include "gui_thread.h"
76 #include "color_manager.h"
80 using namespace ARDOUR;
82 using namespace Gtkmm2ext;
86 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
88 sigc::signal<void,bool> ARDOUR_UI::Blink;
89 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
90 sigc::signal<void> ARDOUR_UI::MidRapidScreenUpdate;
91 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
92 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
94 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
96 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
98 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
99 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
100 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
101 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
105 adjuster_table (3, 3),
109 preroll_button (_("pre\nroll")),
110 postroll_button (_("post\nroll")),
114 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
118 roll_controllable ("transport roll", *this, TransportControllable::Roll),
119 stop_controllable ("transport stop", *this, TransportControllable::Stop),
120 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
121 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
122 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
123 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
124 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
125 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
126 shuttle_controller_binding_proxy (shuttle_controllable),
128 roll_button (roll_controllable),
129 stop_button (stop_controllable),
130 goto_start_button (goto_start_controllable),
131 goto_end_button (goto_end_controllable),
132 auto_loop_button (auto_loop_controllable),
133 play_selection_button (play_selection_controllable),
134 rec_button (rec_controllable),
136 shuttle_units_button (_("% ")),
138 punch_in_button (_("Punch In")),
139 punch_out_button (_("Punch Out")),
140 auto_return_button (_("Auto Return")),
141 auto_play_button (_("Auto Play")),
142 auto_input_button (_("Auto Input")),
143 click_button (_("Click")),
144 time_master_button (_("time\nmaster")),
146 auditioning_alert_button (_("AUDITION")),
147 solo_alert_button (_("SOLO")),
150 using namespace Gtk::Menu_Helpers;
156 if (theArdourUI == 0) {
162 color_manager = new ColorManager();
164 std::string color_file = ARDOUR::find_config_file("ardour.colors");
166 color_manager->load (color_file);
171 _session_is_new = false;
172 big_clock_window = 0;
173 session_selector_window = 0;
174 last_key_press_time = 0;
175 connection_editor = 0;
176 add_route_dialog = 0;
180 open_session_selector = 0;
181 have_configure_timeout = false;
182 have_disk_speed_dialog_displayed = false;
183 _will_create_new_session_automatically = false;
184 session_loaded = false;
185 last_speed_displayed = -1.0f;
186 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
188 can_save_keybindings = false;
189 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle));
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 if (AudioSource::start_peak_thread ()) {
267 throw failed_constructor();
270 /* set default clock modes */
272 primary_clock.set_mode (AudioClock::SMPTE);
273 secondary_clock.set_mode (AudioClock::BBT);
275 /* start the time-of-day-clock */
277 update_wall_clock ();
278 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
280 update_disk_space ();
282 update_sample_rate (engine->frame_rate());
284 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
285 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
288 ARDOUR_UI::~ARDOUR_UI ()
290 save_ardour_state ();
304 if (add_route_dialog) {
305 delete add_route_dialog;
308 AudioSource::stop_peak_thread ();
312 ARDOUR_UI::configure_timeout ()
317 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
318 /* no configure events yet */
322 gettimeofday (&now, 0);
323 timersub (&now, &last_configure_time, &diff);
325 /* force a gap of 0.5 seconds since the last configure event
328 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
331 have_configure_timeout = false;
332 save_ardour_state ();
338 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
340 if (have_configure_timeout) {
341 gettimeofday (&last_configure_time, 0);
343 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
344 have_configure_timeout = true;
351 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
353 const XMLProperty* prop;
355 if ((prop = node.property ("roll")) != 0) {
356 roll_controllable.set_id (prop->value());
358 if ((prop = node.property ("stop")) != 0) {
359 stop_controllable.set_id (prop->value());
361 if ((prop = node.property ("goto_start")) != 0) {
362 goto_start_controllable.set_id (prop->value());
364 if ((prop = node.property ("goto_end")) != 0) {
365 goto_end_controllable.set_id (prop->value());
367 if ((prop = node.property ("auto_loop")) != 0) {
368 auto_loop_controllable.set_id (prop->value());
370 if ((prop = node.property ("play_selection")) != 0) {
371 play_selection_controllable.set_id (prop->value());
373 if ((prop = node.property ("rec")) != 0) {
374 rec_controllable.set_id (prop->value());
376 if ((prop = node.property ("shuttle")) != 0) {
377 shuttle_controllable.set_id (prop->value());
382 ARDOUR_UI::get_transport_controllable_state ()
384 XMLNode* node = new XMLNode(X_("TransportControllables"));
387 roll_controllable.id().print (buf, sizeof (buf));
388 node->add_property (X_("roll"), buf);
389 stop_controllable.id().print (buf, sizeof (buf));
390 node->add_property (X_("stop"), buf);
391 goto_start_controllable.id().print (buf, sizeof (buf));
392 node->add_property (X_("goto_start"), buf);
393 goto_end_controllable.id().print (buf, sizeof (buf));
394 node->add_property (X_("goto_end"), buf);
395 auto_loop_controllable.id().print (buf, sizeof (buf));
396 node->add_property (X_("auto_loop"), buf);
397 play_selection_controllable.id().print (buf, sizeof (buf));
398 node->add_property (X_("play_selection"), buf);
399 rec_controllable.id().print (buf, sizeof (buf));
400 node->add_property (X_("rec"), buf);
401 shuttle_controllable.id().print (buf, sizeof (buf));
402 node->add_property (X_("shuttle"), buf);
408 ARDOUR_UI::save_ardour_state ()
410 if (!keyboard || !mixer || !editor) {
414 /* XXX this is all a bit dubious. add_extra_xml() uses
415 a different lifetime model from add_instant_xml().
418 XMLNode* node = new XMLNode (keyboard->get_state());
419 Config->add_extra_xml (*node);
420 Config->add_extra_xml (get_transport_controllable_state());
421 Config->save_state();
423 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
424 XMLNode mnode(mixer->get_state());
427 session->add_instant_xml (enode, session->path());
428 session->add_instant_xml (mnode, session->path());
430 Config->add_instant_xml (enode, get_user_ardour_path());
431 Config->add_instant_xml (mnode, get_user_ardour_path());
438 ARDOUR_UI::startup ()
440 check_memory_locking();
444 ARDOUR_UI::no_memory_warning ()
446 XMLNode node (X_("no-memory-warning"));
447 Config->add_instant_xml (node, get_user_ardour_path());
451 ARDOUR_UI::check_memory_locking ()
454 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
458 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
460 if (engine->is_realtime() && memory_warning_node == 0) {
462 struct rlimit limits;
464 long pages, page_size;
466 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
469 ram = (int64_t) pages * (int64_t) page_size;
472 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
476 if (limits.rlim_cur != RLIM_INFINITY) {
478 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
481 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
482 "This might cause Ardour to run out of memory before your system "
483 "runs out of memory. \n\n"
484 "You can view the memory limit with 'ulimit -l', "
485 "and it is normally controlled by /etc/security/limits.conf"));
487 VBox* vbox = msg.get_vbox();
489 CheckButton cb (_("Do not show this window again"));
491 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
493 hbox.pack_start (cb, true, false);
494 vbox->pack_start (hbox);
497 editor->ensure_float (msg);
509 if (session && session->dirty()) {
510 switch (ask_about_saving_session(_("quit"))) {
515 /* use the default name */
516 if (save_state_canfail ("")) {
517 /* failed - don't quit */
518 MessageDialog msg (*editor,
520 Ardour was unable to save your session.\n\n\
521 If you still wish to quit, please use the\n\n\
522 \"Just quit\" option."));
533 session->set_deletion_in_progress ();
536 Config->save_state();
541 ARDOUR_UI::ask_about_saving_session (const string & what)
543 ArdourDialog window (_("ardour: save session?"));
544 Gtk::HBox dhbox; // the hbox for the image and text
545 Gtk::Label prompt_label;
546 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
550 msg = string_compose(_("Don't %1"), what);
551 window.add_button (msg, RESPONSE_REJECT);
552 msg = string_compose(_("Just %1"), what);
553 window.add_button (msg, RESPONSE_APPLY);
554 msg = string_compose(_("Save and %1"), what);
555 window.add_button (msg, RESPONSE_ACCEPT);
557 window.set_default_response (RESPONSE_ACCEPT);
559 Gtk::Button noquit_button (msg);
560 noquit_button.set_name ("EditorGTKButton");
565 if (session->snap_name() == session->name()) {
568 type = _("snapshot");
570 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?"),
571 type, session->snap_name());
573 prompt_label.set_text (prompt);
574 prompt_label.set_name (X_("PrompterLabel"));
575 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
577 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
579 dhbox.set_homogeneous (false);
580 dhbox.pack_start (*dimage, false, false, 5);
581 dhbox.pack_start (prompt_label, true, false, 5);
582 window.get_vbox()->pack_start (dhbox);
584 window.set_name (_("Prompter"));
585 window.set_position (Gtk::WIN_POS_MOUSE);
586 window.set_modal (true);
587 window.set_resizable (false);
590 save_the_session = 0;
592 window.set_keep_above (true);
595 ResponseType r = (ResponseType) window.run();
600 case RESPONSE_ACCEPT: // save and get out of here
602 case RESPONSE_APPLY: // get out of here
612 ARDOUR_UI::every_second ()
615 update_buffer_load ();
616 update_disk_space ();
621 ARDOUR_UI::every_point_one_seconds ()
623 update_speed_display ();
624 RapidScreenUpdate(); /* EMIT_SIGNAL */
629 ARDOUR_UI::every_point_oh_five_seconds ()
631 MidRapidScreenUpdate(); /* EMIT_SIGNAL */
636 ARDOUR_UI::every_point_zero_one_seconds ()
638 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
643 ARDOUR_UI::update_sample_rate (nframes_t ignored)
647 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
649 if (!engine->connected()) {
651 snprintf (buf, sizeof (buf), _("disconnected"));
655 nframes_t rate = engine->frame_rate();
657 if (fmod (rate, 1000.0) != 0.0) {
658 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"),
659 (float) rate/1000.0f,
660 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
662 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"),
664 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
668 sample_rate_label.set_text (buf);
672 ARDOUR_UI::update_cpu_load ()
675 snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load());
676 cpu_load_label.set_text (buf);
680 ARDOUR_UI::update_buffer_load ()
685 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
686 session->playback_load(), session->capture_load());
687 buffer_load_label.set_text (buf);
689 buffer_load_label.set_text ("");
694 ARDOUR_UI::count_recenabled_streams (Route& route)
696 Track* track = dynamic_cast<Track*>(&route);
697 if (track && track->diskstream()->record_enabled()) {
698 rec_enabled_streams += track->n_inputs();
703 ARDOUR_UI::update_disk_space()
709 nframes_t frames = session->available_capture_duration();
712 if (frames == max_frames) {
713 strcpy (buf, _("Disk: 24hrs+"));
718 nframes_t fr = session->frame_rate();
720 rec_enabled_streams = 0;
721 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
723 if (rec_enabled_streams) {
724 frames /= rec_enabled_streams;
727 hrs = frames / (fr * 3600);
728 frames -= hrs * fr * 3600;
729 mins = frames / (fr * 60);
730 frames -= mins * fr * 60;
733 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
736 disk_space_label.set_text (buf);
740 ARDOUR_UI::update_wall_clock ()
747 tm_now = localtime (&now);
749 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
750 wall_clock_label.set_text (buf);
756 ARDOUR_UI::session_menu (GdkEventButton *ev)
758 session_popup_menu->popup (0, 0);
763 ARDOUR_UI::redisplay_recent_sessions ()
765 vector<string *> *sessions;
766 vector<string *>::iterator i;
767 RecentSessionsSorter cmp;
769 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
770 recent_session_model->clear ();
773 ARDOUR::read_recent_sessions (rs);
776 recent_session_display.set_model (recent_session_model);
780 /* sort them alphabetically */
781 sort (rs.begin(), rs.end(), cmp);
782 sessions = new vector<string*>;
784 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
785 sessions->push_back (new string ((*i).second));
788 for (i = sessions->begin(); i != sessions->end(); ++i) {
790 vector<string*>* states;
791 vector<const gchar*> item;
792 string fullpath = *(*i);
794 /* remove any trailing / */
796 if (fullpath[fullpath.length()-1] == '/') {
797 fullpath = fullpath.substr (0, fullpath.length()-1);
800 /* now get available states for this session */
802 if ((states = Session::possible_states (fullpath)) == 0) {
807 TreeModel::Row row = *(recent_session_model->append());
809 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
810 row[recent_session_columns.fullpath] = fullpath;
812 if (states->size() > 1) {
814 /* add the children */
816 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
818 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
820 child_row[recent_session_columns.visible_name] = **i2;
821 child_row[recent_session_columns.fullpath] = fullpath;
830 recent_session_display.set_model (recent_session_model);
835 ARDOUR_UI::build_session_selector ()
837 session_selector_window = new ArdourDialog ("session selector");
839 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
841 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
842 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
843 session_selector_window->set_default_response (RESPONSE_ACCEPT);
844 recent_session_model = TreeStore::create (recent_session_columns);
845 recent_session_display.set_model (recent_session_model);
846 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
847 recent_session_display.set_headers_visible (false);
848 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
850 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
852 scroller->add (recent_session_display);
853 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
855 session_selector_window->set_name ("SessionSelectorWindow");
856 session_selector_window->set_size_request (200, 400);
857 session_selector_window->get_vbox()->pack_start (*scroller);
858 session_selector_window->show_all_children();
862 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
864 session_selector_window->response (RESPONSE_ACCEPT);
868 ARDOUR_UI::open_recent_session ()
870 /* popup selector window */
872 if (session_selector_window == 0) {
873 build_session_selector ();
876 redisplay_recent_sessions ();
878 ResponseType r = (ResponseType) session_selector_window->run ();
880 session_selector_window->hide();
883 case RESPONSE_ACCEPT:
889 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
891 if (i == recent_session_model->children().end()) {
895 Glib::ustring path = (*i)[recent_session_columns.fullpath];
896 Glib::ustring state = (*i)[recent_session_columns.visible_name];
898 _session_is_new = false;
900 load_session (path, state);
904 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
908 if (stat (info.filename.c_str(), &statbuf) != 0) {
912 if (!S_ISDIR(statbuf.st_mode)) {
918 string session_file = info.filename;
920 session_file += Glib::path_get_basename (info.filename);
921 session_file += ".ardour";
923 if (stat (session_file.c_str(), &statbuf) != 0) {
927 return S_ISREG (statbuf.st_mode);
931 ARDOUR_UI::open_session ()
933 /* popup selector window */
935 if (open_session_selector == 0) {
937 /* ardour sessions are folders */
939 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
940 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
941 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
943 FileFilter session_filter;
944 session_filter.add_pattern ("*.ardour");
945 session_filter.set_name (_("Ardour sessions"));
946 open_session_selector->add_filter (session_filter);
947 open_session_selector->set_filter (session_filter);
950 int response = open_session_selector->run();
951 open_session_selector->hide ();
954 case RESPONSE_ACCEPT:
957 open_session_selector->hide();
961 open_session_selector->hide();
962 string session_path = open_session_selector->get_filename();
966 if (session_path.length() > 0) {
967 if (Session::find_session (session_path, path, name, isnew) == 0) {
968 _session_is_new = isnew;
969 load_session (path, name);
976 ARDOUR_UI::session_add_midi_track ()
978 cerr << _("Patience is a virtue.\n");
982 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
984 list<boost::shared_ptr<AudioTrack> > tracks;
985 Session::RouteList routes;
988 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
994 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
996 if (tracks.size() != how_many) {
998 error << _("could not create a new audio track") << endmsg;
1000 error << string_compose (_("could only create %1 of %2 new audio %3"),
1001 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1007 routes = session->new_audio_route (input_channels, output_channels, how_many);
1009 if (routes.size() != how_many) {
1010 if (how_many == 1) {
1011 error << _("could not create a new audio track") << endmsg;
1013 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1019 if (need_control_room_outs) {
1025 route->set_stereo_control_outs (control_lr_channels);
1026 route->control_outs()->set_stereo_pan (pans, this);
1028 #endif /* CONTROLOUTS */
1032 cerr << "About to complain about JACK\n";
1033 MessageDialog msg (*editor,
1034 _("There are insufficient JACK ports available\n\
1035 to create a new track or bus.\n\
1036 You should save Ardour, exit and\n\
1037 restart JACK with more ports."));
1043 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1045 nframes_t _preroll = 0;
1048 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1049 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1051 if (new_position > _preroll) {
1052 new_position -= _preroll;
1057 session->request_locate (new_position);
1062 ARDOUR_UI::transport_goto_start ()
1065 session->goto_start();
1068 /* force displayed area in editor to start no matter
1069 what "follow playhead" setting is.
1073 editor->reset_x_origin (session->current_start_frame());
1079 ARDOUR_UI::transport_goto_zero ()
1082 session->request_locate (0);
1085 /* force displayed area in editor to start no matter
1086 what "follow playhead" setting is.
1090 editor->reset_x_origin (0);
1096 ARDOUR_UI::transport_goto_end ()
1099 nframes_t frame = session->current_end_frame();
1100 session->request_locate (frame);
1102 /* force displayed area in editor to start no matter
1103 what "follow playhead" setting is.
1107 editor->reset_x_origin (frame);
1113 ARDOUR_UI::transport_stop ()
1119 if (session->is_auditioning()) {
1120 session->cancel_audition ();
1124 if (session->get_play_loop ()) {
1125 session->request_play_loop (false);
1128 session->request_stop ();
1132 ARDOUR_UI::transport_stop_and_forget_capture ()
1135 session->request_stop (true);
1140 ARDOUR_UI::remove_last_capture()
1143 editor->remove_last_capture();
1148 ARDOUR_UI::transport_record ()
1150 cerr << "transport record\n";
1153 switch (session->record_status()) {
1154 case Session::Disabled:
1155 if (session->ntracks() == 0) {
1156 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1160 session->maybe_enable_record ();
1162 case Session::Recording:
1163 case Session::Enabled:
1164 session->disable_record (true);
1170 ARDOUR_UI::transport_roll ()
1178 rolling = session->transport_rolling ();
1180 if (session->get_play_loop()) {
1181 session->request_play_loop (false);
1182 auto_loop_button.set_visual_state (1);
1183 roll_button.set_visual_state (1);
1184 } else if (session->get_play_range ()) {
1185 session->request_play_range (false);
1186 play_selection_button.set_visual_state (0);
1187 } else if (rolling) {
1188 session->request_locate (session->last_transport_start(), true);
1191 session->request_transport_speed (1.0f);
1195 ARDOUR_UI::transport_loop()
1198 if (session->get_play_loop()) {
1199 if (session->transport_rolling()) {
1200 Location * looploc = session->locations()->auto_loop_location();
1202 session->request_locate (looploc->start(), true);
1207 session->request_play_loop (true);
1213 ARDOUR_UI::transport_play_selection ()
1219 if (!session->get_play_range()) {
1220 session->request_stop ();
1223 editor->play_selection ();
1227 ARDOUR_UI::transport_rewind (int option)
1229 float current_transport_speed;
1232 current_transport_speed = session->transport_speed();
1234 if (current_transport_speed >= 0.0f) {
1237 session->request_transport_speed (-1.0f);
1240 session->request_transport_speed (-4.0f);
1243 session->request_transport_speed (-0.5f);
1248 session->request_transport_speed (current_transport_speed * 1.5f);
1254 ARDOUR_UI::transport_forward (int option)
1256 float current_transport_speed;
1259 current_transport_speed = session->transport_speed();
1261 if (current_transport_speed <= 0.0f) {
1264 session->request_transport_speed (1.0f);
1267 session->request_transport_speed (4.0f);
1270 session->request_transport_speed (0.5f);
1275 session->request_transport_speed (current_transport_speed * 1.5f);
1281 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1287 boost::shared_ptr<Route> r;
1289 if ((r = session->route_by_remote_id (dstream)) != 0) {
1293 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1294 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1303 ARDOUR_UI::queue_transport_change ()
1305 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1309 ARDOUR_UI::map_transport_state ()
1311 float sp = session->transport_speed();
1314 transport_rolling ();
1315 } else if (sp < 0.0f) {
1316 transport_rewinding ();
1317 } else if (sp > 0.0f) {
1318 transport_forwarding ();
1320 transport_stopped ();
1325 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1327 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1328 (int) adj.get_value()].c_str());
1332 ARDOUR_UI::engine_stopped ()
1334 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1335 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1336 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1340 ARDOUR_UI::engine_running ()
1342 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1343 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1344 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1346 Glib::RefPtr<Action> action;
1347 char* action_name = 0;
1349 switch (engine->frames_per_cycle()) {
1351 action_name = X_("JACKLatency32");
1354 action_name = X_("JACKLatency64");
1357 action_name = X_("JACKLatency128");
1360 action_name = X_("JACKLatency512");
1363 action_name = X_("JACKLatency1024");
1366 action_name = X_("JACKLatency2048");
1369 action_name = X_("JACKLatency4096");
1372 action_name = X_("JACKLatency8192");
1375 /* XXX can we do anything useful ? */
1381 action = ActionManager::get_action (X_("JACK"), action_name);
1384 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1385 ract->set_active ();
1391 ARDOUR_UI::engine_halted ()
1393 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1395 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1396 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1398 update_sample_rate (0);
1400 MessageDialog msg (*editor,
1402 JACK has either been shutdown or it\n\
1403 disconnected Ardour because Ardour\n\
1404 was not fast enough. You can save the\n\
1405 session and/or try to reconnect to JACK ."));
1410 ARDOUR_UI::do_engine_start ()
1418 error << _("Unable to start the session running")
1428 ARDOUR_UI::start_engine ()
1430 if (do_engine_start () == 0) {
1431 if (session && _session_is_new) {
1432 /* we need to retain initial visual
1433 settings for a new session
1435 session->save_state ("");
1443 ARDOUR_UI::update_clocks ()
1445 if (!editor || !editor->dragging_playhead()) {
1446 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1451 ARDOUR_UI::start_clocking ()
1453 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1457 ARDOUR_UI::stop_clocking ()
1459 clock_signal_connection.disconnect ();
1463 ARDOUR_UI::toggle_clocking ()
1466 if (clock_button.get_active()) {
1475 ARDOUR_UI::_blink (void *arg)
1478 ((ARDOUR_UI *) arg)->blink ();
1485 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1489 ARDOUR_UI::start_blinking ()
1491 /* Start the blink signal. Everybody with a blinking widget
1492 uses Blink to drive the widget's state.
1495 if (blink_timeout_tag < 0) {
1497 blink_timeout_tag = g_timeout_add (240, _blink, this);
1502 ARDOUR_UI::stop_blinking ()
1504 if (blink_timeout_tag >= 0) {
1505 g_source_remove (blink_timeout_tag);
1506 blink_timeout_tag = -1;
1511 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1517 if (io.n_inputs() == 0) {
1522 /* XXX we're not handling multiple ports yet. */
1524 const char **connections = io.input(0)->get_connections();
1526 if (connections == 0 || connections[0] == '\0') {
1529 buf = connections[0];
1536 if (io.n_outputs() == 0) {
1541 /* XXX we're not handling multiple ports yet. */
1543 const char **connections = io.output(0)->get_connections();
1545 if (connections == 0 || connections[0] == '\0') {
1548 buf = connections[0];
1556 ARDOUR_UI::snapshot_session ()
1558 ArdourPrompter prompter (true);
1562 struct tm local_time;
1565 localtime_r (&n, &local_time);
1566 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1568 prompter.set_name ("Prompter");
1569 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1570 prompter.set_prompt (_("Name of New Snapshot"));
1571 prompter.set_initial_text (timebuf);
1573 switch (prompter.run()) {
1574 case RESPONSE_ACCEPT:
1575 prompter.get_result (snapname);
1576 if (snapname.length()){
1577 save_state (snapname);
1587 ARDOUR_UI::save_state (const string & name)
1589 (void) save_state_canfail (name);
1593 ARDOUR_UI::save_state_canfail (string name)
1598 if (name.length() == 0) {
1599 name = session->snap_name();
1602 if ((ret = session->save_state (name)) != 0) {
1606 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1611 ARDOUR_UI::restore_state (string name)
1614 if (name.length() == 0) {
1615 name = session->name();
1617 session->restore_state (name);
1622 ARDOUR_UI::primary_clock_value_changed ()
1625 session->request_locate (primary_clock.current_time ());
1630 ARDOUR_UI::secondary_clock_value_changed ()
1633 session->request_locate (secondary_clock.current_time ());
1638 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1640 if (session && dstream && dstream->record_enabled()) {
1642 Session::RecordState rs;
1644 rs = session->record_status ();
1647 case Session::Disabled:
1648 case Session::Enabled:
1649 if (w->get_state() != STATE_SELECTED) {
1650 w->set_state (STATE_SELECTED);
1654 case Session::Recording:
1655 if (w->get_state() != STATE_ACTIVE) {
1656 w->set_state (STATE_ACTIVE);
1662 if (w->get_state() != STATE_NORMAL) {
1663 w->set_state (STATE_NORMAL);
1669 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1675 switch (session->record_status()) {
1676 case Session::Enabled:
1678 rec_button.set_visual_state (2);
1680 rec_button.set_visual_state (0);
1684 case Session::Recording:
1685 rec_button.set_visual_state (1);
1689 rec_button.set_visual_state (0);
1695 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1703 ARDOUR_UI::save_template ()
1706 ArdourPrompter prompter (true);
1709 prompter.set_name (X_("Prompter"));
1710 prompter.set_prompt (_("Name for mix template:"));
1711 prompter.set_initial_text(session->name() + _("-template"));
1712 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1714 switch (prompter.run()) {
1715 case RESPONSE_ACCEPT:
1716 prompter.get_result (name);
1718 if (name.length()) {
1719 session->save_template (name);
1729 ARDOUR_UI::new_session (std::string predetermined_path)
1731 string session_name;
1732 string session_path;
1734 if (!engine->connected()) {
1735 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1740 int response = Gtk::RESPONSE_NONE;
1742 new_session_dialog->set_modal(true);
1743 new_session_dialog->set_name (predetermined_path);
1744 new_session_dialog->reset_recent();
1745 new_session_dialog->show();
1748 response = new_session_dialog->run ();
1750 if (!engine->connected()) {
1751 new_session_dialog->hide ();
1752 MessageDialog msg (_("Ardour is no longer connected to JACK. Creating a new session is not possible."));
1757 _session_is_new = false;
1759 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1764 new_session_dialog->hide ();
1767 } else if (response == Gtk::RESPONSE_NONE) {
1769 /* Clear was pressed */
1770 new_session_dialog->reset();
1772 } else if (response == Gtk::RESPONSE_YES) {
1774 /* YES == OPEN, but there's no enum for that */
1776 session_name = new_session_dialog->session_name();
1778 if (session_name.empty()) {
1779 response = Gtk::RESPONSE_NONE;
1783 if (session_name[0] == '/' ||
1784 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1785 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1786 load_session (Glib::path_get_dirname (session_name), session_name);
1788 session_path = new_session_dialog->session_folder();
1789 load_session (session_path, session_name);
1792 } else if (response == Gtk::RESPONSE_OK) {
1794 session_name = new_session_dialog->session_name();
1796 if (new_session_dialog->get_current_page() == 1) {
1798 /* XXX this is a bit of a hack..
1799 i really want the new sesion dialog to return RESPONSE_YES
1800 if we're on page 1 (the load page)
1801 Unfortunately i can't see how atm..
1804 if (session_name.empty()) {
1805 response = Gtk::RESPONSE_NONE;
1809 if (session_name[0] == '/' ||
1810 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1811 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1812 load_session (Glib::path_get_dirname (session_name), session_name);
1814 session_path = new_session_dialog->session_folder();
1815 load_session (session_path, session_name);
1820 if (session_name.empty()) {
1821 response = Gtk::RESPONSE_NONE;
1825 if (session_name[0] == '/' ||
1826 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1827 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1829 session_path = Glib::path_get_dirname (session_name);
1830 session_name = Glib::path_get_basename (session_name);
1834 session_path = new_session_dialog->session_folder();
1838 //XXX This is needed because session constructor wants a
1839 //non-existant path. hopefully this will be fixed at some point.
1841 session_path = Glib::build_filename (session_path, session_name);
1843 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1845 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1847 MessageDialog msg (str,
1849 Gtk::MESSAGE_WARNING,
1850 Gtk::BUTTONS_YES_NO,
1854 msg.set_name (X_("CleanupDialog"));
1855 msg.set_wmclass (X_("existing_session"), "Ardour");
1856 msg.set_position (Gtk::WIN_POS_MOUSE);
1858 switch (msg.run()) {
1860 load_session (session_path, session_name);
1864 response = RESPONSE_NONE;
1865 new_session_dialog->reset ();
1870 _session_is_new = true;
1872 std::string template_name = new_session_dialog->session_template_name();
1874 if (new_session_dialog->use_session_template()) {
1876 load_session (session_path, session_name, &template_name);
1882 AutoConnectOption iconnect;
1883 AutoConnectOption oconnect;
1885 if (new_session_dialog->create_control_bus()) {
1886 cchns = (uint32_t) new_session_dialog->control_channel_count();
1891 if (new_session_dialog->create_master_bus()) {
1892 mchns = (uint32_t) new_session_dialog->master_channel_count();
1897 if (new_session_dialog->connect_inputs()) {
1898 iconnect = AutoConnectPhysical;
1900 iconnect = AutoConnectOption (0);
1903 /// @todo some minor tweaks.
1905 if (new_session_dialog->connect_outs_to_master()) {
1906 oconnect = AutoConnectMaster;
1907 } else if (new_session_dialog->connect_outs_to_physical()) {
1908 oconnect = AutoConnectPhysical;
1910 oconnect = AutoConnectOption (0);
1913 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1914 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1916 if (build_session (session_path,
1924 engine->frame_rate() * 60 * 5)) {
1926 response = Gtk::RESPONSE_NONE;
1927 new_session_dialog->reset ();
1934 } while (response == Gtk::RESPONSE_NONE);
1938 new_session_dialog->get_window()->set_cursor();
1939 new_session_dialog->hide();
1943 ARDOUR_UI::close_session()
1950 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1952 Session *new_session;
1954 session_loaded = false;
1956 x = unload_session ();
1964 /* if it already exists, we must have write access */
1966 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1967 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1968 "This prevents the session from being loaded."));
1974 new_session = new Session (*engine, path, snap_name, mix_template);
1979 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1983 connect_to_session (new_session);
1985 Config->set_current_owner (ConfigVariableBase::Interface);
1987 session_loaded = true;
1989 goto_editor_window ();
1992 session->set_clean ();
1999 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2000 uint32_t control_channels,
2001 uint32_t master_channels,
2002 AutoConnectOption input_connect,
2003 AutoConnectOption output_connect,
2006 nframes_t initial_length)
2008 Session *new_session;
2011 session_loaded = false;
2012 x = unload_session ();
2019 _session_is_new = true;
2022 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2023 control_channels, master_channels, nphysin, nphysout, initial_length);
2028 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2033 connect_to_session (new_session);
2035 session_loaded = true;
2043 editor->show_window ();
2054 ARDOUR_UI::show_splash ()
2057 about = new About();
2058 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2065 ARDOUR_UI::about_signal_response(int response)
2071 ARDOUR_UI::hide_splash ()
2074 about->get_window()->set_cursor ();
2080 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2084 removed = rep.paths.size();
2087 MessageDialog msgd (*editor,
2088 _("No audio files were ready for cleanup"),
2091 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2092 msgd.set_secondary_text (_("If this seems suprising, \n\
2093 check for any existing snapshots.\n\
2094 These may still include regions that\n\
2095 require some unused files to continue to exist."));
2101 ArdourDialog results (_("ardour: cleanup"), true, false);
2103 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2104 CleanupResultsModelColumns() {
2108 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2109 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2113 CleanupResultsModelColumns results_columns;
2114 Glib::RefPtr<Gtk::ListStore> results_model;
2115 Gtk::TreeView results_display;
2117 results_model = ListStore::create (results_columns);
2118 results_display.set_model (results_model);
2119 results_display.append_column (list_title, results_columns.visible_name);
2121 results_display.set_name ("CleanupResultsList");
2122 results_display.set_headers_visible (true);
2123 results_display.set_headers_clickable (false);
2124 results_display.set_reorderable (false);
2126 Gtk::ScrolledWindow list_scroller;
2129 Gtk::HBox dhbox; // the hbox for the image and text
2130 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2131 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2133 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2135 if (rep.space < 1048576.0f) {
2137 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2139 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2143 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2145 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2149 dhbox.pack_start (*dimage, true, false, 5);
2150 dhbox.pack_start (txt, true, false, 5);
2152 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2153 TreeModel::Row row = *(results_model->append());
2154 row[results_columns.visible_name] = *i;
2155 row[results_columns.fullpath] = *i;
2158 list_scroller.add (results_display);
2159 list_scroller.set_size_request (-1, 150);
2160 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2162 dvbox.pack_start (dhbox, true, false, 5);
2163 dvbox.pack_start (list_scroller, true, false, 5);
2164 ddhbox.pack_start (dvbox, true, false, 5);
2166 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2167 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2168 results.set_default_response (RESPONSE_CLOSE);
2169 results.set_position (Gtk::WIN_POS_MOUSE);
2170 results.show_all_children ();
2171 results.set_resizable (false);
2178 ARDOUR_UI::cleanup ()
2181 /* shouldn't happen: menu item is insensitive */
2186 MessageDialog checker (_("Are you sure you want to cleanup?"),
2188 Gtk::MESSAGE_QUESTION,
2189 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2191 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2192 ALL undo/redo information will be lost if you cleanup.\n\
2193 After cleanup, unused audio files will be moved to a \
2194 \"dead sounds\" location."));
2196 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2197 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2198 checker.set_default_response (RESPONSE_CANCEL);
2200 checker.set_name (_("CleanupDialog"));
2201 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2202 checker.set_position (Gtk::WIN_POS_MOUSE);
2204 switch (checker.run()) {
2205 case RESPONSE_ACCEPT:
2211 Session::cleanup_report rep;
2213 editor->prepare_for_cleanup ();
2215 /* do not allow flush until a session is reloaded */
2217 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2219 act->set_sensitive (false);
2222 if (session->cleanup_sources (rep)) {
2227 display_cleanup_results (rep,
2230 The following %1 %2 not in use and \n\
2231 have been moved to:\n\
2233 Flushing the wastebasket will \n\
2234 release an additional\n\
2235 %4 %5bytes of disk space.\n"
2243 ARDOUR_UI::flush_trash ()
2246 /* shouldn't happen: menu item is insensitive */
2250 Session::cleanup_report rep;
2252 if (session->cleanup_trash_sources (rep)) {
2256 display_cleanup_results (rep,
2258 _("The following %1 %2 deleted from\n\
2260 releasing %4 %5bytes of disk space"));
2264 ARDOUR_UI::add_route (Gtk::Window* float_window)
2272 if (add_route_dialog == 0) {
2273 add_route_dialog = new AddRouteDialog;
2275 add_route_dialog->set_transient_for (*float_window);
2279 if (add_route_dialog->is_visible()) {
2280 /* we're already doing this */
2284 ResponseType r = (ResponseType) add_route_dialog->run ();
2286 add_route_dialog->hide();
2289 case RESPONSE_ACCEPT:
2296 if ((count = add_route_dialog->count()) <= 0) {
2300 uint32_t input_chan = add_route_dialog->channels ();
2301 uint32_t output_chan;
2302 string name_template = add_route_dialog->name_template ();
2303 bool track = add_route_dialog->track ();
2305 AutoConnectOption oac = Config->get_output_auto_connect();
2307 if (oac & AutoConnectMaster) {
2308 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2310 output_chan = input_chan;
2313 /* XXX do something with name template */
2316 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2318 session_add_audio_bus (input_chan, output_chan, count);
2323 ARDOUR_UI::mixer_settings () const
2328 node = session->instant_xml(X_("Mixer"), session->path());
2330 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2334 node = new XMLNode (X_("Mixer"));
2341 ARDOUR_UI::editor_settings () const
2346 node = session->instant_xml(X_("Editor"), session->path());
2348 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2352 node = new XMLNode (X_("Editor"));
2358 ARDOUR_UI::keyboard_settings () const
2362 node = Config->extra_xml(X_("Keyboard"));
2365 node = new XMLNode (X_("Keyboard"));
2371 ARDOUR_UI::halt_on_xrun_message ()
2373 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2375 MessageDialog msg (*editor,
2376 _("Recording was stopped because your system could not keep up."));
2381 ARDOUR_UI::disk_overrun_handler ()
2383 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2385 if (!have_disk_speed_dialog_displayed) {
2386 have_disk_speed_dialog_displayed = true;
2387 MessageDialog* msg = new MessageDialog (*editor, X_("diskrate dialog"), _("\
2388 The disk system on your computer\n\
2389 was not able to keep up with Ardour.\n\
2391 Specifically, it failed to write data to disk\n\
2392 quickly enough to keep up with recording.\n"));
2393 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2399 ARDOUR_UI::disk_underrun_handler ()
2401 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2403 if (!have_disk_speed_dialog_displayed) {
2404 have_disk_speed_dialog_displayed = true;
2405 MessageDialog* msg = new MessageDialog (*editor,
2406 _("The disk system on your computer\n\
2407 was not able to keep up with Ardour.\n\
2409 Specifically, it failed to read data from disk\n\
2410 quickly enough to keep up with playback.\n"));
2411 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2417 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2419 have_disk_speed_dialog_displayed = false;
2424 ARDOUR_UI::pending_state_dialog ()
2426 ArdourDialog dialog ("pending state dialog");
2428 This session appears to have been in\n\
2429 middle of recording when ardour or\n\
2430 the computer was shutdown.\n\
2432 Ardour can recover any captured audio for\n\
2433 you, or it can ignore it. Please decide\n\
2434 what you would like to do.\n"));
2436 dialog.get_vbox()->pack_start (message);
2437 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2438 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2440 dialog.set_position (WIN_POS_CENTER);
2443 switch (dialog.run ()) {
2444 case RESPONSE_ACCEPT:
2452 ARDOUR_UI::disconnect_from_jack ()
2455 if( engine->disconnect_from_jack ()) {
2456 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2460 update_sample_rate (0);
2465 ARDOUR_UI::reconnect_to_jack ()
2468 if (engine->reconnect_to_jack ()) {
2469 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2473 update_sample_rate (0);
2478 ARDOUR_UI::cmdline_new_session (string path)
2480 if (path[0] != '/') {
2481 char buf[PATH_MAX+1];
2484 getcwd (buf, sizeof (buf));
2493 _will_create_new_session_automatically = false; /* done it */
2494 return FALSE; /* don't call it again */
2498 ARDOUR_UI::use_config ()
2500 Glib::RefPtr<Action> act;
2502 switch (Config->get_native_file_data_format ()) {
2504 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2507 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2512 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2513 ract->set_active ();
2516 switch (Config->get_native_file_header_format ()) {
2518 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2521 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2524 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2527 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2530 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2533 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2536 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2541 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2542 ract->set_active ();
2545 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2547 set_transport_controllable_state (*node);
2552 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2554 primary_clock.set (pos);
2555 secondary_clock.set (pos);
2557 if (big_clock_window) {
2558 big_clock.set (pos);
2563 ARDOUR_UI::record_state_changed ()
2565 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2567 if (!session || !big_clock_window) {
2568 /* why bother - the clock isn't visible */
2572 switch (session->record_status()) {
2573 case Session::Recording:
2574 big_clock.set_widget_name ("BigClockRecording");
2577 big_clock.set_widget_name ("BigClockNonRecording");
2583 ARDOUR_UI::set_keybindings_path (string path)
2585 keybindings_path = path;
2589 ARDOUR_UI::save_keybindings ()
2591 if (can_save_keybindings) {
2592 AccelMap::save (keybindings_path);
2597 ARDOUR_UI::first_idle ()
2599 can_save_keybindings = true;
2604 ARDOUR_UI::store_clock_modes ()
2606 XMLNode* node = new XMLNode(X_("ClockModes"));
2608 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2609 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2612 session->add_extra_xml (*node);
2613 session->set_dirty ();
2618 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2619 : Controllable (name), ui (u), type(tp)
2625 ARDOUR_UI::TransportControllable::set_value (float val)
2627 if (type == ShuttleControl) {
2634 fract = -((0.5f - val)/0.5f);
2636 fract = ((val - 0.5f)/0.5f);
2640 ui.set_shuttle_fract (fract);
2645 /* do nothing: these are radio-style actions */
2653 action = X_("Roll");
2656 action = X_("Stop");
2659 action = X_("Goto Start");
2662 action = X_("Goto End");
2665 action = X_("Loop");
2668 action = X_("Play Selection");
2671 action = X_("Record");
2681 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2689 ARDOUR_UI::TransportControllable::get_value (void) const
2708 case ShuttleControl:
2718 ARDOUR_UI::TransportControllable::set_id (const string& str)