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 "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;
136 if (theArdourUI == 0) {
140 ActionManager::init ();
144 color_manager = new ColorManager();
146 std::string color_file = ARDOUR::find_config_file("ardour.colors");
148 color_manager->load (color_file);
150 m_new_session_dialog = 0;
151 m_new_session_dialog_ref = NewSessionDialogFactory::create();
152 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
156 _session_is_new = false;
157 big_clock_window = 0;
158 session_selector_window = 0;
159 last_key_press_time = 0;
160 connection_editor = 0;
161 add_route_dialog = 0;
166 open_session_selector = 0;
167 have_configure_timeout = false;
168 have_disk_overrun_displayed = false;
169 have_disk_underrun_displayed = false;
170 _will_create_new_session_automatically = false;
171 session_loaded = false;
172 last_speed_displayed = -1.0f;
174 last_configure_time.tv_sec = 0;
175 last_configure_time.tv_usec = 0;
177 shuttle_grabbed = false;
179 shuttle_max_speed = 8.0f;
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 ();
235 meter_path = ARDOUR::find_data_file("v_meter_strip.xpm", "pixmaps");
236 if (meter_path.empty()) {
237 error << _("no vertical meter strip image found") << endmsg;
240 FastMeter::set_vertical_xpm (meter_path);
242 meter_path = ARDOUR::find_data_file("h_meter_strip.xpm", "pixmaps");
243 if (meter_path.empty()) {
244 error << _("no horizontal meter strip image found") << endmsg;
247 FastMeter::set_horizontal_xpm (meter_path);
249 if (setup_windows ()) {
250 throw failed_constructor ();
253 if (GTK_ARDOUR::show_key_actions) {
254 vector<string> names;
255 vector<string> paths;
257 vector<AccelKey> bindings;
259 ActionManager::get_all_actions (names, paths, keys, bindings);
261 vector<string>::iterator n;
262 vector<string>::iterator k;
263 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
264 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
270 /* start with timecode, metering enabled
273 blink_timeout_tag = -1;
275 /* this being a GUI and all, we want peakfiles */
277 FileSource::set_build_peakfiles (true);
278 FileSource::set_build_missing_peakfiles (true);
280 if (Source::start_peak_thread ()) {
281 throw failed_constructor();
284 /* start the time-of-day-clock */
286 update_wall_clock ();
287 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
289 update_disk_space ();
291 update_sample_rate (engine->frame_rate());
293 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
294 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
297 ARDOUR_UI::~ARDOUR_UI ()
299 save_ardour_state ();
313 if (add_route_dialog) {
314 delete add_route_dialog;
317 Source::stop_peak_thread ();
321 ARDOUR_UI::configure_timeout ()
326 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
327 /* no configure events yet */
331 gettimeofday (&now, 0);
332 timersub (&now, &last_configure_time, &diff);
334 /* force a gap of 0.5 seconds since the last configure event
337 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
340 have_configure_timeout = false;
341 save_ardour_state ();
347 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
349 if (have_configure_timeout) {
350 gettimeofday (&last_configure_time, 0);
352 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
353 have_configure_timeout = true;
360 ARDOUR_UI::save_ardour_state ()
362 if (!keyboard || !mixer || !editor) {
366 /* XXX this is all a bit dubious. add_extra_xml() uses
367 a different lifetime model from add_instant_xml().
370 XMLNode* node = new XMLNode (keyboard->get_state());
371 Config->add_extra_xml (*node);
372 Config->save_state();
374 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
375 XMLNode& mnode (mixer->get_state());
378 session->add_instant_xml(enode, session->path());
379 session->add_instant_xml(mnode, session->path());
381 Config->add_instant_xml(enode, get_user_ardour_path());
382 Config->add_instant_xml(mnode, get_user_ardour_path());
387 ARDOUR_UI::startup ()
389 /* Once the UI is up and running, start the audio engine. Doing
390 this before the UI is up and running can cause problems
391 when not running with SCHED_FIFO, because the amount of
392 CPU and disk work needed to get the UI started can interfere
393 with the scheduling of the audio thread.
396 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
402 if (session && session->dirty()) {
403 switch (ask_about_saving_session(_("quit"))) {
408 /* use the default name */
409 if (save_state_canfail ("")) {
410 /* failed - don't quit */
411 MessageDialog msg (*editor,
413 Ardour was unable to save your session.\n\n\
414 If you still wish to quit, please use the\n\n\
415 \"Just quit\" option."));
429 ARDOUR_UI::ask_about_saving_session (const string & what)
431 ArdourDialog window (_("ardour: save session?"));
432 Gtk::Label prompt_label;
435 msg = string_compose(_("Save and %1"), what);
436 window.add_button (msg, RESPONSE_ACCEPT);
437 msg = string_compose(_("Just %1"), what);
438 window.add_button (msg, RESPONSE_APPLY);
439 msg = string_compose(_("Don't %1"), what);
440 window.add_button (msg, RESPONSE_REJECT);
442 Gtk::Button noquit_button (msg);
443 noquit_button.set_name ("EditorGTKButton");
448 if (session->snap_name() == session->name()) {
451 type = _("snapshot");
453 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?"),
454 type, session->snap_name());
456 prompt_label.set_text (prompt);
457 prompt_label.set_alignment (0.5, 0.5);
458 prompt_label.set_name (X_("PrompterLabel"));
460 window.get_vbox()->pack_start (prompt_label);
462 window.set_name (_("Prompter"));
463 window.set_position (Gtk::WIN_POS_MOUSE);
464 window.set_modal (true);
467 save_the_session = 0;
469 editor->ensure_float (window);
471 ResponseType r = (ResponseType) window.run();
476 case RESPONSE_ACCEPT: // save and get out of here
478 case RESPONSE_APPLY: // get out of here
488 ARDOUR_UI::every_second ()
491 update_buffer_load ();
492 update_disk_space ();
493 // update_disk_rate ();
498 ARDOUR_UI::every_point_one_seconds ()
503 /* do not attempt to grab peak power more than once per cycle.
506 gettimeofday (&now, 0);
507 timersub (&now, &last_peak_grab, &diff);
509 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
510 IO::GrabPeakPower(); /* EMIT_SIGNAL */
511 last_peak_grab = now;
514 update_speed_display ();
515 RapidScreenUpdate(); /* EMIT_SIGNAL */
520 ARDOUR_UI::every_point_zero_one_seconds ()
522 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
527 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
531 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
533 if (!engine->connected()) {
535 snprintf (buf, sizeof (buf), _("disconnected"));
539 jack_nframes_t rate = engine->frame_rate();
541 if (fmod (rate, 1000.0) != 0.0) {
542 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
543 (float) rate/1000.0f,
544 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
546 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
548 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
552 sample_rate_label.set_text (buf);
556 ARDOUR_UI::update_cpu_load ()
559 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
560 cpu_load_label.set_text (buf);
564 ARDOUR_UI::update_disk_rate ()
569 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
570 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
571 disk_rate_label.set_text (buf);
573 disk_rate_label.set_text ("");
578 ARDOUR_UI::update_buffer_load ()
583 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
584 session->playback_load(), session->capture_load());
585 buffer_load_label.set_text (buf);
587 buffer_load_label.set_text ("");
592 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
594 if (ds.record_enabled()) {
595 rec_enabled_diskstreams++;
600 ARDOUR_UI::update_disk_space()
606 jack_nframes_t frames = session->available_capture_duration();
609 if (frames == max_frames) {
610 strcpy (buf, _("space: 24hrs+"));
615 jack_nframes_t fr = session->frame_rate();
617 if (session->actively_recording()){
619 rec_enabled_diskstreams = 0;
620 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
622 if (rec_enabled_diskstreams) {
623 frames /= rec_enabled_diskstreams;
628 /* hmmm. shall we divide by the route count? or the diskstream count?
629 or what? for now, do nothing ...
634 hrs = frames / (fr * 3600);
635 frames -= hrs * fr * 3600;
636 mins = frames / (fr * 60);
637 frames -= mins * fr * 60;
640 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
643 disk_space_label.set_text (buf);
647 ARDOUR_UI::update_wall_clock ()
654 tm_now = localtime (&now);
656 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
657 wall_clock_label.set_text (buf);
662 ARDOUR_UI::control_methods_adjusted ()
667 which_method = (int) online_control_button->adjustment.get_value();
668 switch (which_method) {
670 allow_mmc_and_local ();
679 fatal << _("programming error: impossible control method") << endmsg;
685 ARDOUR_UI::mmc_device_id_adjusted ()
690 int dev_id = (int) mmc_id_button->adjustment.get_value();
691 mmc->set_device_id (dev_id);
697 ARDOUR_UI::session_menu (GdkEventButton *ev)
699 session_popup_menu->popup (0, 0);
704 ARDOUR_UI::redisplay_recent_sessions ()
706 vector<string *> *sessions;
707 vector<string *>::iterator i;
708 RecentSessionsSorter cmp;
710 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
711 recent_session_model->clear ();
714 ARDOUR::read_recent_sessions (rs);
717 recent_session_display.set_model (recent_session_model);
721 /* sort them alphabetically */
722 sort (rs.begin(), rs.end(), cmp);
723 sessions = new vector<string*>;
725 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
726 sessions->push_back (new string ((*i).second));
729 for (i = sessions->begin(); i != sessions->end(); ++i) {
731 vector<string*>* states;
732 vector<const gchar*> item;
733 string fullpath = *(*i);
735 /* remove any trailing / */
737 if (fullpath[fullpath.length()-1] == '/') {
738 fullpath = fullpath.substr (0, fullpath.length()-1);
741 /* now get available states for this session */
743 if ((states = Session::possible_states (fullpath)) == 0) {
748 TreeModel::Row row = *(recent_session_model->append());
750 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
751 row[recent_session_columns.fullpath] = fullpath;
753 if (states->size() > 1) {
755 /* add the children */
757 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
759 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
761 child_row[recent_session_columns.visible_name] = **i2;
762 child_row[recent_session_columns.fullpath] = fullpath;
771 recent_session_display.set_model (recent_session_model);
776 ARDOUR_UI::build_session_selector ()
778 session_selector_window = new ArdourDialog ("session selector");
780 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
782 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
783 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
785 recent_session_model = TreeStore::create (recent_session_columns);
786 recent_session_display.set_model (recent_session_model);
787 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
788 recent_session_display.set_headers_visible (false);
790 scroller->add (recent_session_display);
791 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
793 session_selector_window->set_name ("SessionSelectorWindow");
794 session_selector_window->set_size_request (200, 400);
795 session_selector_window->get_vbox()->pack_start (*scroller);
796 session_selector_window->show_all_children();
800 ARDOUR_UI::open_recent_session ()
802 /* popup selector window */
804 if (session_selector_window == 0) {
805 build_session_selector ();
808 redisplay_recent_sessions ();
810 ResponseType r = (ResponseType) session_selector_window->run ();
812 session_selector_window->hide();
815 case RESPONSE_ACCEPT:
821 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
823 if (i == recent_session_model->children().end()) {
827 Glib::ustring path = (*i)[recent_session_columns.fullpath];
828 Glib::ustring state = (*i)[recent_session_columns.visible_name];
830 _session_is_new = false;
832 load_session (path, state);
836 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
840 if (stat (info.filename.c_str(), &statbuf) != 0) {
844 if (!S_ISDIR(statbuf.st_mode)) {
848 string session_file = info.filename;
850 session_file += PBD::basename (info.filename);
851 session_file += ".ardour";
853 if (stat (session_file.c_str(), &statbuf) != 0) {
857 return S_ISREG (statbuf.st_mode);
861 ARDOUR_UI::open_session ()
863 /* popup selector window */
865 if (open_session_selector == 0) {
867 /* ardour sessions are folders */
869 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
870 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
871 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
873 FileFilter session_filter;
874 session_filter.add_pattern ("*.ardour");
875 session_filter.set_name (_("Ardour sessions"));
876 open_session_selector->add_filter (session_filter);
877 open_session_selector->set_filter (session_filter);
880 int response = open_session_selector->run();
881 open_session_selector->hide ();
884 case RESPONSE_ACCEPT:
887 open_session_selector->hide();
891 open_session_selector->hide();
892 string session_path = open_session_selector->get_filename();
896 if (session_path.length() > 0) {
897 if (Session::find_session (session_path, path, name, isnew) == 0) {
898 _session_is_new = isnew;
899 load_session (path, name);
906 ARDOUR_UI::session_add_midi_track ()
908 cerr << _("Patience is a virtue.\n");
912 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
917 warning << _("You cannot add a track without a session already loaded.") << endmsg;
923 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
924 error << _("could not create new audio track") << endmsg;
927 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
928 error << _("could not create new audio bus") << endmsg;
933 if (need_control_room_outs) {
939 route->set_stereo_control_outs (control_lr_channels);
940 route->control_outs()->set_stereo_pan (pans, this);
942 #endif /* CONTROLOUTS */
946 MessageDialog msg (*editor,
947 _("There are insufficient JACK ports available\n\
948 to create a new track or bus.\n\
949 You should save Ardour, exit and\n\
950 restart JACK with more ports."));
956 ARDOUR_UI::diskstream_added (DiskStream* ds)
961 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
963 jack_nframes_t _preroll;
966 _preroll = session->convert_to_frames_at (new_position, session->preroll);
968 if (new_position > _preroll) {
969 new_position -= _preroll;
974 session->request_locate (new_position);
979 ARDOUR_UI::transport_goto_start ()
982 session->goto_start();
985 /* force displayed area in editor to start no matter
986 what "follow playhead" setting is.
990 editor->reposition_x_origin (session->current_start_frame());
996 ARDOUR_UI::transport_goto_zero ()
999 session->request_locate (0);
1002 /* force displayed area in editor to start no matter
1003 what "follow playhead" setting is.
1007 editor->reposition_x_origin (0);
1013 ARDOUR_UI::transport_goto_end ()
1016 jack_nframes_t frame = session->current_end_frame();
1017 session->request_locate (frame);
1019 /* force displayed area in editor to start no matter
1020 what "follow playhead" setting is.
1024 editor->reposition_x_origin (frame);
1030 ARDOUR_UI::transport_stop ()
1036 if (session->is_auditioning()) {
1037 session->cancel_audition ();
1041 if (session->get_auto_loop()) {
1042 session->request_auto_loop (false);
1045 session->request_stop ();
1049 ARDOUR_UI::transport_stop_and_forget_capture ()
1052 session->request_stop (true);
1057 ARDOUR_UI::remove_last_capture()
1060 editor->remove_last_capture();
1065 ARDOUR_UI::transport_record ()
1068 switch (session->record_status()) {
1069 case Session::Disabled:
1070 if (session->ntracks() == 0) {
1071 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1072 MessageDialog msg (*editor, txt);
1076 session->maybe_enable_record ();
1078 case Session::Recording:
1079 case Session::Enabled:
1080 session->disable_record (true);
1086 ARDOUR_UI::transport_roll ()
1094 rolling = session->transport_rolling ();
1096 if (session->get_auto_loop()) {
1097 session->request_auto_loop (false);
1098 auto_loop_button.set_active (false);
1099 roll_button.set_active (true);
1100 } else if (session->get_play_range ()) {
1101 session->request_play_range (false);
1102 play_selection_button.set_active (false);
1103 } else if (rolling) {
1104 session->request_locate (session->last_transport_start(), true);
1107 session->request_transport_speed (1.0f);
1111 ARDOUR_UI::transport_loop()
1114 if (session->get_auto_loop()) {
1115 if (session->transport_rolling()) {
1116 Location * looploc = session->locations()->auto_loop_location();
1118 session->request_locate (looploc->start(), true);
1123 session->request_auto_loop (true);
1129 ARDOUR_UI::transport_play_selection ()
1135 if (!session->get_play_range()) {
1136 session->request_stop ();
1139 editor->play_selection ();
1143 ARDOUR_UI::transport_rewind (int option)
1145 float current_transport_speed;
1148 current_transport_speed = session->transport_speed();
1150 if (current_transport_speed >= 0.0f) {
1153 session->request_transport_speed (-1.0f);
1156 session->request_transport_speed (-4.0f);
1159 session->request_transport_speed (-0.5f);
1164 session->request_transport_speed (current_transport_speed * 1.5f);
1170 ARDOUR_UI::transport_forward (int option)
1172 float current_transport_speed;
1175 current_transport_speed = session->transport_speed();
1177 if (current_transport_speed <= 0.0f) {
1180 session->request_transport_speed (1.0f);
1183 session->request_transport_speed (4.0f);
1186 session->request_transport_speed (0.5f);
1191 session->request_transport_speed (current_transport_speed * 1.5f);
1197 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1205 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1206 Port *port = ds->io()->input (0);
1207 port->request_monitor_input (!port->monitoring_input());
1212 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1220 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1221 ds->set_record_enabled (!ds->record_enabled(), this);
1226 ARDOUR_UI::queue_transport_change ()
1228 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1232 ARDOUR_UI::map_transport_state ()
1234 float sp = session->transport_speed();
1237 transport_rolling ();
1238 } else if (sp < 0.0f) {
1239 transport_rewinding ();
1240 } else if (sp > 0.0f) {
1241 transport_forwarding ();
1243 transport_stopped ();
1248 ARDOUR_UI::send_all_midi_feedback ()
1251 session->send_all_midi_feedback();
1256 ARDOUR_UI::allow_local_only ()
1262 ARDOUR_UI::allow_mmc_only ()
1268 ARDOUR_UI::allow_mmc_and_local ()
1274 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1276 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1277 (int) adj.get_value()].c_str());
1281 ARDOUR_UI::engine_stopped ()
1283 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1284 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1285 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1290 ARDOUR_UI::engine_running ()
1292 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1293 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1294 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1298 ARDOUR_UI::engine_halted ()
1300 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1302 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1303 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1305 update_sample_rate (0);
1307 MessageDialog msg (*editor,
1309 JACK has either been shutdown or it\n\
1310 disconnected Ardour because Ardour\n\
1311 was not fast enough. You can save the\n\
1312 session and/or try to reconnect to JACK ."));
1317 ARDOUR_UI::do_engine_start ()
1323 catch (AudioEngine::PortRegistrationFailure& err) {
1325 error << _("Unable to create all required ports")
1333 error << _("Unable to start the session running")
1343 ARDOUR_UI::start_engine ()
1345 if (do_engine_start () == 0) {
1346 if (session && _session_is_new) {
1347 /* we need to retain initial visual
1348 settings for a new session
1350 session->save_state ("");
1353 /* there is too much going on, in too many threads, for us to
1354 end up with a clean session. So wait 1 second after loading,
1355 and fix it up. its ugly, but until i come across a better
1356 solution, its what we have.
1359 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1366 ARDOUR_UI::update_clocks ()
1368 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1372 ARDOUR_UI::start_clocking ()
1374 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1378 ARDOUR_UI::stop_clocking ()
1380 clock_signal_connection.disconnect ();
1384 ARDOUR_UI::toggle_clocking ()
1387 if (clock_button.get_active()) {
1396 ARDOUR_UI::_blink (void *arg)
1399 ((ARDOUR_UI *) arg)->blink ();
1406 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1410 ARDOUR_UI::start_blinking ()
1412 /* Start the blink signal. Everybody with a blinking widget
1413 uses Blink to drive the widget's state.
1416 if (blink_timeout_tag < 0) {
1418 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1423 ARDOUR_UI::stop_blinking ()
1425 if (blink_timeout_tag >= 0) {
1426 gtk_timeout_remove (blink_timeout_tag);
1427 blink_timeout_tag = -1;
1433 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1435 using namespace Gtk;
1436 using namespace Menu_Helpers;
1438 if (dstream.hidden()) {
1442 MenuList& items = diskstream_menu->items();
1443 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1447 ARDOUR_UI::diskstream_selected (gint32 id)
1449 selected_dstream = id;
1454 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1456 using namespace Gtk;
1457 using namespace Menu_Helpers;
1463 diskstream_menu = new Menu();
1464 diskstream_menu->set_name ("ArdourContextMenu");
1465 using namespace Gtk;
1466 using namespace Menu_Helpers;
1468 MenuList& items = diskstream_menu->items();
1469 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1471 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1474 diskstream_menu->popup (ev->button, ev->time);
1476 diskstream_menu->popup (0, 0);
1479 selected_dstream = -1;
1483 delete diskstream_menu;
1485 return selected_dstream;
1489 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1495 if (io.n_inputs() == 0) {
1500 /* XXX we're not handling multiple ports yet. */
1502 const char **connections = io.input(0)->get_connections();
1504 if (connections == 0 || connections[0] == '\0') {
1507 buf = connections[0];
1514 if (io.n_outputs() == 0) {
1519 /* XXX we're not handling multiple ports yet. */
1521 const char **connections = io.output(0)->get_connections();
1523 if (connections == 0 || connections[0] == '\0') {
1526 buf = connections[0];
1534 ARDOUR_UI::snapshot_session ()
1536 ArdourPrompter prompter (true);
1543 now = now.substr (0, now.length() - 1);
1545 prompter.set_name ("Prompter");
1546 prompter.set_prompt (_("Name for snapshot"));
1547 prompter.set_initial_text (now);
1549 switch (prompter.run()) {
1550 case RESPONSE_ACCEPT:
1551 prompter.get_result (snapname);
1552 if (snapname.length()){
1553 save_state (snapname);
1563 ARDOUR_UI::save_state (const string & name)
1565 (void) save_state_canfail (name);
1569 ARDOUR_UI::save_state_canfail (string name)
1574 if (name.length() == 0) {
1575 name = session->snap_name();
1578 if ((ret = session->save_state (name)) != 0) {
1582 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1587 ARDOUR_UI::restore_state (string name)
1590 if (name.length() == 0) {
1591 name = session->name();
1593 session->restore_state (name);
1598 ARDOUR_UI::primary_clock_value_changed ()
1601 session->request_locate (primary_clock.current_time ());
1606 ARDOUR_UI::secondary_clock_value_changed ()
1609 session->request_locate (secondary_clock.current_time ());
1614 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1616 if (session && dstream && dstream->record_enabled()) {
1618 Session::RecordState rs;
1620 rs = session->record_status ();
1623 case Session::Disabled:
1624 case Session::Enabled:
1625 if (w->get_state() != STATE_SELECTED) {
1626 w->set_state (STATE_SELECTED);
1630 case Session::Recording:
1631 if (w->get_state() != STATE_ACTIVE) {
1632 w->set_state (STATE_ACTIVE);
1638 if (w->get_state() != STATE_NORMAL) {
1639 w->set_state (STATE_NORMAL);
1645 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1651 switch (session->record_status()) {
1652 case Session::Enabled:
1654 rec_button.set_state (1);
1656 rec_button.set_state (0);
1660 case Session::Recording:
1661 rec_button.set_state (2);
1665 rec_button.set_state (0);
1671 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1679 ARDOUR_UI::start_keyboard_prefix ()
1681 keyboard->start_prefix();
1685 ARDOUR_UI::save_template ()
1688 ArdourPrompter prompter (true);
1691 prompter.set_name (X_("Prompter"));
1692 prompter.set_prompt (_("Name for mix template:"));
1693 prompter.set_initial_text(session->name() + _("-template"));
1695 switch (prompter.run()) {
1696 case RESPONSE_ACCEPT:
1697 prompter.get_result (name);
1699 if (name.length()) {
1700 session->save_template (name);
1710 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1712 m_new_session_dialog->show_all();
1713 m_new_session_dialog->set_transient_for(*editor);
1714 m_new_session_dialog->set_name(predetermined_path);
1716 int response = Gtk::RESPONSE_CANCEL;
1719 response = m_new_session_dialog->run ();
1721 if(response == Gtk::RESPONSE_OK) {
1723 _session_is_new = true;
1725 std::string session_name = m_new_session_dialog->session_name();
1726 std::string session_path = m_new_session_dialog->session_folder();
1729 XXX This is needed because session constructor wants a
1730 non-existant path. hopefully this will be fixed at some point.
1732 session_path = Glib::build_filename(session_path, session_name);
1734 std::string template_name = m_new_session_dialog->session_template_name();
1736 if (m_new_session_dialog->use_session_template()) {
1738 load_session (session_path, session_name, &template_name);
1744 Session::AutoConnectOption iconnect;
1745 Session::AutoConnectOption oconnect;
1747 if (m_new_session_dialog->create_control_bus()) {
1748 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1753 if (m_new_session_dialog->create_master_bus()) {
1754 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1759 if (m_new_session_dialog->connect_inputs()) {
1760 iconnect = Session::AutoConnectPhysical;
1762 iconnect = Session::AutoConnectOption (0);
1765 /// @todo some minor tweaks.
1767 if (m_new_session_dialog->connect_outs_to_master()) {
1768 oconnect = Session::AutoConnectMaster;
1769 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1770 oconnect = Session::AutoConnectPhysical;
1772 oconnect = Session::AutoConnectOption (0);
1775 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1776 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1778 build_session (session_path,
1786 engine->frame_rate() * 60 * 5);
1790 } while(response == Gtk::RESPONSE_HELP);
1791 m_new_session_dialog->hide_all();
1795 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1797 Session *new_session;
1799 session_loaded = false;
1800 x = unload_session ();
1808 /* if it already exists, we must have write access */
1810 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1811 MessageDialog msg (*editor, _("\
1812 You do not have write access to this session.\n\
1813 This prevents the session from being loaded."));
1819 new_session = new Session (*engine, path, snap_name, mix_template);
1824 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1828 connect_to_session (new_session);
1830 //if (engine->running()) {
1831 //mixer->show_window();
1833 session_loaded = true;
1838 ARDOUR_UI::make_session_clean ()
1841 session->set_clean ();
1848 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1849 uint32_t control_channels,
1850 uint32_t master_channels,
1851 Session::AutoConnectOption input_connect,
1852 Session::AutoConnectOption output_connect,
1855 jack_nframes_t initial_length)
1857 Session *new_session;
1860 session_loaded = false;
1861 x = unload_session ();
1868 _session_is_new = true;
1871 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1872 control_channels, master_channels, nphysin, nphysout, initial_length);
1877 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1881 connect_to_session (new_session);
1883 //if (engine->running()) {
1884 //mixer->show_window();
1886 session_loaded = true;
1894 editor->show_window ();
1898 if (session && mixer) {
1899 // mixer->show_window ();
1908 ARDOUR_UI::show_splash ()
1911 about = new About();
1917 ARDOUR_UI::hide_splash ()
1925 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1929 removed = rep.paths.size();
1932 MessageDialog msg (*editor, X_("cleanupresults"),
1934 No audio files were ready for cleanup\n\n\
1935 If this seems suprising, check for any existing\n\
1936 snapshots. These may still include regions that\n\
1937 require some unused files to continue to exist."));
1942 ArdourDialog results (_("ardour: cleanup"), true);
1944 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1945 CleanupResultsModelColumns() {
1949 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1950 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1954 Glib::RefPtr<Gtk::ListStore> results_model;
1955 CleanupResultsModelColumns results_columns;
1956 Gtk::TreeView results_display;
1958 results_model = ListStore::create (results_columns);
1959 results_display.set_model (results_model);
1960 results_display.append_column (list_title, results_columns.visible_name);
1961 results_display.set_headers_visible (true);
1963 Gtk::ScrolledWindow list_scroller;
1966 if (rep.space < 1048576.0f) {
1968 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1970 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1974 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1976 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1980 results.get_vbox()->pack_start (txt, false, false);
1982 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1983 TreeModel::Row row = *(results_model->append());
1984 row[results_columns.visible_name] = *i;
1985 row[results_columns.fullpath] = *i;
1988 list_scroller.add (results_display);
1989 list_scroller.set_size_request (-1, 250);
1990 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1992 results.get_vbox()->pack_start (list_scroller, true, true);
1993 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1994 results.set_position (Gtk::WIN_POS_MOUSE);
2000 ARDOUR_UI::cleanup ()
2003 /* shouldn't happen: menu item is insensitive */
2007 ArdourDialog checker (_("ardour cleanup"));
2008 Gtk::Label label (_("\
2009 Cleanup is a destructive operation.\n\
2010 ALL undo/redo information will be lost if you cleanup.\n\
2011 Unused audio files will be moved to a \"dead sounds\" location."));
2013 checker.get_vbox()->pack_start (label, false, false);
2014 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2015 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2017 checker.set_name (_("CleanupDialog"));
2018 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2019 checker.set_position (Gtk::WIN_POS_MOUSE);
2021 switch (checker.run()) {
2022 case RESPONSE_ACCEPT:
2028 Session::cleanup_report rep;
2030 editor->prepare_for_cleanup ();
2032 if (session->cleanup_sources (rep)) {
2036 display_cleanup_results (rep,
2039 The following %1 %2 were not in use.\n\
2040 The next time you flush the wastebasket\n\
2041 it will release an additional %3 %4bytes\n\
2047 ARDOUR_UI::flush_trash ()
2050 /* shouldn't happen: menu item is insensitive */
2054 Session::cleanup_report rep;
2056 if (session->cleanup_trash_sources (rep)) {
2060 display_cleanup_results (rep,
2062 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2066 ARDOUR_UI::add_route ()
2074 if (add_route_dialog == 0) {
2075 add_route_dialog = new AddRouteDialog;
2076 editor->ensure_float (*add_route_dialog);
2079 if (add_route_dialog->is_visible()) {
2080 /* we're already doing this */
2084 ResponseType r = (ResponseType) add_route_dialog->run ();
2086 add_route_dialog->hide();
2089 case RESPONSE_ACCEPT:
2096 if ((count = add_route_dialog->count()) <= 0) {
2100 uint32_t input_chan = add_route_dialog->channels ();
2101 uint32_t output_chan;
2102 string name_template = add_route_dialog->name_template ();
2103 bool track = add_route_dialog->track ();
2105 Session::AutoConnectOption oac = session->get_output_auto_connect();
2107 if (oac & Session::AutoConnectMaster) {
2108 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2110 output_chan = input_chan;
2113 /* XXX do something with name template */
2117 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2119 session_add_audio_bus (input_chan, output_chan);
2123 while (Main::events_pending()) {
2130 ARDOUR_UI::mixer_settings () const
2135 node = session->instant_xml(X_("Mixer"), session->path());
2137 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2141 node = new XMLNode (X_("Mixer"));
2148 ARDOUR_UI::editor_settings () const
2153 node = session->instant_xml(X_("Editor"), session->path());
2155 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2159 node = new XMLNode (X_("Editor"));
2165 ARDOUR_UI::keyboard_settings () const
2169 node = Config->extra_xml(X_("Keyboard"));
2172 node = new XMLNode (X_("Keyboard"));
2178 ARDOUR_UI::halt_on_xrun_message ()
2180 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2182 MessageDialog msg (*editor,
2183 _("Recording was stopped because your system could not keep up."));
2188 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2190 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2192 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2196 delete deletion_list;
2200 ARDOUR_UI::disk_overrun_handler ()
2202 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2204 if (!have_disk_overrun_displayed) {
2205 have_disk_overrun_displayed = true;
2206 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2207 The disk system on your computer\n\
2208 was not able to keep up with Ardour.\n\
2210 Specifically, it failed to write data to disk\n\
2211 quickly enough to keep up with recording.\n"));
2213 have_disk_overrun_displayed = false;
2218 ARDOUR_UI::disk_underrun_handler ()
2220 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2222 if (!have_disk_underrun_displayed) {
2223 have_disk_underrun_displayed = true;
2224 MessageDialog msg (*editor,
2225 (_("The disk system on your computer\n\
2226 was not able to keep up with Ardour.\n\
2228 Specifically, it failed to read data from disk\n\
2229 quickly enough to keep up with playback.\n")));
2231 have_disk_underrun_displayed = false;
2236 ARDOUR_UI::disk_underrun_message_gone ()
2238 have_disk_underrun_displayed = false;
2242 ARDOUR_UI::disk_overrun_message_gone ()
2244 have_disk_underrun_displayed = false;
2248 ARDOUR_UI::pending_state_dialog ()
2250 ArdourDialog dialog ("pending state dialog");
2252 This session appears to have been in\n\
2253 middle of recording when ardour or\n\
2254 the computer was shutdown.\n\
2256 Ardour can recover any captured audio for\n\
2257 you, or it can ignore it. Please decide\n\
2258 what you would like to do.\n"));
2260 dialog.get_vbox()->pack_start (message);
2261 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2262 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2264 dialog.set_position (WIN_POS_CENTER);
2267 switch (dialog.run ()) {
2268 case RESPONSE_ACCEPT:
2279 ARDOUR_UI::disconnect_from_jack ()
2282 if( engine->disconnect_from_jack ()) {
2283 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2287 update_sample_rate (0);
2292 ARDOUR_UI::reconnect_to_jack ()
2295 if (engine->reconnect_to_jack ()) {
2296 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2300 update_sample_rate (0);
2305 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2307 engine->request_buffer_size (nframes);
2308 update_sample_rate (0);
2312 ARDOUR_UI::cmdline_new_session (string path)
2314 if (path[0] != '/') {
2315 char buf[PATH_MAX+1];
2318 getcwd (buf, sizeof (buf));
2325 new_session (false, path);
2327 _will_create_new_session_automatically = false; /* done it */
2328 return FALSE; /* don't call it again */