2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
60 #include "ardour_ui.h"
61 #include "ardour_message.h"
62 #include "public_editor.h"
63 #include "audio_clock.h"
68 #include "keyboard_target.h"
69 #include "add_route_dialog.h"
70 #include "new_session_dialog.h"
73 #include "gui_thread.h"
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
90 static const gchar *h_meter_strip_xpm[] = {
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
286 static const gchar * v_meter_strip_xpm[] = {
769 static const char* channel_setup_names[] = {
780 vector<string> channel_combo_strings;
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
784 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
786 primary_clock (X_("TransportClockDisplay"), true, false, true),
787 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788 preroll_clock (X_("PreRollClock"), true, true),
789 postroll_clock (X_("PostRollClock"), true, true),
793 adjuster_table (3, 3),
797 preroll_button (_("pre\nroll")),
798 postroll_button (_("post\nroll")),
802 big_clock ("BigClockDisplay", true),
806 shuttle_units_button (_("% ")),
807 shuttle_style_button (_("spring")),
809 punch_in_button (_("punch\nin")),
810 punch_out_button (_("punch\nout")),
811 auto_return_button (_("auto\nreturn")),
812 auto_play_button (_("auto\nplay")),
813 auto_input_button (_("auto\ninput")),
814 click_button (_("click")),
815 follow_button (_("follow\nPH")),
816 auditioning_alert_button (_("AUDITIONING")),
817 solo_alert_button (_("SOLO")),
821 using namespace Gtk::Menu_Helpers;
825 /* actually, its already loaded, but ... */
827 cerr << "Loading UI configuration file " << rcfile << endl;
831 if (theArdourUI == 0) {
835 // allow run-time rebinding of accels
837 Settings::get_default()->property_gtk_can_change_accels() = true;
839 ActionManager::init ();
841 m_new_session_dialog = 0;
842 m_new_session_dialog_ref = NewSessionDialogFactory::create();
843 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
847 _session_is_new = false;
848 big_clock_window = 0;
849 session_selector_window = 0;
850 last_key_press_time = 0;
851 connection_editor = 0;
852 add_route_dialog = 0;
856 open_session_selector = 0;
857 have_configure_timeout = false;
858 have_disk_overrun_displayed = false;
859 have_disk_underrun_displayed = false;
860 _will_create_new_session_automatically = false;
861 session_loaded = false;
864 last_configure_time.tv_sec = 0;
865 last_configure_time.tv_usec = 0;
867 shuttle_grabbed = false;
870 set_shuttle_units (Percentage);
871 set_shuttle_behaviour (Sprung);
873 shuttle_style_menu = 0;
874 shuttle_unit_menu = 0;
876 gettimeofday (&last_peak_grab, 0);
877 gettimeofday (&last_shuttle_request, 0);
879 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
884 /* handle pending state with a dialog */
886 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
888 channel_combo_strings = internationalize (channel_setup_names);
890 /* have to wait for AudioEngine and Configuration before proceeding */
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
896 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
898 string msg = string_compose (_("\
899 You cannot record-enable\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
905 ArdourMessage message (editor, X_("cannotrecord"), msg);
909 ARDOUR_UI::set_engine (AudioEngine& e)
913 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
920 keyboard = new Keyboard;
921 install_keybindings ();
923 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
926 if (setup_windows ()) {
927 throw failed_constructor ();
930 if (GTK_ARDOUR::show_key_actions) {
932 // show_all_actions ();
936 /* start with timecode, metering enabled
939 blink_timeout_tag = -1;
941 /* this being a GUI and all, we want peakfiles */
943 FileSource::set_build_peakfiles (true);
944 FileSource::set_build_missing_peakfiles (true);
946 if (Source::start_peak_thread ()) {
947 throw failed_constructor();
950 /* start the time-of-day-clock */
952 update_wall_clock ();
953 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
955 update_disk_space ();
957 update_sample_rate (engine->frame_rate());
959 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
960 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
963 ARDOUR_UI::~ARDOUR_UI ()
965 save_ardour_state ();
979 if (add_route_dialog) {
980 delete add_route_dialog;
983 Source::stop_peak_thread ();
987 ARDOUR_UI::configure_timeout ()
992 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
993 /* no configure events yet */
997 gettimeofday (&now, 0);
998 timersub (&now, &last_configure_time, &diff);
1000 /* force a gap of 0.5 seconds since the last configure event
1003 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1006 have_configure_timeout = false;
1007 save_ardour_state ();
1013 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1015 if (have_configure_timeout) {
1016 gettimeofday (&last_configure_time, 0);
1018 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1019 have_configure_timeout = true;
1026 ARDOUR_UI::save_ardour_state ()
1028 if (!keyboard || !mixer || !editor) {
1032 /* XXX this is all a bit dubious. add_extra_xml() uses
1033 a different lifetime model from add_instant_xml().
1036 XMLNode* node = new XMLNode (keyboard->get_state());
1037 Config->add_extra_xml (*node);
1038 Config->save_state();
1040 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1041 XMLNode& mnode (mixer->get_state());
1044 session->add_instant_xml(enode, session->path());
1045 session->add_instant_xml(mnode, session->path());
1047 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1048 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1053 ARDOUR_UI::startup ()
1055 /* Once the UI is up and running, start the audio engine. Doing
1056 this before the UI is up and running can cause problems
1057 when not running with SCHED_FIFO, because the amount of
1058 CPU and disk work needed to get the UI started can interfere
1059 with the scheduling of the audio thread.
1062 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1068 if (session && session->dirty()) {
1069 switch (ask_about_saving_session(_("quit"))) {
1074 /* use the default name */
1075 if (save_state_canfail ("")) {
1076 /* failed - don't quit */
1077 ArdourMessage (editor, X_("badsave dialog"),
1079 Ardour was unable to save your session.\n\n\
1080 If you still wish to quit, please use the\n\n\
1081 \"Just quit\" option."));
1094 ARDOUR_UI::ask_about_saving_session (string what)
1096 ArdourDialog window (_("ardour: save session?"));
1097 Gtk::Label prompt_label;
1100 msg = string_compose(_("Save and %1"), what);
1101 window.add_button (msg, RESPONSE_ACCEPT);
1102 msg = string_compose(_("Just %1"), what);
1103 window.add_button (msg, RESPONSE_APPLY);
1104 msg = string_compose(_("Don't %1"), what);
1105 window.add_button (msg, RESPONSE_REJECT);
1107 Gtk::Button noquit_button (msg);
1108 noquit_button.set_name ("EditorGTKButton");
1113 if (session->snap_name() == session->name()) {
1114 type = _("session");
1116 type = _("snapshot");
1118 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?"),
1119 type, session->snap_name());
1121 prompt_label.set_text (prompt);
1122 prompt_label.set_alignment (0.5, 0.5);
1123 prompt_label.set_name (X_("PrompterLabel"));
1125 window.get_vbox()->pack_start (prompt_label);
1127 window.set_name (_("Prompter"));
1128 window.set_position (Gtk::WIN_POS_MOUSE);
1129 window.set_modal (true);
1132 save_the_session = 0;
1134 editor->ensure_float (window);
1136 ResponseType r = (ResponseType) window.run();
1141 case RESPONSE_ACCEPT: // save and get out of here
1143 case RESPONSE_APPLY: // get out of here
1153 ARDOUR_UI::every_second ()
1156 update_buffer_load ();
1157 update_disk_space ();
1158 // update_disk_rate ();
1163 ARDOUR_UI::every_point_one_seconds ()
1166 struct timeval diff;
1168 /* do not attempt to grab peak power more than once per cycle.
1171 gettimeofday (&now, 0);
1172 timersub (&now, &last_peak_grab, &diff);
1174 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1175 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1176 last_peak_grab = now;
1179 update_speed_display ();
1180 RapidScreenUpdate(); /* EMIT_SIGNAL */
1185 ARDOUR_UI::every_point_zero_one_seconds ()
1187 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1192 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1196 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1198 if (!engine->connected()) {
1200 snprintf (buf, sizeof (buf), _("disconnected"));
1204 jack_nframes_t rate = engine->frame_rate();
1206 if (fmod (rate, 1000.0) != 0.0) {
1207 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1208 (float) rate/1000.0f,
1209 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1211 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1213 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1217 sample_rate_label.set_text (buf);
1221 ARDOUR_UI::update_cpu_load ()
1224 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1225 cpu_load_label.set_text (buf);
1229 ARDOUR_UI::update_disk_rate ()
1234 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1235 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1236 disk_rate_label.set_text (buf);
1238 disk_rate_label.set_text ("");
1243 ARDOUR_UI::update_buffer_load ()
1248 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1249 session->playback_load(), session->capture_load());
1250 buffer_load_label.set_text (buf);
1252 buffer_load_label.set_text ("");
1257 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1259 if (ds.record_enabled()) {
1260 rec_enabled_diskstreams++;
1265 ARDOUR_UI::update_disk_space()
1271 jack_nframes_t frames = session->available_capture_duration();
1274 if (frames == max_frames) {
1275 strcpy (buf, _("space: 24hrs+"));
1280 jack_nframes_t fr = session->frame_rate();
1282 if (session->actively_recording()){
1284 rec_enabled_diskstreams = 0;
1285 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1287 if (rec_enabled_diskstreams) {
1288 frames /= rec_enabled_diskstreams;
1293 /* hmmm. shall we divide by the route count? or the diskstream count?
1294 or what? for now, do nothing ...
1299 hrs = frames / (fr * 3600);
1300 frames -= hrs * fr * 3600;
1301 mins = frames / (fr * 60);
1302 frames -= mins * fr * 60;
1305 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1308 disk_space_label.set_text (buf);
1312 ARDOUR_UI::update_wall_clock ()
1319 tm_now = localtime (&now);
1321 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1322 wall_clock_label.set_text (buf);
1328 ARDOUR_UI::toggle_recording_plugins ()
1330 /* XXX use toggle_some_session_state */
1336 session->set_recording_plugins (!session->get_recording_plugins());
1340 ARDOUR_UI::toggle_auto_play ()
1343 toggle_some_session_state (auto_play_button,
1344 &Session::get_auto_play,
1345 &Session::set_auto_play);
1349 ARDOUR_UI::toggle_auto_return ()
1352 toggle_some_session_state (auto_return_button,
1353 &Session::get_auto_return,
1354 &Session::set_auto_return);
1358 ARDOUR_UI::toggle_click ()
1360 toggle_some_session_state (click_button,
1361 &Session::get_clicking,
1362 &Session::set_clicking);
1366 ARDOUR_UI::follow_changed ()
1374 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1375 follow_button.set_active (x);
1380 ARDOUR_UI::toggle_follow ()
1388 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1389 editor->set_follow_playhead (x);
1394 ARDOUR_UI::toggle_session_auto_loop ()
1397 if (session->get_auto_loop()) {
1398 if (session->transport_rolling()) {
1402 session->request_auto_loop (false);
1406 session->request_auto_loop (true);
1412 ARDOUR_UI::toggle_session_punch_in ()
1415 session->set_punch_in (!session->get_punch_in());
1420 ARDOUR_UI::toggle_punch_out ()
1422 toggle_some_session_state (punch_out_button,
1423 &Session::get_punch_out,
1424 &Session::set_punch_out);
1428 ARDOUR_UI::toggle_punch_in ()
1430 toggle_some_session_state (punch_in_button,
1431 &Session::get_punch_in,
1432 &Session::set_punch_in);
1436 ARDOUR_UI::map_button_state ()
1439 map_some_session_state (auto_return_button,
1440 &Session::get_auto_return);
1441 map_some_session_state (auto_play_button,
1442 &Session::get_auto_play);
1443 map_some_session_state (auto_input_button,
1444 &Session::get_auto_input);
1445 map_some_session_state (punch_in_button,
1446 &Session::get_punch_in);
1447 map_some_session_state (punch_out_button,
1448 &Session::get_punch_out);
1449 map_some_session_state (click_button,
1450 &Session::get_clicking);
1454 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1456 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1460 ARDOUR_UI::map_control_change (Session::ControlType t)
1463 case Session::AutoPlay:
1464 map_some_session_state (auto_play_button, &Session::get_auto_play);
1467 case Session::AutoLoop:
1470 case Session::AutoReturn:
1471 map_some_session_state (auto_return_button, &Session::get_auto_return);
1474 case Session::AutoInput:
1475 map_some_session_state (auto_input_button, &Session::get_auto_input);
1478 case Session::PunchOut:
1479 map_some_session_state (punch_in_button, &Session::get_punch_out);
1482 case Session::PunchIn:
1483 map_some_session_state (punch_in_button, &Session::get_punch_in);
1486 case Session::Clicking:
1487 map_some_session_state (click_button, &Session::get_clicking);
1490 case Session::SlaveType:
1491 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1494 case Session::SendMTC:
1495 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1498 case Session::SendMMC:
1499 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1502 case Session::MMCControl:
1503 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1506 case Session::MidiFeedback:
1507 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1509 case Session::MidiControl:
1510 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1516 case Session::RecordingPlugins:
1519 case Session::CrossFadesActive:
1522 case Session::EditingMode:
1525 case Session::PlayRange:
1528 case Session::AlignChoice:
1529 /* don't care, this is handled by the options editor */
1531 case Session::SeamlessLoop:
1532 /* don't care, this is handled by the options editor */
1539 ARDOUR_UI::control_methods_adjusted ()
1544 which_method = (int) online_control_button->adjustment.get_value();
1545 switch (which_method) {
1547 allow_mmc_and_local ();
1553 allow_local_only ();
1556 fatal << _("programming error: impossible control method") << endmsg;
1562 ARDOUR_UI::mmc_device_id_adjusted ()
1567 int dev_id = (int) mmc_id_button->adjustment.get_value();
1568 mmc->set_device_id (dev_id);
1574 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1575 bool (Session::*get)() const)
1584 if (button.get_active() != (x = (session->*get)())) {
1585 button.set_active (x);
1590 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1591 bool (Session::*get)() const,
1592 void (Session::*set)(bool))
1602 button_state = button.get_active ();
1603 session_state = (session->*get)();
1605 if (button_state != session_state) {
1606 (session->*set) (button_state);
1609 /* check that it worked, and reverse
1610 the button state if it didn't
1613 if ((session->*get)() != button_state) {
1614 button->set_active (!button_state);
1622 ARDOUR_UI::session_menu (GdkEventButton *ev)
1624 session_popup_menu->popup (0, 0);
1629 ARDOUR_UI::redisplay_recent_sessions ()
1631 vector<string *> *sessions;
1632 vector<string *>::iterator i;
1633 RecentSessionsSorter cmp;
1635 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1636 recent_session_model->clear ();
1639 ARDOUR::read_recent_sessions (rs);
1642 recent_session_display.set_model (recent_session_model);
1646 /* sort them alphabetically */
1647 sort (rs.begin(), rs.end(), cmp);
1648 sessions = new vector<string*>;
1650 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1651 sessions->push_back (new string ((*i).second));
1654 for (i = sessions->begin(); i != sessions->end(); ++i) {
1656 vector<string*>* states;
1657 vector<const gchar*> item;
1658 string fullpath = *(*i);
1660 /* remove any trailing / */
1662 if (fullpath[fullpath.length()-1] == '/') {
1663 fullpath = fullpath.substr (0, fullpath.length()-1);
1666 /* now get available states for this session */
1668 if ((states = Session::possible_states (fullpath)) == 0) {
1669 /* no state file? */
1673 TreeModel::Row row = *(recent_session_model->append());
1675 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1676 row[recent_session_columns.fullpath] = fullpath;
1678 if (states->size() > 1) {
1680 /* add the children */
1682 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1684 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1686 child_row[recent_session_columns.visible_name] = **i2;
1687 child_row[recent_session_columns.fullpath] = fullpath;
1696 recent_session_display.set_model (recent_session_model);
1701 ARDOUR_UI::build_session_selector ()
1703 session_selector_window = new ArdourDialog ("session selector");
1705 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1707 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1708 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1710 recent_session_model = TreeStore::create (recent_session_columns);
1711 recent_session_display.set_model (recent_session_model);
1712 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1713 recent_session_display.set_headers_visible (false);
1715 scroller->add (recent_session_display);
1716 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1718 session_selector_window->set_name ("SessionSelectorWindow");
1719 session_selector_window->set_size_request (200, 400);
1720 session_selector_window->get_vbox()->pack_start (*scroller);
1721 session_selector_window->show_all_children();
1725 ARDOUR_UI::open_recent_session ()
1727 /* popup selector window */
1729 if (session_selector_window == 0) {
1730 build_session_selector ();
1733 redisplay_recent_sessions ();
1735 ResponseType r = (ResponseType) session_selector_window->run ();
1737 session_selector_window->hide();
1740 case RESPONSE_ACCEPT:
1746 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1748 if (i == recent_session_model->children().end()) {
1752 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1753 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1755 _session_is_new = false;
1757 load_session (path, state);
1761 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1763 struct stat statbuf;
1765 if (stat (info.filename.c_str(), &statbuf) != 0) {
1769 if (!S_ISDIR(statbuf.st_mode)) {
1773 string session_file = info.filename;
1774 session_file += '/';
1775 session_file += PBD::basename (info.filename);
1776 session_file += ".ardour";
1778 if (stat (session_file.c_str(), &statbuf) != 0) {
1782 return S_ISREG (statbuf.st_mode);
1786 ARDOUR_UI::open_session ()
1788 /* popup selector window */
1790 if (open_session_selector == 0) {
1791 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1792 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1793 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1795 FileFilter filter_ardour;
1796 filter_ardour.set_name (_("Ardour sessions"));
1797 filter_ardour.add_pattern("*.ardour");
1798 open_session_selector->add_filter (filter_ardour);
1801 switch (open_session_selector->run ()) {
1805 open_session_selector->hide();
1809 open_session_selector->hide();
1810 string session_path = open_session_selector->get_filename();
1814 if (session_path.length() > 0) {
1815 if (Session::find_session (session_path, path, name, isnew) == 0) {
1816 _session_is_new = isnew;
1817 load_session (path, name);
1824 ARDOUR_UI::session_add_midi_track ()
1826 cerr << _("Patience is a virtue.\n");
1830 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1835 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1841 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1842 error << _("could not create new audio track") << endmsg;
1845 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1846 error << _("could not create new audio bus") << endmsg;
1851 if (need_control_room_outs) {
1857 route->set_stereo_control_outs (control_lr_channels);
1858 route->control_outs()->set_stereo_pan (pans, this);
1860 #endif /* CONTROLOUTS */
1864 ArdourMessage msg (editor, X_("noport dialog"),
1865 _("There are insufficient JACK ports available\n\
1866 to create a new track or bus.\n\
1867 You should save Ardour, exit and\n\
1868 restart JACK with more ports."));
1873 ARDOUR_UI::diskstream_added (DiskStream* ds)
1878 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1880 jack_nframes_t _preroll;
1883 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1885 if (new_position > _preroll) {
1886 new_position -= _preroll;
1891 session->request_locate (new_position);
1896 ARDOUR_UI::transport_goto_start ()
1899 session->request_locate (0);
1902 /* force displayed area in editor to start no matter
1903 what "follow playhead" setting is.
1907 editor->reposition_x_origin (0);
1913 ARDOUR_UI::transport_goto_end ()
1916 jack_nframes_t frame = session->current_end_frame();
1917 session->request_locate (frame);
1919 /* force displayed area in editor to start no matter
1920 what "follow playhead" setting is.
1924 editor->reposition_x_origin (frame);
1930 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1935 if (session->transport_stopped()) {
1936 session->request_locate (session->last_transport_start());
1938 if (session->get_auto_loop()) {
1939 session->request_auto_loop (false);
1942 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1943 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1951 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1958 ARDOUR_UI::transport_stop ()
1964 if (session->is_auditioning()) {
1965 session->cancel_audition ();
1969 if (session->get_auto_loop()) {
1970 session->request_auto_loop (false);
1973 session->request_stop ();
1977 ARDOUR_UI::transport_stop_and_forget_capture ()
1980 session->request_stop (true);
1985 ARDOUR_UI::remove_last_capture()
1988 editor->remove_last_capture();
1993 ARDOUR_UI::transport_record ()
1996 switch (session->record_status()) {
1997 case Session::Disabled:
1998 if (session->ntracks() == 0) {
1999 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
2000 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2003 session->maybe_enable_record ();
2005 case Session::Recording:
2006 case Session::Enabled:
2007 session->disable_record ();
2013 ARDOUR_UI::transport_roll ()
2021 rolling = session->transport_rolling ();
2023 if (session->get_auto_loop()) {
2024 session->request_auto_loop (false);
2025 auto_loop_button.set_active (false);
2026 roll_button.set_active (true);
2027 } else if (session->get_play_range ()) {
2028 session->request_play_range (false);
2029 play_selection_button.set_active (false);
2030 } else if (rolling) {
2031 session->request_locate (session->last_transport_start(), true);
2034 session->request_transport_speed (1.0f);
2038 ARDOUR_UI::transport_loop()
2041 if (session->get_auto_loop()) {
2042 if (session->transport_rolling()) {
2043 Location * looploc = session->locations()->auto_loop_location();
2045 session->request_locate (looploc->start(), true);
2050 session->request_auto_loop (true);
2056 ARDOUR_UI::transport_play_selection ()
2062 if (!session->get_play_range()) {
2063 session->request_stop ();
2066 editor->play_selection ();
2070 ARDOUR_UI::transport_rewind (int option)
2072 float current_transport_speed;
2075 current_transport_speed = session->transport_speed();
2077 if (current_transport_speed >= 0.0f) {
2080 session->request_transport_speed (-1.0f);
2083 session->request_transport_speed (-4.0f);
2086 session->request_transport_speed (-0.5f);
2091 session->request_transport_speed (current_transport_speed * 1.5f);
2097 ARDOUR_UI::transport_forward (int option)
2099 float current_transport_speed;
2102 current_transport_speed = session->transport_speed();
2104 if (current_transport_speed <= 0.0f) {
2107 session->request_transport_speed (1.0f);
2110 session->request_transport_speed (4.0f);
2113 session->request_transport_speed (0.5f);
2118 session->request_transport_speed (current_transport_speed * 1.5f);
2124 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2132 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2133 Port *port = ds->io()->input (0);
2134 port->request_monitor_input (!port->monitoring_input());
2139 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2147 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2148 ds->set_record_enabled (!ds->record_enabled(), this);
2153 ARDOUR_UI::queue_transport_change ()
2155 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2159 ARDOUR_UI::map_transport_state ()
2161 float sp = session->transport_speed();
2164 transport_rolling ();
2165 } else if (sp < 0.0f) {
2166 transport_rewinding ();
2167 } else if (sp > 0.0f) {
2168 transport_forwarding ();
2170 transport_stopped ();
2175 ARDOUR_UI::send_all_midi_feedback ()
2178 session->send_all_midi_feedback();
2183 ARDOUR_UI::allow_local_only ()
2189 ARDOUR_UI::allow_mmc_only ()
2195 ARDOUR_UI::allow_mmc_and_local ()
2201 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2203 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2204 (int) adj.get_value()].c_str());
2208 ARDOUR_UI::engine_stopped ()
2210 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2211 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2212 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2217 ARDOUR_UI::engine_running ()
2219 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2220 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2221 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2225 ARDOUR_UI::engine_halted ()
2227 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2229 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2230 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2232 update_sample_rate (0);
2234 ArdourMessage msg (editor, X_("halted"),
2236 JACK has either been shutdown or it\n\
2237 disconnected Ardour because Ardour\n\
2238 was not fast enough. You can save the\n\
2239 session and/or try to reconnect to JACK ."));
2243 ARDOUR_UI::do_engine_start ()
2249 catch (AudioEngine::PortRegistrationFailure& err) {
2251 error << _("Unable to create all required ports")
2259 error << _("Unable to start the session running")
2269 ARDOUR_UI::start_engine ()
2271 if (do_engine_start () == 0) {
2272 if (session && _session_is_new) {
2273 /* we need to retain initial visual
2274 settings for a new session
2276 session->save_state ("");
2279 /* there is too much going on, in too many threads, for us to
2280 end up with a clean session. So wait 1 second after loading,
2281 and fix it up. its ugly, but until i come across a better
2282 solution, its what we have.
2285 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2292 ARDOUR_UI::update_clocks ()
2294 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2298 ARDOUR_UI::start_clocking ()
2300 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2304 ARDOUR_UI::stop_clocking ()
2306 clock_signal_connection.disconnect ();
2310 ARDOUR_UI::toggle_clocking ()
2313 if (clock_button.get_active()) {
2322 ARDOUR_UI::_blink (void *arg)
2325 ((ARDOUR_UI *) arg)->blink ();
2332 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2336 ARDOUR_UI::start_blinking ()
2338 /* Start the blink signal. Everybody with a blinking widget
2339 uses Blink to drive the widget's state.
2342 if (blink_timeout_tag < 0) {
2344 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2349 ARDOUR_UI::stop_blinking ()
2351 if (blink_timeout_tag >= 0) {
2352 gtk_timeout_remove (blink_timeout_tag);
2353 blink_timeout_tag = -1;
2359 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2361 using namespace Gtk;
2362 using namespace Menu_Helpers;
2364 if (dstream.hidden()) {
2368 MenuList& items = diskstream_menu->items();
2369 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2373 ARDOUR_UI::diskstream_selected (gint32 id)
2375 selected_dstream = id;
2380 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2382 using namespace Gtk;
2383 using namespace Menu_Helpers;
2389 diskstream_menu = new Menu();
2390 diskstream_menu->set_name ("ArdourContextMenu");
2391 using namespace Gtk;
2392 using namespace Menu_Helpers;
2394 MenuList& items = diskstream_menu->items();
2395 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2397 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2400 diskstream_menu->popup (ev->button, ev->time);
2402 diskstream_menu->popup (0, 0);
2405 selected_dstream = -1;
2409 delete diskstream_menu;
2411 return selected_dstream;
2415 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2421 if (io.n_inputs() == 0) {
2426 /* XXX we're not handling multiple ports yet. */
2428 const char **connections = io.input(0)->get_connections();
2430 if (connections == 0 || connections[0] == '\0') {
2433 buf = connections[0];
2440 if (io.n_outputs() == 0) {
2445 /* XXX we're not handling multiple ports yet. */
2447 const char **connections = io.output(0)->get_connections();
2449 if (connections == 0 || connections[0] == '\0') {
2452 buf = connections[0];
2460 ARDOUR_UI::snapshot_session ()
2462 ArdourPrompter prompter (true);
2469 now = now.substr (0, now.length() - 1);
2471 prompter.set_name ("Prompter");
2472 prompter.set_prompt (_("Name for snapshot"));
2473 prompter.set_initial_text (now);
2475 switch (prompter.run()) {
2476 case RESPONSE_ACCEPT:
2477 prompter.get_result (snapname);
2478 if (snapname.length()){
2479 save_state (snapname);
2489 ARDOUR_UI::save_state (string name)
2491 (void) save_state_canfail (name);
2495 ARDOUR_UI::save_state_canfail (string name)
2500 if (name.length() == 0) {
2501 name = session->snap_name();
2504 if ((ret = session->save_state (name)) != 0) {
2508 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2513 ARDOUR_UI::restore_state (string name)
2516 if (name.length() == 0) {
2517 name = session->name();
2519 session->restore_state (name);
2524 ARDOUR_UI::primary_clock_value_changed ()
2527 session->request_locate (primary_clock.current_time ());
2532 ARDOUR_UI::secondary_clock_value_changed ()
2535 session->request_locate (secondary_clock.current_time ());
2540 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2542 if (session && dstream && dstream->record_enabled()) {
2544 Session::RecordState rs;
2546 rs = session->record_status ();
2549 case Session::Disabled:
2550 case Session::Enabled:
2551 if (w->get_state() != STATE_SELECTED) {
2552 w->set_state (STATE_SELECTED);
2556 case Session::Recording:
2557 if (w->get_state() != STATE_ACTIVE) {
2558 w->set_state (STATE_ACTIVE);
2564 if (w->get_state() != STATE_NORMAL) {
2565 w->set_state (STATE_NORMAL);
2571 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2577 switch (session->record_status()) {
2578 case Session::Enabled:
2580 rec_button.set_state (STATE_ACTIVE);
2582 rec_button.set_state (STATE_NORMAL);
2586 case Session::Recording:
2587 rec_button.set_state (STATE_ACTIVE);
2591 rec_button.set_active (false);
2592 rec_button.set_state (STATE_NORMAL);
2598 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2606 ARDOUR_UI::start_keyboard_prefix ()
2608 keyboard->start_prefix();
2612 ARDOUR_UI::save_template ()
2615 ArdourPrompter prompter (true);
2618 prompter.set_name (X_("Prompter"));
2619 prompter.set_prompt (_("Name for mix template:"));
2620 prompter.set_initial_text(session->name() + _("-template"));
2622 switch (prompter.run()) {
2623 case RESPONSE_ACCEPT:
2624 prompter.get_result (name);
2626 if (name.length()) {
2627 session->save_template (name);
2637 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2639 m_new_session_dialog->show_all();
2640 m_new_session_dialog->set_transient_for(*editor);
2641 m_new_session_dialog->set_name(predetermined_path);
2643 int response = Gtk::RESPONSE_CANCEL;
2646 response = m_new_session_dialog->run ();
2648 if(response == Gtk::RESPONSE_OK) {
2650 _session_is_new = true;
2652 std::string session_name = m_new_session_dialog->session_name();
2653 std::string session_path = m_new_session_dialog->session_folder();
2656 XXX This is needed because session constructor wants a
2657 non-existant path. hopefully this will be fixed at some point.
2659 session_path = Glib::build_filename(session_path, session_name);
2661 std::string template_name = m_new_session_dialog->session_template_name();
2663 if (m_new_session_dialog->use_session_template()) {
2665 load_session (session_path, session_name, &template_name);
2671 Session::AutoConnectOption iconnect;
2672 Session::AutoConnectOption oconnect;
2674 if (m_new_session_dialog->create_control_bus()) {
2675 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2680 if (m_new_session_dialog->create_master_bus()) {
2681 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2686 if (m_new_session_dialog->connect_inputs()) {
2687 iconnect = Session::AutoConnectPhysical;
2689 iconnect = Session::AutoConnectOption (0);
2692 /// @todo some minor tweaks.
2694 if (m_new_session_dialog->connect_outs_to_master()) {
2695 oconnect = Session::AutoConnectMaster;
2696 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2697 oconnect = Session::AutoConnectPhysical;
2699 oconnect = Session::AutoConnectOption (0);
2702 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2703 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2705 build_session (session_path,
2713 engine->frame_rate() * 60 * 5);
2717 } while(response == Gtk::RESPONSE_HELP);
2718 m_new_session_dialog->hide_all();
2722 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2724 Session *new_session;
2726 session_loaded = false;
2727 x = unload_session ();
2735 /* if it already exists, we must have write access */
2737 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2738 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2739 You do not have write access to this session.\n\
2740 This prevents the session from being loaded."));
2745 new_session = new Session (*engine, path, snap_name, mix_template);
2750 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2754 connect_to_session (new_session);
2756 //if (engine->running()) {
2757 //mixer->show_window();
2759 session_loaded = true;
2764 ARDOUR_UI::make_session_clean ()
2767 session->set_clean ();
2774 ARDOUR_UI::build_session (string path, string snap_name,
2775 uint32_t control_channels,
2776 uint32_t master_channels,
2777 Session::AutoConnectOption input_connect,
2778 Session::AutoConnectOption output_connect,
2781 jack_nframes_t initial_length)
2783 Session *new_session;
2786 session_loaded = false;
2787 x = unload_session ();
2794 _session_is_new = true;
2797 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2798 control_channels, master_channels, nphysin, nphysout, initial_length);
2803 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2807 connect_to_session (new_session);
2809 //if (engine->running()) {
2810 //mixer->show_window();
2812 session_loaded = true;
2820 editor->show_window ();
2824 if (session && mixer) {
2825 // mixer->show_window ();
2834 ARDOUR_UI::show_splash ()
2837 about = new About();
2843 ARDOUR_UI::hide_splash ()
2851 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2855 removed = rep.paths.size();
2858 ArdourMessage msg (editor, X_("cleanupresults"),
2860 No audio files were ready for cleanup\n\n\
2861 If this seems suprising, check for any existing\n\
2862 snapshots. These may still include regions that\n\
2863 require some unused files to continue to exist."));
2867 ArdourDialog results (_("ardour: cleanup"), true);
2869 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2870 CleanupResultsModelColumns() {
2874 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2875 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2879 Glib::RefPtr<Gtk::ListStore> results_model;
2880 CleanupResultsModelColumns results_columns;
2881 Gtk::TreeView results_display;
2883 results_model = ListStore::create (results_columns);
2884 results_display.set_model (results_model);
2885 results_display.append_column (list_title, results_columns.visible_name);
2886 results_display.set_headers_visible (true);
2888 Gtk::ScrolledWindow list_scroller;
2891 if (rep.space < 1048576.0f) {
2893 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2895 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2899 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2901 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2905 results.get_vbox()->pack_start (txt, false, false);
2907 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2908 TreeModel::Row row = *(results_model->append());
2909 row[results_columns.visible_name] = *i;
2910 row[results_columns.fullpath] = *i;
2913 list_scroller.add (results_display);
2914 list_scroller.set_size_request (-1, 250);
2915 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2917 results.get_vbox()->pack_start (list_scroller, true, true);
2918 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2919 results.set_position (Gtk::WIN_POS_MOUSE);
2925 ARDOUR_UI::cleanup ()
2928 /* shouldn't happen: menu item is insensitive */
2932 ArdourDialog checker (_("ardour cleanup"));
2933 Gtk::Label label (_("\
2934 Cleanup is a destructive operation.\n\
2935 ALL undo/redo information will be lost if you cleanup.\n\
2936 Unused audio files will be moved to a \"dead sounds\" location."));
2938 checker.get_vbox()->pack_start (label, false, false);
2939 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2940 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2942 checker.set_name (_("CleanupDialog"));
2943 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2944 checker.set_position (Gtk::WIN_POS_MOUSE);
2946 switch (checker.run()) {
2947 case RESPONSE_ACCEPT:
2953 Session::cleanup_report rep;
2955 editor->prepare_for_cleanup ();
2957 if (session->cleanup_sources (rep)) {
2961 display_cleanup_results (rep,
2964 The following %1 %2 were not in use.\n\
2965 The next time you flush the wastebasket\n\
2966 it will release an additional %3 %4bytes\n\
2972 ARDOUR_UI::flush_trash ()
2975 /* shouldn't happen: menu item is insensitive */
2979 Session::cleanup_report rep;
2981 if (session->cleanup_trash_sources (rep)) {
2985 display_cleanup_results (rep,
2987 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2991 ARDOUR_UI::add_route ()
2999 if (add_route_dialog == 0) {
3000 add_route_dialog = new AddRouteDialog;
3001 editor->ensure_float (*add_route_dialog);
3004 if (add_route_dialog->is_visible()) {
3005 /* we're already doing this */
3009 ResponseType r = (ResponseType) add_route_dialog->run ();
3011 add_route_dialog->hide();
3014 case RESPONSE_ACCEPT:
3021 if ((count = add_route_dialog->count()) <= 0) {
3025 uint32_t input_chan = add_route_dialog->channels ();
3026 uint32_t output_chan;
3027 string name_template = add_route_dialog->name_template ();
3028 bool track = add_route_dialog->track ();
3030 Session::AutoConnectOption oac = session->get_output_auto_connect();
3032 if (oac & Session::AutoConnectMaster) {
3033 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3035 output_chan = input_chan;
3038 /* XXX do something with name template */
3042 session_add_audio_track (input_chan, output_chan);
3044 session_add_audio_bus (input_chan, output_chan);
3048 while (Main::events_pending()) {
3055 ARDOUR_UI::mixer_settings () const
3060 node = session->instant_xml(X_("Mixer"), session->path());
3062 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3066 node = new XMLNode (X_("Mixer"));
3073 ARDOUR_UI::editor_settings () const
3078 node = session->instant_xml(X_("Editor"), session->path());
3080 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3084 node = new XMLNode (X_("Editor"));
3090 ARDOUR_UI::keyboard_settings () const
3094 node = Config->extra_xml(X_("Keyboard"));
3097 node = new XMLNode (X_("Keyboard"));
3103 ARDOUR_UI::halt_on_xrun_message ()
3105 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3107 ArdourMessage msg (editor, X_("haltonxrun"),
3108 _("Recording was stopped because your system could not keep up."));
3112 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3114 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3116 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3120 delete deletion_list;
3124 ARDOUR_UI::disk_overrun_handler ()
3126 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3128 if (!have_disk_overrun_displayed) {
3129 have_disk_overrun_displayed = true;
3130 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3131 The disk system on your computer\n\
3132 was not able to keep up with Ardour.\n\
3134 Specifically, it failed to write data to disk\n\
3135 quickly enough to keep up with recording.\n"));
3136 have_disk_overrun_displayed = false;
3141 ARDOUR_UI::disk_underrun_handler ()
3143 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3145 if (!have_disk_underrun_displayed) {
3146 have_disk_underrun_displayed = true;
3147 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3148 (_("The disk system on your computer\n\
3149 was not able to keep up with Ardour.\n\
3151 Specifically, it failed to read data from disk\n\
3152 quickly enough to keep up with playback.\n")));
3153 have_disk_underrun_displayed = false;
3158 ARDOUR_UI::disk_underrun_message_gone ()
3160 have_disk_underrun_displayed = false;
3164 ARDOUR_UI::disk_overrun_message_gone ()
3166 have_disk_underrun_displayed = false;
3170 ARDOUR_UI::pending_state_dialog ()
3172 ArdourDialog dialog ("pending state dialog");
3174 This session appears to have been in\n\
3175 middle of recording when ardour or\n\
3176 the computer was shutdown.\n\
3178 Ardour can recover any captured audio for\n\
3179 you, or it can ignore it. Please decide\n\
3180 what you would like to do.\n"));
3182 dialog.get_vbox()->pack_start (message);
3183 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3184 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3186 dialog.set_position (WIN_POS_CENTER);
3189 switch (dialog.run ()) {
3190 case RESPONSE_ACCEPT:
3201 ARDOUR_UI::disconnect_from_jack ()
3204 if( engine->disconnect_from_jack ()) {
3205 ArdourMessage msg (editor, X_("nojack dialog"),
3206 _("Could not disconnect from JACK"));
3209 update_sample_rate (0);
3214 ARDOUR_UI::reconnect_to_jack ()
3217 if (engine->reconnect_to_jack ()) {
3218 ArdourMessage msg (editor, X_("nojack dialog"),
3219 _("Could not reconnect to JACK"));
3222 update_sample_rate (0);
3227 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3229 engine->request_buffer_size (nframes);
3230 update_sample_rate (0);
3234 ARDOUR_UI::cmdline_new_session (string path)
3236 if (path[0] != '/') {
3237 char buf[PATH_MAX+1];
3240 getcwd (buf, sizeof (buf));
3247 new_session (false, path);
3249 _will_create_new_session_automatically = false; /* done it */
3250 return FALSE; /* don't call it again */