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 ()) {
1807 string session_path = open_session_selector->get_filename();
1811 if (session_path.length() > 0) {
1812 if (Session::find_session (session_path, path, name, isnew) == 0) {
1813 _session_is_new = isnew;
1814 load_session (path, name);
1821 ARDOUR_UI::session_add_midi_track ()
1823 cerr << _("Patience is a virtue.\n");
1827 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1832 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1838 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1839 error << _("could not create new audio track") << endmsg;
1842 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1843 error << _("could not create new audio bus") << endmsg;
1848 if (need_control_room_outs) {
1854 route->set_stereo_control_outs (control_lr_channels);
1855 route->control_outs()->set_stereo_pan (pans, this);
1857 #endif /* CONTROLOUTS */
1861 ArdourMessage msg (editor, X_("noport dialog"),
1862 _("There are insufficient JACK ports available\n\
1863 to create a new track or bus.\n\
1864 You should save Ardour, exit and\n\
1865 restart JACK with more ports."));
1870 ARDOUR_UI::diskstream_added (DiskStream* ds)
1875 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1877 jack_nframes_t _preroll;
1880 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1882 if (new_position > _preroll) {
1883 new_position -= _preroll;
1888 session->request_locate (new_position);
1893 ARDOUR_UI::transport_goto_start ()
1896 session->request_locate (0);
1899 /* force displayed area in editor to start no matter
1900 what "follow playhead" setting is.
1904 editor->reposition_x_origin (0);
1910 ARDOUR_UI::transport_goto_end ()
1913 jack_nframes_t frame = session->current_end_frame();
1914 session->request_locate (frame);
1916 /* force displayed area in editor to start no matter
1917 what "follow playhead" setting is.
1921 editor->reposition_x_origin (frame);
1927 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1932 if (session->transport_stopped()) {
1933 session->request_locate (session->last_transport_start());
1935 if (session->get_auto_loop()) {
1936 session->request_auto_loop (false);
1939 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1940 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1948 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1955 ARDOUR_UI::transport_stop ()
1961 if (session->is_auditioning()) {
1962 session->cancel_audition ();
1966 if (session->get_auto_loop()) {
1967 session->request_auto_loop (false);
1970 session->request_stop ();
1974 ARDOUR_UI::transport_stop_and_forget_capture ()
1977 session->request_stop (true);
1982 ARDOUR_UI::remove_last_capture()
1985 editor->remove_last_capture();
1990 ARDOUR_UI::transport_record ()
1993 switch (session->record_status()) {
1994 case Session::Disabled:
1995 if (session->ntracks() == 0) {
1996 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1997 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2000 session->maybe_enable_record ();
2002 case Session::Recording:
2003 case Session::Enabled:
2004 session->disable_record ();
2010 ARDOUR_UI::transport_roll ()
2018 rolling = session->transport_rolling ();
2020 if (session->get_auto_loop()) {
2021 session->request_auto_loop (false);
2022 auto_loop_button.set_active (false);
2023 roll_button.set_active (true);
2024 } else if (session->get_play_range ()) {
2025 session->request_play_range (false);
2026 play_selection_button.set_active (false);
2027 } else if (rolling) {
2028 session->request_locate (session->last_transport_start(), true);
2031 session->request_transport_speed (1.0f);
2035 ARDOUR_UI::transport_loop()
2038 if (session->get_auto_loop()) {
2039 if (session->transport_rolling()) {
2040 Location * looploc = session->locations()->auto_loop_location();
2042 session->request_locate (looploc->start(), true);
2047 session->request_auto_loop (true);
2053 ARDOUR_UI::transport_play_selection ()
2059 if (!session->get_play_range()) {
2060 session->request_stop ();
2063 editor->play_selection ();
2067 ARDOUR_UI::transport_rewind (int option)
2069 float current_transport_speed;
2072 current_transport_speed = session->transport_speed();
2074 if (current_transport_speed >= 0.0f) {
2077 session->request_transport_speed (-1.0f);
2080 session->request_transport_speed (-4.0f);
2083 session->request_transport_speed (-0.5f);
2088 session->request_transport_speed (current_transport_speed * 1.5f);
2094 ARDOUR_UI::transport_forward (int option)
2096 float current_transport_speed;
2099 current_transport_speed = session->transport_speed();
2101 if (current_transport_speed <= 0.0f) {
2104 session->request_transport_speed (1.0f);
2107 session->request_transport_speed (4.0f);
2110 session->request_transport_speed (0.5f);
2115 session->request_transport_speed (current_transport_speed * 1.5f);
2121 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2129 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2130 Port *port = ds->io()->input (0);
2131 port->request_monitor_input (!port->monitoring_input());
2136 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2144 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2145 ds->set_record_enabled (!ds->record_enabled(), this);
2150 ARDOUR_UI::queue_transport_change ()
2152 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2156 ARDOUR_UI::map_transport_state ()
2158 float sp = session->transport_speed();
2161 transport_rolling ();
2162 } else if (sp < 0.0f) {
2163 transport_rewinding ();
2164 } else if (sp > 0.0f) {
2165 transport_forwarding ();
2167 transport_stopped ();
2172 ARDOUR_UI::send_all_midi_feedback ()
2175 session->send_all_midi_feedback();
2180 ARDOUR_UI::allow_local_only ()
2186 ARDOUR_UI::allow_mmc_only ()
2192 ARDOUR_UI::allow_mmc_and_local ()
2198 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2200 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2201 (int) adj.get_value()].c_str());
2205 ARDOUR_UI::engine_stopped ()
2207 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2208 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2209 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2214 ARDOUR_UI::engine_running ()
2216 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2217 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2218 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2222 ARDOUR_UI::engine_halted ()
2224 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2226 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2227 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2229 update_sample_rate (0);
2231 ArdourMessage msg (editor, X_("halted"),
2233 JACK has either been shutdown or it\n\
2234 disconnected Ardour because Ardour\n\
2235 was not fast enough. You can save the\n\
2236 session and/or try to reconnect to JACK ."));
2240 ARDOUR_UI::do_engine_start ()
2246 catch (AudioEngine::PortRegistrationFailure& err) {
2248 error << _("Unable to create all required ports")
2256 error << _("Unable to start the session running")
2266 ARDOUR_UI::start_engine ()
2268 if (do_engine_start () == 0) {
2269 if (session && _session_is_new) {
2270 /* we need to retain initial visual
2271 settings for a new session
2273 session->save_state ("");
2276 /* there is too much going on, in too many threads, for us to
2277 end up with a clean session. So wait 1 second after loading,
2278 and fix it up. its ugly, but until i come across a better
2279 solution, its what we have.
2282 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2289 ARDOUR_UI::update_clocks ()
2291 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2295 ARDOUR_UI::start_clocking ()
2297 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2301 ARDOUR_UI::stop_clocking ()
2303 clock_signal_connection.disconnect ();
2307 ARDOUR_UI::toggle_clocking ()
2310 if (clock_button.get_active()) {
2319 ARDOUR_UI::_blink (void *arg)
2322 ((ARDOUR_UI *) arg)->blink ();
2329 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2333 ARDOUR_UI::start_blinking ()
2335 /* Start the blink signal. Everybody with a blinking widget
2336 uses Blink to drive the widget's state.
2339 if (blink_timeout_tag < 0) {
2341 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2346 ARDOUR_UI::stop_blinking ()
2348 if (blink_timeout_tag >= 0) {
2349 gtk_timeout_remove (blink_timeout_tag);
2350 blink_timeout_tag = -1;
2356 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2358 using namespace Gtk;
2359 using namespace Menu_Helpers;
2361 if (dstream.hidden()) {
2365 MenuList& items = diskstream_menu->items();
2366 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2370 ARDOUR_UI::diskstream_selected (gint32 id)
2372 selected_dstream = id;
2377 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2379 using namespace Gtk;
2380 using namespace Menu_Helpers;
2386 diskstream_menu = new Menu();
2387 diskstream_menu->set_name ("ArdourContextMenu");
2388 using namespace Gtk;
2389 using namespace Menu_Helpers;
2391 MenuList& items = diskstream_menu->items();
2392 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2394 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2397 diskstream_menu->popup (ev->button, ev->time);
2399 diskstream_menu->popup (0, 0);
2402 selected_dstream = -1;
2406 delete diskstream_menu;
2408 return selected_dstream;
2412 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2418 if (io.n_inputs() == 0) {
2423 /* XXX we're not handling multiple ports yet. */
2425 const char **connections = io.input(0)->get_connections();
2427 if (connections == 0 || connections[0] == '\0') {
2430 buf = connections[0];
2437 if (io.n_outputs() == 0) {
2442 /* XXX we're not handling multiple ports yet. */
2444 const char **connections = io.output(0)->get_connections();
2446 if (connections == 0 || connections[0] == '\0') {
2449 buf = connections[0];
2457 ARDOUR_UI::snapshot_session ()
2459 ArdourPrompter prompter (true);
2466 now = now.substr (0, now.length() - 1);
2468 prompter.set_name ("Prompter");
2469 prompter.set_prompt (_("Name for snapshot"));
2470 prompter.set_initial_text (now);
2472 switch (prompter.run()) {
2473 case RESPONSE_ACCEPT:
2474 prompter.get_result (snapname);
2475 if (snapname.length()){
2476 save_state (snapname);
2486 ARDOUR_UI::save_state (string name)
2488 (void) save_state_canfail (name);
2492 ARDOUR_UI::save_state_canfail (string name)
2497 if (name.length() == 0) {
2498 name = session->snap_name();
2501 if ((ret = session->save_state (name)) != 0) {
2505 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2510 ARDOUR_UI::restore_state (string name)
2513 if (name.length() == 0) {
2514 name = session->name();
2516 session->restore_state (name);
2521 ARDOUR_UI::primary_clock_value_changed ()
2524 session->request_locate (primary_clock.current_time ());
2529 ARDOUR_UI::secondary_clock_value_changed ()
2532 session->request_locate (secondary_clock.current_time ());
2537 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2539 if (session && dstream && dstream->record_enabled()) {
2541 Session::RecordState rs;
2543 rs = session->record_status ();
2546 case Session::Disabled:
2547 case Session::Enabled:
2548 if (w->get_state() != STATE_SELECTED) {
2549 w->set_state (STATE_SELECTED);
2553 case Session::Recording:
2554 if (w->get_state() != STATE_ACTIVE) {
2555 w->set_state (STATE_ACTIVE);
2561 if (w->get_state() != STATE_NORMAL) {
2562 w->set_state (STATE_NORMAL);
2568 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2574 switch (session->record_status()) {
2575 case Session::Enabled:
2577 rec_button.set_state (STATE_ACTIVE);
2579 rec_button.set_state (STATE_NORMAL);
2583 case Session::Recording:
2584 rec_button.set_state (STATE_ACTIVE);
2588 rec_button.set_active (false);
2589 rec_button.set_state (STATE_NORMAL);
2595 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2603 ARDOUR_UI::start_keyboard_prefix ()
2605 keyboard->start_prefix();
2609 ARDOUR_UI::save_template ()
2612 ArdourPrompter prompter (true);
2615 prompter.set_name (X_("Prompter"));
2616 prompter.set_prompt (_("Name for mix template:"));
2617 prompter.set_initial_text(session->name() + _("-template"));
2619 switch (prompter.run()) {
2620 case RESPONSE_ACCEPT:
2621 prompter.get_result (name);
2623 if (name.length()) {
2624 session->save_template (name);
2634 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2636 m_new_session_dialog->show_all();
2637 m_new_session_dialog->set_transient_for(*editor);
2638 m_new_session_dialog->set_name(predetermined_path);
2640 int response = Gtk::RESPONSE_CANCEL;
2643 response = m_new_session_dialog->run ();
2645 if(response == Gtk::RESPONSE_OK) {
2647 _session_is_new = true;
2649 std::string session_name = m_new_session_dialog->session_name();
2650 std::string session_path = m_new_session_dialog->session_folder();
2653 XXX This is needed because session constructor wants a
2654 non-existant path. hopefully this will be fixed at some point.
2656 session_path = Glib::build_filename(session_path, session_name);
2658 std::string template_name = m_new_session_dialog->session_template_name();
2660 if (m_new_session_dialog->use_session_template()) {
2662 load_session (session_path, session_name, &template_name);
2668 Session::AutoConnectOption iconnect;
2669 Session::AutoConnectOption oconnect;
2671 if (m_new_session_dialog->create_control_bus()) {
2672 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2677 if (m_new_session_dialog->create_master_bus()) {
2678 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2683 if (m_new_session_dialog->connect_inputs()) {
2684 iconnect = Session::AutoConnectPhysical;
2686 iconnect = Session::AutoConnectOption (0);
2689 /// @todo some minor tweaks.
2691 if (m_new_session_dialog->connect_outs_to_master()) {
2692 oconnect = Session::AutoConnectMaster;
2693 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2694 oconnect = Session::AutoConnectPhysical;
2696 oconnect = Session::AutoConnectOption (0);
2699 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2700 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2702 build_session (session_path,
2710 engine->frame_rate() * 60 * 5);
2714 } while(response == Gtk::RESPONSE_HELP);
2715 m_new_session_dialog->hide_all();
2719 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2721 Session *new_session;
2723 session_loaded = false;
2724 x = unload_session ();
2732 /* if it already exists, we must have write access */
2734 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2735 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2736 You do not have write access to this session.\n\
2737 This prevents the session from being loaded."));
2742 new_session = new Session (*engine, path, snap_name, mix_template);
2747 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2751 connect_to_session (new_session);
2753 //if (engine->running()) {
2754 //mixer->show_window();
2756 session_loaded = true;
2761 ARDOUR_UI::make_session_clean ()
2764 session->set_clean ();
2771 ARDOUR_UI::build_session (string path, string snap_name,
2772 uint32_t control_channels,
2773 uint32_t master_channels,
2774 Session::AutoConnectOption input_connect,
2775 Session::AutoConnectOption output_connect,
2778 jack_nframes_t initial_length)
2780 Session *new_session;
2783 session_loaded = false;
2784 x = unload_session ();
2791 _session_is_new = true;
2794 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2795 control_channels, master_channels, nphysin, nphysout, initial_length);
2800 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2804 connect_to_session (new_session);
2806 //if (engine->running()) {
2807 //mixer->show_window();
2809 session_loaded = true;
2817 editor->show_window ();
2821 if (session && mixer) {
2822 // mixer->show_window ();
2831 ARDOUR_UI::show_splash ()
2834 about = new About();
2840 ARDOUR_UI::hide_splash ()
2848 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2852 removed = rep.paths.size();
2855 ArdourMessage msg (editor, X_("cleanupresults"),
2857 No audio files were ready for cleanup\n\n\
2858 If this seems suprising, check for any existing\n\
2859 snapshots. These may still include regions that\n\
2860 require some unused files to continue to exist."));
2864 ArdourDialog results (_("ardour: cleanup"), true);
2866 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2867 CleanupResultsModelColumns() {
2871 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2872 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2876 Glib::RefPtr<Gtk::ListStore> results_model;
2877 CleanupResultsModelColumns results_columns;
2878 Gtk::TreeView results_display;
2880 results_model = ListStore::create (results_columns);
2881 results_display.set_model (results_model);
2882 results_display.append_column (list_title, results_columns.visible_name);
2883 results_display.set_headers_visible (true);
2885 Gtk::ScrolledWindow list_scroller;
2888 if (rep.space < 1048576.0f) {
2890 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2892 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2896 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2898 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2902 results.get_vbox()->pack_start (txt, false, false);
2904 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2905 TreeModel::Row row = *(results_model->append());
2906 row[results_columns.visible_name] = *i;
2907 row[results_columns.fullpath] = *i;
2910 list_scroller.add (results_display);
2911 list_scroller.set_size_request (-1, 250);
2912 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2914 results.get_vbox()->pack_start (list_scroller, true, true);
2915 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2916 results.set_position (Gtk::WIN_POS_MOUSE);
2922 ARDOUR_UI::cleanup ()
2925 /* shouldn't happen: menu item is insensitive */
2929 ArdourDialog checker (_("ardour cleanup"));
2930 Gtk::Label label (_("\
2931 Cleanup is a destructive operation.\n\
2932 ALL undo/redo information will be lost if you cleanup.\n\
2933 Unused audio files will be moved to a \"dead sounds\" location."));
2935 checker.get_vbox()->pack_start (label, false, false);
2936 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2937 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2939 checker.set_name (_("CleanupDialog"));
2940 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2941 checker.set_position (Gtk::WIN_POS_MOUSE);
2943 switch (checker.run()) {
2944 case RESPONSE_ACCEPT:
2950 Session::cleanup_report rep;
2952 editor->prepare_for_cleanup ();
2954 if (session->cleanup_sources (rep)) {
2958 display_cleanup_results (rep,
2961 The following %1 %2 were not in use.\n\
2962 The next time you flush the wastebasket\n\
2963 it will release an additional %3 %4bytes\n\
2969 ARDOUR_UI::flush_trash ()
2972 /* shouldn't happen: menu item is insensitive */
2976 Session::cleanup_report rep;
2978 if (session->cleanup_trash_sources (rep)) {
2982 display_cleanup_results (rep,
2984 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2988 ARDOUR_UI::add_route ()
2996 if (add_route_dialog == 0) {
2997 add_route_dialog = new AddRouteDialog;
2998 editor->ensure_float (*add_route_dialog);
3001 if (add_route_dialog->is_visible()) {
3002 /* we're already doing this */
3006 ResponseType r = (ResponseType) add_route_dialog->run ();
3008 add_route_dialog->hide();
3011 case RESPONSE_ACCEPT:
3018 if ((count = add_route_dialog->count()) <= 0) {
3022 uint32_t input_chan = add_route_dialog->channels ();
3023 uint32_t output_chan;
3024 string name_template = add_route_dialog->name_template ();
3025 bool track = add_route_dialog->track ();
3027 Session::AutoConnectOption oac = session->get_output_auto_connect();
3029 if (oac & Session::AutoConnectMaster) {
3030 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3032 output_chan = input_chan;
3035 /* XXX do something with name template */
3039 session_add_audio_track (input_chan, output_chan);
3041 session_add_audio_bus (input_chan, output_chan);
3045 while (Main::events_pending()) {
3052 ARDOUR_UI::mixer_settings () const
3057 node = session->instant_xml(X_("Mixer"), session->path());
3059 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3063 node = new XMLNode (X_("Mixer"));
3070 ARDOUR_UI::editor_settings () const
3075 node = session->instant_xml(X_("Editor"), session->path());
3077 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3081 node = new XMLNode (X_("Editor"));
3087 ARDOUR_UI::keyboard_settings () const
3091 node = Config->extra_xml(X_("Keyboard"));
3094 node = new XMLNode (X_("Keyboard"));
3100 ARDOUR_UI::halt_on_xrun_message ()
3102 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3104 ArdourMessage msg (editor, X_("haltonxrun"),
3105 _("Recording was stopped because your system could not keep up."));
3109 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3111 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3113 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3117 delete deletion_list;
3121 ARDOUR_UI::disk_overrun_handler ()
3123 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3125 if (!have_disk_overrun_displayed) {
3126 have_disk_overrun_displayed = true;
3127 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3128 The disk system on your computer\n\
3129 was not able to keep up with Ardour.\n\
3131 Specifically, it failed to write data to disk\n\
3132 quickly enough to keep up with recording.\n"));
3133 have_disk_overrun_displayed = false;
3138 ARDOUR_UI::disk_underrun_handler ()
3140 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3142 if (!have_disk_underrun_displayed) {
3143 have_disk_underrun_displayed = true;
3144 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3145 (_("The disk system on your computer\n\
3146 was not able to keep up with Ardour.\n\
3148 Specifically, it failed to read data from disk\n\
3149 quickly enough to keep up with playback.\n")));
3150 have_disk_underrun_displayed = false;
3155 ARDOUR_UI::disk_underrun_message_gone ()
3157 have_disk_underrun_displayed = false;
3161 ARDOUR_UI::disk_overrun_message_gone ()
3163 have_disk_underrun_displayed = false;
3167 ARDOUR_UI::pending_state_dialog ()
3169 ArdourDialog dialog ("pending state dialog");
3171 This session appears to have been in\n\
3172 middle of recording when ardour or\n\
3173 the computer was shutdown.\n\
3175 Ardour can recover any captured audio for\n\
3176 you, or it can ignore it. Please decide\n\
3177 what you would like to do.\n"));
3179 dialog.get_vbox()->pack_start (message);
3180 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3181 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3183 dialog.set_position (WIN_POS_CENTER);
3186 switch (dialog.run ()) {
3187 case RESPONSE_ACCEPT:
3198 ARDOUR_UI::disconnect_from_jack ()
3201 if( engine->disconnect_from_jack ()) {
3202 ArdourMessage msg (editor, X_("nojack dialog"),
3203 _("Could not disconnect from JACK"));
3206 update_sample_rate (0);
3211 ARDOUR_UI::reconnect_to_jack ()
3214 if (engine->reconnect_to_jack ()) {
3215 ArdourMessage msg (editor, X_("nojack dialog"),
3216 _("Could not reconnect to JACK"));
3219 update_sample_rate (0);
3224 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3226 engine->request_buffer_size (nframes);
3227 update_sample_rate (0);
3231 ARDOUR_UI::cmdline_new_session (string path)
3233 if (path[0] != '/') {
3234 char buf[PATH_MAX+1];
3237 getcwd (buf, sizeof (buf));
3244 new_session (false, path);
3246 _will_create_new_session_automatically = false; /* done it */
3247 return FALSE; /* don't call it again */