2 Copyright (C) 1999-2002 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.
31 #include <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
60 #include "ardour_ui.h"
61 #include "ardour_message.h"
62 #include "public_editor.h"
63 #include "audio_clock.h"
68 #include "keyboard_target.h"
69 #include "add_route_dialog.h"
70 #include "new_session_dialog.h"
73 #include "gui_thread.h"
74 #include "meter_xpms.h"
75 #include "color_manager.h"
79 using namespace ARDOUR;
80 using namespace Gtkmm2ext;
84 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
86 sigc::signal<void,bool> ARDOUR_UI::Blink;
87 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
88 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
89 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
91 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
93 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
95 primary_clock (X_("TransportClockDisplay"), true, false, true),
96 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
97 preroll_clock (X_("PreRollClock"), true, true),
98 postroll_clock (X_("PostRollClock"), true, true),
102 adjuster_table (3, 3),
106 preroll_button (_("pre\nroll")),
107 postroll_button (_("post\nroll")),
111 big_clock ("BigClockDisplay", true),
115 time_master_button (_("time\nmaster")),
117 shuttle_units_button (_("% ")),
119 punch_in_button (_("punch\nin")),
120 punch_out_button (_("punch\nout")),
121 auto_return_button (_("auto\nreturn")),
122 auto_play_button (_("auto\nplay")),
123 auto_input_button (_("auto\ninput")),
124 click_button (_("click")),
125 auditioning_alert_button (_("AUDITIONING")),
126 solo_alert_button (_("SOLO")),
130 using namespace Gtk::Menu_Helpers;
134 /* actually, its already loaded, but ... */
136 cerr << "Loading UI configuration file " << rcfile << endl;
140 if (theArdourUI == 0) {
144 ActionManager::init ();
148 color_manager = new ColorManager();
150 std::string color_file = Glib::getenv(X_("ARDOUR_COLORS"));
151 if(!Glib::file_test(color_file, Glib::FILE_TEST_EXISTS)) {
152 color_file = ARDOUR::find_config_file("ardour.colors");
155 cerr << "Loading UI color configuration file " << color_file << endl;
157 color_manager->load (color_file);
159 m_new_session_dialog = 0;
160 m_new_session_dialog_ref = NewSessionDialogFactory::create();
161 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
165 _session_is_new = false;
166 big_clock_window = 0;
167 session_selector_window = 0;
168 last_key_press_time = 0;
169 connection_editor = 0;
170 add_route_dialog = 0;
175 open_session_selector = 0;
176 have_configure_timeout = false;
177 have_disk_overrun_displayed = false;
178 have_disk_underrun_displayed = false;
179 _will_create_new_session_automatically = false;
180 session_loaded = false;
181 last_speed_displayed = -1.0f;
183 last_configure_time.tv_sec = 0;
184 last_configure_time.tv_usec = 0;
186 shuttle_grabbed = false;
189 set_shuttle_units (Percentage);
190 set_shuttle_behaviour (Sprung);
192 shuttle_style_menu = 0;
193 shuttle_unit_menu = 0;
195 gettimeofday (&last_peak_grab, 0);
196 gettimeofday (&last_shuttle_request, 0);
198 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
199 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
200 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
201 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
203 /* handle pending state with a dialog */
205 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
207 /* have to wait for AudioEngine and Configuration before proceeding */
211 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
213 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
215 string msg = string_compose (_("\
216 You cannot record-enable\n\
218 because it has no input connections.\n\
219 You would be wasting space recording silence."),
222 ArdourMessage message (editor, X_("cannotrecord"), msg);
226 ARDOUR_UI::set_engine (AudioEngine& e)
230 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
231 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
232 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
233 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
237 keyboard = new Keyboard;
238 install_keybindings ();
240 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
241 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
243 if (setup_windows ()) {
244 throw failed_constructor ();
247 if (GTK_ARDOUR::show_key_actions) {
248 vector<string> names;
249 vector<string> paths;
251 vector<AccelKey> bindings;
253 ActionManager::get_all_actions (names, paths, keys, bindings);
255 vector<string>::iterator n;
256 vector<string>::iterator k;
257 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
258 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
264 /* start with timecode, metering enabled
267 blink_timeout_tag = -1;
269 /* this being a GUI and all, we want peakfiles */
271 FileSource::set_build_peakfiles (true);
272 FileSource::set_build_missing_peakfiles (true);
274 if (Source::start_peak_thread ()) {
275 throw failed_constructor();
278 /* start the time-of-day-clock */
280 update_wall_clock ();
281 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
283 update_disk_space ();
285 update_sample_rate (engine->frame_rate());
287 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
288 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
291 ARDOUR_UI::~ARDOUR_UI ()
293 save_ardour_state ();
307 if (add_route_dialog) {
308 delete add_route_dialog;
311 Source::stop_peak_thread ();
315 ARDOUR_UI::configure_timeout ()
320 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
321 /* no configure events yet */
325 gettimeofday (&now, 0);
326 timersub (&now, &last_configure_time, &diff);
328 /* force a gap of 0.5 seconds since the last configure event
331 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
334 have_configure_timeout = false;
335 save_ardour_state ();
341 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
343 if (have_configure_timeout) {
344 gettimeofday (&last_configure_time, 0);
346 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
347 have_configure_timeout = true;
354 ARDOUR_UI::save_ardour_state ()
356 if (!keyboard || !mixer || !editor) {
360 /* XXX this is all a bit dubious. add_extra_xml() uses
361 a different lifetime model from add_instant_xml().
364 XMLNode* node = new XMLNode (keyboard->get_state());
365 Config->add_extra_xml (*node);
366 Config->save_state();
368 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
369 XMLNode& mnode (mixer->get_state());
372 session->add_instant_xml(enode, session->path());
373 session->add_instant_xml(mnode, session->path());
375 Config->add_instant_xml(enode, Config->get_user_ardour_path());
376 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
381 ARDOUR_UI::startup ()
383 /* Once the UI is up and running, start the audio engine. Doing
384 this before the UI is up and running can cause problems
385 when not running with SCHED_FIFO, because the amount of
386 CPU and disk work needed to get the UI started can interfere
387 with the scheduling of the audio thread.
390 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
396 if (session && session->dirty()) {
397 switch (ask_about_saving_session(_("quit"))) {
402 /* use the default name */
403 if (save_state_canfail ("")) {
404 /* failed - don't quit */
405 ArdourMessage (editor, X_("badsave dialog"),
407 Ardour was unable to save your session.\n\n\
408 If you still wish to quit, please use the\n\n\
409 \"Just quit\" option."));
422 ARDOUR_UI::ask_about_saving_session (const string & what)
424 ArdourDialog window (_("ardour: save session?"));
425 Gtk::Label prompt_label;
428 msg = string_compose(_("Save and %1"), what);
429 window.add_button (msg, RESPONSE_ACCEPT);
430 msg = string_compose(_("Just %1"), what);
431 window.add_button (msg, RESPONSE_APPLY);
432 msg = string_compose(_("Don't %1"), what);
433 window.add_button (msg, RESPONSE_REJECT);
435 Gtk::Button noquit_button (msg);
436 noquit_button.set_name ("EditorGTKButton");
441 if (session->snap_name() == session->name()) {
444 type = _("snapshot");
446 prompt = string_compose(_("The %1\n\"%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?"),
447 type, session->snap_name());
449 prompt_label.set_text (prompt);
450 prompt_label.set_alignment (0.5, 0.5);
451 prompt_label.set_name (X_("PrompterLabel"));
453 window.get_vbox()->pack_start (prompt_label);
455 window.set_name (_("Prompter"));
456 window.set_position (Gtk::WIN_POS_MOUSE);
457 window.set_modal (true);
460 save_the_session = 0;
462 editor->ensure_float (window);
464 ResponseType r = (ResponseType) window.run();
469 case RESPONSE_ACCEPT: // save and get out of here
471 case RESPONSE_APPLY: // get out of here
481 ARDOUR_UI::every_second ()
484 update_buffer_load ();
485 update_disk_space ();
486 // update_disk_rate ();
491 ARDOUR_UI::every_point_one_seconds ()
496 /* do not attempt to grab peak power more than once per cycle.
499 gettimeofday (&now, 0);
500 timersub (&now, &last_peak_grab, &diff);
502 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
503 IO::GrabPeakPower(); /* EMIT_SIGNAL */
504 last_peak_grab = now;
507 update_speed_display ();
508 RapidScreenUpdate(); /* EMIT_SIGNAL */
513 ARDOUR_UI::every_point_zero_one_seconds ()
515 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
520 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
524 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
526 if (!engine->connected()) {
528 snprintf (buf, sizeof (buf), _("disconnected"));
532 jack_nframes_t rate = engine->frame_rate();
534 if (fmod (rate, 1000.0) != 0.0) {
535 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
536 (float) rate/1000.0f,
537 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
539 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
541 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
545 sample_rate_label.set_text (buf);
549 ARDOUR_UI::update_cpu_load ()
552 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
553 cpu_load_label.set_text (buf);
557 ARDOUR_UI::update_disk_rate ()
562 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
563 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
564 disk_rate_label.set_text (buf);
566 disk_rate_label.set_text ("");
571 ARDOUR_UI::update_buffer_load ()
576 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
577 session->playback_load(), session->capture_load());
578 buffer_load_label.set_text (buf);
580 buffer_load_label.set_text ("");
585 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
587 if (ds.record_enabled()) {
588 rec_enabled_diskstreams++;
593 ARDOUR_UI::update_disk_space()
599 jack_nframes_t frames = session->available_capture_duration();
602 if (frames == max_frames) {
603 strcpy (buf, _("space: 24hrs+"));
608 jack_nframes_t fr = session->frame_rate();
610 if (session->actively_recording()){
612 rec_enabled_diskstreams = 0;
613 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
615 if (rec_enabled_diskstreams) {
616 frames /= rec_enabled_diskstreams;
621 /* hmmm. shall we divide by the route count? or the diskstream count?
622 or what? for now, do nothing ...
627 hrs = frames / (fr * 3600);
628 frames -= hrs * fr * 3600;
629 mins = frames / (fr * 60);
630 frames -= mins * fr * 60;
633 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
636 disk_space_label.set_text (buf);
640 ARDOUR_UI::update_wall_clock ()
647 tm_now = localtime (&now);
649 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
650 wall_clock_label.set_text (buf);
655 ARDOUR_UI::control_methods_adjusted ()
660 which_method = (int) online_control_button->adjustment.get_value();
661 switch (which_method) {
663 allow_mmc_and_local ();
672 fatal << _("programming error: impossible control method") << endmsg;
678 ARDOUR_UI::mmc_device_id_adjusted ()
683 int dev_id = (int) mmc_id_button->adjustment.get_value();
684 mmc->set_device_id (dev_id);
690 ARDOUR_UI::session_menu (GdkEventButton *ev)
692 session_popup_menu->popup (0, 0);
697 ARDOUR_UI::redisplay_recent_sessions ()
699 vector<string *> *sessions;
700 vector<string *>::iterator i;
701 RecentSessionsSorter cmp;
703 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
704 recent_session_model->clear ();
707 ARDOUR::read_recent_sessions (rs);
710 recent_session_display.set_model (recent_session_model);
714 /* sort them alphabetically */
715 sort (rs.begin(), rs.end(), cmp);
716 sessions = new vector<string*>;
718 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
719 sessions->push_back (new string ((*i).second));
722 for (i = sessions->begin(); i != sessions->end(); ++i) {
724 vector<string*>* states;
725 vector<const gchar*> item;
726 string fullpath = *(*i);
728 /* remove any trailing / */
730 if (fullpath[fullpath.length()-1] == '/') {
731 fullpath = fullpath.substr (0, fullpath.length()-1);
734 /* now get available states for this session */
736 if ((states = Session::possible_states (fullpath)) == 0) {
741 TreeModel::Row row = *(recent_session_model->append());
743 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
744 row[recent_session_columns.fullpath] = fullpath;
746 if (states->size() > 1) {
748 /* add the children */
750 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
752 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
754 child_row[recent_session_columns.visible_name] = **i2;
755 child_row[recent_session_columns.fullpath] = fullpath;
764 recent_session_display.set_model (recent_session_model);
769 ARDOUR_UI::build_session_selector ()
771 session_selector_window = new ArdourDialog ("session selector");
773 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
775 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
776 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
778 recent_session_model = TreeStore::create (recent_session_columns);
779 recent_session_display.set_model (recent_session_model);
780 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
781 recent_session_display.set_headers_visible (false);
783 scroller->add (recent_session_display);
784 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
786 session_selector_window->set_name ("SessionSelectorWindow");
787 session_selector_window->set_size_request (200, 400);
788 session_selector_window->get_vbox()->pack_start (*scroller);
789 session_selector_window->show_all_children();
793 ARDOUR_UI::open_recent_session ()
795 /* popup selector window */
797 if (session_selector_window == 0) {
798 build_session_selector ();
801 redisplay_recent_sessions ();
803 ResponseType r = (ResponseType) session_selector_window->run ();
805 session_selector_window->hide();
808 case RESPONSE_ACCEPT:
814 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
816 if (i == recent_session_model->children().end()) {
820 Glib::ustring path = (*i)[recent_session_columns.fullpath];
821 Glib::ustring state = (*i)[recent_session_columns.visible_name];
823 _session_is_new = false;
825 load_session (path, state);
829 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
833 if (stat (info.filename.c_str(), &statbuf) != 0) {
837 if (!S_ISDIR(statbuf.st_mode)) {
841 string session_file = info.filename;
843 session_file += PBD::basename (info.filename);
844 session_file += ".ardour";
846 if (stat (session_file.c_str(), &statbuf) != 0) {
850 return S_ISREG (statbuf.st_mode);
854 ARDOUR_UI::open_session ()
856 /* popup selector window */
858 if (open_session_selector == 0) {
860 /* ardour sessions are folders */
862 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
863 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
864 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
866 FileFilter session_filter;
867 session_filter.add_pattern ("*.ardour");
868 session_filter.set_name (_("Ardour sessions"));
869 open_session_selector->add_filter (session_filter);
870 open_session_selector->set_filter (session_filter);
873 int response = open_session_selector->run();
874 open_session_selector->hide ();
877 case RESPONSE_ACCEPT:
880 open_session_selector->hide();
884 open_session_selector->hide();
885 string session_path = open_session_selector->get_filename();
889 if (session_path.length() > 0) {
890 if (Session::find_session (session_path, path, name, isnew) == 0) {
891 _session_is_new = isnew;
892 load_session (path, name);
899 ARDOUR_UI::session_add_midi_track ()
901 cerr << _("Patience is a virtue.\n");
905 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
910 warning << _("You cannot add a track without a session already loaded.") << endmsg;
916 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
917 error << _("could not create new audio track") << endmsg;
920 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
921 error << _("could not create new audio bus") << endmsg;
926 if (need_control_room_outs) {
932 route->set_stereo_control_outs (control_lr_channels);
933 route->control_outs()->set_stereo_pan (pans, this);
935 #endif /* CONTROLOUTS */
939 ArdourMessage msg (editor, X_("noport dialog"),
940 _("There are insufficient JACK ports available\n\
941 to create a new track or bus.\n\
942 You should save Ardour, exit and\n\
943 restart JACK with more ports."));
948 ARDOUR_UI::diskstream_added (DiskStream* ds)
953 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
955 jack_nframes_t _preroll;
958 _preroll = session->convert_to_frames_at (new_position, session->preroll);
960 if (new_position > _preroll) {
961 new_position -= _preroll;
966 session->request_locate (new_position);
971 ARDOUR_UI::transport_goto_start ()
974 session->request_locate (0);
977 /* force displayed area in editor to start no matter
978 what "follow playhead" setting is.
982 editor->reposition_x_origin (0);
988 ARDOUR_UI::transport_goto_end ()
991 jack_nframes_t frame = session->current_end_frame();
992 session->request_locate (frame);
994 /* force displayed area in editor to start no matter
995 what "follow playhead" setting is.
999 editor->reposition_x_origin (frame);
1005 ARDOUR_UI::transport_stop ()
1011 if (session->is_auditioning()) {
1012 session->cancel_audition ();
1016 if (session->get_auto_loop()) {
1017 session->request_auto_loop (false);
1020 session->request_stop ();
1024 ARDOUR_UI::transport_stop_and_forget_capture ()
1027 session->request_stop (true);
1032 ARDOUR_UI::remove_last_capture()
1035 editor->remove_last_capture();
1040 ARDOUR_UI::transport_record ()
1043 switch (session->record_status()) {
1044 case Session::Disabled:
1045 if (session->ntracks() == 0) {
1046 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1047 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1050 session->maybe_enable_record ();
1052 case Session::Recording:
1053 case Session::Enabled:
1054 session->disable_record (true);
1060 ARDOUR_UI::transport_roll ()
1068 rolling = session->transport_rolling ();
1070 if (session->get_auto_loop()) {
1071 session->request_auto_loop (false);
1072 auto_loop_button.set_active (false);
1073 roll_button.set_active (true);
1074 } else if (session->get_play_range ()) {
1075 session->request_play_range (false);
1076 play_selection_button.set_active (false);
1077 } else if (rolling) {
1078 session->request_locate (session->last_transport_start(), true);
1081 session->request_transport_speed (1.0f);
1085 ARDOUR_UI::transport_loop()
1088 if (session->get_auto_loop()) {
1089 if (session->transport_rolling()) {
1090 Location * looploc = session->locations()->auto_loop_location();
1092 session->request_locate (looploc->start(), true);
1097 session->request_auto_loop (true);
1103 ARDOUR_UI::transport_play_selection ()
1109 if (!session->get_play_range()) {
1110 session->request_stop ();
1113 editor->play_selection ();
1117 ARDOUR_UI::transport_rewind (int option)
1119 float current_transport_speed;
1122 current_transport_speed = session->transport_speed();
1124 if (current_transport_speed >= 0.0f) {
1127 session->request_transport_speed (-1.0f);
1130 session->request_transport_speed (-4.0f);
1133 session->request_transport_speed (-0.5f);
1138 session->request_transport_speed (current_transport_speed * 1.5f);
1144 ARDOUR_UI::transport_forward (int option)
1146 float current_transport_speed;
1149 current_transport_speed = session->transport_speed();
1151 if (current_transport_speed <= 0.0f) {
1154 session->request_transport_speed (1.0f);
1157 session->request_transport_speed (4.0f);
1160 session->request_transport_speed (0.5f);
1165 session->request_transport_speed (current_transport_speed * 1.5f);
1171 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1179 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1180 Port *port = ds->io()->input (0);
1181 port->request_monitor_input (!port->monitoring_input());
1186 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1194 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1195 ds->set_record_enabled (!ds->record_enabled(), this);
1200 ARDOUR_UI::queue_transport_change ()
1202 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1206 ARDOUR_UI::map_transport_state ()
1208 float sp = session->transport_speed();
1211 transport_rolling ();
1212 } else if (sp < 0.0f) {
1213 transport_rewinding ();
1214 } else if (sp > 0.0f) {
1215 transport_forwarding ();
1217 transport_stopped ();
1222 ARDOUR_UI::send_all_midi_feedback ()
1225 session->send_all_midi_feedback();
1230 ARDOUR_UI::allow_local_only ()
1236 ARDOUR_UI::allow_mmc_only ()
1242 ARDOUR_UI::allow_mmc_and_local ()
1248 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1250 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1251 (int) adj.get_value()].c_str());
1255 ARDOUR_UI::engine_stopped ()
1257 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1258 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1259 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1264 ARDOUR_UI::engine_running ()
1266 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1267 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1268 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1272 ARDOUR_UI::engine_halted ()
1274 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1276 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1277 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1279 update_sample_rate (0);
1281 ArdourMessage msg (editor, X_("halted"),
1283 JACK has either been shutdown or it\n\
1284 disconnected Ardour because Ardour\n\
1285 was not fast enough. You can save the\n\
1286 session and/or try to reconnect to JACK ."));
1290 ARDOUR_UI::do_engine_start ()
1296 catch (AudioEngine::PortRegistrationFailure& err) {
1298 error << _("Unable to create all required ports")
1306 error << _("Unable to start the session running")
1316 ARDOUR_UI::start_engine ()
1318 if (do_engine_start () == 0) {
1319 if (session && _session_is_new) {
1320 /* we need to retain initial visual
1321 settings for a new session
1323 session->save_state ("");
1326 /* there is too much going on, in too many threads, for us to
1327 end up with a clean session. So wait 1 second after loading,
1328 and fix it up. its ugly, but until i come across a better
1329 solution, its what we have.
1332 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1339 ARDOUR_UI::update_clocks ()
1341 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1345 ARDOUR_UI::start_clocking ()
1347 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1351 ARDOUR_UI::stop_clocking ()
1353 clock_signal_connection.disconnect ();
1357 ARDOUR_UI::toggle_clocking ()
1360 if (clock_button.get_active()) {
1369 ARDOUR_UI::_blink (void *arg)
1372 ((ARDOUR_UI *) arg)->blink ();
1379 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1383 ARDOUR_UI::start_blinking ()
1385 /* Start the blink signal. Everybody with a blinking widget
1386 uses Blink to drive the widget's state.
1389 if (blink_timeout_tag < 0) {
1391 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1396 ARDOUR_UI::stop_blinking ()
1398 if (blink_timeout_tag >= 0) {
1399 gtk_timeout_remove (blink_timeout_tag);
1400 blink_timeout_tag = -1;
1406 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1408 using namespace Gtk;
1409 using namespace Menu_Helpers;
1411 if (dstream.hidden()) {
1415 MenuList& items = diskstream_menu->items();
1416 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1420 ARDOUR_UI::diskstream_selected (gint32 id)
1422 selected_dstream = id;
1427 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1429 using namespace Gtk;
1430 using namespace Menu_Helpers;
1436 diskstream_menu = new Menu();
1437 diskstream_menu->set_name ("ArdourContextMenu");
1438 using namespace Gtk;
1439 using namespace Menu_Helpers;
1441 MenuList& items = diskstream_menu->items();
1442 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1444 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1447 diskstream_menu->popup (ev->button, ev->time);
1449 diskstream_menu->popup (0, 0);
1452 selected_dstream = -1;
1456 delete diskstream_menu;
1458 return selected_dstream;
1462 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1468 if (io.n_inputs() == 0) {
1473 /* XXX we're not handling multiple ports yet. */
1475 const char **connections = io.input(0)->get_connections();
1477 if (connections == 0 || connections[0] == '\0') {
1480 buf = connections[0];
1487 if (io.n_outputs() == 0) {
1492 /* XXX we're not handling multiple ports yet. */
1494 const char **connections = io.output(0)->get_connections();
1496 if (connections == 0 || connections[0] == '\0') {
1499 buf = connections[0];
1507 ARDOUR_UI::snapshot_session ()
1509 ArdourPrompter prompter (true);
1516 now = now.substr (0, now.length() - 1);
1518 prompter.set_name ("Prompter");
1519 prompter.set_prompt (_("Name for snapshot"));
1520 prompter.set_initial_text (now);
1522 switch (prompter.run()) {
1523 case RESPONSE_ACCEPT:
1524 prompter.get_result (snapname);
1525 if (snapname.length()){
1526 save_state (snapname);
1536 ARDOUR_UI::save_state (const string & name)
1538 (void) save_state_canfail (name);
1542 ARDOUR_UI::save_state_canfail (string name)
1547 if (name.length() == 0) {
1548 name = session->snap_name();
1551 if ((ret = session->save_state (name)) != 0) {
1555 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1560 ARDOUR_UI::restore_state (string name)
1563 if (name.length() == 0) {
1564 name = session->name();
1566 session->restore_state (name);
1571 ARDOUR_UI::primary_clock_value_changed ()
1574 session->request_locate (primary_clock.current_time ());
1579 ARDOUR_UI::secondary_clock_value_changed ()
1582 session->request_locate (secondary_clock.current_time ());
1587 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1589 if (session && dstream && dstream->record_enabled()) {
1591 Session::RecordState rs;
1593 rs = session->record_status ();
1596 case Session::Disabled:
1597 case Session::Enabled:
1598 if (w->get_state() != STATE_SELECTED) {
1599 w->set_state (STATE_SELECTED);
1603 case Session::Recording:
1604 if (w->get_state() != STATE_ACTIVE) {
1605 w->set_state (STATE_ACTIVE);
1611 if (w->get_state() != STATE_NORMAL) {
1612 w->set_state (STATE_NORMAL);
1618 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1624 switch (session->record_status()) {
1625 case Session::Enabled:
1627 rec_button.set_state (1);
1629 rec_button.set_state (0);
1633 case Session::Recording:
1634 rec_button.set_state (2);
1638 rec_button.set_state (0);
1644 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1652 ARDOUR_UI::start_keyboard_prefix ()
1654 keyboard->start_prefix();
1658 ARDOUR_UI::save_template ()
1661 ArdourPrompter prompter (true);
1664 prompter.set_name (X_("Prompter"));
1665 prompter.set_prompt (_("Name for mix template:"));
1666 prompter.set_initial_text(session->name() + _("-template"));
1668 switch (prompter.run()) {
1669 case RESPONSE_ACCEPT:
1670 prompter.get_result (name);
1672 if (name.length()) {
1673 session->save_template (name);
1683 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1685 m_new_session_dialog->show_all();
1686 m_new_session_dialog->set_transient_for(*editor);
1687 m_new_session_dialog->set_name(predetermined_path);
1689 int response = Gtk::RESPONSE_CANCEL;
1692 response = m_new_session_dialog->run ();
1694 if(response == Gtk::RESPONSE_OK) {
1696 _session_is_new = true;
1698 std::string session_name = m_new_session_dialog->session_name();
1699 std::string session_path = m_new_session_dialog->session_folder();
1702 XXX This is needed because session constructor wants a
1703 non-existant path. hopefully this will be fixed at some point.
1705 session_path = Glib::build_filename(session_path, session_name);
1707 std::string template_name = m_new_session_dialog->session_template_name();
1709 if (m_new_session_dialog->use_session_template()) {
1711 load_session (session_path, session_name, &template_name);
1717 Session::AutoConnectOption iconnect;
1718 Session::AutoConnectOption oconnect;
1720 if (m_new_session_dialog->create_control_bus()) {
1721 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1726 if (m_new_session_dialog->create_master_bus()) {
1727 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1732 if (m_new_session_dialog->connect_inputs()) {
1733 iconnect = Session::AutoConnectPhysical;
1735 iconnect = Session::AutoConnectOption (0);
1738 /// @todo some minor tweaks.
1740 if (m_new_session_dialog->connect_outs_to_master()) {
1741 oconnect = Session::AutoConnectMaster;
1742 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1743 oconnect = Session::AutoConnectPhysical;
1745 oconnect = Session::AutoConnectOption (0);
1748 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1749 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1751 build_session (session_path,
1759 engine->frame_rate() * 60 * 5);
1763 } while(response == Gtk::RESPONSE_HELP);
1764 m_new_session_dialog->hide_all();
1768 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1770 Session *new_session;
1772 session_loaded = false;
1773 x = unload_session ();
1781 /* if it already exists, we must have write access */
1783 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1784 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
1785 You do not have write access to this session.\n\
1786 This prevents the session from being loaded."));
1791 new_session = new Session (*engine, path, snap_name, mix_template);
1796 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1800 connect_to_session (new_session);
1802 //if (engine->running()) {
1803 //mixer->show_window();
1805 session_loaded = true;
1810 ARDOUR_UI::make_session_clean ()
1813 session->set_clean ();
1820 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1821 uint32_t control_channels,
1822 uint32_t master_channels,
1823 Session::AutoConnectOption input_connect,
1824 Session::AutoConnectOption output_connect,
1827 jack_nframes_t initial_length)
1829 Session *new_session;
1832 session_loaded = false;
1833 x = unload_session ();
1840 _session_is_new = true;
1843 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1844 control_channels, master_channels, nphysin, nphysout, initial_length);
1849 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1853 connect_to_session (new_session);
1855 //if (engine->running()) {
1856 //mixer->show_window();
1858 session_loaded = true;
1866 editor->show_window ();
1870 if (session && mixer) {
1871 // mixer->show_window ();
1880 ARDOUR_UI::show_splash ()
1883 about = new About();
1889 ARDOUR_UI::hide_splash ()
1897 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1901 removed = rep.paths.size();
1904 ArdourMessage msg (editor, X_("cleanupresults"),
1906 No audio files were ready for cleanup\n\n\
1907 If this seems suprising, check for any existing\n\
1908 snapshots. These may still include regions that\n\
1909 require some unused files to continue to exist."));
1913 ArdourDialog results (_("ardour: cleanup"), true);
1915 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1916 CleanupResultsModelColumns() {
1920 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1921 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1925 Glib::RefPtr<Gtk::ListStore> results_model;
1926 CleanupResultsModelColumns results_columns;
1927 Gtk::TreeView results_display;
1929 results_model = ListStore::create (results_columns);
1930 results_display.set_model (results_model);
1931 results_display.append_column (list_title, results_columns.visible_name);
1932 results_display.set_headers_visible (true);
1934 Gtk::ScrolledWindow list_scroller;
1937 if (rep.space < 1048576.0f) {
1939 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1941 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1945 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1947 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1951 results.get_vbox()->pack_start (txt, false, false);
1953 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1954 TreeModel::Row row = *(results_model->append());
1955 row[results_columns.visible_name] = *i;
1956 row[results_columns.fullpath] = *i;
1959 list_scroller.add (results_display);
1960 list_scroller.set_size_request (-1, 250);
1961 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1963 results.get_vbox()->pack_start (list_scroller, true, true);
1964 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1965 results.set_position (Gtk::WIN_POS_MOUSE);
1971 ARDOUR_UI::cleanup ()
1974 /* shouldn't happen: menu item is insensitive */
1978 ArdourDialog checker (_("ardour cleanup"));
1979 Gtk::Label label (_("\
1980 Cleanup is a destructive operation.\n\
1981 ALL undo/redo information will be lost if you cleanup.\n\
1982 Unused audio files will be moved to a \"dead sounds\" location."));
1984 checker.get_vbox()->pack_start (label, false, false);
1985 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
1986 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1988 checker.set_name (_("CleanupDialog"));
1989 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
1990 checker.set_position (Gtk::WIN_POS_MOUSE);
1992 switch (checker.run()) {
1993 case RESPONSE_ACCEPT:
1999 Session::cleanup_report rep;
2001 editor->prepare_for_cleanup ();
2003 if (session->cleanup_sources (rep)) {
2007 display_cleanup_results (rep,
2010 The following %1 %2 were not in use.\n\
2011 The next time you flush the wastebasket\n\
2012 it will release an additional %3 %4bytes\n\
2018 ARDOUR_UI::flush_trash ()
2021 /* shouldn't happen: menu item is insensitive */
2025 Session::cleanup_report rep;
2027 if (session->cleanup_trash_sources (rep)) {
2031 display_cleanup_results (rep,
2033 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2037 ARDOUR_UI::add_route ()
2045 if (add_route_dialog == 0) {
2046 add_route_dialog = new AddRouteDialog;
2047 editor->ensure_float (*add_route_dialog);
2050 if (add_route_dialog->is_visible()) {
2051 /* we're already doing this */
2055 ResponseType r = (ResponseType) add_route_dialog->run ();
2057 add_route_dialog->hide();
2060 case RESPONSE_ACCEPT:
2067 if ((count = add_route_dialog->count()) <= 0) {
2071 uint32_t input_chan = add_route_dialog->channels ();
2072 uint32_t output_chan;
2073 string name_template = add_route_dialog->name_template ();
2074 bool track = add_route_dialog->track ();
2076 Session::AutoConnectOption oac = session->get_output_auto_connect();
2078 if (oac & Session::AutoConnectMaster) {
2079 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2081 output_chan = input_chan;
2084 /* XXX do something with name template */
2088 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2090 session_add_audio_bus (input_chan, output_chan);
2094 while (Main::events_pending()) {
2101 ARDOUR_UI::mixer_settings () const
2106 node = session->instant_xml(X_("Mixer"), session->path());
2108 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2112 node = new XMLNode (X_("Mixer"));
2119 ARDOUR_UI::editor_settings () const
2124 node = session->instant_xml(X_("Editor"), session->path());
2126 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2130 node = new XMLNode (X_("Editor"));
2136 ARDOUR_UI::keyboard_settings () const
2140 node = Config->extra_xml(X_("Keyboard"));
2143 node = new XMLNode (X_("Keyboard"));
2149 ARDOUR_UI::halt_on_xrun_message ()
2151 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2153 ArdourMessage msg (editor, X_("haltonxrun"),
2154 _("Recording was stopped because your system could not keep up."));
2158 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2160 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2162 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2166 delete deletion_list;
2170 ARDOUR_UI::disk_overrun_handler ()
2172 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2174 if (!have_disk_overrun_displayed) {
2175 have_disk_overrun_displayed = true;
2176 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
2177 The disk system on your computer\n\
2178 was not able to keep up with Ardour.\n\
2180 Specifically, it failed to write data to disk\n\
2181 quickly enough to keep up with recording.\n"));
2182 have_disk_overrun_displayed = false;
2187 ARDOUR_UI::disk_underrun_handler ()
2189 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2191 if (!have_disk_underrun_displayed) {
2192 have_disk_underrun_displayed = true;
2193 ArdourMessage msg (editor, X_("diskrate2 dialog"),
2194 (_("The disk system on your computer\n\
2195 was not able to keep up with Ardour.\n\
2197 Specifically, it failed to read data from disk\n\
2198 quickly enough to keep up with playback.\n")));
2199 have_disk_underrun_displayed = false;
2204 ARDOUR_UI::disk_underrun_message_gone ()
2206 have_disk_underrun_displayed = false;
2210 ARDOUR_UI::disk_overrun_message_gone ()
2212 have_disk_underrun_displayed = false;
2216 ARDOUR_UI::pending_state_dialog ()
2218 ArdourDialog dialog ("pending state dialog");
2220 This session appears to have been in\n\
2221 middle of recording when ardour or\n\
2222 the computer was shutdown.\n\
2224 Ardour can recover any captured audio for\n\
2225 you, or it can ignore it. Please decide\n\
2226 what you would like to do.\n"));
2228 dialog.get_vbox()->pack_start (message);
2229 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2230 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2232 dialog.set_position (WIN_POS_CENTER);
2235 switch (dialog.run ()) {
2236 case RESPONSE_ACCEPT:
2247 ARDOUR_UI::disconnect_from_jack ()
2250 if( engine->disconnect_from_jack ()) {
2251 ArdourMessage msg (editor, X_("nojack dialog"),
2252 _("Could not disconnect from JACK"));
2255 update_sample_rate (0);
2260 ARDOUR_UI::reconnect_to_jack ()
2263 if (engine->reconnect_to_jack ()) {
2264 ArdourMessage msg (editor, X_("nojack dialog"),
2265 _("Could not reconnect to JACK"));
2268 update_sample_rate (0);
2273 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2275 engine->request_buffer_size (nframes);
2276 update_sample_rate (0);
2280 ARDOUR_UI::cmdline_new_session (string path)
2282 if (path[0] != '/') {
2283 char buf[PATH_MAX+1];
2286 getcwd (buf, sizeof (buf));
2293 new_session (false, path);
2295 _will_create_new_session_automatically = false; /* done it */
2296 return FALSE; /* don't call it again */