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);
1724 ARDOUR_UI::open_recent_session ()
1726 /* popup selector window */
1728 if (session_selector_window == 0) {
1729 build_session_selector ();
1732 redisplay_recent_sessions ();
1734 ResponseType r = (ResponseType) session_selector_window->run ();
1736 session_selector_window->hide();
1739 case RESPONSE_ACCEPT:
1745 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1747 if (i == recent_session_model->children().end()) {
1751 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1752 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1754 _session_is_new = false;
1756 load_session (path, state);
1760 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1762 struct stat statbuf;
1764 if (stat (info.filename.c_str(), &statbuf) != 0) {
1768 if (!S_ISDIR(statbuf.st_mode)) {
1772 string session_file = info.filename;
1773 session_file += '/';
1774 session_file += PBD::basename (info.filename);
1775 session_file += ".ardour";
1777 if (stat (session_file.c_str(), &statbuf) != 0) {
1781 return S_ISREG (statbuf.st_mode);
1785 ARDOUR_UI::open_session ()
1787 /* popup selector window */
1789 if (open_session_selector == 0) {
1790 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1791 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1792 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1794 FileFilter filter_ardour;
1795 filter_ardour.set_name (_("Ardour sessions"));
1796 filter_ardour.add_pattern("*.ardour");
1797 open_session_selector->add_filter (filter_ardour);
1800 switch (open_session_selector->run ()) {
1804 open_session_selector->hide();
1808 open_session_selector->hide();
1809 string session_path = open_session_selector->get_filename();
1813 if (session_path.length() > 0) {
1814 if (Session::find_session (session_path, path, name, isnew) == 0) {
1815 _session_is_new = isnew;
1816 load_session (path, name);
1823 ARDOUR_UI::session_add_midi_track ()
1825 cerr << _("Patience is a virtue.\n");
1829 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1834 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1840 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1841 error << _("could not create new audio track") << endmsg;
1844 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1845 error << _("could not create new audio bus") << endmsg;
1850 if (need_control_room_outs) {
1856 route->set_stereo_control_outs (control_lr_channels);
1857 route->control_outs()->set_stereo_pan (pans, this);
1859 #endif /* CONTROLOUTS */
1863 ArdourMessage msg (editor, X_("noport dialog"),
1864 _("There are insufficient JACK ports available\n\
1865 to create a new track or bus.\n\
1866 You should save Ardour, exit and\n\
1867 restart JACK with more ports."));
1872 ARDOUR_UI::diskstream_added (DiskStream* ds)
1877 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1879 jack_nframes_t _preroll;
1882 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1884 if (new_position > _preroll) {
1885 new_position -= _preroll;
1890 session->request_locate (new_position);
1895 ARDOUR_UI::transport_goto_start ()
1898 session->request_locate (0);
1901 /* force displayed area in editor to start no matter
1902 what "follow playhead" setting is.
1906 editor->reposition_x_origin (0);
1912 ARDOUR_UI::transport_goto_end ()
1915 jack_nframes_t frame = session->current_end_frame();
1916 session->request_locate (frame);
1918 /* force displayed area in editor to start no matter
1919 what "follow playhead" setting is.
1923 editor->reposition_x_origin (frame);
1929 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1934 if (session->transport_stopped()) {
1935 session->request_locate (session->last_transport_start());
1937 if (session->get_auto_loop()) {
1938 session->request_auto_loop (false);
1941 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1942 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1950 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1957 ARDOUR_UI::transport_stop ()
1963 if (session->is_auditioning()) {
1964 session->cancel_audition ();
1968 if (session->get_auto_loop()) {
1969 session->request_auto_loop (false);
1972 session->request_stop ();
1976 ARDOUR_UI::transport_stop_and_forget_capture ()
1979 session->request_stop (true);
1984 ARDOUR_UI::remove_last_capture()
1987 editor->remove_last_capture();
1992 ARDOUR_UI::transport_record ()
1995 switch (session->record_status()) {
1996 case Session::Disabled:
1997 if (session->ntracks() == 0) {
1998 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1999 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2002 session->maybe_enable_record ();
2004 case Session::Recording:
2005 case Session::Enabled:
2006 session->disable_record ();
2012 ARDOUR_UI::transport_roll ()
2020 rolling = session->transport_rolling ();
2022 if (session->get_auto_loop()) {
2023 session->request_auto_loop (false);
2024 auto_loop_button.set_active (false);
2025 roll_button.set_active (true);
2026 } else if (session->get_play_range ()) {
2027 session->request_play_range (false);
2028 play_selection_button.set_active (false);
2029 } else if (rolling) {
2030 session->request_locate (session->last_transport_start(), true);
2033 session->request_transport_speed (1.0f);
2037 ARDOUR_UI::transport_loop()
2040 if (session->get_auto_loop()) {
2041 if (session->transport_rolling()) {
2042 Location * looploc = session->locations()->auto_loop_location();
2044 session->request_locate (looploc->start(), true);
2049 session->request_auto_loop (true);
2055 ARDOUR_UI::transport_play_selection ()
2061 if (!session->get_play_range()) {
2062 session->request_stop ();
2065 editor->play_selection ();
2069 ARDOUR_UI::transport_rewind (int option)
2071 float current_transport_speed;
2074 current_transport_speed = session->transport_speed();
2076 if (current_transport_speed >= 0.0f) {
2079 session->request_transport_speed (-1.0f);
2082 session->request_transport_speed (-4.0f);
2085 session->request_transport_speed (-0.5f);
2090 session->request_transport_speed (current_transport_speed * 1.5f);
2096 ARDOUR_UI::transport_forward (int option)
2098 float current_transport_speed;
2101 current_transport_speed = session->transport_speed();
2103 if (current_transport_speed <= 0.0f) {
2106 session->request_transport_speed (1.0f);
2109 session->request_transport_speed (4.0f);
2112 session->request_transport_speed (0.5f);
2117 session->request_transport_speed (current_transport_speed * 1.5f);
2123 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2131 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2132 Port *port = ds->io()->input (0);
2133 port->request_monitor_input (!port->monitoring_input());
2138 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2146 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2147 ds->set_record_enabled (!ds->record_enabled(), this);
2152 ARDOUR_UI::queue_transport_change ()
2154 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2158 ARDOUR_UI::map_transport_state ()
2160 float sp = session->transport_speed();
2163 transport_rolling ();
2164 } else if (sp < 0.0f) {
2165 transport_rewinding ();
2166 } else if (sp > 0.0f) {
2167 transport_forwarding ();
2169 transport_stopped ();
2174 ARDOUR_UI::send_all_midi_feedback ()
2177 session->send_all_midi_feedback();
2182 ARDOUR_UI::allow_local_only ()
2188 ARDOUR_UI::allow_mmc_only ()
2194 ARDOUR_UI::allow_mmc_and_local ()
2200 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2202 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2203 (int) adj.get_value()].c_str());
2207 ARDOUR_UI::engine_stopped ()
2209 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2210 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2211 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2216 ARDOUR_UI::engine_running ()
2218 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2219 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2220 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2224 ARDOUR_UI::engine_halted ()
2226 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2228 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2229 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2231 update_sample_rate (0);
2233 ArdourMessage msg (editor, X_("halted"),
2235 JACK has either been shutdown or it\n\
2236 disconnected Ardour because Ardour\n\
2237 was not fast enough. You can save the\n\
2238 session and/or try to reconnect to JACK ."));
2242 ARDOUR_UI::do_engine_start ()
2248 catch (AudioEngine::PortRegistrationFailure& err) {
2250 error << _("Unable to create all required ports")
2258 error << _("Unable to start the session running")
2268 ARDOUR_UI::start_engine ()
2270 if (do_engine_start () == 0) {
2271 if (session && _session_is_new) {
2272 /* we need to retain initial visual
2273 settings for a new session
2275 session->save_state ("");
2278 /* there is too much going on, in too many threads, for us to
2279 end up with a clean session. So wait 1 second after loading,
2280 and fix it up. its ugly, but until i come across a better
2281 solution, its what we have.
2284 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2291 ARDOUR_UI::update_clocks ()
2293 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2297 ARDOUR_UI::start_clocking ()
2299 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2303 ARDOUR_UI::stop_clocking ()
2305 clock_signal_connection.disconnect ();
2309 ARDOUR_UI::toggle_clocking ()
2312 if (clock_button.get_active()) {
2321 ARDOUR_UI::_blink (void *arg)
2324 ((ARDOUR_UI *) arg)->blink ();
2331 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2335 ARDOUR_UI::start_blinking ()
2337 /* Start the blink signal. Everybody with a blinking widget
2338 uses Blink to drive the widget's state.
2341 if (blink_timeout_tag < 0) {
2343 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2348 ARDOUR_UI::stop_blinking ()
2350 if (blink_timeout_tag >= 0) {
2351 gtk_timeout_remove (blink_timeout_tag);
2352 blink_timeout_tag = -1;
2358 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2360 using namespace Gtk;
2361 using namespace Menu_Helpers;
2363 if (dstream.hidden()) {
2367 MenuList& items = diskstream_menu->items();
2368 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2372 ARDOUR_UI::diskstream_selected (gint32 id)
2374 selected_dstream = id;
2379 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2381 using namespace Gtk;
2382 using namespace Menu_Helpers;
2388 diskstream_menu = new Menu();
2389 diskstream_menu->set_name ("ArdourContextMenu");
2390 using namespace Gtk;
2391 using namespace Menu_Helpers;
2393 MenuList& items = diskstream_menu->items();
2394 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2396 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2399 diskstream_menu->popup (ev->button, ev->time);
2401 diskstream_menu->popup (0, 0);
2404 selected_dstream = -1;
2408 delete diskstream_menu;
2410 return selected_dstream;
2414 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2420 if (io.n_inputs() == 0) {
2425 /* XXX we're not handling multiple ports yet. */
2427 const char **connections = io.input(0)->get_connections();
2429 if (connections == 0 || connections[0] == '\0') {
2432 buf = connections[0];
2439 if (io.n_outputs() == 0) {
2444 /* XXX we're not handling multiple ports yet. */
2446 const char **connections = io.output(0)->get_connections();
2448 if (connections == 0 || connections[0] == '\0') {
2451 buf = connections[0];
2459 ARDOUR_UI::snapshot_session ()
2461 ArdourPrompter prompter (true);
2468 now = now.substr (0, now.length() - 1);
2470 prompter.set_name ("Prompter");
2471 prompter.set_prompt (_("Name for snapshot"));
2472 prompter.set_initial_text (now);
2474 switch (prompter.run()) {
2475 case RESPONSE_ACCEPT:
2476 prompter.get_result (snapname);
2477 if (snapname.length()){
2478 save_state (snapname);
2488 ARDOUR_UI::save_state (string name)
2490 (void) save_state_canfail (name);
2494 ARDOUR_UI::save_state_canfail (string name)
2499 if (name.length() == 0) {
2500 name = session->snap_name();
2503 if ((ret = session->save_state (name)) != 0) {
2507 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2512 ARDOUR_UI::restore_state (string name)
2515 if (name.length() == 0) {
2516 name = session->name();
2518 session->restore_state (name);
2523 ARDOUR_UI::primary_clock_value_changed ()
2526 session->request_locate (primary_clock.current_time ());
2531 ARDOUR_UI::secondary_clock_value_changed ()
2534 session->request_locate (secondary_clock.current_time ());
2539 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2541 if (session && dstream && dstream->record_enabled()) {
2543 Session::RecordState rs;
2545 rs = session->record_status ();
2548 case Session::Disabled:
2549 case Session::Enabled:
2550 if (w->get_state() != STATE_SELECTED) {
2551 w->set_state (STATE_SELECTED);
2555 case Session::Recording:
2556 if (w->get_state() != STATE_ACTIVE) {
2557 w->set_state (STATE_ACTIVE);
2563 if (w->get_state() != STATE_NORMAL) {
2564 w->set_state (STATE_NORMAL);
2570 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2576 switch (session->record_status()) {
2577 case Session::Enabled:
2579 rec_button.set_state (STATE_ACTIVE);
2581 rec_button.set_state (STATE_NORMAL);
2585 case Session::Recording:
2586 rec_button.set_state (STATE_ACTIVE);
2590 rec_button.set_active (false);
2591 rec_button.set_state (STATE_NORMAL);
2597 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2605 ARDOUR_UI::start_keyboard_prefix ()
2607 keyboard->start_prefix();
2611 ARDOUR_UI::save_template ()
2614 ArdourPrompter prompter (true);
2617 prompter.set_name (X_("Prompter"));
2618 prompter.set_prompt (_("Name for mix template:"));
2619 prompter.set_initial_text(session->name() + _("-template"));
2621 switch (prompter.run()) {
2622 case RESPONSE_ACCEPT:
2623 prompter.get_result (name);
2625 if (name.length()) {
2626 session->save_template (name);
2636 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2638 m_new_session_dialog->show_all();
2639 m_new_session_dialog->set_transient_for(*editor);
2640 m_new_session_dialog->set_name(predetermined_path);
2642 int response = Gtk::RESPONSE_CANCEL;
2645 response = m_new_session_dialog->run ();
2647 if(response == Gtk::RESPONSE_OK) {
2649 _session_is_new = true;
2651 std::string session_name = m_new_session_dialog->session_name();
2652 std::string session_path = m_new_session_dialog->session_folder();
2655 XXX This is needed because session constructor wants a
2656 non-existant path. hopefully this will be fixed at some point.
2658 session_path = Glib::build_filename(session_path, session_name);
2660 std::string template_name = m_new_session_dialog->session_template_name();
2662 if (m_new_session_dialog->use_session_template()) {
2664 load_session (session_path, session_name, &template_name);
2670 Session::AutoConnectOption iconnect;
2671 Session::AutoConnectOption oconnect;
2673 if (m_new_session_dialog->create_control_bus()) {
2674 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2679 if (m_new_session_dialog->create_master_bus()) {
2680 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2685 if (m_new_session_dialog->connect_inputs()) {
2686 iconnect = Session::AutoConnectPhysical;
2688 iconnect = Session::AutoConnectOption (0);
2691 /// @todo some minor tweaks.
2693 if (m_new_session_dialog->connect_outs_to_master()) {
2694 oconnect = Session::AutoConnectMaster;
2695 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2696 oconnect = Session::AutoConnectPhysical;
2698 oconnect = Session::AutoConnectOption (0);
2701 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2702 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2704 build_session (session_path,
2712 engine->frame_rate() * 60 * 5);
2716 } while(response == Gtk::RESPONSE_HELP);
2717 m_new_session_dialog->hide_all();
2721 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2723 Session *new_session;
2725 session_loaded = false;
2726 x = unload_session ();
2734 /* if it already exists, we must have write access */
2736 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2737 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2738 You do not have write access to this session.\n\
2739 This prevents the session from being loaded."));
2744 new_session = new Session (*engine, path, snap_name, mix_template);
2749 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2753 connect_to_session (new_session);
2755 //if (engine->running()) {
2756 //mixer->show_window();
2758 session_loaded = true;
2763 ARDOUR_UI::make_session_clean ()
2766 session->set_clean ();
2773 ARDOUR_UI::build_session (string path, string snap_name,
2774 uint32_t control_channels,
2775 uint32_t master_channels,
2776 Session::AutoConnectOption input_connect,
2777 Session::AutoConnectOption output_connect,
2780 jack_nframes_t initial_length)
2782 Session *new_session;
2785 session_loaded = false;
2786 x = unload_session ();
2793 _session_is_new = true;
2796 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2797 control_channels, master_channels, nphysin, nphysout, initial_length);
2802 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2806 connect_to_session (new_session);
2808 //if (engine->running()) {
2809 //mixer->show_window();
2811 session_loaded = true;
2819 editor->show_window ();
2823 if (session && mixer) {
2824 // mixer->show_window ();
2833 ARDOUR_UI::show_splash ()
2836 about = new About();
2842 ARDOUR_UI::hide_splash ()
2850 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2854 removed = rep.paths.size();
2857 ArdourMessage msg (editor, X_("cleanupresults"),
2859 No audio files were ready for cleanup\n\n\
2860 If this seems suprising, check for any existing\n\
2861 snapshots. These may still include regions that\n\
2862 require some unused files to continue to exist."));
2866 ArdourDialog results (_("ardour: cleanup"), true);
2868 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2869 CleanupResultsModelColumns() {
2873 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2874 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2878 Glib::RefPtr<Gtk::ListStore> results_model;
2879 CleanupResultsModelColumns results_columns;
2880 Gtk::TreeView results_display;
2882 results_model = ListStore::create (results_columns);
2883 results_display.set_model (results_model);
2884 results_display.append_column (list_title, results_columns.visible_name);
2885 results_display.set_headers_visible (true);
2887 Gtk::ScrolledWindow list_scroller;
2890 if (rep.space < 1048576.0f) {
2892 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2894 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2898 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2900 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2904 results.get_vbox()->pack_start (txt, false, false);
2906 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2907 TreeModel::Row row = *(results_model->append());
2908 row[results_columns.visible_name] = *i;
2909 row[results_columns.fullpath] = *i;
2912 list_scroller.add (results_display);
2913 list_scroller.set_size_request (-1, 250);
2914 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2916 results.get_vbox()->pack_start (list_scroller, true, true);
2917 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2918 results.set_position (Gtk::WIN_POS_MOUSE);
2924 ARDOUR_UI::cleanup ()
2927 /* shouldn't happen: menu item is insensitive */
2931 ArdourDialog checker (_("ardour cleanup"));
2932 Gtk::Label label (_("\
2933 Cleanup is a destructive operation.\n\
2934 ALL undo/redo information will be lost if you cleanup.\n\
2935 Unused audio files will be moved to a \"dead sounds\" location."));
2937 checker.get_vbox()->pack_start (label, false, false);
2938 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2939 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2941 checker.set_name (_("CleanupDialog"));
2942 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2943 checker.set_position (Gtk::WIN_POS_MOUSE);
2945 switch (checker.run()) {
2946 case RESPONSE_ACCEPT:
2952 Session::cleanup_report rep;
2954 editor->prepare_for_cleanup ();
2956 if (session->cleanup_sources (rep)) {
2960 display_cleanup_results (rep,
2963 The following %1 %2 were not in use.\n\
2964 The next time you flush the wastebasket\n\
2965 it will release an additional %3 %4bytes\n\
2971 ARDOUR_UI::flush_trash ()
2974 /* shouldn't happen: menu item is insensitive */
2978 Session::cleanup_report rep;
2980 if (session->cleanup_trash_sources (rep)) {
2984 display_cleanup_results (rep,
2986 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2990 ARDOUR_UI::add_route ()
2998 if (add_route_dialog == 0) {
2999 add_route_dialog = new AddRouteDialog;
3000 editor->ensure_float (*add_route_dialog);
3003 if (add_route_dialog->is_visible()) {
3004 /* we're already doing this */
3008 ResponseType r = (ResponseType) add_route_dialog->run ();
3010 add_route_dialog->hide();
3013 case RESPONSE_ACCEPT:
3020 if ((count = add_route_dialog->count()) <= 0) {
3024 uint32_t input_chan = add_route_dialog->channels ();
3025 uint32_t output_chan;
3026 string name_template = add_route_dialog->name_template ();
3027 bool track = add_route_dialog->track ();
3029 Session::AutoConnectOption oac = session->get_output_auto_connect();
3031 if (oac & Session::AutoConnectMaster) {
3032 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3034 output_chan = input_chan;
3037 /* XXX do something with name template */
3041 session_add_audio_track (input_chan, output_chan);
3043 session_add_audio_bus (input_chan, output_chan);
3047 while (Main::events_pending()) {
3054 ARDOUR_UI::mixer_settings () const
3059 node = session->instant_xml(X_("Mixer"), session->path());
3061 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3065 node = new XMLNode (X_("Mixer"));
3072 ARDOUR_UI::editor_settings () const
3077 node = session->instant_xml(X_("Editor"), session->path());
3079 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3083 node = new XMLNode (X_("Editor"));
3089 ARDOUR_UI::keyboard_settings () const
3093 node = Config->extra_xml(X_("Keyboard"));
3096 node = new XMLNode (X_("Keyboard"));
3102 ARDOUR_UI::halt_on_xrun_message ()
3104 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3106 ArdourMessage msg (editor, X_("haltonxrun"),
3107 _("Recording was stopped because your system could not keep up."));
3111 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3113 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3115 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3119 delete deletion_list;
3123 ARDOUR_UI::disk_overrun_handler ()
3125 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3127 if (!have_disk_overrun_displayed) {
3128 have_disk_overrun_displayed = true;
3129 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3130 The disk system on your computer\n\
3131 was not able to keep up with Ardour.\n\
3133 Specifically, it failed to write data to disk\n\
3134 quickly enough to keep up with recording.\n"));
3135 have_disk_overrun_displayed = false;
3140 ARDOUR_UI::disk_underrun_handler ()
3142 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3144 if (!have_disk_underrun_displayed) {
3145 have_disk_underrun_displayed = true;
3146 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3147 (_("The disk system on your computer\n\
3148 was not able to keep up with Ardour.\n\
3150 Specifically, it failed to read data from disk\n\
3151 quickly enough to keep up with playback.\n")));
3152 have_disk_underrun_displayed = false;
3157 ARDOUR_UI::disk_underrun_message_gone ()
3159 have_disk_underrun_displayed = false;
3163 ARDOUR_UI::disk_overrun_message_gone ()
3165 have_disk_underrun_displayed = false;
3169 ARDOUR_UI::pending_state_dialog ()
3171 ArdourDialog dialog ("pending state dialog");
3173 This session appears to have been in\n\
3174 middle of recording when ardour or\n\
3175 the computer was shutdown.\n\
3177 Ardour can recover any captured audio for\n\
3178 you, or it can ignore it. Please decide\n\
3179 what you would like to do.\n"));
3181 dialog.get_vbox()->pack_start (message);
3182 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3183 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3185 dialog.set_position (WIN_POS_CENTER);
3188 switch (dialog.run ()) {
3189 case RESPONSE_ACCEPT:
3200 ARDOUR_UI::disconnect_from_jack ()
3203 if( engine->disconnect_from_jack ()) {
3204 ArdourMessage msg (editor, X_("nojack dialog"),
3205 _("Could not disconnect from JACK"));
3208 update_sample_rate (0);
3213 ARDOUR_UI::reconnect_to_jack ()
3216 if (engine->reconnect_to_jack ()) {
3217 ArdourMessage msg (editor, X_("nojack dialog"),
3218 _("Could not reconnect to JACK"));
3221 update_sample_rate (0);
3226 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3228 engine->request_buffer_size (nframes);
3229 update_sample_rate (0);
3233 ARDOUR_UI::cmdline_new_session (string path)
3235 if (path[0] != '/') {
3236 char buf[PATH_MAX+1];
3239 getcwd (buf, sizeof (buf));
3246 new_session (false, path);
3248 _will_create_new_session_automatically = false; /* done it */
3249 return FALSE; /* don't call it again */