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 <gtkmm/messagedialog.h>
33 #include <pbd/error.h>
34 #include <pbd/compose.h>
35 #include <pbd/basename.h>
36 #include <pbd/pathscanner.h>
37 #include <pbd/failed_constructor.h>
38 #include <gtkmm2ext/gtk_ui.h>
39 #include <gtkmm2ext/pix.h>
40 #include <gtkmm2ext/utils.h>
41 #include <gtkmm2ext/click_box.h>
42 #include <gtkmm2ext/fastmeter.h>
43 #include <gtkmm2ext/stop_signal.h>
44 #include <gtkmm2ext/popup.h>
46 #include <midi++/port.h>
47 #include <midi++/mmc.h>
49 #include <ardour/ardour.h>
50 #include <ardour/port.h>
51 #include <ardour/audioengine.h>
52 #include <ardour/playlist.h>
53 #include <ardour/utils.h>
54 #include <ardour/diskstream.h>
55 #include <ardour/filesource.h>
56 #include <ardour/recent_sessions.h>
57 #include <ardour/session_diskstream.h>
58 #include <ardour/port.h>
59 #include <ardour/audio_track.h>
62 #include "ardour_ui.h"
63 #include "public_editor.h"
64 #include "audio_clock.h"
69 #include "keyboard_target.h"
70 #include "add_route_dialog.h"
71 #include "new_session_dialog.h"
74 #include "gui_thread.h"
75 #include "meter_xpms.h"
76 #include "color_manager.h"
80 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
85 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
87 sigc::signal<void,bool> ARDOUR_UI::Blink;
88 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
89 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
90 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
92 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
94 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
96 primary_clock (X_("TransportClockDisplay"), true, false, true),
97 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
98 preroll_clock (X_("PreRollClock"), true, true),
99 postroll_clock (X_("PostRollClock"), true, true),
103 adjuster_table (3, 3),
107 preroll_button (_("pre\nroll")),
108 postroll_button (_("post\nroll")),
112 big_clock ("BigClockDisplay", true),
116 time_master_button (_("time\nmaster")),
118 shuttle_units_button (_("% ")),
120 punch_in_button (_("punch\nin")),
121 punch_out_button (_("punch\nout")),
122 auto_return_button (_("auto\nreturn")),
123 auto_play_button (_("auto\nplay")),
124 auto_input_button (_("auto\ninput")),
125 click_button (_("click")),
126 auditioning_alert_button (_("AUDITIONING")),
127 solo_alert_button (_("SOLO")),
131 using namespace Gtk::Menu_Helpers;
137 if (theArdourUI == 0) {
141 ActionManager::init ();
145 color_manager = new ColorManager();
147 std::string color_file = ARDOUR::find_config_file("ardour.colors");
149 color_manager->load (color_file);
151 m_new_session_dialog = 0;
152 m_new_session_dialog_ref = NewSessionDialogFactory::create();
153 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
157 _session_is_new = false;
158 big_clock_window = 0;
159 session_selector_window = 0;
160 last_key_press_time = 0;
161 connection_editor = 0;
162 add_route_dialog = 0;
167 open_session_selector = 0;
168 have_configure_timeout = false;
169 have_disk_overrun_displayed = false;
170 have_disk_underrun_displayed = false;
171 _will_create_new_session_automatically = false;
172 session_loaded = false;
173 last_speed_displayed = -1.0f;
175 last_configure_time.tv_sec = 0;
176 last_configure_time.tv_usec = 0;
178 shuttle_grabbed = false;
181 set_shuttle_units (Percentage);
182 set_shuttle_behaviour (Sprung);
184 shuttle_style_menu = 0;
185 shuttle_unit_menu = 0;
187 gettimeofday (&last_peak_grab, 0);
188 gettimeofday (&last_shuttle_request, 0);
190 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
191 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
192 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
193 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
195 /* handle pending state with a dialog */
197 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
199 /* have to wait for AudioEngine and Configuration before proceeding */
203 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
205 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
207 string msg = string_compose (_("\
208 You cannot record-enable\n\
210 because it has no input connections.\n\
211 You would be wasting space recording silence."),
214 MessageDialog message (*editor, msg);
219 ARDOUR_UI::set_engine (AudioEngine& e)
223 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
224 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
225 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
226 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
230 keyboard = new Keyboard;
231 install_keybindings ();
233 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
234 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
236 if (setup_windows ()) {
237 throw failed_constructor ();
240 if (GTK_ARDOUR::show_key_actions) {
241 vector<string> names;
242 vector<string> paths;
244 vector<AccelKey> bindings;
246 ActionManager::get_all_actions (names, paths, keys, bindings);
248 vector<string>::iterator n;
249 vector<string>::iterator k;
250 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
251 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
257 /* start with timecode, metering enabled
260 blink_timeout_tag = -1;
262 /* this being a GUI and all, we want peakfiles */
264 FileSource::set_build_peakfiles (true);
265 FileSource::set_build_missing_peakfiles (true);
267 if (Source::start_peak_thread ()) {
268 throw failed_constructor();
271 /* start the time-of-day-clock */
273 update_wall_clock ();
274 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
276 update_disk_space ();
278 update_sample_rate (engine->frame_rate());
280 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
281 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
284 ARDOUR_UI::~ARDOUR_UI ()
286 save_ardour_state ();
300 if (add_route_dialog) {
301 delete add_route_dialog;
304 Source::stop_peak_thread ();
308 ARDOUR_UI::configure_timeout ()
313 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
314 /* no configure events yet */
318 gettimeofday (&now, 0);
319 timersub (&now, &last_configure_time, &diff);
321 /* force a gap of 0.5 seconds since the last configure event
324 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
327 have_configure_timeout = false;
328 save_ardour_state ();
334 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
336 if (have_configure_timeout) {
337 gettimeofday (&last_configure_time, 0);
339 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
340 have_configure_timeout = true;
347 ARDOUR_UI::save_ardour_state ()
349 if (!keyboard || !mixer || !editor) {
353 /* XXX this is all a bit dubious. add_extra_xml() uses
354 a different lifetime model from add_instant_xml().
357 XMLNode* node = new XMLNode (keyboard->get_state());
358 Config->add_extra_xml (*node);
359 Config->save_state();
361 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
362 XMLNode& mnode (mixer->get_state());
365 session->add_instant_xml(enode, session->path());
366 session->add_instant_xml(mnode, session->path());
368 Config->add_instant_xml(enode, get_user_ardour_path());
369 Config->add_instant_xml(mnode, get_user_ardour_path());
374 ARDOUR_UI::startup ()
376 /* Once the UI is up and running, start the audio engine. Doing
377 this before the UI is up and running can cause problems
378 when not running with SCHED_FIFO, because the amount of
379 CPU and disk work needed to get the UI started can interfere
380 with the scheduling of the audio thread.
383 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
389 if (session && session->dirty()) {
390 switch (ask_about_saving_session(_("quit"))) {
395 /* use the default name */
396 if (save_state_canfail ("")) {
397 /* failed - don't quit */
398 MessageDialog msg (*editor,
400 Ardour was unable to save your session.\n\n\
401 If you still wish to quit, please use the\n\n\
402 \"Just quit\" option."));
416 ARDOUR_UI::ask_about_saving_session (const string & what)
418 ArdourDialog window (_("ardour: save session?"));
419 Gtk::Label prompt_label;
422 msg = string_compose(_("Save and %1"), what);
423 window.add_button (msg, RESPONSE_ACCEPT);
424 msg = string_compose(_("Just %1"), what);
425 window.add_button (msg, RESPONSE_APPLY);
426 msg = string_compose(_("Don't %1"), what);
427 window.add_button (msg, RESPONSE_REJECT);
429 Gtk::Button noquit_button (msg);
430 noquit_button.set_name ("EditorGTKButton");
435 if (session->snap_name() == session->name()) {
438 type = _("snapshot");
440 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?"),
441 type, session->snap_name());
443 prompt_label.set_text (prompt);
444 prompt_label.set_alignment (0.5, 0.5);
445 prompt_label.set_name (X_("PrompterLabel"));
447 window.get_vbox()->pack_start (prompt_label);
449 window.set_name (_("Prompter"));
450 window.set_position (Gtk::WIN_POS_MOUSE);
451 window.set_modal (true);
454 save_the_session = 0;
456 editor->ensure_float (window);
458 ResponseType r = (ResponseType) window.run();
463 case RESPONSE_ACCEPT: // save and get out of here
465 case RESPONSE_APPLY: // get out of here
475 ARDOUR_UI::every_second ()
478 update_buffer_load ();
479 update_disk_space ();
480 // update_disk_rate ();
485 ARDOUR_UI::every_point_one_seconds ()
490 /* do not attempt to grab peak power more than once per cycle.
493 gettimeofday (&now, 0);
494 timersub (&now, &last_peak_grab, &diff);
496 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
497 IO::GrabPeakPower(); /* EMIT_SIGNAL */
498 last_peak_grab = now;
501 update_speed_display ();
502 RapidScreenUpdate(); /* EMIT_SIGNAL */
507 ARDOUR_UI::every_point_zero_one_seconds ()
509 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
514 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
518 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
520 if (!engine->connected()) {
522 snprintf (buf, sizeof (buf), _("disconnected"));
526 jack_nframes_t rate = engine->frame_rate();
528 if (fmod (rate, 1000.0) != 0.0) {
529 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
530 (float) rate/1000.0f,
531 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
533 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
535 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
539 sample_rate_label.set_text (buf);
543 ARDOUR_UI::update_cpu_load ()
546 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
547 cpu_load_label.set_text (buf);
551 ARDOUR_UI::update_disk_rate ()
556 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
557 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
558 disk_rate_label.set_text (buf);
560 disk_rate_label.set_text ("");
565 ARDOUR_UI::update_buffer_load ()
570 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
571 session->playback_load(), session->capture_load());
572 buffer_load_label.set_text (buf);
574 buffer_load_label.set_text ("");
579 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
581 if (ds.record_enabled()) {
582 rec_enabled_diskstreams++;
587 ARDOUR_UI::update_disk_space()
593 jack_nframes_t frames = session->available_capture_duration();
596 if (frames == max_frames) {
597 strcpy (buf, _("space: 24hrs+"));
602 jack_nframes_t fr = session->frame_rate();
604 if (session->actively_recording()){
606 rec_enabled_diskstreams = 0;
607 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
609 if (rec_enabled_diskstreams) {
610 frames /= rec_enabled_diskstreams;
615 /* hmmm. shall we divide by the route count? or the diskstream count?
616 or what? for now, do nothing ...
621 hrs = frames / (fr * 3600);
622 frames -= hrs * fr * 3600;
623 mins = frames / (fr * 60);
624 frames -= mins * fr * 60;
627 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
630 disk_space_label.set_text (buf);
634 ARDOUR_UI::update_wall_clock ()
641 tm_now = localtime (&now);
643 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
644 wall_clock_label.set_text (buf);
649 ARDOUR_UI::control_methods_adjusted ()
654 which_method = (int) online_control_button->adjustment.get_value();
655 switch (which_method) {
657 allow_mmc_and_local ();
666 fatal << _("programming error: impossible control method") << endmsg;
672 ARDOUR_UI::mmc_device_id_adjusted ()
677 int dev_id = (int) mmc_id_button->adjustment.get_value();
678 mmc->set_device_id (dev_id);
684 ARDOUR_UI::session_menu (GdkEventButton *ev)
686 session_popup_menu->popup (0, 0);
691 ARDOUR_UI::redisplay_recent_sessions ()
693 vector<string *> *sessions;
694 vector<string *>::iterator i;
695 RecentSessionsSorter cmp;
697 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
698 recent_session_model->clear ();
701 ARDOUR::read_recent_sessions (rs);
704 recent_session_display.set_model (recent_session_model);
708 /* sort them alphabetically */
709 sort (rs.begin(), rs.end(), cmp);
710 sessions = new vector<string*>;
712 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
713 sessions->push_back (new string ((*i).second));
716 for (i = sessions->begin(); i != sessions->end(); ++i) {
718 vector<string*>* states;
719 vector<const gchar*> item;
720 string fullpath = *(*i);
722 /* remove any trailing / */
724 if (fullpath[fullpath.length()-1] == '/') {
725 fullpath = fullpath.substr (0, fullpath.length()-1);
728 /* now get available states for this session */
730 if ((states = Session::possible_states (fullpath)) == 0) {
735 TreeModel::Row row = *(recent_session_model->append());
737 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
738 row[recent_session_columns.fullpath] = fullpath;
740 if (states->size() > 1) {
742 /* add the children */
744 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
746 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
748 child_row[recent_session_columns.visible_name] = **i2;
749 child_row[recent_session_columns.fullpath] = fullpath;
758 recent_session_display.set_model (recent_session_model);
763 ARDOUR_UI::build_session_selector ()
765 session_selector_window = new ArdourDialog ("session selector");
767 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
769 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
770 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
772 recent_session_model = TreeStore::create (recent_session_columns);
773 recent_session_display.set_model (recent_session_model);
774 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
775 recent_session_display.set_headers_visible (false);
777 scroller->add (recent_session_display);
778 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
780 session_selector_window->set_name ("SessionSelectorWindow");
781 session_selector_window->set_size_request (200, 400);
782 session_selector_window->get_vbox()->pack_start (*scroller);
783 session_selector_window->show_all_children();
787 ARDOUR_UI::open_recent_session ()
789 /* popup selector window */
791 if (session_selector_window == 0) {
792 build_session_selector ();
795 redisplay_recent_sessions ();
797 ResponseType r = (ResponseType) session_selector_window->run ();
799 session_selector_window->hide();
802 case RESPONSE_ACCEPT:
808 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
810 if (i == recent_session_model->children().end()) {
814 Glib::ustring path = (*i)[recent_session_columns.fullpath];
815 Glib::ustring state = (*i)[recent_session_columns.visible_name];
817 _session_is_new = false;
819 load_session (path, state);
823 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
827 if (stat (info.filename.c_str(), &statbuf) != 0) {
831 if (!S_ISDIR(statbuf.st_mode)) {
835 string session_file = info.filename;
837 session_file += PBD::basename (info.filename);
838 session_file += ".ardour";
840 if (stat (session_file.c_str(), &statbuf) != 0) {
844 return S_ISREG (statbuf.st_mode);
848 ARDOUR_UI::open_session ()
850 /* popup selector window */
852 if (open_session_selector == 0) {
854 /* ardour sessions are folders */
856 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
857 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
858 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
860 FileFilter session_filter;
861 session_filter.add_pattern ("*.ardour");
862 session_filter.set_name (_("Ardour sessions"));
863 open_session_selector->add_filter (session_filter);
864 open_session_selector->set_filter (session_filter);
867 int response = open_session_selector->run();
868 open_session_selector->hide ();
871 case RESPONSE_ACCEPT:
874 open_session_selector->hide();
878 open_session_selector->hide();
879 string session_path = open_session_selector->get_filename();
883 if (session_path.length() > 0) {
884 if (Session::find_session (session_path, path, name, isnew) == 0) {
885 _session_is_new = isnew;
886 load_session (path, name);
893 ARDOUR_UI::session_add_midi_track ()
895 cerr << _("Patience is a virtue.\n");
899 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
904 warning << _("You cannot add a track without a session already loaded.") << endmsg;
910 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
911 error << _("could not create new audio track") << endmsg;
914 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
915 error << _("could not create new audio bus") << endmsg;
920 if (need_control_room_outs) {
926 route->set_stereo_control_outs (control_lr_channels);
927 route->control_outs()->set_stereo_pan (pans, this);
929 #endif /* CONTROLOUTS */
933 MessageDialog msg (*editor,
934 _("There are insufficient JACK ports available\n\
935 to create a new track or bus.\n\
936 You should save Ardour, exit and\n\
937 restart JACK with more ports."));
943 ARDOUR_UI::diskstream_added (DiskStream* ds)
948 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
950 jack_nframes_t _preroll;
953 _preroll = session->convert_to_frames_at (new_position, session->preroll);
955 if (new_position > _preroll) {
956 new_position -= _preroll;
961 session->request_locate (new_position);
966 ARDOUR_UI::transport_goto_start ()
969 session->goto_start();
972 /* force displayed area in editor to start no matter
973 what "follow playhead" setting is.
977 editor->reposition_x_origin (session->current_start_frame());
983 ARDOUR_UI::transport_goto_zero ()
986 session->request_locate (0);
989 /* force displayed area in editor to start no matter
990 what "follow playhead" setting is.
994 editor->reposition_x_origin (0);
1000 ARDOUR_UI::transport_goto_end ()
1003 jack_nframes_t frame = session->current_end_frame();
1004 session->request_locate (frame);
1006 /* force displayed area in editor to start no matter
1007 what "follow playhead" setting is.
1011 editor->reposition_x_origin (frame);
1017 ARDOUR_UI::transport_stop ()
1023 if (session->is_auditioning()) {
1024 session->cancel_audition ();
1028 if (session->get_auto_loop()) {
1029 session->request_auto_loop (false);
1032 session->request_stop ();
1036 ARDOUR_UI::transport_stop_and_forget_capture ()
1039 session->request_stop (true);
1044 ARDOUR_UI::remove_last_capture()
1047 editor->remove_last_capture();
1052 ARDOUR_UI::transport_record ()
1055 switch (session->record_status()) {
1056 case Session::Disabled:
1057 if (session->ntracks() == 0) {
1058 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1059 MessageDialog msg (*editor, txt);
1063 session->maybe_enable_record ();
1065 case Session::Recording:
1066 case Session::Enabled:
1067 session->disable_record (true);
1073 ARDOUR_UI::transport_roll ()
1081 rolling = session->transport_rolling ();
1083 if (session->get_auto_loop()) {
1084 session->request_auto_loop (false);
1085 auto_loop_button.set_active (false);
1086 roll_button.set_active (true);
1087 } else if (session->get_play_range ()) {
1088 session->request_play_range (false);
1089 play_selection_button.set_active (false);
1090 } else if (rolling) {
1091 session->request_locate (session->last_transport_start(), true);
1094 session->request_transport_speed (1.0f);
1098 ARDOUR_UI::transport_loop()
1101 if (session->get_auto_loop()) {
1102 if (session->transport_rolling()) {
1103 Location * looploc = session->locations()->auto_loop_location();
1105 session->request_locate (looploc->start(), true);
1110 session->request_auto_loop (true);
1116 ARDOUR_UI::transport_play_selection ()
1122 if (!session->get_play_range()) {
1123 session->request_stop ();
1126 editor->play_selection ();
1130 ARDOUR_UI::transport_rewind (int option)
1132 float current_transport_speed;
1135 current_transport_speed = session->transport_speed();
1137 if (current_transport_speed >= 0.0f) {
1140 session->request_transport_speed (-1.0f);
1143 session->request_transport_speed (-4.0f);
1146 session->request_transport_speed (-0.5f);
1151 session->request_transport_speed (current_transport_speed * 1.5f);
1157 ARDOUR_UI::transport_forward (int option)
1159 float current_transport_speed;
1162 current_transport_speed = session->transport_speed();
1164 if (current_transport_speed <= 0.0f) {
1167 session->request_transport_speed (1.0f);
1170 session->request_transport_speed (4.0f);
1173 session->request_transport_speed (0.5f);
1178 session->request_transport_speed (current_transport_speed * 1.5f);
1184 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1192 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1193 Port *port = ds->io()->input (0);
1194 port->request_monitor_input (!port->monitoring_input());
1199 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1207 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1208 ds->set_record_enabled (!ds->record_enabled(), this);
1213 ARDOUR_UI::queue_transport_change ()
1215 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1219 ARDOUR_UI::map_transport_state ()
1221 float sp = session->transport_speed();
1224 transport_rolling ();
1225 } else if (sp < 0.0f) {
1226 transport_rewinding ();
1227 } else if (sp > 0.0f) {
1228 transport_forwarding ();
1230 transport_stopped ();
1235 ARDOUR_UI::send_all_midi_feedback ()
1238 session->send_all_midi_feedback();
1243 ARDOUR_UI::allow_local_only ()
1249 ARDOUR_UI::allow_mmc_only ()
1255 ARDOUR_UI::allow_mmc_and_local ()
1261 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1263 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1264 (int) adj.get_value()].c_str());
1268 ARDOUR_UI::engine_stopped ()
1270 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1271 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1272 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1277 ARDOUR_UI::engine_running ()
1279 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1280 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1281 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1285 ARDOUR_UI::engine_halted ()
1287 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1289 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1290 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1292 update_sample_rate (0);
1294 MessageDialog msg (*editor,
1296 JACK has either been shutdown or it\n\
1297 disconnected Ardour because Ardour\n\
1298 was not fast enough. You can save the\n\
1299 session and/or try to reconnect to JACK ."));
1304 ARDOUR_UI::do_engine_start ()
1310 catch (AudioEngine::PortRegistrationFailure& err) {
1312 error << _("Unable to create all required ports")
1320 error << _("Unable to start the session running")
1330 ARDOUR_UI::start_engine ()
1332 if (do_engine_start () == 0) {
1333 if (session && _session_is_new) {
1334 /* we need to retain initial visual
1335 settings for a new session
1337 session->save_state ("");
1340 /* there is too much going on, in too many threads, for us to
1341 end up with a clean session. So wait 1 second after loading,
1342 and fix it up. its ugly, but until i come across a better
1343 solution, its what we have.
1346 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1353 ARDOUR_UI::update_clocks ()
1355 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1359 ARDOUR_UI::start_clocking ()
1361 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1365 ARDOUR_UI::stop_clocking ()
1367 clock_signal_connection.disconnect ();
1371 ARDOUR_UI::toggle_clocking ()
1374 if (clock_button.get_active()) {
1383 ARDOUR_UI::_blink (void *arg)
1386 ((ARDOUR_UI *) arg)->blink ();
1393 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1397 ARDOUR_UI::start_blinking ()
1399 /* Start the blink signal. Everybody with a blinking widget
1400 uses Blink to drive the widget's state.
1403 if (blink_timeout_tag < 0) {
1405 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1410 ARDOUR_UI::stop_blinking ()
1412 if (blink_timeout_tag >= 0) {
1413 gtk_timeout_remove (blink_timeout_tag);
1414 blink_timeout_tag = -1;
1420 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1422 using namespace Gtk;
1423 using namespace Menu_Helpers;
1425 if (dstream.hidden()) {
1429 MenuList& items = diskstream_menu->items();
1430 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1434 ARDOUR_UI::diskstream_selected (gint32 id)
1436 selected_dstream = id;
1441 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1443 using namespace Gtk;
1444 using namespace Menu_Helpers;
1450 diskstream_menu = new Menu();
1451 diskstream_menu->set_name ("ArdourContextMenu");
1452 using namespace Gtk;
1453 using namespace Menu_Helpers;
1455 MenuList& items = diskstream_menu->items();
1456 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1458 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1461 diskstream_menu->popup (ev->button, ev->time);
1463 diskstream_menu->popup (0, 0);
1466 selected_dstream = -1;
1470 delete diskstream_menu;
1472 return selected_dstream;
1476 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1482 if (io.n_inputs() == 0) {
1487 /* XXX we're not handling multiple ports yet. */
1489 const char **connections = io.input(0)->get_connections();
1491 if (connections == 0 || connections[0] == '\0') {
1494 buf = connections[0];
1501 if (io.n_outputs() == 0) {
1506 /* XXX we're not handling multiple ports yet. */
1508 const char **connections = io.output(0)->get_connections();
1510 if (connections == 0 || connections[0] == '\0') {
1513 buf = connections[0];
1521 ARDOUR_UI::snapshot_session ()
1523 ArdourPrompter prompter (true);
1530 now = now.substr (0, now.length() - 1);
1532 prompter.set_name ("Prompter");
1533 prompter.set_prompt (_("Name for snapshot"));
1534 prompter.set_initial_text (now);
1536 switch (prompter.run()) {
1537 case RESPONSE_ACCEPT:
1538 prompter.get_result (snapname);
1539 if (snapname.length()){
1540 save_state (snapname);
1550 ARDOUR_UI::save_state (const string & name)
1552 (void) save_state_canfail (name);
1556 ARDOUR_UI::save_state_canfail (string name)
1561 if (name.length() == 0) {
1562 name = session->snap_name();
1565 if ((ret = session->save_state (name)) != 0) {
1569 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1574 ARDOUR_UI::restore_state (string name)
1577 if (name.length() == 0) {
1578 name = session->name();
1580 session->restore_state (name);
1585 ARDOUR_UI::primary_clock_value_changed ()
1588 session->request_locate (primary_clock.current_time ());
1593 ARDOUR_UI::secondary_clock_value_changed ()
1596 session->request_locate (secondary_clock.current_time ());
1601 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1603 if (session && dstream && dstream->record_enabled()) {
1605 Session::RecordState rs;
1607 rs = session->record_status ();
1610 case Session::Disabled:
1611 case Session::Enabled:
1612 if (w->get_state() != STATE_SELECTED) {
1613 w->set_state (STATE_SELECTED);
1617 case Session::Recording:
1618 if (w->get_state() != STATE_ACTIVE) {
1619 w->set_state (STATE_ACTIVE);
1625 if (w->get_state() != STATE_NORMAL) {
1626 w->set_state (STATE_NORMAL);
1632 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1638 switch (session->record_status()) {
1639 case Session::Enabled:
1641 rec_button.set_state (1);
1643 rec_button.set_state (0);
1647 case Session::Recording:
1648 rec_button.set_state (2);
1652 rec_button.set_state (0);
1658 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1666 ARDOUR_UI::start_keyboard_prefix ()
1668 keyboard->start_prefix();
1672 ARDOUR_UI::save_template ()
1675 ArdourPrompter prompter (true);
1678 prompter.set_name (X_("Prompter"));
1679 prompter.set_prompt (_("Name for mix template:"));
1680 prompter.set_initial_text(session->name() + _("-template"));
1682 switch (prompter.run()) {
1683 case RESPONSE_ACCEPT:
1684 prompter.get_result (name);
1686 if (name.length()) {
1687 session->save_template (name);
1697 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1699 m_new_session_dialog->show_all();
1700 m_new_session_dialog->set_transient_for(*editor);
1701 m_new_session_dialog->set_name(predetermined_path);
1703 int response = Gtk::RESPONSE_CANCEL;
1706 response = m_new_session_dialog->run ();
1708 if(response == Gtk::RESPONSE_OK) {
1710 _session_is_new = true;
1712 std::string session_name = m_new_session_dialog->session_name();
1713 std::string session_path = m_new_session_dialog->session_folder();
1716 XXX This is needed because session constructor wants a
1717 non-existant path. hopefully this will be fixed at some point.
1719 session_path = Glib::build_filename(session_path, session_name);
1721 std::string template_name = m_new_session_dialog->session_template_name();
1723 if (m_new_session_dialog->use_session_template()) {
1725 load_session (session_path, session_name, &template_name);
1731 Session::AutoConnectOption iconnect;
1732 Session::AutoConnectOption oconnect;
1734 if (m_new_session_dialog->create_control_bus()) {
1735 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1740 if (m_new_session_dialog->create_master_bus()) {
1741 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1746 if (m_new_session_dialog->connect_inputs()) {
1747 iconnect = Session::AutoConnectPhysical;
1749 iconnect = Session::AutoConnectOption (0);
1752 /// @todo some minor tweaks.
1754 if (m_new_session_dialog->connect_outs_to_master()) {
1755 oconnect = Session::AutoConnectMaster;
1756 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1757 oconnect = Session::AutoConnectPhysical;
1759 oconnect = Session::AutoConnectOption (0);
1762 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1763 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1765 build_session (session_path,
1773 engine->frame_rate() * 60 * 5);
1777 } while(response == Gtk::RESPONSE_HELP);
1778 m_new_session_dialog->hide_all();
1782 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1784 Session *new_session;
1786 session_loaded = false;
1787 x = unload_session ();
1795 /* if it already exists, we must have write access */
1797 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1798 MessageDialog msg (*editor, _("\
1799 You do not have write access to this session.\n\
1800 This prevents the session from being loaded."));
1806 new_session = new Session (*engine, path, snap_name, mix_template);
1811 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1815 connect_to_session (new_session);
1817 //if (engine->running()) {
1818 //mixer->show_window();
1820 session_loaded = true;
1825 ARDOUR_UI::make_session_clean ()
1828 session->set_clean ();
1835 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1836 uint32_t control_channels,
1837 uint32_t master_channels,
1838 Session::AutoConnectOption input_connect,
1839 Session::AutoConnectOption output_connect,
1842 jack_nframes_t initial_length)
1844 Session *new_session;
1847 session_loaded = false;
1848 x = unload_session ();
1855 _session_is_new = true;
1858 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1859 control_channels, master_channels, nphysin, nphysout, initial_length);
1864 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1868 connect_to_session (new_session);
1870 //if (engine->running()) {
1871 //mixer->show_window();
1873 session_loaded = true;
1881 editor->show_window ();
1885 if (session && mixer) {
1886 // mixer->show_window ();
1895 ARDOUR_UI::show_splash ()
1898 about = new About();
1904 ARDOUR_UI::hide_splash ()
1912 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1916 removed = rep.paths.size();
1919 MessageDialog msg (*editor, X_("cleanupresults"),
1921 No audio files were ready for cleanup\n\n\
1922 If this seems suprising, check for any existing\n\
1923 snapshots. These may still include regions that\n\
1924 require some unused files to continue to exist."));
1929 ArdourDialog results (_("ardour: cleanup"), true);
1931 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1932 CleanupResultsModelColumns() {
1936 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1937 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1941 Glib::RefPtr<Gtk::ListStore> results_model;
1942 CleanupResultsModelColumns results_columns;
1943 Gtk::TreeView results_display;
1945 results_model = ListStore::create (results_columns);
1946 results_display.set_model (results_model);
1947 results_display.append_column (list_title, results_columns.visible_name);
1948 results_display.set_headers_visible (true);
1950 Gtk::ScrolledWindow list_scroller;
1953 if (rep.space < 1048576.0f) {
1955 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1957 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1961 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1963 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1967 results.get_vbox()->pack_start (txt, false, false);
1969 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1970 TreeModel::Row row = *(results_model->append());
1971 row[results_columns.visible_name] = *i;
1972 row[results_columns.fullpath] = *i;
1975 list_scroller.add (results_display);
1976 list_scroller.set_size_request (-1, 250);
1977 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1979 results.get_vbox()->pack_start (list_scroller, true, true);
1980 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1981 results.set_position (Gtk::WIN_POS_MOUSE);
1987 ARDOUR_UI::cleanup ()
1990 /* shouldn't happen: menu item is insensitive */
1994 ArdourDialog checker (_("ardour cleanup"));
1995 Gtk::Label label (_("\
1996 Cleanup is a destructive operation.\n\
1997 ALL undo/redo information will be lost if you cleanup.\n\
1998 Unused audio files will be moved to a \"dead sounds\" location."));
2000 checker.get_vbox()->pack_start (label, false, false);
2001 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2002 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2004 checker.set_name (_("CleanupDialog"));
2005 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2006 checker.set_position (Gtk::WIN_POS_MOUSE);
2008 switch (checker.run()) {
2009 case RESPONSE_ACCEPT:
2015 Session::cleanup_report rep;
2017 editor->prepare_for_cleanup ();
2019 if (session->cleanup_sources (rep)) {
2023 display_cleanup_results (rep,
2026 The following %1 %2 were not in use.\n\
2027 The next time you flush the wastebasket\n\
2028 it will release an additional %3 %4bytes\n\
2034 ARDOUR_UI::flush_trash ()
2037 /* shouldn't happen: menu item is insensitive */
2041 Session::cleanup_report rep;
2043 if (session->cleanup_trash_sources (rep)) {
2047 display_cleanup_results (rep,
2049 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2053 ARDOUR_UI::add_route ()
2061 if (add_route_dialog == 0) {
2062 add_route_dialog = new AddRouteDialog;
2063 editor->ensure_float (*add_route_dialog);
2066 if (add_route_dialog->is_visible()) {
2067 /* we're already doing this */
2071 ResponseType r = (ResponseType) add_route_dialog->run ();
2073 add_route_dialog->hide();
2076 case RESPONSE_ACCEPT:
2083 if ((count = add_route_dialog->count()) <= 0) {
2087 uint32_t input_chan = add_route_dialog->channels ();
2088 uint32_t output_chan;
2089 string name_template = add_route_dialog->name_template ();
2090 bool track = add_route_dialog->track ();
2092 Session::AutoConnectOption oac = session->get_output_auto_connect();
2094 if (oac & Session::AutoConnectMaster) {
2095 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2097 output_chan = input_chan;
2100 /* XXX do something with name template */
2104 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2106 session_add_audio_bus (input_chan, output_chan);
2110 while (Main::events_pending()) {
2117 ARDOUR_UI::mixer_settings () const
2122 node = session->instant_xml(X_("Mixer"), session->path());
2124 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2128 node = new XMLNode (X_("Mixer"));
2135 ARDOUR_UI::editor_settings () const
2140 node = session->instant_xml(X_("Editor"), session->path());
2142 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2146 node = new XMLNode (X_("Editor"));
2152 ARDOUR_UI::keyboard_settings () const
2156 node = Config->extra_xml(X_("Keyboard"));
2159 node = new XMLNode (X_("Keyboard"));
2165 ARDOUR_UI::halt_on_xrun_message ()
2167 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2169 MessageDialog msg (*editor,
2170 _("Recording was stopped because your system could not keep up."));
2175 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2177 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2179 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2183 delete deletion_list;
2187 ARDOUR_UI::disk_overrun_handler ()
2189 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2191 if (!have_disk_overrun_displayed) {
2192 have_disk_overrun_displayed = true;
2193 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2194 The disk system on your computer\n\
2195 was not able to keep up with Ardour.\n\
2197 Specifically, it failed to write data to disk\n\
2198 quickly enough to keep up with recording.\n"));
2200 have_disk_overrun_displayed = false;
2205 ARDOUR_UI::disk_underrun_handler ()
2207 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2209 if (!have_disk_underrun_displayed) {
2210 have_disk_underrun_displayed = true;
2211 MessageDialog msg (*editor,
2212 (_("The disk system on your computer\n\
2213 was not able to keep up with Ardour.\n\
2215 Specifically, it failed to read data from disk\n\
2216 quickly enough to keep up with playback.\n")));
2218 have_disk_underrun_displayed = false;
2223 ARDOUR_UI::disk_underrun_message_gone ()
2225 have_disk_underrun_displayed = false;
2229 ARDOUR_UI::disk_overrun_message_gone ()
2231 have_disk_underrun_displayed = false;
2235 ARDOUR_UI::pending_state_dialog ()
2237 ArdourDialog dialog ("pending state dialog");
2239 This session appears to have been in\n\
2240 middle of recording when ardour or\n\
2241 the computer was shutdown.\n\
2243 Ardour can recover any captured audio for\n\
2244 you, or it can ignore it. Please decide\n\
2245 what you would like to do.\n"));
2247 dialog.get_vbox()->pack_start (message);
2248 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2249 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2251 dialog.set_position (WIN_POS_CENTER);
2254 switch (dialog.run ()) {
2255 case RESPONSE_ACCEPT:
2266 ARDOUR_UI::disconnect_from_jack ()
2269 if( engine->disconnect_from_jack ()) {
2270 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2274 update_sample_rate (0);
2279 ARDOUR_UI::reconnect_to_jack ()
2282 if (engine->reconnect_to_jack ()) {
2283 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2287 update_sample_rate (0);
2292 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2294 engine->request_buffer_size (nframes);
2295 update_sample_rate (0);
2299 ARDOUR_UI::cmdline_new_session (string path)
2301 if (path[0] != '/') {
2302 char buf[PATH_MAX+1];
2305 getcwd (buf, sizeof (buf));
2312 new_session (false, path);
2314 _will_create_new_session_automatically = false; /* done it */
2315 return FALSE; /* don't call it again */