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;
135 /* actually, its already loaded, but ... */
137 cerr << "Loading UI configuration file " << rcfile << endl;
141 if (theArdourUI == 0) {
145 ActionManager::init ();
149 color_manager = new ColorManager();
151 std::string color_file = Glib::getenv(X_("ARDOUR_COLORS"));
152 if(!Glib::file_test(color_file, Glib::FILE_TEST_EXISTS)) {
153 color_file = ARDOUR::find_config_file("ardour.colors");
156 cerr << "Loading UI color configuration file " << color_file << endl;
158 color_manager->load (color_file);
160 m_new_session_dialog = 0;
161 m_new_session_dialog_ref = NewSessionDialogFactory::create();
162 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
166 _session_is_new = false;
167 big_clock_window = 0;
168 session_selector_window = 0;
169 last_key_press_time = 0;
170 connection_editor = 0;
171 add_route_dialog = 0;
176 open_session_selector = 0;
177 have_configure_timeout = false;
178 have_disk_overrun_displayed = false;
179 have_disk_underrun_displayed = false;
180 _will_create_new_session_automatically = false;
181 session_loaded = false;
182 last_speed_displayed = -1.0f;
184 last_configure_time.tv_sec = 0;
185 last_configure_time.tv_usec = 0;
187 shuttle_grabbed = false;
190 set_shuttle_units (Percentage);
191 set_shuttle_behaviour (Sprung);
193 shuttle_style_menu = 0;
194 shuttle_unit_menu = 0;
196 gettimeofday (&last_peak_grab, 0);
197 gettimeofday (&last_shuttle_request, 0);
199 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
200 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
201 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
202 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
204 /* handle pending state with a dialog */
206 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
208 /* have to wait for AudioEngine and Configuration before proceeding */
212 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
214 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
216 string msg = string_compose (_("\
217 You cannot record-enable\n\
219 because it has no input connections.\n\
220 You would be wasting space recording silence."),
223 MessageDialog message (*editor, msg);
228 ARDOUR_UI::set_engine (AudioEngine& e)
232 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
233 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
234 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
235 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
239 keyboard = new Keyboard;
240 install_keybindings ();
242 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
243 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
245 if (setup_windows ()) {
246 throw failed_constructor ();
249 if (GTK_ARDOUR::show_key_actions) {
250 vector<string> names;
251 vector<string> paths;
253 vector<AccelKey> bindings;
255 ActionManager::get_all_actions (names, paths, keys, bindings);
257 vector<string>::iterator n;
258 vector<string>::iterator k;
259 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
260 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
266 /* start with timecode, metering enabled
269 blink_timeout_tag = -1;
271 /* this being a GUI and all, we want peakfiles */
273 FileSource::set_build_peakfiles (true);
274 FileSource::set_build_missing_peakfiles (true);
276 if (Source::start_peak_thread ()) {
277 throw failed_constructor();
280 /* start the time-of-day-clock */
282 update_wall_clock ();
283 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
285 update_disk_space ();
287 update_sample_rate (engine->frame_rate());
289 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
290 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
293 ARDOUR_UI::~ARDOUR_UI ()
295 save_ardour_state ();
309 if (add_route_dialog) {
310 delete add_route_dialog;
313 Source::stop_peak_thread ();
317 ARDOUR_UI::configure_timeout ()
322 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
323 /* no configure events yet */
327 gettimeofday (&now, 0);
328 timersub (&now, &last_configure_time, &diff);
330 /* force a gap of 0.5 seconds since the last configure event
333 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
336 have_configure_timeout = false;
337 save_ardour_state ();
343 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
345 if (have_configure_timeout) {
346 gettimeofday (&last_configure_time, 0);
348 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
349 have_configure_timeout = true;
356 ARDOUR_UI::save_ardour_state ()
358 if (!keyboard || !mixer || !editor) {
362 /* XXX this is all a bit dubious. add_extra_xml() uses
363 a different lifetime model from add_instant_xml().
366 XMLNode* node = new XMLNode (keyboard->get_state());
367 Config->add_extra_xml (*node);
368 Config->save_state();
370 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
371 XMLNode& mnode (mixer->get_state());
374 session->add_instant_xml(enode, session->path());
375 session->add_instant_xml(mnode, session->path());
377 Config->add_instant_xml(enode, Config->get_user_ardour_path());
378 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
383 ARDOUR_UI::startup ()
385 /* Once the UI is up and running, start the audio engine. Doing
386 this before the UI is up and running can cause problems
387 when not running with SCHED_FIFO, because the amount of
388 CPU and disk work needed to get the UI started can interfere
389 with the scheduling of the audio thread.
392 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
398 if (session && session->dirty()) {
399 switch (ask_about_saving_session(_("quit"))) {
404 /* use the default name */
405 if (save_state_canfail ("")) {
406 /* failed - don't quit */
407 MessageDialog msg (*editor,
409 Ardour was unable to save your session.\n\n\
410 If you still wish to quit, please use the\n\n\
411 \"Just quit\" option."));
425 ARDOUR_UI::ask_about_saving_session (const string & what)
427 ArdourDialog window (_("ardour: save session?"));
428 Gtk::Label prompt_label;
431 msg = string_compose(_("Save and %1"), what);
432 window.add_button (msg, RESPONSE_ACCEPT);
433 msg = string_compose(_("Just %1"), what);
434 window.add_button (msg, RESPONSE_APPLY);
435 msg = string_compose(_("Don't %1"), what);
436 window.add_button (msg, RESPONSE_REJECT);
438 Gtk::Button noquit_button (msg);
439 noquit_button.set_name ("EditorGTKButton");
444 if (session->snap_name() == session->name()) {
447 type = _("snapshot");
449 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?"),
450 type, session->snap_name());
452 prompt_label.set_text (prompt);
453 prompt_label.set_alignment (0.5, 0.5);
454 prompt_label.set_name (X_("PrompterLabel"));
456 window.get_vbox()->pack_start (prompt_label);
458 window.set_name (_("Prompter"));
459 window.set_position (Gtk::WIN_POS_MOUSE);
460 window.set_modal (true);
463 save_the_session = 0;
465 editor->ensure_float (window);
467 ResponseType r = (ResponseType) window.run();
472 case RESPONSE_ACCEPT: // save and get out of here
474 case RESPONSE_APPLY: // get out of here
484 ARDOUR_UI::every_second ()
487 update_buffer_load ();
488 update_disk_space ();
489 // update_disk_rate ();
494 ARDOUR_UI::every_point_one_seconds ()
499 /* do not attempt to grab peak power more than once per cycle.
502 gettimeofday (&now, 0);
503 timersub (&now, &last_peak_grab, &diff);
505 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
506 IO::GrabPeakPower(); /* EMIT_SIGNAL */
507 last_peak_grab = now;
510 update_speed_display ();
511 RapidScreenUpdate(); /* EMIT_SIGNAL */
516 ARDOUR_UI::every_point_zero_one_seconds ()
518 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
523 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
527 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
529 if (!engine->connected()) {
531 snprintf (buf, sizeof (buf), _("disconnected"));
535 jack_nframes_t rate = engine->frame_rate();
537 if (fmod (rate, 1000.0) != 0.0) {
538 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
539 (float) rate/1000.0f,
540 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
542 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
544 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
548 sample_rate_label.set_text (buf);
552 ARDOUR_UI::update_cpu_load ()
555 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
556 cpu_load_label.set_text (buf);
560 ARDOUR_UI::update_disk_rate ()
565 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
566 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
567 disk_rate_label.set_text (buf);
569 disk_rate_label.set_text ("");
574 ARDOUR_UI::update_buffer_load ()
579 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
580 session->playback_load(), session->capture_load());
581 buffer_load_label.set_text (buf);
583 buffer_load_label.set_text ("");
588 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
590 if (ds.record_enabled()) {
591 rec_enabled_diskstreams++;
596 ARDOUR_UI::update_disk_space()
602 jack_nframes_t frames = session->available_capture_duration();
605 if (frames == max_frames) {
606 strcpy (buf, _("space: 24hrs+"));
611 jack_nframes_t fr = session->frame_rate();
613 if (session->actively_recording()){
615 rec_enabled_diskstreams = 0;
616 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
618 if (rec_enabled_diskstreams) {
619 frames /= rec_enabled_diskstreams;
624 /* hmmm. shall we divide by the route count? or the diskstream count?
625 or what? for now, do nothing ...
630 hrs = frames / (fr * 3600);
631 frames -= hrs * fr * 3600;
632 mins = frames / (fr * 60);
633 frames -= mins * fr * 60;
636 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
639 disk_space_label.set_text (buf);
643 ARDOUR_UI::update_wall_clock ()
650 tm_now = localtime (&now);
652 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
653 wall_clock_label.set_text (buf);
658 ARDOUR_UI::control_methods_adjusted ()
663 which_method = (int) online_control_button->adjustment.get_value();
664 switch (which_method) {
666 allow_mmc_and_local ();
675 fatal << _("programming error: impossible control method") << endmsg;
681 ARDOUR_UI::mmc_device_id_adjusted ()
686 int dev_id = (int) mmc_id_button->adjustment.get_value();
687 mmc->set_device_id (dev_id);
693 ARDOUR_UI::session_menu (GdkEventButton *ev)
695 session_popup_menu->popup (0, 0);
700 ARDOUR_UI::redisplay_recent_sessions ()
702 vector<string *> *sessions;
703 vector<string *>::iterator i;
704 RecentSessionsSorter cmp;
706 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
707 recent_session_model->clear ();
710 ARDOUR::read_recent_sessions (rs);
713 recent_session_display.set_model (recent_session_model);
717 /* sort them alphabetically */
718 sort (rs.begin(), rs.end(), cmp);
719 sessions = new vector<string*>;
721 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
722 sessions->push_back (new string ((*i).second));
725 for (i = sessions->begin(); i != sessions->end(); ++i) {
727 vector<string*>* states;
728 vector<const gchar*> item;
729 string fullpath = *(*i);
731 /* remove any trailing / */
733 if (fullpath[fullpath.length()-1] == '/') {
734 fullpath = fullpath.substr (0, fullpath.length()-1);
737 /* now get available states for this session */
739 if ((states = Session::possible_states (fullpath)) == 0) {
744 TreeModel::Row row = *(recent_session_model->append());
746 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
747 row[recent_session_columns.fullpath] = fullpath;
749 if (states->size() > 1) {
751 /* add the children */
753 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
755 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
757 child_row[recent_session_columns.visible_name] = **i2;
758 child_row[recent_session_columns.fullpath] = fullpath;
767 recent_session_display.set_model (recent_session_model);
772 ARDOUR_UI::build_session_selector ()
774 session_selector_window = new ArdourDialog ("session selector");
776 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
778 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
779 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
781 recent_session_model = TreeStore::create (recent_session_columns);
782 recent_session_display.set_model (recent_session_model);
783 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
784 recent_session_display.set_headers_visible (false);
786 scroller->add (recent_session_display);
787 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
789 session_selector_window->set_name ("SessionSelectorWindow");
790 session_selector_window->set_size_request (200, 400);
791 session_selector_window->get_vbox()->pack_start (*scroller);
792 session_selector_window->show_all_children();
796 ARDOUR_UI::open_recent_session ()
798 /* popup selector window */
800 if (session_selector_window == 0) {
801 build_session_selector ();
804 redisplay_recent_sessions ();
806 ResponseType r = (ResponseType) session_selector_window->run ();
808 session_selector_window->hide();
811 case RESPONSE_ACCEPT:
817 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
819 if (i == recent_session_model->children().end()) {
823 Glib::ustring path = (*i)[recent_session_columns.fullpath];
824 Glib::ustring state = (*i)[recent_session_columns.visible_name];
826 _session_is_new = false;
828 load_session (path, state);
832 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
836 if (stat (info.filename.c_str(), &statbuf) != 0) {
840 if (!S_ISDIR(statbuf.st_mode)) {
844 string session_file = info.filename;
846 session_file += PBD::basename (info.filename);
847 session_file += ".ardour";
849 if (stat (session_file.c_str(), &statbuf) != 0) {
853 return S_ISREG (statbuf.st_mode);
857 ARDOUR_UI::open_session ()
859 /* popup selector window */
861 if (open_session_selector == 0) {
863 /* ardour sessions are folders */
865 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
866 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
867 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
869 FileFilter session_filter;
870 session_filter.add_pattern ("*.ardour");
871 session_filter.set_name (_("Ardour sessions"));
872 open_session_selector->add_filter (session_filter);
873 open_session_selector->set_filter (session_filter);
876 int response = open_session_selector->run();
877 open_session_selector->hide ();
880 case RESPONSE_ACCEPT:
883 open_session_selector->hide();
887 open_session_selector->hide();
888 string session_path = open_session_selector->get_filename();
892 if (session_path.length() > 0) {
893 if (Session::find_session (session_path, path, name, isnew) == 0) {
894 _session_is_new = isnew;
895 load_session (path, name);
902 ARDOUR_UI::session_add_midi_track ()
904 cerr << _("Patience is a virtue.\n");
908 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
913 warning << _("You cannot add a track without a session already loaded.") << endmsg;
919 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
920 error << _("could not create new audio track") << endmsg;
923 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
924 error << _("could not create new audio bus") << endmsg;
929 if (need_control_room_outs) {
935 route->set_stereo_control_outs (control_lr_channels);
936 route->control_outs()->set_stereo_pan (pans, this);
938 #endif /* CONTROLOUTS */
942 MessageDialog msg (*editor,
943 _("There are insufficient JACK ports available\n\
944 to create a new track or bus.\n\
945 You should save Ardour, exit and\n\
946 restart JACK with more ports."));
952 ARDOUR_UI::diskstream_added (DiskStream* ds)
957 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
959 jack_nframes_t _preroll;
962 _preroll = session->convert_to_frames_at (new_position, session->preroll);
964 if (new_position > _preroll) {
965 new_position -= _preroll;
970 session->request_locate (new_position);
975 ARDOUR_UI::transport_goto_start ()
978 session->goto_start();
981 /* force displayed area in editor to start no matter
982 what "follow playhead" setting is.
986 editor->reposition_x_origin (session->current_start_frame());
992 ARDOUR_UI::transport_goto_zero ()
995 session->request_locate (0);
998 /* force displayed area in editor to start no matter
999 what "follow playhead" setting is.
1003 editor->reposition_x_origin (0);
1009 ARDOUR_UI::transport_goto_end ()
1012 jack_nframes_t frame = session->current_end_frame();
1013 session->request_locate (frame);
1015 /* force displayed area in editor to start no matter
1016 what "follow playhead" setting is.
1020 editor->reposition_x_origin (frame);
1026 ARDOUR_UI::transport_stop ()
1032 if (session->is_auditioning()) {
1033 session->cancel_audition ();
1037 if (session->get_auto_loop()) {
1038 session->request_auto_loop (false);
1041 session->request_stop ();
1045 ARDOUR_UI::transport_stop_and_forget_capture ()
1048 session->request_stop (true);
1053 ARDOUR_UI::remove_last_capture()
1056 editor->remove_last_capture();
1061 ARDOUR_UI::transport_record ()
1064 switch (session->record_status()) {
1065 case Session::Disabled:
1066 if (session->ntracks() == 0) {
1067 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1068 MessageDialog msg (*editor, txt);
1072 session->maybe_enable_record ();
1074 case Session::Recording:
1075 case Session::Enabled:
1076 session->disable_record (true);
1082 ARDOUR_UI::transport_roll ()
1090 rolling = session->transport_rolling ();
1092 if (session->get_auto_loop()) {
1093 session->request_auto_loop (false);
1094 auto_loop_button.set_active (false);
1095 roll_button.set_active (true);
1096 } else if (session->get_play_range ()) {
1097 session->request_play_range (false);
1098 play_selection_button.set_active (false);
1099 } else if (rolling) {
1100 session->request_locate (session->last_transport_start(), true);
1103 session->request_transport_speed (1.0f);
1107 ARDOUR_UI::transport_loop()
1110 if (session->get_auto_loop()) {
1111 if (session->transport_rolling()) {
1112 Location * looploc = session->locations()->auto_loop_location();
1114 session->request_locate (looploc->start(), true);
1119 session->request_auto_loop (true);
1125 ARDOUR_UI::transport_play_selection ()
1131 if (!session->get_play_range()) {
1132 session->request_stop ();
1135 editor->play_selection ();
1139 ARDOUR_UI::transport_rewind (int option)
1141 float current_transport_speed;
1144 current_transport_speed = session->transport_speed();
1146 if (current_transport_speed >= 0.0f) {
1149 session->request_transport_speed (-1.0f);
1152 session->request_transport_speed (-4.0f);
1155 session->request_transport_speed (-0.5f);
1160 session->request_transport_speed (current_transport_speed * 1.5f);
1166 ARDOUR_UI::transport_forward (int option)
1168 float current_transport_speed;
1171 current_transport_speed = session->transport_speed();
1173 if (current_transport_speed <= 0.0f) {
1176 session->request_transport_speed (1.0f);
1179 session->request_transport_speed (4.0f);
1182 session->request_transport_speed (0.5f);
1187 session->request_transport_speed (current_transport_speed * 1.5f);
1193 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1201 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1202 Port *port = ds->io()->input (0);
1203 port->request_monitor_input (!port->monitoring_input());
1208 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1216 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1217 ds->set_record_enabled (!ds->record_enabled(), this);
1222 ARDOUR_UI::queue_transport_change ()
1224 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1228 ARDOUR_UI::map_transport_state ()
1230 float sp = session->transport_speed();
1233 transport_rolling ();
1234 } else if (sp < 0.0f) {
1235 transport_rewinding ();
1236 } else if (sp > 0.0f) {
1237 transport_forwarding ();
1239 transport_stopped ();
1244 ARDOUR_UI::send_all_midi_feedback ()
1247 session->send_all_midi_feedback();
1252 ARDOUR_UI::allow_local_only ()
1258 ARDOUR_UI::allow_mmc_only ()
1264 ARDOUR_UI::allow_mmc_and_local ()
1270 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1272 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1273 (int) adj.get_value()].c_str());
1277 ARDOUR_UI::engine_stopped ()
1279 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1280 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1281 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1286 ARDOUR_UI::engine_running ()
1288 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1289 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1290 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1294 ARDOUR_UI::engine_halted ()
1296 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1298 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1299 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1301 update_sample_rate (0);
1303 MessageDialog msg (*editor,
1305 JACK has either been shutdown or it\n\
1306 disconnected Ardour because Ardour\n\
1307 was not fast enough. You can save the\n\
1308 session and/or try to reconnect to JACK ."));
1313 ARDOUR_UI::do_engine_start ()
1319 catch (AudioEngine::PortRegistrationFailure& err) {
1321 error << _("Unable to create all required ports")
1329 error << _("Unable to start the session running")
1339 ARDOUR_UI::start_engine ()
1341 if (do_engine_start () == 0) {
1342 if (session && _session_is_new) {
1343 /* we need to retain initial visual
1344 settings for a new session
1346 session->save_state ("");
1349 /* there is too much going on, in too many threads, for us to
1350 end up with a clean session. So wait 1 second after loading,
1351 and fix it up. its ugly, but until i come across a better
1352 solution, its what we have.
1355 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1362 ARDOUR_UI::update_clocks ()
1364 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1368 ARDOUR_UI::start_clocking ()
1370 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1374 ARDOUR_UI::stop_clocking ()
1376 clock_signal_connection.disconnect ();
1380 ARDOUR_UI::toggle_clocking ()
1383 if (clock_button.get_active()) {
1392 ARDOUR_UI::_blink (void *arg)
1395 ((ARDOUR_UI *) arg)->blink ();
1402 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1406 ARDOUR_UI::start_blinking ()
1408 /* Start the blink signal. Everybody with a blinking widget
1409 uses Blink to drive the widget's state.
1412 if (blink_timeout_tag < 0) {
1414 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1419 ARDOUR_UI::stop_blinking ()
1421 if (blink_timeout_tag >= 0) {
1422 gtk_timeout_remove (blink_timeout_tag);
1423 blink_timeout_tag = -1;
1429 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1431 using namespace Gtk;
1432 using namespace Menu_Helpers;
1434 if (dstream.hidden()) {
1438 MenuList& items = diskstream_menu->items();
1439 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1443 ARDOUR_UI::diskstream_selected (gint32 id)
1445 selected_dstream = id;
1450 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1452 using namespace Gtk;
1453 using namespace Menu_Helpers;
1459 diskstream_menu = new Menu();
1460 diskstream_menu->set_name ("ArdourContextMenu");
1461 using namespace Gtk;
1462 using namespace Menu_Helpers;
1464 MenuList& items = diskstream_menu->items();
1465 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1467 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1470 diskstream_menu->popup (ev->button, ev->time);
1472 diskstream_menu->popup (0, 0);
1475 selected_dstream = -1;
1479 delete diskstream_menu;
1481 return selected_dstream;
1485 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1491 if (io.n_inputs() == 0) {
1496 /* XXX we're not handling multiple ports yet. */
1498 const char **connections = io.input(0)->get_connections();
1500 if (connections == 0 || connections[0] == '\0') {
1503 buf = connections[0];
1510 if (io.n_outputs() == 0) {
1515 /* XXX we're not handling multiple ports yet. */
1517 const char **connections = io.output(0)->get_connections();
1519 if (connections == 0 || connections[0] == '\0') {
1522 buf = connections[0];
1530 ARDOUR_UI::snapshot_session ()
1532 ArdourPrompter prompter (true);
1539 now = now.substr (0, now.length() - 1);
1541 prompter.set_name ("Prompter");
1542 prompter.set_prompt (_("Name for snapshot"));
1543 prompter.set_initial_text (now);
1545 switch (prompter.run()) {
1546 case RESPONSE_ACCEPT:
1547 prompter.get_result (snapname);
1548 if (snapname.length()){
1549 save_state (snapname);
1559 ARDOUR_UI::save_state (const string & name)
1561 (void) save_state_canfail (name);
1565 ARDOUR_UI::save_state_canfail (string name)
1570 if (name.length() == 0) {
1571 name = session->snap_name();
1574 if ((ret = session->save_state (name)) != 0) {
1578 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1583 ARDOUR_UI::restore_state (string name)
1586 if (name.length() == 0) {
1587 name = session->name();
1589 session->restore_state (name);
1594 ARDOUR_UI::primary_clock_value_changed ()
1597 session->request_locate (primary_clock.current_time ());
1602 ARDOUR_UI::secondary_clock_value_changed ()
1605 session->request_locate (secondary_clock.current_time ());
1610 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1612 if (session && dstream && dstream->record_enabled()) {
1614 Session::RecordState rs;
1616 rs = session->record_status ();
1619 case Session::Disabled:
1620 case Session::Enabled:
1621 if (w->get_state() != STATE_SELECTED) {
1622 w->set_state (STATE_SELECTED);
1626 case Session::Recording:
1627 if (w->get_state() != STATE_ACTIVE) {
1628 w->set_state (STATE_ACTIVE);
1634 if (w->get_state() != STATE_NORMAL) {
1635 w->set_state (STATE_NORMAL);
1641 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1647 switch (session->record_status()) {
1648 case Session::Enabled:
1650 rec_button.set_state (1);
1652 rec_button.set_state (0);
1656 case Session::Recording:
1657 rec_button.set_state (2);
1661 rec_button.set_state (0);
1667 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1675 ARDOUR_UI::start_keyboard_prefix ()
1677 keyboard->start_prefix();
1681 ARDOUR_UI::save_template ()
1684 ArdourPrompter prompter (true);
1687 prompter.set_name (X_("Prompter"));
1688 prompter.set_prompt (_("Name for mix template:"));
1689 prompter.set_initial_text(session->name() + _("-template"));
1691 switch (prompter.run()) {
1692 case RESPONSE_ACCEPT:
1693 prompter.get_result (name);
1695 if (name.length()) {
1696 session->save_template (name);
1706 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1708 m_new_session_dialog->show_all();
1709 m_new_session_dialog->set_transient_for(*editor);
1710 m_new_session_dialog->set_name(predetermined_path);
1712 int response = Gtk::RESPONSE_CANCEL;
1715 response = m_new_session_dialog->run ();
1717 if(response == Gtk::RESPONSE_OK) {
1719 _session_is_new = true;
1721 std::string session_name = m_new_session_dialog->session_name();
1722 std::string session_path = m_new_session_dialog->session_folder();
1725 XXX This is needed because session constructor wants a
1726 non-existant path. hopefully this will be fixed at some point.
1728 session_path = Glib::build_filename(session_path, session_name);
1730 std::string template_name = m_new_session_dialog->session_template_name();
1732 if (m_new_session_dialog->use_session_template()) {
1734 load_session (session_path, session_name, &template_name);
1740 Session::AutoConnectOption iconnect;
1741 Session::AutoConnectOption oconnect;
1743 if (m_new_session_dialog->create_control_bus()) {
1744 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1749 if (m_new_session_dialog->create_master_bus()) {
1750 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1755 if (m_new_session_dialog->connect_inputs()) {
1756 iconnect = Session::AutoConnectPhysical;
1758 iconnect = Session::AutoConnectOption (0);
1761 /// @todo some minor tweaks.
1763 if (m_new_session_dialog->connect_outs_to_master()) {
1764 oconnect = Session::AutoConnectMaster;
1765 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1766 oconnect = Session::AutoConnectPhysical;
1768 oconnect = Session::AutoConnectOption (0);
1771 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1772 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1774 build_session (session_path,
1782 engine->frame_rate() * 60 * 5);
1786 } while(response == Gtk::RESPONSE_HELP);
1787 m_new_session_dialog->hide_all();
1791 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1793 Session *new_session;
1795 session_loaded = false;
1796 x = unload_session ();
1804 /* if it already exists, we must have write access */
1806 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1807 MessageDialog msg (*editor, _("\
1808 You do not have write access to this session.\n\
1809 This prevents the session from being loaded."));
1815 new_session = new Session (*engine, path, snap_name, mix_template);
1820 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1824 connect_to_session (new_session);
1826 //if (engine->running()) {
1827 //mixer->show_window();
1829 session_loaded = true;
1834 ARDOUR_UI::make_session_clean ()
1837 session->set_clean ();
1844 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1845 uint32_t control_channels,
1846 uint32_t master_channels,
1847 Session::AutoConnectOption input_connect,
1848 Session::AutoConnectOption output_connect,
1851 jack_nframes_t initial_length)
1853 Session *new_session;
1856 session_loaded = false;
1857 x = unload_session ();
1864 _session_is_new = true;
1867 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1868 control_channels, master_channels, nphysin, nphysout, initial_length);
1873 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1877 connect_to_session (new_session);
1879 //if (engine->running()) {
1880 //mixer->show_window();
1882 session_loaded = true;
1890 editor->show_window ();
1894 if (session && mixer) {
1895 // mixer->show_window ();
1904 ARDOUR_UI::show_splash ()
1907 about = new About();
1913 ARDOUR_UI::hide_splash ()
1921 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1925 removed = rep.paths.size();
1928 MessageDialog msg (*editor, X_("cleanupresults"),
1930 No audio files were ready for cleanup\n\n\
1931 If this seems suprising, check for any existing\n\
1932 snapshots. These may still include regions that\n\
1933 require some unused files to continue to exist."));
1938 ArdourDialog results (_("ardour: cleanup"), true);
1940 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1941 CleanupResultsModelColumns() {
1945 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1946 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1950 Glib::RefPtr<Gtk::ListStore> results_model;
1951 CleanupResultsModelColumns results_columns;
1952 Gtk::TreeView results_display;
1954 results_model = ListStore::create (results_columns);
1955 results_display.set_model (results_model);
1956 results_display.append_column (list_title, results_columns.visible_name);
1957 results_display.set_headers_visible (true);
1959 Gtk::ScrolledWindow list_scroller;
1962 if (rep.space < 1048576.0f) {
1964 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1966 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1970 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1972 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1976 results.get_vbox()->pack_start (txt, false, false);
1978 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1979 TreeModel::Row row = *(results_model->append());
1980 row[results_columns.visible_name] = *i;
1981 row[results_columns.fullpath] = *i;
1984 list_scroller.add (results_display);
1985 list_scroller.set_size_request (-1, 250);
1986 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1988 results.get_vbox()->pack_start (list_scroller, true, true);
1989 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1990 results.set_position (Gtk::WIN_POS_MOUSE);
1996 ARDOUR_UI::cleanup ()
1999 /* shouldn't happen: menu item is insensitive */
2003 ArdourDialog checker (_("ardour cleanup"));
2004 Gtk::Label label (_("\
2005 Cleanup is a destructive operation.\n\
2006 ALL undo/redo information will be lost if you cleanup.\n\
2007 Unused audio files will be moved to a \"dead sounds\" location."));
2009 checker.get_vbox()->pack_start (label, false, false);
2010 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2011 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2013 checker.set_name (_("CleanupDialog"));
2014 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2015 checker.set_position (Gtk::WIN_POS_MOUSE);
2017 switch (checker.run()) {
2018 case RESPONSE_ACCEPT:
2024 Session::cleanup_report rep;
2026 editor->prepare_for_cleanup ();
2028 if (session->cleanup_sources (rep)) {
2032 display_cleanup_results (rep,
2035 The following %1 %2 were not in use.\n\
2036 The next time you flush the wastebasket\n\
2037 it will release an additional %3 %4bytes\n\
2043 ARDOUR_UI::flush_trash ()
2046 /* shouldn't happen: menu item is insensitive */
2050 Session::cleanup_report rep;
2052 if (session->cleanup_trash_sources (rep)) {
2056 display_cleanup_results (rep,
2058 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2062 ARDOUR_UI::add_route ()
2070 if (add_route_dialog == 0) {
2071 add_route_dialog = new AddRouteDialog;
2072 editor->ensure_float (*add_route_dialog);
2075 if (add_route_dialog->is_visible()) {
2076 /* we're already doing this */
2080 ResponseType r = (ResponseType) add_route_dialog->run ();
2082 add_route_dialog->hide();
2085 case RESPONSE_ACCEPT:
2092 if ((count = add_route_dialog->count()) <= 0) {
2096 uint32_t input_chan = add_route_dialog->channels ();
2097 uint32_t output_chan;
2098 string name_template = add_route_dialog->name_template ();
2099 bool track = add_route_dialog->track ();
2101 Session::AutoConnectOption oac = session->get_output_auto_connect();
2103 if (oac & Session::AutoConnectMaster) {
2104 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2106 output_chan = input_chan;
2109 /* XXX do something with name template */
2113 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2115 session_add_audio_bus (input_chan, output_chan);
2119 while (Main::events_pending()) {
2126 ARDOUR_UI::mixer_settings () const
2131 node = session->instant_xml(X_("Mixer"), session->path());
2133 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2137 node = new XMLNode (X_("Mixer"));
2144 ARDOUR_UI::editor_settings () const
2149 node = session->instant_xml(X_("Editor"), session->path());
2151 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2155 node = new XMLNode (X_("Editor"));
2161 ARDOUR_UI::keyboard_settings () const
2165 node = Config->extra_xml(X_("Keyboard"));
2168 node = new XMLNode (X_("Keyboard"));
2174 ARDOUR_UI::halt_on_xrun_message ()
2176 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2178 MessageDialog msg (*editor,
2179 _("Recording was stopped because your system could not keep up."));
2184 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2186 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2188 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2192 delete deletion_list;
2196 ARDOUR_UI::disk_overrun_handler ()
2198 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2200 if (!have_disk_overrun_displayed) {
2201 have_disk_overrun_displayed = true;
2202 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2203 The disk system on your computer\n\
2204 was not able to keep up with Ardour.\n\
2206 Specifically, it failed to write data to disk\n\
2207 quickly enough to keep up with recording.\n"));
2209 have_disk_overrun_displayed = false;
2214 ARDOUR_UI::disk_underrun_handler ()
2216 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2218 if (!have_disk_underrun_displayed) {
2219 have_disk_underrun_displayed = true;
2220 MessageDialog msg (*editor,
2221 (_("The disk system on your computer\n\
2222 was not able to keep up with Ardour.\n\
2224 Specifically, it failed to read data from disk\n\
2225 quickly enough to keep up with playback.\n")));
2227 have_disk_underrun_displayed = false;
2232 ARDOUR_UI::disk_underrun_message_gone ()
2234 have_disk_underrun_displayed = false;
2238 ARDOUR_UI::disk_overrun_message_gone ()
2240 have_disk_underrun_displayed = false;
2244 ARDOUR_UI::pending_state_dialog ()
2246 ArdourDialog dialog ("pending state dialog");
2248 This session appears to have been in\n\
2249 middle of recording when ardour or\n\
2250 the computer was shutdown.\n\
2252 Ardour can recover any captured audio for\n\
2253 you, or it can ignore it. Please decide\n\
2254 what you would like to do.\n"));
2256 dialog.get_vbox()->pack_start (message);
2257 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2258 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2260 dialog.set_position (WIN_POS_CENTER);
2263 switch (dialog.run ()) {
2264 case RESPONSE_ACCEPT:
2275 ARDOUR_UI::disconnect_from_jack ()
2278 if( engine->disconnect_from_jack ()) {
2279 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2283 update_sample_rate (0);
2288 ARDOUR_UI::reconnect_to_jack ()
2291 if (engine->reconnect_to_jack ()) {
2292 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2296 update_sample_rate (0);
2301 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2303 engine->request_buffer_size (nframes);
2304 update_sample_rate (0);
2308 ARDOUR_UI::cmdline_new_session (string path)
2310 if (path[0] != '/') {
2311 char buf[PATH_MAX+1];
2314 getcwd (buf, sizeof (buf));
2321 new_session (false, path);
2323 _will_create_new_session_automatically = false; /* done it */
2324 return FALSE; /* don't call it again */