2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/compose.h>
37 #include <pbd/pathscanner.h>
38 #include <pbd/failed_constructor.h>
39 #include <pbd/enumwriter.h>
40 #include <pbd/stacktrace.h>
41 #include <gtkmm2ext/gtk_ui.h>
42 #include <gtkmm2ext/utils.h>
43 #include <gtkmm2ext/click_box.h>
44 #include <gtkmm2ext/fastmeter.h>
45 #include <gtkmm2ext/stop_signal.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/window_title.h>
49 #include <midi++/port.h>
50 #include <midi++/mmc.h>
52 #include <ardour/ardour.h>
53 #include <ardour/profile.h>
54 #include <ardour/session_route.h>
55 #include <ardour/port.h>
56 #include <ardour/audioengine.h>
57 #include <ardour/playlist.h>
58 #include <ardour/utils.h>
59 #include <ardour/audio_diskstream.h>
60 #include <ardour/audiofilesource.h>
61 #include <ardour/recent_sessions.h>
62 #include <ardour/port.h>
63 #include <ardour/audio_track.h>
66 #include "ardour_ui.h"
67 #include "public_editor.h"
68 #include "audio_clock.h"
73 #include "add_route_dialog.h"
74 #include "new_session_dialog.h"
77 #include "gui_thread.h"
78 #include "color_manager.h"
82 using namespace ARDOUR;
84 using namespace Gtkmm2ext;
88 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
90 sigc::signal<void,bool> ARDOUR_UI::Blink;
91 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
92 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
93 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
95 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
97 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp, rcfile),
99 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
100 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
101 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
102 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
106 adjuster_table (3, 3),
110 preroll_button (_("pre\nroll")),
111 postroll_button (_("post\nroll")),
115 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
119 roll_controllable ("transport roll", *this, TransportControllable::Roll),
120 stop_controllable ("transport stop", *this, TransportControllable::Stop),
121 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
122 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
123 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
124 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
125 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
126 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
127 shuttle_controller_binding_proxy (shuttle_controllable),
129 roll_button (roll_controllable),
130 stop_button (stop_controllable),
131 goto_start_button (goto_start_controllable),
132 goto_end_button (goto_end_controllable),
133 auto_loop_button (auto_loop_controllable),
134 play_selection_button (play_selection_controllable),
135 rec_button (rec_controllable),
137 shuttle_units_button (_("% ")),
139 punch_in_button (_("Punch In")),
140 punch_out_button (_("Punch Out")),
141 auto_return_button (_("Auto Return")),
142 auto_play_button (_("Auto Play")),
143 auto_input_button (_("Auto Input")),
144 click_button (_("Click")),
145 time_master_button (_("time\nmaster")),
147 auditioning_alert_button (_("AUDITION")),
148 solo_alert_button (_("SOLO")),
151 using namespace Gtk::Menu_Helpers;
157 if (theArdourUI == 0) {
163 color_manager = new ColorManager();
165 std::string color_file = ARDOUR::find_config_file("ardour.colors");
167 color_manager->load (color_file);
172 _session_is_new = false;
173 big_clock_window = 0;
174 session_selector_window = 0;
175 last_key_press_time = 0;
176 connection_editor = 0;
177 add_route_dialog = 0;
181 open_session_selector = 0;
182 have_configure_timeout = false;
183 have_disk_speed_dialog_displayed = false;
184 _will_create_new_session_automatically = false;
185 session_loaded = false;
186 last_speed_displayed = -1.0f;
187 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
189 can_save_keybindings = false;
190 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle));
192 last_configure_time.tv_sec = 0;
193 last_configure_time.tv_usec = 0;
195 shuttle_grabbed = false;
197 shuttle_max_speed = 8.0f;
199 shuttle_style_menu = 0;
200 shuttle_unit_menu = 0;
202 gettimeofday (&last_peak_grab, 0);
203 gettimeofday (&last_shuttle_request, 0);
205 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
206 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
208 /* handle pending state with a dialog */
210 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
212 /* have to wait for AudioEngine and Configuration before proceeding */
216 ARDOUR_UI::set_engine (AudioEngine& e)
220 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
221 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
222 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
223 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
225 ActionManager::init ();
226 new_session_dialog = new NewSessionDialog();
230 keyboard = new Keyboard;
232 if (setup_windows ()) {
233 throw failed_constructor ();
236 if (GTK_ARDOUR::show_key_actions) {
237 vector<string> names;
238 vector<string> paths;
240 vector<AccelKey> bindings;
242 ActionManager::get_all_actions (names, paths, keys, bindings);
244 vector<string>::iterator n;
245 vector<string>::iterator k;
246 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
247 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
253 /* start with timecode, metering enabled
256 blink_timeout_tag = -1;
258 /* the global configuration object is now valid */
262 /* this being a GUI and all, we want peakfiles */
264 AudioFileSource::set_build_peakfiles (true);
265 AudioFileSource::set_build_missing_peakfiles (true);
267 /* set default clock modes */
269 primary_clock.set_mode (AudioClock::SMPTE);
270 secondary_clock.set_mode (AudioClock::BBT);
272 /* start the time-of-day-clock */
274 update_wall_clock ();
275 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
277 update_disk_space ();
279 update_sample_rate (engine->frame_rate());
281 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
282 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
285 ARDOUR_UI::~ARDOUR_UI ()
287 save_ardour_state ();
301 if (add_route_dialog) {
302 delete add_route_dialog;
307 ARDOUR_UI::configure_timeout ()
312 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
313 /* no configure events yet */
317 gettimeofday (&now, 0);
318 timersub (&now, &last_configure_time, &diff);
320 /* force a gap of 0.5 seconds since the last configure event
323 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
326 have_configure_timeout = false;
327 save_ardour_state ();
333 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
335 if (have_configure_timeout) {
336 gettimeofday (&last_configure_time, 0);
338 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
339 have_configure_timeout = true;
346 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
348 const XMLProperty* prop;
350 if ((prop = node.property ("roll")) != 0) {
351 roll_controllable.set_id (prop->value());
353 if ((prop = node.property ("stop")) != 0) {
354 stop_controllable.set_id (prop->value());
356 if ((prop = node.property ("goto_start")) != 0) {
357 goto_start_controllable.set_id (prop->value());
359 if ((prop = node.property ("goto_end")) != 0) {
360 goto_end_controllable.set_id (prop->value());
362 if ((prop = node.property ("auto_loop")) != 0) {
363 auto_loop_controllable.set_id (prop->value());
365 if ((prop = node.property ("play_selection")) != 0) {
366 play_selection_controllable.set_id (prop->value());
368 if ((prop = node.property ("rec")) != 0) {
369 rec_controllable.set_id (prop->value());
371 if ((prop = node.property ("shuttle")) != 0) {
372 shuttle_controllable.set_id (prop->value());
377 ARDOUR_UI::get_transport_controllable_state ()
379 XMLNode* node = new XMLNode(X_("TransportControllables"));
382 roll_controllable.id().print (buf, sizeof (buf));
383 node->add_property (X_("roll"), buf);
384 stop_controllable.id().print (buf, sizeof (buf));
385 node->add_property (X_("stop"), buf);
386 goto_start_controllable.id().print (buf, sizeof (buf));
387 node->add_property (X_("goto_start"), buf);
388 goto_end_controllable.id().print (buf, sizeof (buf));
389 node->add_property (X_("goto_end"), buf);
390 auto_loop_controllable.id().print (buf, sizeof (buf));
391 node->add_property (X_("auto_loop"), buf);
392 play_selection_controllable.id().print (buf, sizeof (buf));
393 node->add_property (X_("play_selection"), buf);
394 rec_controllable.id().print (buf, sizeof (buf));
395 node->add_property (X_("rec"), buf);
396 shuttle_controllable.id().print (buf, sizeof (buf));
397 node->add_property (X_("shuttle"), buf);
403 ARDOUR_UI::save_ardour_state ()
405 if (!keyboard || !mixer || !editor) {
409 /* XXX this is all a bit dubious. add_extra_xml() uses
410 a different lifetime model from add_instant_xml().
413 XMLNode* node = new XMLNode (keyboard->get_state());
414 Config->add_extra_xml (*node);
415 Config->add_extra_xml (get_transport_controllable_state());
416 Config->save_state();
418 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
419 XMLNode mnode(mixer->get_state());
422 session->add_instant_xml (enode, session->path());
423 session->add_instant_xml (mnode, session->path());
425 Config->add_instant_xml (enode, get_user_ardour_path());
426 Config->add_instant_xml (mnode, get_user_ardour_path());
433 ARDOUR_UI::startup ()
435 check_memory_locking();
439 ARDOUR_UI::no_memory_warning ()
441 XMLNode node (X_("no-memory-warning"));
442 Config->add_instant_xml (node, get_user_ardour_path());
446 ARDOUR_UI::check_memory_locking ()
449 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
453 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
455 if (engine->is_realtime() && memory_warning_node == 0) {
457 struct rlimit limits;
459 long pages, page_size;
461 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
464 ram = (int64_t) pages * (int64_t) page_size;
467 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
471 if (limits.rlim_cur != RLIM_INFINITY) {
473 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
476 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
477 "This might cause Ardour to run out of memory before your system "
478 "runs out of memory. \n\n"
479 "You can view the memory limit with 'ulimit -l', "
480 "and it is normally controlled by /etc/security/limits.conf"));
482 VBox* vbox = msg.get_vbox();
484 CheckButton cb (_("Do not show this window again"));
486 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
488 hbox.pack_start (cb, true, false);
489 vbox->pack_start (hbox);
492 editor->ensure_float (msg);
504 if (session && session->dirty()) {
505 switch (ask_about_saving_session(_("quit"))) {
510 /* use the default name */
511 if (save_state_canfail ("")) {
512 /* failed - don't quit */
513 MessageDialog msg (*editor,
515 Ardour was unable to save your session.\n\n\
516 If you still wish to quit, please use the\n\n\
517 \"Just quit\" option."));
528 session->set_deletion_in_progress ();
531 Config->save_state();
536 ARDOUR_UI::ask_about_saving_session (const string & what)
538 ArdourDialog window (_("ardour: save session?"));
539 Gtk::HBox dhbox; // the hbox for the image and text
540 Gtk::Label prompt_label;
541 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
545 msg = string_compose(_("Don't %1"), what);
546 window.add_button (msg, RESPONSE_REJECT);
547 msg = string_compose(_("Just %1"), what);
548 window.add_button (msg, RESPONSE_APPLY);
549 msg = string_compose(_("Save and %1"), what);
550 window.add_button (msg, RESPONSE_ACCEPT);
552 window.set_default_response (RESPONSE_ACCEPT);
554 Gtk::Button noquit_button (msg);
555 noquit_button.set_name ("EditorGTKButton");
560 if (session->snap_name() == session->name()) {
563 type = _("snapshot");
565 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?"),
566 type, session->snap_name());
568 prompt_label.set_text (prompt);
569 prompt_label.set_name (X_("PrompterLabel"));
570 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
572 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
574 dhbox.set_homogeneous (false);
575 dhbox.pack_start (*dimage, false, false, 5);
576 dhbox.pack_start (prompt_label, true, false, 5);
577 window.get_vbox()->pack_start (dhbox);
579 window.set_name (_("Prompter"));
580 window.set_position (Gtk::WIN_POS_MOUSE);
581 window.set_modal (true);
582 window.set_resizable (false);
585 save_the_session = 0;
587 window.set_keep_above (true);
590 ResponseType r = (ResponseType) window.run();
595 case RESPONSE_ACCEPT: // save and get out of here
597 case RESPONSE_APPLY: // get out of here
607 ARDOUR_UI::every_second ()
610 update_buffer_load ();
611 update_disk_space ();
616 ARDOUR_UI::every_point_one_seconds ()
618 update_speed_display ();
619 RapidScreenUpdate(); /* EMIT_SIGNAL */
624 ARDOUR_UI::every_point_zero_one_seconds ()
626 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
631 ARDOUR_UI::update_sample_rate (nframes_t ignored)
635 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
637 if (!engine->connected()) {
639 snprintf (buf, sizeof (buf), _("disconnected"));
643 nframes_t rate = engine->frame_rate();
645 if (fmod (rate, 1000.0) != 0.0) {
646 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
647 (float) rate/1000.0f,
648 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
650 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
652 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
656 sample_rate_label.set_text (buf);
660 ARDOUR_UI::update_cpu_load ()
663 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
664 cpu_load_label.set_text (buf);
668 ARDOUR_UI::update_buffer_load ()
673 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
674 session->playback_load(), session->capture_load());
675 buffer_load_label.set_text (buf);
677 buffer_load_label.set_text ("");
682 ARDOUR_UI::count_recenabled_streams (Route& route)
684 Track* track = dynamic_cast<Track*>(&route);
685 if (track && track->diskstream()->record_enabled()) {
686 rec_enabled_streams += track->n_inputs();
691 ARDOUR_UI::update_disk_space()
697 nframes_t frames = session->available_capture_duration();
700 if (frames == max_frames) {
701 strcpy (buf, _("Disk: 24hrs+"));
706 nframes_t fr = session->frame_rate();
708 rec_enabled_streams = 0;
709 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
711 if (rec_enabled_streams) {
712 frames /= rec_enabled_streams;
715 hrs = frames / (fr * 3600);
716 frames -= hrs * fr * 3600;
717 mins = frames / (fr * 60);
718 frames -= mins * fr * 60;
721 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
724 disk_space_label.set_text (buf);
728 ARDOUR_UI::update_wall_clock ()
735 tm_now = localtime (&now);
737 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
738 wall_clock_label.set_text (buf);
744 ARDOUR_UI::session_menu (GdkEventButton *ev)
746 session_popup_menu->popup (0, 0);
751 ARDOUR_UI::redisplay_recent_sessions ()
753 vector<string *> *sessions;
754 vector<string *>::iterator i;
755 RecentSessionsSorter cmp;
757 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
758 recent_session_model->clear ();
761 ARDOUR::read_recent_sessions (rs);
764 recent_session_display.set_model (recent_session_model);
768 /* sort them alphabetically */
769 sort (rs.begin(), rs.end(), cmp);
770 sessions = new vector<string*>;
772 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
773 sessions->push_back (new string ((*i).second));
776 for (i = sessions->begin(); i != sessions->end(); ++i) {
778 vector<string*>* states;
779 vector<const gchar*> item;
780 string fullpath = *(*i);
782 /* remove any trailing / */
784 if (fullpath[fullpath.length()-1] == '/') {
785 fullpath = fullpath.substr (0, fullpath.length()-1);
788 /* now get available states for this session */
790 if ((states = Session::possible_states (fullpath)) == 0) {
795 TreeModel::Row row = *(recent_session_model->append());
797 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
798 row[recent_session_columns.fullpath] = fullpath;
800 if (states->size() > 1) {
802 /* add the children */
804 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
806 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
808 child_row[recent_session_columns.visible_name] = **i2;
809 child_row[recent_session_columns.fullpath] = fullpath;
818 recent_session_display.set_model (recent_session_model);
823 ARDOUR_UI::build_session_selector ()
825 session_selector_window = new ArdourDialog ("session selector");
827 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
829 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
830 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
831 session_selector_window->set_default_response (RESPONSE_ACCEPT);
832 recent_session_model = TreeStore::create (recent_session_columns);
833 recent_session_display.set_model (recent_session_model);
834 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
835 recent_session_display.set_headers_visible (false);
836 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
838 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
840 scroller->add (recent_session_display);
841 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
843 session_selector_window->set_name ("SessionSelectorWindow");
844 session_selector_window->set_size_request (200, 400);
845 session_selector_window->get_vbox()->pack_start (*scroller);
846 session_selector_window->show_all_children();
850 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
852 session_selector_window->response (RESPONSE_ACCEPT);
856 ARDOUR_UI::open_recent_session ()
858 /* popup selector window */
860 if (session_selector_window == 0) {
861 build_session_selector ();
864 redisplay_recent_sessions ();
866 ResponseType r = (ResponseType) session_selector_window->run ();
868 session_selector_window->hide();
871 case RESPONSE_ACCEPT:
877 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
879 if (i == recent_session_model->children().end()) {
883 Glib::ustring path = (*i)[recent_session_columns.fullpath];
884 Glib::ustring state = (*i)[recent_session_columns.visible_name];
886 _session_is_new = false;
888 load_session (path, state);
892 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
896 if (stat (info.filename.c_str(), &statbuf) != 0) {
900 if (!S_ISDIR(statbuf.st_mode)) {
906 string session_file = info.filename;
908 session_file += Glib::path_get_basename (info.filename);
909 session_file += ".ardour";
911 if (stat (session_file.c_str(), &statbuf) != 0) {
915 return S_ISREG (statbuf.st_mode);
919 ARDOUR_UI::open_session ()
921 /* popup selector window */
923 if (open_session_selector == 0) {
925 /* ardour sessions are folders */
927 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
928 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
929 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
931 FileFilter session_filter;
932 session_filter.add_pattern ("*.ardour");
933 session_filter.set_name (_("Ardour sessions"));
934 open_session_selector->add_filter (session_filter);
935 open_session_selector->set_filter (session_filter);
938 int response = open_session_selector->run();
939 open_session_selector->hide ();
942 case RESPONSE_ACCEPT:
945 open_session_selector->hide();
949 open_session_selector->hide();
950 string session_path = open_session_selector->get_filename();
954 if (session_path.length() > 0) {
955 if (Session::find_session (session_path, path, name, isnew) == 0) {
956 _session_is_new = isnew;
957 load_session (path, name);
964 ARDOUR_UI::session_add_midi_track ()
966 cerr << _("Patience is a virtue.\n");
970 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
972 list<boost::shared_ptr<AudioTrack> > tracks;
973 Session::RouteList routes;
976 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
982 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
984 if (tracks.size() != how_many) {
986 error << _("could not create a new audio track") << endmsg;
988 error << string_compose (_("could only create %1 of %2 new audio %3"),
989 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
995 routes = session->new_audio_route (input_channels, output_channels, how_many);
997 if (routes.size() != how_many) {
999 error << _("could not create a new audio track") << endmsg;
1001 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1007 if (need_control_room_outs) {
1013 route->set_stereo_control_outs (control_lr_channels);
1014 route->control_outs()->set_stereo_pan (pans, this);
1016 #endif /* CONTROLOUTS */
1020 cerr << "About to complain about JACK\n";
1021 MessageDialog msg (*editor,
1022 _("There are insufficient JACK ports available\n\
1023 to create a new track or bus.\n\
1024 You should save Ardour, exit and\n\
1025 restart JACK with more ports."));
1031 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1033 nframes_t _preroll = 0;
1036 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1037 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1039 if (new_position > _preroll) {
1040 new_position -= _preroll;
1045 session->request_locate (new_position);
1050 ARDOUR_UI::transport_goto_start ()
1053 session->goto_start();
1056 /* force displayed area in editor to start no matter
1057 what "follow playhead" setting is.
1061 editor->reset_x_origin (session->current_start_frame());
1067 ARDOUR_UI::transport_goto_zero ()
1070 session->request_locate (0);
1073 /* force displayed area in editor to start no matter
1074 what "follow playhead" setting is.
1078 editor->reset_x_origin (0);
1084 ARDOUR_UI::transport_goto_end ()
1087 nframes_t frame = session->current_end_frame();
1088 session->request_locate (frame);
1090 /* force displayed area in editor to start no matter
1091 what "follow playhead" setting is.
1095 editor->reset_x_origin (frame);
1101 ARDOUR_UI::transport_stop ()
1107 if (session->is_auditioning()) {
1108 session->cancel_audition ();
1112 if (session->get_play_loop ()) {
1113 session->request_play_loop (false);
1116 session->request_stop ();
1120 ARDOUR_UI::transport_stop_and_forget_capture ()
1123 session->request_stop (true);
1128 ARDOUR_UI::remove_last_capture()
1131 editor->remove_last_capture();
1136 ARDOUR_UI::transport_record ()
1139 switch (session->record_status()) {
1140 case Session::Disabled:
1141 if (session->ntracks() == 0) {
1142 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1146 session->maybe_enable_record ();
1148 case Session::Recording:
1149 case Session::Enabled:
1150 session->disable_record (true);
1156 ARDOUR_UI::transport_roll ()
1164 rolling = session->transport_rolling ();
1166 if (session->get_play_loop()) {
1167 session->request_play_loop (false);
1168 auto_loop_button.set_visual_state (1);
1169 roll_button.set_visual_state (1);
1170 } else if (session->get_play_range ()) {
1171 session->request_play_range (false);
1172 play_selection_button.set_visual_state (0);
1173 } else if (rolling) {
1174 session->request_locate (session->last_transport_start(), true);
1177 session->request_transport_speed (1.0f);
1181 ARDOUR_UI::transport_loop()
1184 if (session->get_play_loop()) {
1185 if (session->transport_rolling()) {
1186 Location * looploc = session->locations()->auto_loop_location();
1188 session->request_locate (looploc->start(), true);
1193 session->request_play_loop (true);
1199 ARDOUR_UI::transport_play_selection ()
1205 if (!session->get_play_range()) {
1206 session->request_stop ();
1209 editor->play_selection ();
1213 ARDOUR_UI::transport_rewind (int option)
1215 float current_transport_speed;
1218 current_transport_speed = session->transport_speed();
1220 if (current_transport_speed >= 0.0f) {
1223 session->request_transport_speed (-1.0f);
1226 session->request_transport_speed (-4.0f);
1229 session->request_transport_speed (-0.5f);
1234 session->request_transport_speed (current_transport_speed * 1.5f);
1240 ARDOUR_UI::transport_forward (int option)
1242 float current_transport_speed;
1245 current_transport_speed = session->transport_speed();
1247 if (current_transport_speed <= 0.0f) {
1250 session->request_transport_speed (1.0f);
1253 session->request_transport_speed (4.0f);
1256 session->request_transport_speed (0.5f);
1261 session->request_transport_speed (current_transport_speed * 1.5f);
1267 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1273 boost::shared_ptr<Route> r;
1275 if ((r = session->route_by_remote_id (dstream)) != 0) {
1279 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1280 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1289 ARDOUR_UI::queue_transport_change ()
1291 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1295 ARDOUR_UI::map_transport_state ()
1297 float sp = session->transport_speed();
1300 transport_rolling ();
1301 } else if (sp < 0.0f) {
1302 transport_rewinding ();
1303 } else if (sp > 0.0f) {
1304 transport_forwarding ();
1306 transport_stopped ();
1311 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1313 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1314 (int) adj.get_value()].c_str());
1318 ARDOUR_UI::engine_stopped ()
1320 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1321 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1322 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1326 ARDOUR_UI::engine_running ()
1328 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1329 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1330 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1332 Glib::RefPtr<Action> action;
1333 char* action_name = 0;
1335 switch (engine->frames_per_cycle()) {
1337 action_name = X_("JACKLatency32");
1340 action_name = X_("JACKLatency64");
1343 action_name = X_("JACKLatency128");
1346 action_name = X_("JACKLatency512");
1349 action_name = X_("JACKLatency1024");
1352 action_name = X_("JACKLatency2048");
1355 action_name = X_("JACKLatency4096");
1358 action_name = X_("JACKLatency8192");
1361 /* XXX can we do anything useful ? */
1367 action = ActionManager::get_action (X_("JACK"), action_name);
1370 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1371 ract->set_active ();
1377 ARDOUR_UI::engine_halted ()
1379 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1381 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1382 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1384 update_sample_rate (0);
1386 MessageDialog msg (*editor,
1388 JACK has either been shutdown or it\n\
1389 disconnected Ardour because Ardour\n\
1390 was not fast enough. You can save the\n\
1391 session and/or try to reconnect to JACK ."));
1396 ARDOUR_UI::do_engine_start ()
1404 error << _("Unable to start the session running")
1414 ARDOUR_UI::start_engine ()
1416 if (do_engine_start () == 0) {
1417 if (session && _session_is_new) {
1418 /* we need to retain initial visual
1419 settings for a new session
1421 session->save_state ("");
1429 ARDOUR_UI::update_clocks ()
1431 if (!editor || !editor->dragging_playhead()) {
1432 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1437 ARDOUR_UI::start_clocking ()
1439 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1443 ARDOUR_UI::stop_clocking ()
1445 clock_signal_connection.disconnect ();
1449 ARDOUR_UI::toggle_clocking ()
1452 if (clock_button.get_active()) {
1461 ARDOUR_UI::_blink (void *arg)
1464 ((ARDOUR_UI *) arg)->blink ();
1471 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1475 ARDOUR_UI::start_blinking ()
1477 /* Start the blink signal. Everybody with a blinking widget
1478 uses Blink to drive the widget's state.
1481 if (blink_timeout_tag < 0) {
1483 blink_timeout_tag = g_timeout_add (240, _blink, this);
1488 ARDOUR_UI::stop_blinking ()
1490 if (blink_timeout_tag >= 0) {
1491 g_source_remove (blink_timeout_tag);
1492 blink_timeout_tag = -1;
1497 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1503 if (io.n_inputs() == 0) {
1508 /* XXX we're not handling multiple ports yet. */
1510 const char **connections = io.input(0)->get_connections();
1512 if (connections == 0 || connections[0] == '\0') {
1515 buf = connections[0];
1522 if (io.n_outputs() == 0) {
1527 /* XXX we're not handling multiple ports yet. */
1529 const char **connections = io.output(0)->get_connections();
1531 if (connections == 0 || connections[0] == '\0') {
1534 buf = connections[0];
1541 /** Ask the user for the name of a new shapshot and then take it.
1544 ARDOUR_UI::snapshot_session ()
1546 ArdourPrompter prompter (true);
1550 struct tm local_time;
1553 localtime_r (&n, &local_time);
1554 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1556 prompter.set_name ("Prompter");
1557 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1558 prompter.set_prompt (_("Name of New Snapshot"));
1559 prompter.set_initial_text (timebuf);
1561 switch (prompter.run()) {
1562 case RESPONSE_ACCEPT:
1563 prompter.get_result (snapname);
1564 if (snapname.length()){
1565 save_state (snapname);
1575 ARDOUR_UI::save_state (const string & name)
1577 (void) save_state_canfail (name);
1581 ARDOUR_UI::save_state_canfail (string name)
1586 if (name.length() == 0) {
1587 name = session->snap_name();
1590 if ((ret = session->save_state (name)) != 0) {
1594 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1599 ARDOUR_UI::restore_state (string name)
1602 if (name.length() == 0) {
1603 name = session->name();
1605 session->restore_state (name);
1610 ARDOUR_UI::primary_clock_value_changed ()
1613 session->request_locate (primary_clock.current_time ());
1618 ARDOUR_UI::secondary_clock_value_changed ()
1621 session->request_locate (secondary_clock.current_time ());
1626 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1628 if (session && dstream && dstream->record_enabled()) {
1630 Session::RecordState rs;
1632 rs = session->record_status ();
1635 case Session::Disabled:
1636 case Session::Enabled:
1637 if (w->get_state() != STATE_SELECTED) {
1638 w->set_state (STATE_SELECTED);
1642 case Session::Recording:
1643 if (w->get_state() != STATE_ACTIVE) {
1644 w->set_state (STATE_ACTIVE);
1650 if (w->get_state() != STATE_NORMAL) {
1651 w->set_state (STATE_NORMAL);
1657 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1663 switch (session->record_status()) {
1664 case Session::Enabled:
1666 rec_button.set_visual_state (2);
1668 rec_button.set_visual_state (0);
1672 case Session::Recording:
1673 rec_button.set_visual_state (1);
1677 rec_button.set_visual_state (0);
1683 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1691 ARDOUR_UI::save_template ()
1694 ArdourPrompter prompter (true);
1697 prompter.set_name (X_("Prompter"));
1698 prompter.set_prompt (_("Name for mix template:"));
1699 prompter.set_initial_text(session->name() + _("-template"));
1700 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1702 switch (prompter.run()) {
1703 case RESPONSE_ACCEPT:
1704 prompter.get_result (name);
1706 if (name.length()) {
1707 session->save_template (name);
1717 ARDOUR_UI::new_session (std::string predetermined_path)
1719 string session_name;
1720 string session_path;
1722 if (!engine->connected()) {
1723 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1728 int response = Gtk::RESPONSE_NONE;
1730 new_session_dialog->set_modal(true);
1731 new_session_dialog->set_name (predetermined_path);
1732 new_session_dialog->reset_recent();
1733 new_session_dialog->show();
1736 response = new_session_dialog->run ();
1738 if (!engine->connected()) {
1739 new_session_dialog->hide ();
1740 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1745 _session_is_new = false;
1747 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1752 new_session_dialog->hide ();
1755 } else if (response == Gtk::RESPONSE_NONE) {
1757 /* Clear was pressed */
1758 new_session_dialog->reset();
1760 } else if (response == Gtk::RESPONSE_YES) {
1762 /* YES == OPEN, but there's no enum for that */
1764 session_name = new_session_dialog->session_name();
1766 if (session_name.empty()) {
1767 response = Gtk::RESPONSE_NONE;
1771 if (session_name[0] == '/' ||
1772 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1773 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1774 load_session (Glib::path_get_dirname (session_name), session_name);
1776 session_path = new_session_dialog->session_folder();
1777 load_session (session_path, session_name);
1780 } else if (response == Gtk::RESPONSE_OK) {
1782 session_name = new_session_dialog->session_name();
1784 if (new_session_dialog->get_current_page() == 1) {
1786 /* XXX this is a bit of a hack..
1787 i really want the new sesion dialog to return RESPONSE_YES
1788 if we're on page 1 (the load page)
1789 Unfortunately i can't see how atm..
1792 if (session_name.empty()) {
1793 response = Gtk::RESPONSE_NONE;
1797 if (session_name[0] == '/' ||
1798 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1799 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1800 load_session (Glib::path_get_dirname (session_name), session_name);
1802 session_path = new_session_dialog->session_folder();
1803 load_session (session_path, session_name);
1808 if (session_name.empty()) {
1809 response = Gtk::RESPONSE_NONE;
1813 if (session_name[0] == '/' ||
1814 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1815 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1817 session_path = Glib::path_get_dirname (session_name);
1818 session_name = Glib::path_get_basename (session_name);
1822 session_path = new_session_dialog->session_folder();
1826 //XXX This is needed because session constructor wants a
1827 //non-existant path. hopefully this will be fixed at some point.
1829 session_path = Glib::build_filename (session_path, session_name);
1831 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1833 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1835 MessageDialog msg (str,
1837 Gtk::MESSAGE_WARNING,
1838 Gtk::BUTTONS_YES_NO,
1842 msg.set_name (X_("CleanupDialog"));
1843 msg.set_wmclass (X_("existing_session"), "Ardour");
1844 msg.set_position (Gtk::WIN_POS_MOUSE);
1846 switch (msg.run()) {
1848 load_session (session_path, session_name);
1852 response = RESPONSE_NONE;
1853 new_session_dialog->reset ();
1858 _session_is_new = true;
1860 std::string template_name = new_session_dialog->session_template_name();
1862 if (new_session_dialog->use_session_template()) {
1864 load_session (session_path, session_name, &template_name);
1870 AutoConnectOption iconnect;
1871 AutoConnectOption oconnect;
1873 if (new_session_dialog->create_control_bus()) {
1874 cchns = (uint32_t) new_session_dialog->control_channel_count();
1879 if (new_session_dialog->create_master_bus()) {
1880 mchns = (uint32_t) new_session_dialog->master_channel_count();
1885 if (new_session_dialog->connect_inputs()) {
1886 iconnect = AutoConnectPhysical;
1888 iconnect = AutoConnectOption (0);
1891 /// @todo some minor tweaks.
1893 if (new_session_dialog->connect_outs_to_master()) {
1894 oconnect = AutoConnectMaster;
1895 } else if (new_session_dialog->connect_outs_to_physical()) {
1896 oconnect = AutoConnectPhysical;
1898 oconnect = AutoConnectOption (0);
1901 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1902 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1904 if (build_session (session_path,
1912 engine->frame_rate() * 60 * 5)) {
1914 response = Gtk::RESPONSE_NONE;
1915 new_session_dialog->reset ();
1922 } while (response == Gtk::RESPONSE_NONE);
1926 new_session_dialog->get_window()->set_cursor();
1927 new_session_dialog->hide();
1932 ARDOUR_UI::close_session()
1939 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1941 Session *new_session;
1943 session_loaded = false;
1945 x = unload_session ();
1953 /* if it already exists, we must have write access */
1955 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1956 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1957 "This prevents the session from being loaded."));
1963 new_session = new Session (*engine, path, snap_name, mix_template);
1968 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1972 connect_to_session (new_session);
1974 Config->set_current_owner (ConfigVariableBase::Interface);
1976 session_loaded = true;
1978 goto_editor_window ();
1981 session->set_clean ();
1984 editor->edit_cursor_position (true);
1989 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1990 uint32_t control_channels,
1991 uint32_t master_channels,
1992 AutoConnectOption input_connect,
1993 AutoConnectOption output_connect,
1996 nframes_t initial_length)
1998 Session *new_session;
2001 session_loaded = false;
2002 x = unload_session ();
2009 _session_is_new = true;
2012 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2013 control_channels, master_channels, nphysin, nphysout, initial_length);
2018 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2023 connect_to_session (new_session);
2025 session_loaded = true;
2033 editor->show_window ();
2044 ARDOUR_UI::show_splash ()
2047 about = new About();
2048 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2055 ARDOUR_UI::about_signal_response(int response)
2061 ARDOUR_UI::hide_splash ()
2064 about->get_window()->set_cursor ();
2070 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2074 removed = rep.paths.size();
2077 MessageDialog msgd (*editor,
2078 _("No audio files were ready for cleanup"),
2081 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2082 msgd.set_secondary_text (_("If this seems suprising, \n\
2083 check for any existing snapshots.\n\
2084 These may still include regions that\n\
2085 require some unused files to continue to exist."));
2091 ArdourDialog results (_("ardour: cleanup"), true, false);
2093 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2094 CleanupResultsModelColumns() {
2098 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2099 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2103 CleanupResultsModelColumns results_columns;
2104 Glib::RefPtr<Gtk::ListStore> results_model;
2105 Gtk::TreeView results_display;
2107 results_model = ListStore::create (results_columns);
2108 results_display.set_model (results_model);
2109 results_display.append_column (list_title, results_columns.visible_name);
2111 results_display.set_name ("CleanupResultsList");
2112 results_display.set_headers_visible (true);
2113 results_display.set_headers_clickable (false);
2114 results_display.set_reorderable (false);
2116 Gtk::ScrolledWindow list_scroller;
2119 Gtk::HBox dhbox; // the hbox for the image and text
2120 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2121 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2123 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2125 if (rep.space < 1048576.0f) {
2127 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2129 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2133 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2135 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2139 dhbox.pack_start (*dimage, true, false, 5);
2140 dhbox.pack_start (txt, true, false, 5);
2142 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2143 TreeModel::Row row = *(results_model->append());
2144 row[results_columns.visible_name] = *i;
2145 row[results_columns.fullpath] = *i;
2148 list_scroller.add (results_display);
2149 list_scroller.set_size_request (-1, 150);
2150 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2152 dvbox.pack_start (dhbox, true, false, 5);
2153 dvbox.pack_start (list_scroller, true, false, 5);
2154 ddhbox.pack_start (dvbox, true, false, 5);
2156 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2157 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2158 results.set_default_response (RESPONSE_CLOSE);
2159 results.set_position (Gtk::WIN_POS_MOUSE);
2160 results.show_all_children ();
2161 results.set_resizable (false);
2168 ARDOUR_UI::cleanup ()
2171 /* shouldn't happen: menu item is insensitive */
2176 MessageDialog checker (_("Are you sure you want to cleanup?"),
2178 Gtk::MESSAGE_QUESTION,
2179 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2181 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2182 ALL undo/redo information will be lost if you cleanup.\n\
2183 After cleanup, unused audio files will be moved to a \
2184 \"dead sounds\" location."));
2186 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2187 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2188 checker.set_default_response (RESPONSE_CANCEL);
2190 checker.set_name (_("CleanupDialog"));
2191 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2192 checker.set_position (Gtk::WIN_POS_MOUSE);
2194 switch (checker.run()) {
2195 case RESPONSE_ACCEPT:
2201 Session::cleanup_report rep;
2203 editor->prepare_for_cleanup ();
2205 /* do not allow flush until a session is reloaded */
2207 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2209 act->set_sensitive (false);
2212 if (session->cleanup_sources (rep)) {
2217 display_cleanup_results (rep,
2220 The following %1 %2 not in use and \n\
2221 have been moved to:\n\
2223 Flushing the wastebasket will \n\
2224 release an additional\n\
2225 %4 %5bytes of disk space.\n"
2233 ARDOUR_UI::flush_trash ()
2236 /* shouldn't happen: menu item is insensitive */
2240 Session::cleanup_report rep;
2242 if (session->cleanup_trash_sources (rep)) {
2246 display_cleanup_results (rep,
2248 _("The following %1 %2 deleted from\n\
2250 releasing %4 %5bytes of disk space"));
2254 ARDOUR_UI::add_route (Gtk::Window* float_window)
2262 if (add_route_dialog == 0) {
2263 add_route_dialog = new AddRouteDialog;
2265 add_route_dialog->set_transient_for (*float_window);
2269 if (add_route_dialog->is_visible()) {
2270 /* we're already doing this */
2274 ResponseType r = (ResponseType) add_route_dialog->run ();
2276 add_route_dialog->hide();
2279 case RESPONSE_ACCEPT:
2286 if ((count = add_route_dialog->count()) <= 0) {
2290 uint32_t input_chan = add_route_dialog->channels ();
2291 uint32_t output_chan;
2292 string name_template = add_route_dialog->name_template ();
2293 bool track = add_route_dialog->track ();
2295 AutoConnectOption oac = Config->get_output_auto_connect();
2297 if (oac & AutoConnectMaster) {
2298 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2300 output_chan = input_chan;
2303 /* XXX do something with name template */
2306 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2308 session_add_audio_bus (input_chan, output_chan, count);
2313 ARDOUR_UI::mixer_settings () const
2318 node = session->instant_xml(X_("Mixer"), session->path());
2320 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2324 node = new XMLNode (X_("Mixer"));
2331 ARDOUR_UI::editor_settings () const
2336 node = session->instant_xml(X_("Editor"), session->path());
2338 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2342 node = new XMLNode (X_("Editor"));
2348 ARDOUR_UI::keyboard_settings () const
2352 node = Config->extra_xml(X_("Keyboard"));
2355 node = new XMLNode (X_("Keyboard"));
2361 ARDOUR_UI::halt_on_xrun_message ()
2363 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2365 MessageDialog msg (*editor,
2366 _("Recording was stopped because your system could not keep up."));
2371 ARDOUR_UI::disk_overrun_handler ()
2373 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2375 if (!have_disk_speed_dialog_displayed) {
2376 have_disk_speed_dialog_displayed = true;
2377 MessageDialog* msg = new MessageDialog (*editor, _("\
2378 The disk system on your computer\n\
2379 was not able to keep up with Ardour.\n\
2381 Specifically, it failed to write data to disk\n\
2382 quickly enough to keep up with recording.\n"));
2383 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2389 ARDOUR_UI::disk_underrun_handler ()
2391 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2393 if (!have_disk_speed_dialog_displayed) {
2394 have_disk_speed_dialog_displayed = true;
2395 MessageDialog* msg = new MessageDialog (*editor,
2396 _("The disk system on your computer\n\
2397 was not able to keep up with Ardour.\n\
2399 Specifically, it failed to read data from disk\n\
2400 quickly enough to keep up with playback.\n"));
2401 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2407 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2409 have_disk_speed_dialog_displayed = false;
2414 ARDOUR_UI::pending_state_dialog ()
2416 ArdourDialog dialog ("pending state dialog");
2418 This session appears to have been in\n\
2419 middle of recording when ardour or\n\
2420 the computer was shutdown.\n\
2422 Ardour can recover any captured audio for\n\
2423 you, or it can ignore it. Please decide\n\
2424 what you would like to do.\n"));
2426 dialog.get_vbox()->pack_start (message);
2427 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2428 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2430 dialog.set_position (WIN_POS_CENTER);
2433 switch (dialog.run ()) {
2434 case RESPONSE_ACCEPT:
2442 ARDOUR_UI::disconnect_from_jack ()
2445 if( engine->disconnect_from_jack ()) {
2446 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2450 update_sample_rate (0);
2455 ARDOUR_UI::reconnect_to_jack ()
2458 if (engine->reconnect_to_jack ()) {
2459 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2463 update_sample_rate (0);
2468 ARDOUR_UI::cmdline_new_session (string path)
2470 if (path[0] != '/') {
2471 char buf[PATH_MAX+1];
2474 getcwd (buf, sizeof (buf));
2483 _will_create_new_session_automatically = false; /* done it */
2484 return FALSE; /* don't call it again */
2488 ARDOUR_UI::use_config ()
2490 Glib::RefPtr<Action> act;
2492 switch (Config->get_native_file_data_format ()) {
2494 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2497 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2502 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2503 ract->set_active ();
2506 switch (Config->get_native_file_header_format ()) {
2508 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2511 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2514 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2517 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2520 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2523 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2526 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2531 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2532 ract->set_active ();
2535 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2537 set_transport_controllable_state (*node);
2542 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2544 primary_clock.set (pos);
2545 secondary_clock.set (pos);
2547 if (big_clock_window) {
2548 big_clock.set (pos);
2553 ARDOUR_UI::record_state_changed ()
2555 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2557 if (!session || !big_clock_window) {
2558 /* why bother - the clock isn't visible */
2562 switch (session->record_status()) {
2563 case Session::Recording:
2564 big_clock.set_widget_name ("BigClockRecording");
2567 big_clock.set_widget_name ("BigClockNonRecording");
2573 ARDOUR_UI::set_keybindings_path (string path)
2575 keybindings_path = path;
2579 ARDOUR_UI::save_keybindings ()
2581 if (can_save_keybindings) {
2582 AccelMap::save (keybindings_path);
2587 ARDOUR_UI::first_idle ()
2590 session->allow_auto_play (true);
2592 can_save_keybindings = true;
2597 ARDOUR_UI::store_clock_modes ()
2599 XMLNode* node = new XMLNode(X_("ClockModes"));
2601 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2602 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2605 session->add_extra_xml (*node);
2606 session->set_dirty ();
2611 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2612 : Controllable (name), ui (u), type(tp)
2618 ARDOUR_UI::TransportControllable::set_value (float val)
2620 if (type == ShuttleControl) {
2627 fract = -((0.5f - val)/0.5f);
2629 fract = ((val - 0.5f)/0.5f);
2633 ui.set_shuttle_fract (fract);
2638 /* do nothing: these are radio-style actions */
2646 action = X_("Roll");
2649 action = X_("Stop");
2652 action = X_("Goto Start");
2655 action = X_("Goto End");
2658 action = X_("Loop");
2661 action = X_("Play Selection");
2664 action = X_("Record");
2674 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2682 ARDOUR_UI::TransportControllable::get_value (void) const
2701 case ShuttleControl:
2711 ARDOUR_UI::TransportControllable::set_id (const string& str)
2717 ARDOUR_UI::setup_profile ()
2719 if (gdk_screen_width() < 1200) {
2720 Profile->set_small_screen ();