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 ActionManager::init ();
837 m_new_session_dialog = 0;
838 m_new_session_dialog_ref = NewSessionDialogFactory::create();
839 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
843 _session_is_new = false;
844 big_clock_window = 0;
845 session_selector_window = 0;
846 last_key_press_time = 0;
847 connection_editor = 0;
848 add_route_dialog = 0;
852 open_session_selector = 0;
853 have_configure_timeout = false;
854 have_disk_overrun_displayed = false;
855 have_disk_underrun_displayed = false;
856 _will_create_new_session_automatically = false;
857 session_loaded = false;
860 last_configure_time.tv_sec = 0;
861 last_configure_time.tv_usec = 0;
863 shuttle_grabbed = false;
866 set_shuttle_units (Percentage);
867 set_shuttle_behaviour (Sprung);
869 shuttle_style_menu = 0;
870 shuttle_unit_menu = 0;
872 gettimeofday (&last_peak_grab, 0);
873 gettimeofday (&last_shuttle_request, 0);
875 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
876 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
877 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
878 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
880 /* handle pending state with a dialog */
882 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
884 channel_combo_strings = internationalize (channel_setup_names);
886 /* have to wait for AudioEngine and Configuration before proceeding */
890 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
892 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
894 string msg = string_compose (_("\
895 You cannot record-enable\n\
897 because it has no input connections.\n\
898 You would be wasting space recording silence."),
901 ArdourMessage message (editor, X_("cannotrecord"), msg);
905 ARDOUR_UI::set_engine (AudioEngine& e)
909 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
910 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
911 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
912 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
916 keyboard = new Keyboard;
917 install_keybindings ();
919 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
920 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
922 if (setup_windows ()) {
923 throw failed_constructor ();
926 if (GTK_ARDOUR::show_key_actions) {
928 // show_all_actions ();
932 /* start with timecode, metering enabled
935 blink_timeout_tag = -1;
937 /* this being a GUI and all, we want peakfiles */
939 FileSource::set_build_peakfiles (true);
940 FileSource::set_build_missing_peakfiles (true);
942 if (Source::start_peak_thread ()) {
943 throw failed_constructor();
946 /* start the time-of-day-clock */
948 update_wall_clock ();
949 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
951 update_disk_space ();
953 update_sample_rate (engine->frame_rate());
955 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
956 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
959 ARDOUR_UI::~ARDOUR_UI ()
961 save_ardour_state ();
975 if (add_route_dialog) {
976 delete add_route_dialog;
979 Source::stop_peak_thread ();
983 ARDOUR_UI::configure_timeout ()
988 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
989 /* no configure events yet */
993 gettimeofday (&now, 0);
994 timersub (&now, &last_configure_time, &diff);
996 /* force a gap of 0.5 seconds since the last configure event
999 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1002 have_configure_timeout = false;
1003 save_ardour_state ();
1009 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1011 if (have_configure_timeout) {
1012 gettimeofday (&last_configure_time, 0);
1014 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1015 have_configure_timeout = true;
1022 ARDOUR_UI::save_ardour_state ()
1024 if (!keyboard || !mixer || !editor) {
1028 /* XXX this is all a bit dubious. add_extra_xml() uses
1029 a different lifetime model from add_instant_xml().
1032 XMLNode* node = new XMLNode (keyboard->get_state());
1033 Config->add_extra_xml (*node);
1034 Config->save_state();
1036 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1037 XMLNode& mnode (mixer->get_state());
1040 session->add_instant_xml(enode, session->path());
1041 session->add_instant_xml(mnode, session->path());
1043 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1044 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1049 ARDOUR_UI::startup ()
1051 /* Once the UI is up and running, start the audio engine. Doing
1052 this before the UI is up and running can cause problems
1053 when not running with SCHED_FIFO, because the amount of
1054 CPU and disk work needed to get the UI started can interfere
1055 with the scheduling of the audio thread.
1058 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1064 if (session && session->dirty()) {
1065 switch (ask_about_saving_session(_("quit"))) {
1070 /* use the default name */
1071 if (save_state_canfail ("")) {
1072 /* failed - don't quit */
1073 ArdourMessage (editor, X_("badsave dialog"),
1075 Ardour was unable to save your session.\n\n\
1076 If you still wish to quit, please use the\n\n\
1077 \"Just quit\" option."));
1090 ARDOUR_UI::ask_about_saving_session (string what)
1092 ArdourDialog window (_("ardour: save session?"));
1093 Gtk::Label prompt_label;
1096 msg = string_compose(_("Save and %1"), what);
1097 window.add_button (msg, RESPONSE_ACCEPT);
1098 msg = string_compose(_("Just %1"), what);
1099 window.add_button (msg, RESPONSE_REJECT);
1100 msg = string_compose(_("Don't %1"), what);
1101 window.add_button (msg, RESPONSE_REJECT);
1103 Gtk::Button noquit_button (msg);
1104 noquit_button.set_name ("EditorGTKButton");
1109 if (session->snap_name() == session->name()) {
1110 type = _("session");
1112 type = _("snapshot");
1114 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?"),
1115 type, session->snap_name());
1117 prompt_label.set_text (prompt);
1118 prompt_label.set_alignment (0.5, 0.5);
1119 prompt_label.set_name (X_("PrompterLabel"));
1121 window.get_vbox()->pack_start (prompt_label);
1123 window.set_name (_("Prompter"));
1124 window.set_position (Gtk::WIN_POS_MOUSE);
1125 window.set_modal (true);
1128 save_the_session = 0;
1130 editor->ensure_float (window);
1132 ResponseType r = (ResponseType) window.run();
1137 case RESPONSE_ACCEPT:
1147 ARDOUR_UI::every_second ()
1150 update_buffer_load ();
1151 update_disk_space ();
1152 // update_disk_rate ();
1157 ARDOUR_UI::every_point_one_seconds ()
1160 struct timeval diff;
1162 /* do not attempt to grab peak power more than once per cycle.
1165 gettimeofday (&now, 0);
1166 timersub (&now, &last_peak_grab, &diff);
1168 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1169 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1170 last_peak_grab = now;
1173 update_speed_display ();
1174 RapidScreenUpdate(); /* EMIT_SIGNAL */
1179 ARDOUR_UI::every_point_zero_one_seconds ()
1181 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1186 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1190 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1192 if (!engine->connected()) {
1194 snprintf (buf, sizeof (buf), _("disconnected"));
1198 jack_nframes_t rate = engine->frame_rate();
1200 if (fmod (rate, 1000.0) != 0.0) {
1201 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1202 (float) rate/1000.0f,
1203 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1205 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1207 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1211 sample_rate_label.set_text (buf);
1215 ARDOUR_UI::update_cpu_load ()
1218 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1219 cpu_load_label.set_text (buf);
1223 ARDOUR_UI::update_disk_rate ()
1228 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1229 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1230 disk_rate_label.set_text (buf);
1232 disk_rate_label.set_text ("");
1237 ARDOUR_UI::update_buffer_load ()
1242 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1243 session->playback_load(), session->capture_load());
1244 buffer_load_label.set_text (buf);
1246 buffer_load_label.set_text ("");
1251 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1253 if (ds.record_enabled()) {
1254 rec_enabled_diskstreams++;
1259 ARDOUR_UI::update_disk_space()
1265 jack_nframes_t frames = session->available_capture_duration();
1268 if (frames == max_frames) {
1269 strcpy (buf, _("space: 24hrs+"));
1274 jack_nframes_t fr = session->frame_rate();
1276 if (session->actively_recording()){
1278 rec_enabled_diskstreams = 0;
1279 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1281 if (rec_enabled_diskstreams) {
1282 frames /= rec_enabled_diskstreams;
1287 /* hmmm. shall we divide by the route count? or the diskstream count?
1288 or what? for now, do nothing ...
1293 hrs = frames / (fr * 3600);
1294 frames -= hrs * fr * 3600;
1295 mins = frames / (fr * 60);
1296 frames -= mins * fr * 60;
1299 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1302 disk_space_label.set_text (buf);
1306 ARDOUR_UI::update_wall_clock ()
1313 tm_now = localtime (&now);
1315 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1316 wall_clock_label.set_text (buf);
1322 ARDOUR_UI::toggle_recording_plugins ()
1324 /* XXX use toggle_some_session_state */
1330 session->set_recording_plugins (!session->get_recording_plugins());
1334 ARDOUR_UI::toggle_auto_play ()
1337 toggle_some_session_state (auto_play_button,
1338 &Session::get_auto_play,
1339 &Session::set_auto_play);
1343 ARDOUR_UI::toggle_auto_return ()
1346 toggle_some_session_state (auto_return_button,
1347 &Session::get_auto_return,
1348 &Session::set_auto_return);
1352 ARDOUR_UI::toggle_click ()
1354 toggle_some_session_state (click_button,
1355 &Session::get_clicking,
1356 &Session::set_clicking);
1360 ARDOUR_UI::follow_changed ()
1368 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1369 follow_button.set_active (x);
1374 ARDOUR_UI::toggle_follow ()
1382 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1383 editor->set_follow_playhead (x);
1388 ARDOUR_UI::toggle_session_auto_loop ()
1391 if (session->get_auto_loop()) {
1392 if (session->transport_rolling()) {
1396 session->request_auto_loop (false);
1400 session->request_auto_loop (true);
1406 ARDOUR_UI::toggle_session_punch_in ()
1409 session->set_punch_in (!session->get_punch_in());
1414 ARDOUR_UI::toggle_punch_out ()
1416 toggle_some_session_state (punch_out_button,
1417 &Session::get_punch_out,
1418 &Session::set_punch_out);
1422 ARDOUR_UI::toggle_punch_in ()
1424 toggle_some_session_state (punch_in_button,
1425 &Session::get_punch_in,
1426 &Session::set_punch_in);
1430 ARDOUR_UI::map_button_state ()
1433 map_some_session_state (auto_return_button,
1434 &Session::get_auto_return);
1435 map_some_session_state (auto_play_button,
1436 &Session::get_auto_play);
1437 map_some_session_state (auto_input_button,
1438 &Session::get_auto_input);
1439 map_some_session_state (punch_in_button,
1440 &Session::get_punch_in);
1441 map_some_session_state (punch_out_button,
1442 &Session::get_punch_out);
1443 map_some_session_state (click_button,
1444 &Session::get_clicking);
1448 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1450 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1454 ARDOUR_UI::map_control_change (Session::ControlType t)
1457 case Session::AutoPlay:
1458 map_some_session_state (auto_play_button, &Session::get_auto_play);
1461 case Session::AutoLoop:
1464 case Session::AutoReturn:
1465 map_some_session_state (auto_return_button, &Session::get_auto_return);
1468 case Session::AutoInput:
1469 map_some_session_state (auto_input_button, &Session::get_auto_input);
1472 case Session::PunchOut:
1473 map_some_session_state (punch_in_button, &Session::get_punch_out);
1476 case Session::PunchIn:
1477 map_some_session_state (punch_in_button, &Session::get_punch_in);
1480 case Session::Clicking:
1481 map_some_session_state (click_button, &Session::get_clicking);
1484 case Session::SlaveType:
1485 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1488 case Session::SendMTC:
1489 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1492 case Session::SendMMC:
1493 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1496 case Session::MMCControl:
1497 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1500 case Session::MidiFeedback:
1501 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1503 case Session::MidiControl:
1504 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1510 case Session::RecordingPlugins:
1513 case Session::CrossFadesActive:
1516 case Session::EditingMode:
1519 case Session::PlayRange:
1522 case Session::AlignChoice:
1523 /* don't care, this is handled by the options editor */
1525 case Session::SeamlessLoop:
1526 /* don't care, this is handled by the options editor */
1533 ARDOUR_UI::control_methods_adjusted ()
1538 which_method = (int) online_control_button->adjustment.get_value();
1539 switch (which_method) {
1541 allow_mmc_and_local ();
1547 allow_local_only ();
1550 fatal << _("programming error: impossible control method") << endmsg;
1556 ARDOUR_UI::mmc_device_id_adjusted ()
1561 int dev_id = (int) mmc_id_button->adjustment.get_value();
1562 mmc->set_device_id (dev_id);
1568 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1569 bool (Session::*get)() const)
1578 if (button.get_active() != (x = (session->*get)())) {
1579 button.set_active (x);
1584 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1585 bool (Session::*get)() const,
1586 void (Session::*set)(bool))
1596 button_state = button.get_active ();
1597 session_state = (session->*get)();
1599 if (button_state != session_state) {
1600 (session->*set) (button_state);
1603 /* check that it worked, and reverse
1604 the button state if it didn't
1607 if ((session->*get)() != button_state) {
1608 button->set_active (!button_state);
1616 ARDOUR_UI::session_menu (GdkEventButton *ev)
1618 session_popup_menu->popup (0, 0);
1623 ARDOUR_UI::redisplay_recent_sessions ()
1625 vector<string *> *sessions;
1626 vector<string *>::iterator i;
1627 RecentSessionsSorter cmp;
1629 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1630 recent_session_model->clear ();
1633 ARDOUR::read_recent_sessions (rs);
1636 recent_session_display.set_model (recent_session_model);
1640 /* sort them alphabetically */
1641 sort (rs.begin(), rs.end(), cmp);
1642 sessions = new vector<string*>;
1644 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1645 sessions->push_back (new string ((*i).second));
1648 for (i = sessions->begin(); i != sessions->end(); ++i) {
1650 vector<string*>* states;
1651 vector<const gchar*> item;
1652 string fullpath = *(*i);
1654 /* remove any trailing / */
1656 if (fullpath[fullpath.length()-1] == '/') {
1657 fullpath = fullpath.substr (0, fullpath.length()-1);
1660 /* now get available states for this session */
1662 if ((states = Session::possible_states (fullpath)) == 0) {
1663 /* no state file? */
1667 TreeModel::Row row = *(recent_session_model->append());
1669 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1670 row[recent_session_columns.fullpath] = fullpath;
1672 if (states->size() > 1) {
1674 /* add the children */
1676 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1678 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1680 child_row[recent_session_columns.visible_name] = **i2;
1681 child_row[recent_session_columns.fullpath] = fullpath;
1690 recent_session_display.set_model (recent_session_model);
1695 ARDOUR_UI::build_session_selector ()
1697 session_selector_window = new ArdourDialog ("session selector");
1699 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1701 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1702 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1704 recent_session_model = TreeStore::create (recent_session_columns);
1705 recent_session_display.set_model (recent_session_model);
1706 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1707 recent_session_display.set_headers_visible (false);
1709 scroller->add (recent_session_display);
1710 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1712 session_selector_window->set_name ("SessionSelectorWindow");
1713 session_selector_window->set_size_request (200, 400);
1714 session_selector_window->get_vbox()->pack_start (*scroller);
1718 ARDOUR_UI::open_recent_session ()
1720 /* popup selector window */
1722 if (session_selector_window == 0) {
1723 build_session_selector ();
1726 redisplay_recent_sessions ();
1728 ResponseType r = (ResponseType) session_selector_window->run ();
1730 session_selector_window->hide();
1733 case RESPONSE_ACCEPT:
1739 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1741 if (i == recent_session_model->children().end()) {
1745 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1746 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1748 _session_is_new = false;
1750 load_session (path, state);
1754 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1756 struct stat statbuf;
1758 if (stat (info.filename.c_str(), &statbuf) != 0) {
1762 if (!S_ISDIR(statbuf.st_mode)) {
1766 string session_file = info.filename;
1767 session_file += '/';
1768 session_file += PBD::basename (info.filename);
1769 session_file += ".ardour";
1771 if (stat (session_file.c_str(), &statbuf) != 0) {
1775 return S_ISREG (statbuf.st_mode);
1779 ARDOUR_UI::open_session ()
1781 /* popup selector window */
1783 if (open_session_selector == 0) {
1784 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1785 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1786 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1788 FileFilter filter_ardour;
1789 filter_ardour.set_name (_("Ardour sessions"));
1790 filter_ardour.add_custom (FILE_FILTER_FILENAME, mem_fun (*this, &ARDOUR_UI::filter_ardour_session_dirs));
1792 open_session_selector->add_filter (filter_ardour);
1795 switch (open_session_selector->run ()) {
1802 string session_path = open_session_selector->get_filename();
1806 if (session_path.length() > 0) {
1807 if (Session::find_session (session_path, path, name, isnew) == 0) {
1808 _session_is_new = isnew;
1809 load_session (path, name);
1816 ARDOUR_UI::session_add_midi_track ()
1818 cerr << _("Patience is a virtue.\n");
1822 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1827 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1833 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1834 error << _("could not create new audio track") << endmsg;
1837 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1838 error << _("could not create new audio bus") << endmsg;
1843 if (need_control_room_outs) {
1849 route->set_stereo_control_outs (control_lr_channels);
1850 route->control_outs()->set_stereo_pan (pans, this);
1852 #endif /* CONTROLOUTS */
1856 ArdourMessage msg (editor, X_("noport dialog"),
1857 _("There are insufficient JACK ports available\n\
1858 to create a new track or bus.\n\
1859 You should save Ardour, exit and\n\
1860 restart JACK with more ports."));
1865 ARDOUR_UI::diskstream_added (DiskStream* ds)
1870 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1872 jack_nframes_t _preroll;
1875 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1877 if (new_position > _preroll) {
1878 new_position -= _preroll;
1883 session->request_locate (new_position);
1888 ARDOUR_UI::transport_goto_start ()
1891 session->request_locate (0);
1894 /* force displayed area in editor to start no matter
1895 what "follow playhead" setting is.
1899 editor->reposition_x_origin (0);
1905 ARDOUR_UI::transport_goto_end ()
1908 jack_nframes_t frame = session->current_end_frame();
1909 session->request_locate (frame);
1911 /* force displayed area in editor to start no matter
1912 what "follow playhead" setting is.
1916 editor->reposition_x_origin (frame);
1922 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1927 if (session->transport_stopped()) {
1928 session->request_locate (session->last_transport_start());
1930 if (session->get_auto_loop()) {
1931 session->request_auto_loop (false);
1934 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1935 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1943 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1950 ARDOUR_UI::transport_stop ()
1956 if (session->is_auditioning()) {
1957 session->cancel_audition ();
1961 if (session->get_auto_loop()) {
1962 session->request_auto_loop (false);
1965 session->request_stop ();
1969 ARDOUR_UI::transport_stop_and_forget_capture ()
1972 session->request_stop (true);
1977 ARDOUR_UI::remove_last_capture()
1980 editor->remove_last_capture();
1985 ARDOUR_UI::transport_record ()
1988 switch (session->record_status()) {
1989 case Session::Disabled:
1990 if (session->ntracks() == 0) {
1991 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1992 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1995 session->maybe_enable_record ();
1997 case Session::Recording:
1998 case Session::Enabled:
1999 session->disable_record ();
2005 ARDOUR_UI::transport_roll ()
2013 rolling = session->transport_rolling ();
2015 if (session->get_auto_loop()) {
2016 session->request_auto_loop (false);
2017 auto_loop_button.set_active (false);
2018 roll_button.set_active (true);
2019 } else if (session->get_play_range ()) {
2020 session->request_play_range (false);
2021 play_selection_button.set_active (false);
2022 } else if (rolling) {
2023 session->request_locate (session->last_transport_start(), true);
2026 session->request_transport_speed (1.0f);
2030 ARDOUR_UI::transport_loop()
2033 if (session->get_auto_loop()) {
2034 if (session->transport_rolling()) {
2035 Location * looploc = session->locations()->auto_loop_location();
2037 session->request_locate (looploc->start(), true);
2042 session->request_auto_loop (true);
2048 ARDOUR_UI::transport_play_selection ()
2054 if (!session->get_play_range()) {
2055 session->request_stop ();
2058 editor->play_selection ();
2062 ARDOUR_UI::transport_rewind (int option)
2064 float current_transport_speed;
2067 current_transport_speed = session->transport_speed();
2069 if (current_transport_speed >= 0.0f) {
2072 session->request_transport_speed (-1.0f);
2075 session->request_transport_speed (-4.0f);
2078 session->request_transport_speed (-0.5f);
2083 session->request_transport_speed (current_transport_speed * 1.5f);
2089 ARDOUR_UI::transport_forward (int option)
2091 float current_transport_speed;
2094 current_transport_speed = session->transport_speed();
2096 if (current_transport_speed <= 0.0f) {
2099 session->request_transport_speed (1.0f);
2102 session->request_transport_speed (4.0f);
2105 session->request_transport_speed (0.5f);
2110 session->request_transport_speed (current_transport_speed * 1.5f);
2116 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2124 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2125 Port *port = ds->io()->input (0);
2126 port->request_monitor_input (!port->monitoring_input());
2131 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2139 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2140 ds->set_record_enabled (!ds->record_enabled(), this);
2145 ARDOUR_UI::queue_transport_change ()
2147 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2151 ARDOUR_UI::map_transport_state ()
2153 float sp = session->transport_speed();
2156 transport_rolling ();
2157 } else if (sp < 0.0f) {
2158 transport_rewinding ();
2159 } else if (sp > 0.0f) {
2160 transport_forwarding ();
2162 transport_stopped ();
2167 ARDOUR_UI::send_all_midi_feedback ()
2170 session->send_all_midi_feedback();
2175 ARDOUR_UI::allow_local_only ()
2181 ARDOUR_UI::allow_mmc_only ()
2187 ARDOUR_UI::allow_mmc_and_local ()
2193 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2195 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2196 (int) adj.get_value()].c_str());
2200 ARDOUR_UI::engine_stopped ()
2202 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2203 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2204 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2209 ARDOUR_UI::engine_running ()
2211 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2212 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2213 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2217 ARDOUR_UI::engine_halted ()
2219 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2221 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2222 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2224 update_sample_rate (0);
2226 ArdourMessage msg (editor, X_("halted"),
2228 JACK has either been shutdown or it\n\
2229 disconnected Ardour because Ardour\n\
2230 was not fast enough. You can save the\n\
2231 session and/or try to reconnect to JACK ."));
2235 ARDOUR_UI::do_engine_start ()
2241 catch (AudioEngine::PortRegistrationFailure& err) {
2243 error << _("Unable to create all required ports")
2251 error << _("Unable to start the session running")
2261 ARDOUR_UI::start_engine ()
2263 if (do_engine_start () == 0) {
2264 if (session && _session_is_new) {
2265 /* we need to retain initial visual
2266 settings for a new session
2268 session->save_state ("");
2271 /* there is too much going on, in too many threads, for us to
2272 end up with a clean session. So wait 1 second after loading,
2273 and fix it up. its ugly, but until i come across a better
2274 solution, its what we have.
2277 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2284 ARDOUR_UI::update_clocks ()
2286 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2290 ARDOUR_UI::start_clocking ()
2292 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2296 ARDOUR_UI::stop_clocking ()
2298 clock_signal_connection.disconnect ();
2302 ARDOUR_UI::toggle_clocking ()
2305 if (clock_button.get_active()) {
2314 ARDOUR_UI::_blink (void *arg)
2317 ((ARDOUR_UI *) arg)->blink ();
2324 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2328 ARDOUR_UI::start_blinking ()
2330 /* Start the blink signal. Everybody with a blinking widget
2331 uses Blink to drive the widget's state.
2334 if (blink_timeout_tag < 0) {
2336 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2341 ARDOUR_UI::stop_blinking ()
2343 if (blink_timeout_tag >= 0) {
2344 gtk_timeout_remove (blink_timeout_tag);
2345 blink_timeout_tag = -1;
2351 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2353 using namespace Gtk;
2354 using namespace Menu_Helpers;
2356 if (dstream.hidden()) {
2360 MenuList& items = diskstream_menu->items();
2361 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2365 ARDOUR_UI::diskstream_selected (gint32 id)
2367 selected_dstream = id;
2372 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2374 using namespace Gtk;
2375 using namespace Menu_Helpers;
2381 diskstream_menu = new Menu();
2382 diskstream_menu->set_name ("ArdourContextMenu");
2383 using namespace Gtk;
2384 using namespace Menu_Helpers;
2386 MenuList& items = diskstream_menu->items();
2387 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2389 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2392 diskstream_menu->popup (ev->button, ev->time);
2394 diskstream_menu->popup (0, 0);
2397 selected_dstream = -1;
2401 delete diskstream_menu;
2403 return selected_dstream;
2407 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2413 if (io.n_inputs() == 0) {
2418 /* XXX we're not handling multiple ports yet. */
2420 const char **connections = io.input(0)->get_connections();
2422 if (connections == 0 || connections[0] == '\0') {
2425 buf = connections[0];
2432 if (io.n_outputs() == 0) {
2437 /* XXX we're not handling multiple ports yet. */
2439 const char **connections = io.output(0)->get_connections();
2441 if (connections == 0 || connections[0] == '\0') {
2444 buf = connections[0];
2452 ARDOUR_UI::snapshot_session ()
2454 ArdourPrompter prompter (true);
2461 now = now.substr (0, now.length() - 1);
2463 prompter.set_name ("Prompter");
2464 prompter.set_prompt (_("Name for snapshot"));
2465 prompter.set_initial_text (now);
2467 switch (prompter.run()) {
2468 case RESPONSE_ACCEPT:
2469 prompter.get_result (snapname);
2470 if (snapname.length()){
2471 save_state (snapname);
2481 ARDOUR_UI::save_state (string name)
2483 (void) save_state_canfail (name);
2487 ARDOUR_UI::save_state_canfail (string name)
2492 if (name.length() == 0) {
2493 name = session->snap_name();
2496 if ((ret = session->save_state (name)) != 0) {
2500 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2505 ARDOUR_UI::restore_state (string name)
2508 if (name.length() == 0) {
2509 name = session->name();
2511 session->restore_state (name);
2516 ARDOUR_UI::primary_clock_value_changed ()
2519 session->request_locate (primary_clock.current_time ());
2524 ARDOUR_UI::secondary_clock_value_changed ()
2527 session->request_locate (secondary_clock.current_time ());
2532 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2534 if (session && dstream && dstream->record_enabled()) {
2536 Session::RecordState rs;
2538 rs = session->record_status ();
2541 case Session::Disabled:
2542 case Session::Enabled:
2543 if (w->get_state() != STATE_SELECTED) {
2544 w->set_state (STATE_SELECTED);
2548 case Session::Recording:
2549 if (w->get_state() != STATE_ACTIVE) {
2550 w->set_state (STATE_ACTIVE);
2556 if (w->get_state() != STATE_NORMAL) {
2557 w->set_state (STATE_NORMAL);
2563 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2569 switch (session->record_status()) {
2570 case Session::Enabled:
2572 rec_button.set_state (STATE_ACTIVE);
2574 rec_button.set_state (STATE_NORMAL);
2578 case Session::Recording:
2579 rec_button.set_state (STATE_ACTIVE);
2583 rec_button.set_active (false);
2584 rec_button.set_state (STATE_NORMAL);
2590 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2598 ARDOUR_UI::start_keyboard_prefix ()
2600 keyboard->start_prefix();
2604 ARDOUR_UI::save_template ()
2607 ArdourPrompter prompter (true);
2610 prompter.set_name (X_("Prompter"));
2611 prompter.set_prompt (_("Name for mix template:"));
2612 prompter.set_initial_text(session->name() + _("-template"));
2614 switch (prompter.run()) {
2615 case RESPONSE_ACCEPT:
2616 prompter.get_result (name);
2618 if (name.length()) {
2619 session->save_template (name);
2629 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2631 m_new_session_dialog->show_all();
2632 m_new_session_dialog->set_transient_for(*editor);
2633 m_new_session_dialog->set_name(predetermined_path);
2635 int response = Gtk::RESPONSE_CANCEL;
2638 response = m_new_session_dialog->run ();
2640 if(response == Gtk::RESPONSE_OK) {
2642 _session_is_new = true;
2644 std::string session_name = m_new_session_dialog->session_name();
2645 std::string session_path = m_new_session_dialog->session_folder();
2646 std::string template_name = m_new_session_dialog->session_template_name();
2648 if (m_new_session_dialog->use_session_template()) {
2650 load_session (session_path, session_name, &template_name);
2656 Session::AutoConnectOption iconnect;
2657 Session::AutoConnectOption oconnect;
2659 if (m_new_session_dialog->create_control_bus()) {
2660 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2665 if (m_new_session_dialog->create_master_bus()) {
2666 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2671 if (m_new_session_dialog->connect_inputs()) {
2672 iconnect = Session::AutoConnectPhysical;
2674 iconnect = Session::AutoConnectOption (0);
2677 /// @todo some minor tweaks.
2679 if (m_new_session_dialog->connect_outs_to_master()) {
2680 oconnect = Session::AutoConnectMaster;
2681 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2682 oconnect = Session::AutoConnectPhysical;
2684 oconnect = Session::AutoConnectOption (0);
2687 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2688 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2690 build_session (session_path,
2698 engine->frame_rate() * 60 * 5);
2702 } while(response == Gtk::RESPONSE_HELP);
2703 m_new_session_dialog->hide_all();
2707 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2709 Session *new_session;
2711 session_loaded = false;
2712 x = unload_session ();
2720 /* if it already exists, we must have write access */
2722 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2723 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2724 You do not have write access to this session.\n\
2725 This prevents the session from being loaded."));
2730 new_session = new Session (*engine, path, snap_name, mix_template);
2735 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2739 connect_to_session (new_session);
2741 //if (engine->running()) {
2742 //mixer->show_window();
2744 session_loaded = true;
2749 ARDOUR_UI::make_session_clean ()
2752 session->set_clean ();
2759 ARDOUR_UI::build_session (string path, string snap_name,
2760 uint32_t control_channels,
2761 uint32_t master_channels,
2762 Session::AutoConnectOption input_connect,
2763 Session::AutoConnectOption output_connect,
2766 jack_nframes_t initial_length)
2768 Session *new_session;
2771 session_loaded = false;
2772 x = unload_session ();
2779 _session_is_new = true;
2782 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2783 control_channels, master_channels, nphysin, nphysout, initial_length);
2788 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2792 connect_to_session (new_session);
2794 //if (engine->running()) {
2795 //mixer->show_window();
2797 session_loaded = true;
2805 editor->show_window ();
2809 if (session && mixer) {
2810 mixer->show_window ();
2819 ARDOUR_UI::show_splash ()
2822 about = new About();
2828 ARDOUR_UI::hide_splash ()
2836 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2840 removed = rep.paths.size();
2843 ArdourMessage msg (editor, X_("cleanupresults"),
2845 No audio files were ready for cleanup\n\n\
2846 If this seems suprising, check for any existing\n\
2847 snapshots. These may still include regions that\n\
2848 require some unused files to continue to exist."));
2852 ArdourDialog results (_("ardour: cleanup"), true);
2854 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2855 CleanupResultsModelColumns() {
2859 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2860 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2864 Glib::RefPtr<Gtk::ListStore> results_model;
2865 CleanupResultsModelColumns results_columns;
2866 Gtk::TreeView results_display;
2868 results_model = ListStore::create (results_columns);
2869 results_display.set_model (results_model);
2870 results_display.append_column (list_title, results_columns.visible_name);
2871 results_display.set_headers_visible (true);
2873 Gtk::ScrolledWindow list_scroller;
2876 if (rep.space < 1048576.0f) {
2878 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2880 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2884 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2886 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2890 results.get_vbox()->pack_start (txt, false, false);
2892 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2893 TreeModel::Row row = *(results_model->append());
2894 row[results_columns.visible_name] = *i;
2895 row[results_columns.fullpath] = *i;
2898 list_scroller.add (results_display);
2899 list_scroller.set_size_request (-1, 250);
2900 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2902 results.get_vbox()->pack_start (list_scroller, true, true);
2903 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2904 results.set_position (Gtk::WIN_POS_MOUSE);
2910 ARDOUR_UI::cleanup ()
2913 /* shouldn't happen: menu item is insensitive */
2917 ArdourDialog checker (_("ardour cleanup"));
2918 Gtk::Label label (_("\
2919 Cleanup is a destructive operation.\n\
2920 ALL undo/redo information will be lost if you cleanup.\n\
2921 Unused audio files will be moved to a \"dead sounds\" location."));
2923 checker.get_vbox()->pack_start (label, false, false);
2924 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2925 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2927 checker.set_name (_("CleanupDialog"));
2928 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2929 checker.set_position (Gtk::WIN_POS_MOUSE);
2931 switch (checker.run()) {
2932 case RESPONSE_ACCEPT:
2938 Session::cleanup_report rep;
2940 editor->prepare_for_cleanup ();
2942 if (session->cleanup_sources (rep)) {
2946 display_cleanup_results (rep,
2949 The following %1 %2 were not in use.\n\
2950 The next time you flush the wastebasket\n\
2951 it will release an additional %3 %4bytes\n\
2957 ARDOUR_UI::flush_trash ()
2960 /* shouldn't happen: menu item is insensitive */
2964 Session::cleanup_report rep;
2966 if (session->cleanup_trash_sources (rep)) {
2970 display_cleanup_results (rep,
2972 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2976 ARDOUR_UI::add_route ()
2984 if (add_route_dialog == 0) {
2985 add_route_dialog = new AddRouteDialog;
2986 editor->ensure_float (*add_route_dialog);
2989 if (add_route_dialog->is_visible()) {
2990 /* we're already doing this */
2994 ResponseType r = (ResponseType) add_route_dialog->run ();
2996 add_route_dialog->hide();
2999 case RESPONSE_ACCEPT:
3006 if ((count = add_route_dialog->count()) <= 0) {
3010 uint32_t input_chan = add_route_dialog->channels ();
3011 uint32_t output_chan;
3012 string name_template = add_route_dialog->name_template ();
3013 bool track = add_route_dialog->track ();
3015 Session::AutoConnectOption oac = session->get_output_auto_connect();
3017 if (oac & Session::AutoConnectMaster) {
3018 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3020 output_chan = input_chan;
3023 /* XXX do something with name template */
3027 session_add_audio_track (input_chan, output_chan);
3029 session_add_audio_bus (input_chan, output_chan);
3033 while (Main::events_pending()) {
3040 ARDOUR_UI::mixer_settings () const
3045 node = session->instant_xml(X_("Mixer"), session->path());
3047 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3051 node = new XMLNode (X_("Mixer"));
3058 ARDOUR_UI::editor_settings () const
3063 node = session->instant_xml(X_("Editor"), session->path());
3065 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3069 node = new XMLNode (X_("Editor"));
3075 ARDOUR_UI::keyboard_settings () const
3079 node = Config->extra_xml(X_("Keyboard"));
3082 node = new XMLNode (X_("Keyboard"));
3088 ARDOUR_UI::halt_on_xrun_message ()
3090 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3092 ArdourMessage msg (editor, X_("haltonxrun"),
3093 _("Recording was stopped because your system could not keep up."));
3097 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3099 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3101 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3105 delete deletion_list;
3109 ARDOUR_UI::disk_overrun_handler ()
3111 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3113 if (!have_disk_overrun_displayed) {
3114 have_disk_overrun_displayed = true;
3115 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3116 The disk system on your computer\n\
3117 was not able to keep up with Ardour.\n\
3119 Specifically, it failed to write data to disk\n\
3120 quickly enough to keep up with recording.\n"));
3121 have_disk_overrun_displayed = false;
3126 ARDOUR_UI::disk_underrun_handler ()
3128 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3130 if (!have_disk_underrun_displayed) {
3131 have_disk_underrun_displayed = true;
3132 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3133 (_("The disk system on your computer\n\
3134 was not able to keep up with Ardour.\n\
3136 Specifically, it failed to read data from disk\n\
3137 quickly enough to keep up with playback.\n")));
3138 have_disk_underrun_displayed = false;
3143 ARDOUR_UI::disk_underrun_message_gone ()
3145 have_disk_underrun_displayed = false;
3149 ARDOUR_UI::disk_overrun_message_gone ()
3151 have_disk_underrun_displayed = false;
3155 ARDOUR_UI::pending_state_dialog ()
3157 ArdourDialog dialog ("pending state dialog");
3159 This session appears to have been in\n\
3160 middle of recording when ardour or\n\
3161 the computer was shutdown.\n\
3163 Ardour can recover any captured audio for\n\
3164 you, or it can ignore it. Please decide\n\
3165 what you would like to do.\n"));
3167 dialog.get_vbox()->pack_start (message);
3168 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3169 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3171 dialog.set_position (WIN_POS_CENTER);
3174 switch (dialog.run ()) {
3175 case RESPONSE_ACCEPT:
3186 ARDOUR_UI::disconnect_from_jack ()
3189 if( engine->disconnect_from_jack ()) {
3190 ArdourMessage msg (editor, X_("nojack dialog"),
3191 _("Could not disconnect from JACK"));
3194 update_sample_rate (0);
3199 ARDOUR_UI::reconnect_to_jack ()
3202 if (engine->reconnect_to_jack ()) {
3203 ArdourMessage msg (editor, X_("nojack dialog"),
3204 _("Could not reconnect to JACK"));
3207 update_sample_rate (0);
3212 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3214 engine->request_buffer_size (nframes);
3215 update_sample_rate (0);
3219 ARDOUR_UI::cmdline_new_session (string path)
3221 if (path[0] != '/') {
3222 char buf[PATH_MAX+1];
3225 getcwd (buf, sizeof (buf));
3232 new_session (false, path);
3234 _will_create_new_session_automatically = false; /* done it */
3235 return FALSE; /* don't call it again */