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/session_route.h>
54 #include <ardour/port.h>
55 #include <ardour/audioengine.h>
56 #include <ardour/playlist.h>
57 #include <ardour/utils.h>
58 #include <ardour/audio_diskstream.h>
59 #include <ardour/audiofilesource.h>
60 #include <ardour/recent_sessions.h>
61 #include <ardour/port.h>
62 #include <ardour/audio_track.h>
65 #include "ardour_ui.h"
66 #include "public_editor.h"
67 #include "audio_clock.h"
72 #include "add_route_dialog.h"
73 #include "new_session_dialog.h"
76 #include "gui_thread.h"
77 #include "color_manager.h"
81 using namespace ARDOUR;
83 using namespace Gtkmm2ext;
87 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
89 sigc::signal<void,bool> ARDOUR_UI::Blink;
90 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
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 (X_("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 /* 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::startup ()
434 check_memory_locking();
438 ARDOUR_UI::no_memory_warning ()
440 XMLNode node (X_("no-memory-warning"));
441 Config->add_instant_xml (node, get_user_ardour_path());
445 ARDOUR_UI::check_memory_locking ()
448 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
452 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
454 if (engine->is_realtime() && memory_warning_node == 0) {
456 struct rlimit limits;
458 long pages, page_size;
460 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
463 ram = (int64_t) pages * (int64_t) page_size;
466 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
470 if (limits.rlim_cur != RLIM_INFINITY) {
472 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
475 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
476 "This might cause Ardour to run out of memory before your system "
477 "runs out of memory. \n\n"
478 "You can view the memory limit with 'ulimit -l', "
479 "and it is normally controlled by /etc/security/limits.conf"));
481 VBox* vbox = msg.get_vbox();
483 CheckButton cb (_("Do not show this window again"));
485 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
487 hbox.pack_start (cb, true, false);
488 vbox->pack_start (hbox);
491 editor->ensure_float (msg);
503 if (session && session->dirty()) {
504 switch (ask_about_saving_session(_("quit"))) {
509 /* use the default name */
510 if (save_state_canfail ("")) {
511 /* failed - don't quit */
512 MessageDialog msg (*editor,
514 Ardour was unable to save your session.\n\n\
515 If you still wish to quit, please use the\n\n\
516 \"Just quit\" option."));
527 session->set_deletion_in_progress ();
530 Config->save_state();
535 ARDOUR_UI::ask_about_saving_session (const string & what)
537 ArdourDialog window (_("ardour: save session?"));
538 Gtk::HBox dhbox; // the hbox for the image and text
539 Gtk::Label prompt_label;
540 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
544 msg = string_compose(_("Don't %1"), what);
545 window.add_button (msg, RESPONSE_REJECT);
546 msg = string_compose(_("Just %1"), what);
547 window.add_button (msg, RESPONSE_APPLY);
548 msg = string_compose(_("Save and %1"), what);
549 window.add_button (msg, RESPONSE_ACCEPT);
551 window.set_default_response (RESPONSE_ACCEPT);
553 Gtk::Button noquit_button (msg);
554 noquit_button.set_name ("EditorGTKButton");
559 if (session->snap_name() == session->name()) {
562 type = _("snapshot");
564 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?"),
565 type, session->snap_name());
567 prompt_label.set_text (prompt);
568 prompt_label.set_name (X_("PrompterLabel"));
569 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
571 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
573 dhbox.set_homogeneous (false);
574 dhbox.pack_start (*dimage, false, false, 5);
575 dhbox.pack_start (prompt_label, true, false, 5);
576 window.get_vbox()->pack_start (dhbox);
578 window.set_name (_("Prompter"));
579 window.set_position (Gtk::WIN_POS_MOUSE);
580 window.set_modal (true);
581 window.set_resizable (false);
584 save_the_session = 0;
586 window.set_keep_above (true);
589 ResponseType r = (ResponseType) window.run();
594 case RESPONSE_ACCEPT: // save and get out of here
596 case RESPONSE_APPLY: // get out of here
606 ARDOUR_UI::every_second ()
609 update_buffer_load ();
610 update_disk_space ();
615 ARDOUR_UI::every_point_one_seconds ()
617 update_speed_display ();
618 RapidScreenUpdate(); /* EMIT_SIGNAL */
623 ARDOUR_UI::every_point_zero_one_seconds ()
625 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
630 ARDOUR_UI::update_sample_rate (nframes_t ignored)
634 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
636 if (!engine->connected()) {
638 snprintf (buf, sizeof (buf), _("disconnected"));
642 nframes_t rate = engine->frame_rate();
644 if (fmod (rate, 1000.0) != 0.0) {
645 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"),
646 (float) rate/1000.0f,
647 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
649 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"),
651 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
655 sample_rate_label.set_text (buf);
659 ARDOUR_UI::update_cpu_load ()
662 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
663 cpu_load_label.set_text (buf);
667 ARDOUR_UI::update_buffer_load ()
672 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
673 session->playback_load(), session->capture_load());
674 buffer_load_label.set_text (buf);
676 buffer_load_label.set_text ("");
681 ARDOUR_UI::count_recenabled_streams (Route& route)
683 Track* track = dynamic_cast<Track*>(&route);
684 if (track && track->diskstream()->record_enabled()) {
685 rec_enabled_streams += track->n_inputs();
690 ARDOUR_UI::update_disk_space()
696 nframes_t frames = session->available_capture_duration();
699 if (frames == max_frames) {
700 strcpy (buf, _("Disk: 24hrs+"));
705 nframes_t fr = session->frame_rate();
707 rec_enabled_streams = 0;
708 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
710 if (rec_enabled_streams) {
711 frames /= rec_enabled_streams;
714 hrs = frames / (fr * 3600);
715 frames -= hrs * fr * 3600;
716 mins = frames / (fr * 60);
717 frames -= mins * fr * 60;
720 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
723 disk_space_label.set_text (buf);
727 ARDOUR_UI::update_wall_clock ()
734 tm_now = localtime (&now);
736 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
737 wall_clock_label.set_text (buf);
743 ARDOUR_UI::session_menu (GdkEventButton *ev)
745 session_popup_menu->popup (0, 0);
750 ARDOUR_UI::redisplay_recent_sessions ()
752 vector<string *> *sessions;
753 vector<string *>::iterator i;
754 RecentSessionsSorter cmp;
756 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
757 recent_session_model->clear ();
760 ARDOUR::read_recent_sessions (rs);
763 recent_session_display.set_model (recent_session_model);
767 /* sort them alphabetically */
768 sort (rs.begin(), rs.end(), cmp);
769 sessions = new vector<string*>;
771 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
772 sessions->push_back (new string ((*i).second));
775 for (i = sessions->begin(); i != sessions->end(); ++i) {
777 vector<string*>* states;
778 vector<const gchar*> item;
779 string fullpath = *(*i);
781 /* remove any trailing / */
783 if (fullpath[fullpath.length()-1] == '/') {
784 fullpath = fullpath.substr (0, fullpath.length()-1);
787 /* now get available states for this session */
789 if ((states = Session::possible_states (fullpath)) == 0) {
794 TreeModel::Row row = *(recent_session_model->append());
796 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
797 row[recent_session_columns.fullpath] = fullpath;
799 if (states->size() > 1) {
801 /* add the children */
803 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
805 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
807 child_row[recent_session_columns.visible_name] = **i2;
808 child_row[recent_session_columns.fullpath] = fullpath;
817 recent_session_display.set_model (recent_session_model);
822 ARDOUR_UI::build_session_selector ()
824 session_selector_window = new ArdourDialog ("session selector");
826 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
828 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
829 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
830 session_selector_window->set_default_response (RESPONSE_ACCEPT);
831 recent_session_model = TreeStore::create (recent_session_columns);
832 recent_session_display.set_model (recent_session_model);
833 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
834 recent_session_display.set_headers_visible (false);
835 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
837 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
839 scroller->add (recent_session_display);
840 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
842 session_selector_window->set_name ("SessionSelectorWindow");
843 session_selector_window->set_size_request (200, 400);
844 session_selector_window->get_vbox()->pack_start (*scroller);
845 session_selector_window->show_all_children();
849 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
851 session_selector_window->response (RESPONSE_ACCEPT);
855 ARDOUR_UI::open_recent_session ()
857 /* popup selector window */
859 if (session_selector_window == 0) {
860 build_session_selector ();
863 redisplay_recent_sessions ();
865 ResponseType r = (ResponseType) session_selector_window->run ();
867 session_selector_window->hide();
870 case RESPONSE_ACCEPT:
876 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
878 if (i == recent_session_model->children().end()) {
882 Glib::ustring path = (*i)[recent_session_columns.fullpath];
883 Glib::ustring state = (*i)[recent_session_columns.visible_name];
885 _session_is_new = false;
887 load_session (path, state);
891 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
895 if (stat (info.filename.c_str(), &statbuf) != 0) {
899 if (!S_ISDIR(statbuf.st_mode)) {
905 string session_file = info.filename;
907 session_file += Glib::path_get_basename (info.filename);
908 session_file += ".ardour";
910 if (stat (session_file.c_str(), &statbuf) != 0) {
914 return S_ISREG (statbuf.st_mode);
918 ARDOUR_UI::open_session ()
920 /* popup selector window */
922 if (open_session_selector == 0) {
924 /* ardour sessions are folders */
926 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
927 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
928 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
930 FileFilter session_filter;
931 session_filter.add_pattern ("*.ardour");
932 session_filter.set_name (_("Ardour sessions"));
933 open_session_selector->add_filter (session_filter);
934 open_session_selector->set_filter (session_filter);
937 int response = open_session_selector->run();
938 open_session_selector->hide ();
941 case RESPONSE_ACCEPT:
944 open_session_selector->hide();
948 open_session_selector->hide();
949 string session_path = open_session_selector->get_filename();
953 if (session_path.length() > 0) {
954 if (Session::find_session (session_path, path, name, isnew) == 0) {
955 _session_is_new = isnew;
956 load_session (path, name);
963 ARDOUR_UI::session_add_midi_track ()
965 cerr << _("Patience is a virtue.\n");
969 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
971 list<boost::shared_ptr<AudioTrack> > tracks;
972 Session::RouteList routes;
975 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
981 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
983 if (tracks.size() != how_many) {
985 error << _("could not create a new audio track") << endmsg;
987 error << string_compose (_("could only create %1 of %2 new audio %3"),
988 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
994 routes = session->new_audio_route (input_channels, output_channels, how_many);
996 if (routes.size() != how_many) {
998 error << _("could not create a new audio track") << endmsg;
1000 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1006 if (need_control_room_outs) {
1012 route->set_stereo_control_outs (control_lr_channels);
1013 route->control_outs()->set_stereo_pan (pans, this);
1015 #endif /* CONTROLOUTS */
1019 cerr << "About to complain about JACK\n";
1020 MessageDialog msg (*editor,
1021 _("There are insufficient JACK ports available\n\
1022 to create a new track or bus.\n\
1023 You should save Ardour, exit and\n\
1024 restart JACK with more ports."));
1030 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1032 nframes_t _preroll = 0;
1035 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1036 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1038 if (new_position > _preroll) {
1039 new_position -= _preroll;
1044 session->request_locate (new_position);
1049 ARDOUR_UI::transport_goto_start ()
1052 session->goto_start();
1055 /* force displayed area in editor to start no matter
1056 what "follow playhead" setting is.
1060 editor->reset_x_origin (session->current_start_frame());
1066 ARDOUR_UI::transport_goto_zero ()
1069 session->request_locate (0);
1072 /* force displayed area in editor to start no matter
1073 what "follow playhead" setting is.
1077 editor->reset_x_origin (0);
1083 ARDOUR_UI::transport_goto_end ()
1086 nframes_t frame = session->current_end_frame();
1087 session->request_locate (frame);
1089 /* force displayed area in editor to start no matter
1090 what "follow playhead" setting is.
1094 editor->reset_x_origin (frame);
1100 ARDOUR_UI::transport_stop ()
1106 if (session->is_auditioning()) {
1107 session->cancel_audition ();
1111 if (session->get_play_loop ()) {
1112 session->request_play_loop (false);
1115 session->request_stop ();
1119 ARDOUR_UI::transport_stop_and_forget_capture ()
1122 session->request_stop (true);
1127 ARDOUR_UI::remove_last_capture()
1130 editor->remove_last_capture();
1135 ARDOUR_UI::transport_record ()
1138 switch (session->record_status()) {
1139 case Session::Disabled:
1140 if (session->ntracks() == 0) {
1141 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1145 session->maybe_enable_record ();
1147 case Session::Recording:
1148 case Session::Enabled:
1149 session->disable_record (true);
1155 ARDOUR_UI::transport_roll ()
1163 rolling = session->transport_rolling ();
1165 if (session->get_play_loop()) {
1166 session->request_play_loop (false);
1167 auto_loop_button.set_visual_state (1);
1168 roll_button.set_visual_state (1);
1169 } else if (session->get_play_range ()) {
1170 session->request_play_range (false);
1171 play_selection_button.set_visual_state (0);
1172 } else if (rolling) {
1173 session->request_locate (session->last_transport_start(), true);
1176 session->request_transport_speed (1.0f);
1180 ARDOUR_UI::transport_loop()
1183 if (session->get_play_loop()) {
1184 if (session->transport_rolling()) {
1185 Location * looploc = session->locations()->auto_loop_location();
1187 session->request_locate (looploc->start(), true);
1192 session->request_play_loop (true);
1198 ARDOUR_UI::transport_play_selection ()
1204 if (!session->get_play_range()) {
1205 session->request_stop ();
1208 editor->play_selection ();
1212 ARDOUR_UI::transport_rewind (int option)
1214 float current_transport_speed;
1217 current_transport_speed = session->transport_speed();
1219 if (current_transport_speed >= 0.0f) {
1222 session->request_transport_speed (-1.0f);
1225 session->request_transport_speed (-4.0f);
1228 session->request_transport_speed (-0.5f);
1233 session->request_transport_speed (current_transport_speed * 1.5f);
1239 ARDOUR_UI::transport_forward (int option)
1241 float current_transport_speed;
1244 current_transport_speed = session->transport_speed();
1246 if (current_transport_speed <= 0.0f) {
1249 session->request_transport_speed (1.0f);
1252 session->request_transport_speed (4.0f);
1255 session->request_transport_speed (0.5f);
1260 session->request_transport_speed (current_transport_speed * 1.5f);
1266 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1272 boost::shared_ptr<Route> r;
1274 if ((r = session->route_by_remote_id (dstream)) != 0) {
1278 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1279 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1288 ARDOUR_UI::queue_transport_change ()
1290 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1294 ARDOUR_UI::map_transport_state ()
1296 float sp = session->transport_speed();
1299 transport_rolling ();
1300 } else if (sp < 0.0f) {
1301 transport_rewinding ();
1302 } else if (sp > 0.0f) {
1303 transport_forwarding ();
1305 transport_stopped ();
1310 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1312 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1313 (int) adj.get_value()].c_str());
1317 ARDOUR_UI::engine_stopped ()
1319 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1320 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1321 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1325 ARDOUR_UI::engine_running ()
1327 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1328 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1329 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1331 Glib::RefPtr<Action> action;
1332 char* action_name = 0;
1334 switch (engine->frames_per_cycle()) {
1336 action_name = X_("JACKLatency32");
1339 action_name = X_("JACKLatency64");
1342 action_name = X_("JACKLatency128");
1345 action_name = X_("JACKLatency512");
1348 action_name = X_("JACKLatency1024");
1351 action_name = X_("JACKLatency2048");
1354 action_name = X_("JACKLatency4096");
1357 action_name = X_("JACKLatency8192");
1360 /* XXX can we do anything useful ? */
1366 action = ActionManager::get_action (X_("JACK"), action_name);
1369 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1370 ract->set_active ();
1376 ARDOUR_UI::engine_halted ()
1378 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1380 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1381 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1383 update_sample_rate (0);
1385 MessageDialog msg (*editor,
1387 JACK has either been shutdown or it\n\
1388 disconnected Ardour because Ardour\n\
1389 was not fast enough. You can save the\n\
1390 session and/or try to reconnect to JACK ."));
1395 ARDOUR_UI::do_engine_start ()
1403 error << _("Unable to start the session running")
1413 ARDOUR_UI::start_engine ()
1415 if (do_engine_start () == 0) {
1416 if (session && _session_is_new) {
1417 /* we need to retain initial visual
1418 settings for a new session
1420 session->save_state ("");
1428 ARDOUR_UI::update_clocks ()
1430 if (!editor || !editor->dragging_playhead()) {
1431 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1436 ARDOUR_UI::start_clocking ()
1438 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1442 ARDOUR_UI::stop_clocking ()
1444 clock_signal_connection.disconnect ();
1448 ARDOUR_UI::toggle_clocking ()
1451 if (clock_button.get_active()) {
1460 ARDOUR_UI::_blink (void *arg)
1463 ((ARDOUR_UI *) arg)->blink ();
1470 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1474 ARDOUR_UI::start_blinking ()
1476 /* Start the blink signal. Everybody with a blinking widget
1477 uses Blink to drive the widget's state.
1480 if (blink_timeout_tag < 0) {
1482 blink_timeout_tag = g_timeout_add (240, _blink, this);
1487 ARDOUR_UI::stop_blinking ()
1489 if (blink_timeout_tag >= 0) {
1490 g_source_remove (blink_timeout_tag);
1491 blink_timeout_tag = -1;
1496 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1502 if (io.n_inputs() == 0) {
1507 /* XXX we're not handling multiple ports yet. */
1509 const char **connections = io.input(0)->get_connections();
1511 if (connections == 0 || connections[0] == '\0') {
1514 buf = connections[0];
1521 if (io.n_outputs() == 0) {
1526 /* XXX we're not handling multiple ports yet. */
1528 const char **connections = io.output(0)->get_connections();
1530 if (connections == 0 || connections[0] == '\0') {
1533 buf = connections[0];
1541 ARDOUR_UI::snapshot_session ()
1543 ArdourPrompter prompter (true);
1547 struct tm local_time;
1550 localtime_r (&n, &local_time);
1551 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1553 prompter.set_name ("Prompter");
1554 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1555 prompter.set_prompt (_("Name of New Snapshot"));
1556 prompter.set_initial_text (timebuf);
1558 switch (prompter.run()) {
1559 case RESPONSE_ACCEPT:
1560 prompter.get_result (snapname);
1561 if (snapname.length()){
1562 save_state (snapname);
1572 ARDOUR_UI::save_state (const string & name)
1574 (void) save_state_canfail (name);
1578 ARDOUR_UI::save_state_canfail (string name)
1583 if (name.length() == 0) {
1584 name = session->snap_name();
1587 if ((ret = session->save_state (name)) != 0) {
1591 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1596 ARDOUR_UI::restore_state (string name)
1599 if (name.length() == 0) {
1600 name = session->name();
1602 session->restore_state (name);
1607 ARDOUR_UI::primary_clock_value_changed ()
1610 session->request_locate (primary_clock.current_time ());
1615 ARDOUR_UI::secondary_clock_value_changed ()
1618 session->request_locate (secondary_clock.current_time ());
1623 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1625 if (session && dstream && dstream->record_enabled()) {
1627 Session::RecordState rs;
1629 rs = session->record_status ();
1632 case Session::Disabled:
1633 case Session::Enabled:
1634 if (w->get_state() != STATE_SELECTED) {
1635 w->set_state (STATE_SELECTED);
1639 case Session::Recording:
1640 if (w->get_state() != STATE_ACTIVE) {
1641 w->set_state (STATE_ACTIVE);
1647 if (w->get_state() != STATE_NORMAL) {
1648 w->set_state (STATE_NORMAL);
1654 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1660 switch (session->record_status()) {
1661 case Session::Enabled:
1663 rec_button.set_visual_state (2);
1665 rec_button.set_visual_state (0);
1669 case Session::Recording:
1670 rec_button.set_visual_state (1);
1674 rec_button.set_visual_state (0);
1680 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1688 ARDOUR_UI::save_template ()
1691 ArdourPrompter prompter (true);
1694 prompter.set_name (X_("Prompter"));
1695 prompter.set_prompt (_("Name for mix template:"));
1696 prompter.set_initial_text(session->name() + _("-template"));
1697 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1699 switch (prompter.run()) {
1700 case RESPONSE_ACCEPT:
1701 prompter.get_result (name);
1703 if (name.length()) {
1704 session->save_template (name);
1714 ARDOUR_UI::new_session (std::string predetermined_path)
1716 string session_name;
1717 string session_path;
1719 if (!engine->connected()) {
1720 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1725 int response = Gtk::RESPONSE_NONE;
1727 new_session_dialog->set_modal(true);
1728 new_session_dialog->set_name (predetermined_path);
1729 new_session_dialog->reset_recent();
1730 new_session_dialog->show();
1733 response = new_session_dialog->run ();
1735 if (!engine->connected()) {
1736 new_session_dialog->hide ();
1737 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1742 _session_is_new = false;
1744 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1749 new_session_dialog->hide ();
1752 } else if (response == Gtk::RESPONSE_NONE) {
1754 /* Clear was pressed */
1755 new_session_dialog->reset();
1757 } else if (response == Gtk::RESPONSE_YES) {
1759 /* YES == OPEN, but there's no enum for that */
1761 session_name = new_session_dialog->session_name();
1763 if (session_name.empty()) {
1764 response = Gtk::RESPONSE_NONE;
1768 if (session_name[0] == '/' ||
1769 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1770 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1771 load_session (Glib::path_get_dirname (session_name), session_name);
1773 session_path = new_session_dialog->session_folder();
1774 load_session (session_path, session_name);
1777 } else if (response == Gtk::RESPONSE_OK) {
1779 session_name = new_session_dialog->session_name();
1781 if (new_session_dialog->get_current_page() == 1) {
1783 /* XXX this is a bit of a hack..
1784 i really want the new sesion dialog to return RESPONSE_YES
1785 if we're on page 1 (the load page)
1786 Unfortunately i can't see how atm..
1789 if (session_name.empty()) {
1790 response = Gtk::RESPONSE_NONE;
1794 if (session_name[0] == '/' ||
1795 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1796 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1797 load_session (Glib::path_get_dirname (session_name), session_name);
1799 session_path = new_session_dialog->session_folder();
1800 load_session (session_path, session_name);
1805 if (session_name.empty()) {
1806 response = Gtk::RESPONSE_NONE;
1810 if (session_name[0] == '/' ||
1811 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1812 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1814 session_path = Glib::path_get_dirname (session_name);
1815 session_name = Glib::path_get_basename (session_name);
1819 session_path = new_session_dialog->session_folder();
1823 //XXX This is needed because session constructor wants a
1824 //non-existant path. hopefully this will be fixed at some point.
1826 session_path = Glib::build_filename (session_path, session_name);
1828 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1830 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1832 MessageDialog msg (str,
1834 Gtk::MESSAGE_WARNING,
1835 Gtk::BUTTONS_YES_NO,
1839 msg.set_name (X_("CleanupDialog"));
1840 msg.set_wmclass (X_("existing_session"), "Ardour");
1841 msg.set_position (Gtk::WIN_POS_MOUSE);
1843 switch (msg.run()) {
1845 load_session (session_path, session_name);
1849 response = RESPONSE_NONE;
1850 new_session_dialog->reset ();
1855 _session_is_new = true;
1857 std::string template_name = new_session_dialog->session_template_name();
1859 if (new_session_dialog->use_session_template()) {
1861 load_session (session_path, session_name, &template_name);
1867 AutoConnectOption iconnect;
1868 AutoConnectOption oconnect;
1870 if (new_session_dialog->create_control_bus()) {
1871 cchns = (uint32_t) new_session_dialog->control_channel_count();
1876 if (new_session_dialog->create_master_bus()) {
1877 mchns = (uint32_t) new_session_dialog->master_channel_count();
1882 if (new_session_dialog->connect_inputs()) {
1883 iconnect = AutoConnectPhysical;
1885 iconnect = AutoConnectOption (0);
1888 /// @todo some minor tweaks.
1890 if (new_session_dialog->connect_outs_to_master()) {
1891 oconnect = AutoConnectMaster;
1892 } else if (new_session_dialog->connect_outs_to_physical()) {
1893 oconnect = AutoConnectPhysical;
1895 oconnect = AutoConnectOption (0);
1898 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1899 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1901 if (build_session (session_path,
1909 engine->frame_rate() * 60 * 5)) {
1911 response = Gtk::RESPONSE_NONE;
1912 new_session_dialog->reset ();
1919 } while (response == Gtk::RESPONSE_NONE);
1923 new_session_dialog->get_window()->set_cursor();
1924 new_session_dialog->hide();
1929 ARDOUR_UI::close_session()
1936 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1938 Session *new_session;
1940 session_loaded = false;
1942 x = unload_session ();
1950 /* if it already exists, we must have write access */
1952 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1953 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1954 "This prevents the session from being loaded."));
1960 new_session = new Session (*engine, path, snap_name, mix_template);
1965 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1969 connect_to_session (new_session);
1971 Config->set_current_owner (ConfigVariableBase::Interface);
1973 session_loaded = true;
1975 goto_editor_window ();
1978 session->set_clean ();
1981 editor->edit_cursor_position (true);
1986 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1987 uint32_t control_channels,
1988 uint32_t master_channels,
1989 AutoConnectOption input_connect,
1990 AutoConnectOption output_connect,
1993 nframes_t initial_length)
1995 Session *new_session;
1998 session_loaded = false;
1999 x = unload_session ();
2006 _session_is_new = true;
2009 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2010 control_channels, master_channels, nphysin, nphysout, initial_length);
2015 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2020 connect_to_session (new_session);
2022 session_loaded = true;
2030 editor->show_window ();
2041 ARDOUR_UI::show_splash ()
2044 about = new About();
2045 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2052 ARDOUR_UI::about_signal_response(int response)
2058 ARDOUR_UI::hide_splash ()
2061 about->get_window()->set_cursor ();
2067 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2071 removed = rep.paths.size();
2074 MessageDialog msgd (*editor,
2075 _("No audio files were ready for cleanup"),
2078 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2079 msgd.set_secondary_text (_("If this seems suprising, \n\
2080 check for any existing snapshots.\n\
2081 These may still include regions that\n\
2082 require some unused files to continue to exist."));
2088 ArdourDialog results (_("ardour: cleanup"), true, false);
2090 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2091 CleanupResultsModelColumns() {
2095 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2096 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2100 CleanupResultsModelColumns results_columns;
2101 Glib::RefPtr<Gtk::ListStore> results_model;
2102 Gtk::TreeView results_display;
2104 results_model = ListStore::create (results_columns);
2105 results_display.set_model (results_model);
2106 results_display.append_column (list_title, results_columns.visible_name);
2108 results_display.set_name ("CleanupResultsList");
2109 results_display.set_headers_visible (true);
2110 results_display.set_headers_clickable (false);
2111 results_display.set_reorderable (false);
2113 Gtk::ScrolledWindow list_scroller;
2116 Gtk::HBox dhbox; // the hbox for the image and text
2117 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2118 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2120 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2122 if (rep.space < 1048576.0f) {
2124 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2126 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2130 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2132 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2136 dhbox.pack_start (*dimage, true, false, 5);
2137 dhbox.pack_start (txt, true, false, 5);
2139 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2140 TreeModel::Row row = *(results_model->append());
2141 row[results_columns.visible_name] = *i;
2142 row[results_columns.fullpath] = *i;
2145 list_scroller.add (results_display);
2146 list_scroller.set_size_request (-1, 150);
2147 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2149 dvbox.pack_start (dhbox, true, false, 5);
2150 dvbox.pack_start (list_scroller, true, false, 5);
2151 ddhbox.pack_start (dvbox, true, false, 5);
2153 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2154 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2155 results.set_default_response (RESPONSE_CLOSE);
2156 results.set_position (Gtk::WIN_POS_MOUSE);
2157 results.show_all_children ();
2158 results.set_resizable (false);
2165 ARDOUR_UI::cleanup ()
2168 /* shouldn't happen: menu item is insensitive */
2173 MessageDialog checker (_("Are you sure you want to cleanup?"),
2175 Gtk::MESSAGE_QUESTION,
2176 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2178 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2179 ALL undo/redo information will be lost if you cleanup.\n\
2180 After cleanup, unused audio files will be moved to a \
2181 \"dead sounds\" location."));
2183 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2184 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2185 checker.set_default_response (RESPONSE_CANCEL);
2187 checker.set_name (_("CleanupDialog"));
2188 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2189 checker.set_position (Gtk::WIN_POS_MOUSE);
2191 switch (checker.run()) {
2192 case RESPONSE_ACCEPT:
2198 Session::cleanup_report rep;
2200 editor->prepare_for_cleanup ();
2202 /* do not allow flush until a session is reloaded */
2204 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2206 act->set_sensitive (false);
2209 if (session->cleanup_sources (rep)) {
2214 display_cleanup_results (rep,
2217 The following %1 %2 not in use and \n\
2218 have been moved to:\n\
2220 Flushing the wastebasket will \n\
2221 release an additional\n\
2222 %4 %5bytes of disk space.\n"
2230 ARDOUR_UI::flush_trash ()
2233 /* shouldn't happen: menu item is insensitive */
2237 Session::cleanup_report rep;
2239 if (session->cleanup_trash_sources (rep)) {
2243 display_cleanup_results (rep,
2245 _("The following %1 %2 deleted from\n\
2247 releasing %4 %5bytes of disk space"));
2251 ARDOUR_UI::add_route (Gtk::Window* float_window)
2259 if (add_route_dialog == 0) {
2260 add_route_dialog = new AddRouteDialog;
2262 add_route_dialog->set_transient_for (*float_window);
2266 if (add_route_dialog->is_visible()) {
2267 /* we're already doing this */
2271 ResponseType r = (ResponseType) add_route_dialog->run ();
2273 add_route_dialog->hide();
2276 case RESPONSE_ACCEPT:
2283 if ((count = add_route_dialog->count()) <= 0) {
2287 uint32_t input_chan = add_route_dialog->channels ();
2288 uint32_t output_chan;
2289 string name_template = add_route_dialog->name_template ();
2290 bool track = add_route_dialog->track ();
2292 AutoConnectOption oac = Config->get_output_auto_connect();
2294 if (oac & AutoConnectMaster) {
2295 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2297 output_chan = input_chan;
2300 /* XXX do something with name template */
2303 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2305 session_add_audio_bus (input_chan, output_chan, count);
2310 ARDOUR_UI::mixer_settings () const
2315 node = session->instant_xml(X_("Mixer"), session->path());
2317 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2321 node = new XMLNode (X_("Mixer"));
2328 ARDOUR_UI::editor_settings () const
2333 node = session->instant_xml(X_("Editor"), session->path());
2335 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2339 node = new XMLNode (X_("Editor"));
2345 ARDOUR_UI::keyboard_settings () const
2349 node = Config->extra_xml(X_("Keyboard"));
2352 node = new XMLNode (X_("Keyboard"));
2358 ARDOUR_UI::halt_on_xrun_message ()
2360 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2362 MessageDialog msg (*editor,
2363 _("Recording was stopped because your system could not keep up."));
2368 ARDOUR_UI::disk_overrun_handler ()
2370 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2372 if (!have_disk_speed_dialog_displayed) {
2373 have_disk_speed_dialog_displayed = true;
2374 MessageDialog* msg = new MessageDialog (*editor, _("\
2375 The disk system on your computer\n\
2376 was not able to keep up with Ardour.\n\
2378 Specifically, it failed to write data to disk\n\
2379 quickly enough to keep up with recording.\n"));
2380 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2386 ARDOUR_UI::disk_underrun_handler ()
2388 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2390 if (!have_disk_speed_dialog_displayed) {
2391 have_disk_speed_dialog_displayed = true;
2392 MessageDialog* msg = new MessageDialog (*editor,
2393 _("The disk system on your computer\n\
2394 was not able to keep up with Ardour.\n\
2396 Specifically, it failed to read data from disk\n\
2397 quickly enough to keep up with playback.\n"));
2398 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2404 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2406 have_disk_speed_dialog_displayed = false;
2411 ARDOUR_UI::pending_state_dialog ()
2413 ArdourDialog dialog ("pending state dialog");
2415 This session appears to have been in\n\
2416 middle of recording when ardour or\n\
2417 the computer was shutdown.\n\
2419 Ardour can recover any captured audio for\n\
2420 you, or it can ignore it. Please decide\n\
2421 what you would like to do.\n"));
2423 dialog.get_vbox()->pack_start (message);
2424 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2425 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2427 dialog.set_position (WIN_POS_CENTER);
2430 switch (dialog.run ()) {
2431 case RESPONSE_ACCEPT:
2439 ARDOUR_UI::disconnect_from_jack ()
2442 if( engine->disconnect_from_jack ()) {
2443 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2447 update_sample_rate (0);
2452 ARDOUR_UI::reconnect_to_jack ()
2455 if (engine->reconnect_to_jack ()) {
2456 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2460 update_sample_rate (0);
2465 ARDOUR_UI::cmdline_new_session (string path)
2467 if (path[0] != '/') {
2468 char buf[PATH_MAX+1];
2471 getcwd (buf, sizeof (buf));
2480 _will_create_new_session_automatically = false; /* done it */
2481 return FALSE; /* don't call it again */
2485 ARDOUR_UI::use_config ()
2487 Glib::RefPtr<Action> act;
2489 switch (Config->get_native_file_data_format ()) {
2491 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2494 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2499 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2500 ract->set_active ();
2503 switch (Config->get_native_file_header_format ()) {
2505 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2508 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2511 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2514 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2517 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2520 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2523 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2528 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2529 ract->set_active ();
2532 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2534 set_transport_controllable_state (*node);
2539 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2541 primary_clock.set (pos);
2542 secondary_clock.set (pos);
2544 if (big_clock_window) {
2545 big_clock.set (pos);
2550 ARDOUR_UI::record_state_changed ()
2552 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2554 if (!session || !big_clock_window) {
2555 /* why bother - the clock isn't visible */
2559 switch (session->record_status()) {
2560 case Session::Recording:
2561 big_clock.set_widget_name ("BigClockRecording");
2564 big_clock.set_widget_name ("BigClockNonRecording");
2570 ARDOUR_UI::set_keybindings_path (string path)
2572 keybindings_path = path;
2576 ARDOUR_UI::save_keybindings ()
2578 if (can_save_keybindings) {
2579 AccelMap::save (keybindings_path);
2584 ARDOUR_UI::first_idle ()
2587 session->allow_auto_play (true);
2589 can_save_keybindings = true;
2594 ARDOUR_UI::store_clock_modes ()
2596 XMLNode* node = new XMLNode(X_("ClockModes"));
2598 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2599 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2602 session->add_extra_xml (*node);
2603 session->set_dirty ();
2608 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2609 : Controllable (name), ui (u), type(tp)
2615 ARDOUR_UI::TransportControllable::set_value (float val)
2617 if (type == ShuttleControl) {
2624 fract = -((0.5f - val)/0.5f);
2626 fract = ((val - 0.5f)/0.5f);
2630 ui.set_shuttle_fract (fract);
2635 /* do nothing: these are radio-style actions */
2643 action = X_("Roll");
2646 action = X_("Stop");
2649 action = X_("Goto Start");
2652 action = X_("Goto End");
2655 action = X_("Loop");
2658 action = X_("Play Selection");
2661 action = X_("Record");
2671 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2679 ARDOUR_UI::TransportControllable::get_value (void) const
2698 case ShuttleControl:
2708 ARDOUR_UI::TransportControllable::set_id (const string& str)