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 time_master_button (_("time\nmaster")),
808 shuttle_units_button (_("% ")),
810 punch_in_button (_("punch\nin")),
811 punch_out_button (_("punch\nout")),
812 auto_return_button (_("auto\nreturn")),
813 auto_play_button (_("auto\nplay")),
814 auto_input_button (_("auto\ninput")),
815 click_button (_("click")),
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;
853 open_session_selector = 0;
854 have_configure_timeout = false;
855 have_disk_overrun_displayed = false;
856 have_disk_underrun_displayed = false;
857 _will_create_new_session_automatically = false;
858 session_loaded = false;
861 last_configure_time.tv_sec = 0;
862 last_configure_time.tv_usec = 0;
864 shuttle_grabbed = false;
867 set_shuttle_units (Percentage);
868 set_shuttle_behaviour (Sprung);
870 shuttle_style_menu = 0;
871 shuttle_unit_menu = 0;
873 gettimeofday (&last_peak_grab, 0);
874 gettimeofday (&last_shuttle_request, 0);
876 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
877 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
878 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
879 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
881 /* handle pending state with a dialog */
883 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
885 channel_combo_strings = internationalize (channel_setup_names);
887 /* have to wait for AudioEngine and Configuration before proceeding */
891 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
893 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
895 string msg = string_compose (_("\
896 You cannot record-enable\n\
898 because it has no input connections.\n\
899 You would be wasting space recording silence."),
902 ArdourMessage message (editor, X_("cannotrecord"), msg);
906 ARDOUR_UI::set_engine (AudioEngine& e)
910 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
911 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
912 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
913 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
917 keyboard = new Keyboard;
918 install_keybindings ();
920 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
921 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
923 if (setup_windows ()) {
924 throw failed_constructor ();
927 if (GTK_ARDOUR::show_key_actions) {
928 vector<string> names;
929 vector<string> paths;
931 vector<AccelKey> bindings;
933 ActionManager::get_all_actions (names, paths, keys, bindings);
935 vector<string>::iterator n;
936 vector<string>::iterator k;
937 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
938 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
944 /* start with timecode, metering enabled
947 blink_timeout_tag = -1;
949 /* this being a GUI and all, we want peakfiles */
951 FileSource::set_build_peakfiles (true);
952 FileSource::set_build_missing_peakfiles (true);
954 if (Source::start_peak_thread ()) {
955 throw failed_constructor();
958 /* start the time-of-day-clock */
960 update_wall_clock ();
961 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
963 update_disk_space ();
965 update_sample_rate (engine->frame_rate());
967 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
968 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
971 ARDOUR_UI::~ARDOUR_UI ()
973 save_ardour_state ();
987 if (add_route_dialog) {
988 delete add_route_dialog;
991 Source::stop_peak_thread ();
995 ARDOUR_UI::configure_timeout ()
1000 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1001 /* no configure events yet */
1005 gettimeofday (&now, 0);
1006 timersub (&now, &last_configure_time, &diff);
1008 /* force a gap of 0.5 seconds since the last configure event
1011 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1014 have_configure_timeout = false;
1015 save_ardour_state ();
1021 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1023 if (have_configure_timeout) {
1024 gettimeofday (&last_configure_time, 0);
1026 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1027 have_configure_timeout = true;
1034 ARDOUR_UI::save_ardour_state ()
1036 if (!keyboard || !mixer || !editor) {
1040 /* XXX this is all a bit dubious. add_extra_xml() uses
1041 a different lifetime model from add_instant_xml().
1044 XMLNode* node = new XMLNode (keyboard->get_state());
1045 Config->add_extra_xml (*node);
1046 Config->save_state();
1048 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1049 XMLNode& mnode (mixer->get_state());
1052 session->add_instant_xml(enode, session->path());
1053 session->add_instant_xml(mnode, session->path());
1055 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1056 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1061 ARDOUR_UI::startup ()
1063 /* Once the UI is up and running, start the audio engine. Doing
1064 this before the UI is up and running can cause problems
1065 when not running with SCHED_FIFO, because the amount of
1066 CPU and disk work needed to get the UI started can interfere
1067 with the scheduling of the audio thread.
1070 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1076 if (session && session->dirty()) {
1077 switch (ask_about_saving_session(_("quit"))) {
1082 /* use the default name */
1083 if (save_state_canfail ("")) {
1084 /* failed - don't quit */
1085 ArdourMessage (editor, X_("badsave dialog"),
1087 Ardour was unable to save your session.\n\n\
1088 If you still wish to quit, please use the\n\n\
1089 \"Just quit\" option."));
1102 ARDOUR_UI::ask_about_saving_session (const string & what)
1104 ArdourDialog window (_("ardour: save session?"));
1105 Gtk::Label prompt_label;
1108 msg = string_compose(_("Save and %1"), what);
1109 window.add_button (msg, RESPONSE_ACCEPT);
1110 msg = string_compose(_("Just %1"), what);
1111 window.add_button (msg, RESPONSE_APPLY);
1112 msg = string_compose(_("Don't %1"), what);
1113 window.add_button (msg, RESPONSE_REJECT);
1115 Gtk::Button noquit_button (msg);
1116 noquit_button.set_name ("EditorGTKButton");
1121 if (session->snap_name() == session->name()) {
1122 type = _("session");
1124 type = _("snapshot");
1126 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?"),
1127 type, session->snap_name());
1129 prompt_label.set_text (prompt);
1130 prompt_label.set_alignment (0.5, 0.5);
1131 prompt_label.set_name (X_("PrompterLabel"));
1133 window.get_vbox()->pack_start (prompt_label);
1135 window.set_name (_("Prompter"));
1136 window.set_position (Gtk::WIN_POS_MOUSE);
1137 window.set_modal (true);
1140 save_the_session = 0;
1142 editor->ensure_float (window);
1144 ResponseType r = (ResponseType) window.run();
1149 case RESPONSE_ACCEPT: // save and get out of here
1151 case RESPONSE_APPLY: // get out of here
1161 ARDOUR_UI::every_second ()
1164 update_buffer_load ();
1165 update_disk_space ();
1166 // update_disk_rate ();
1171 ARDOUR_UI::every_point_one_seconds ()
1174 struct timeval diff;
1176 /* do not attempt to grab peak power more than once per cycle.
1179 gettimeofday (&now, 0);
1180 timersub (&now, &last_peak_grab, &diff);
1182 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1183 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1184 last_peak_grab = now;
1187 update_speed_display ();
1188 RapidScreenUpdate(); /* EMIT_SIGNAL */
1193 ARDOUR_UI::every_point_zero_one_seconds ()
1195 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1200 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1204 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1206 if (!engine->connected()) {
1208 snprintf (buf, sizeof (buf), _("disconnected"));
1212 jack_nframes_t rate = engine->frame_rate();
1214 if (fmod (rate, 1000.0) != 0.0) {
1215 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1216 (float) rate/1000.0f,
1217 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1219 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1221 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1225 sample_rate_label.set_text (buf);
1229 ARDOUR_UI::update_cpu_load ()
1232 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1233 cpu_load_label.set_text (buf);
1237 ARDOUR_UI::update_disk_rate ()
1242 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1243 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1244 disk_rate_label.set_text (buf);
1246 disk_rate_label.set_text ("");
1251 ARDOUR_UI::update_buffer_load ()
1256 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1257 session->playback_load(), session->capture_load());
1258 buffer_load_label.set_text (buf);
1260 buffer_load_label.set_text ("");
1265 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1267 if (ds.record_enabled()) {
1268 rec_enabled_diskstreams++;
1273 ARDOUR_UI::update_disk_space()
1279 jack_nframes_t frames = session->available_capture_duration();
1282 if (frames == max_frames) {
1283 strcpy (buf, _("space: 24hrs+"));
1288 jack_nframes_t fr = session->frame_rate();
1290 if (session->actively_recording()){
1292 rec_enabled_diskstreams = 0;
1293 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1295 if (rec_enabled_diskstreams) {
1296 frames /= rec_enabled_diskstreams;
1301 /* hmmm. shall we divide by the route count? or the diskstream count?
1302 or what? for now, do nothing ...
1307 hrs = frames / (fr * 3600);
1308 frames -= hrs * fr * 3600;
1309 mins = frames / (fr * 60);
1310 frames -= mins * fr * 60;
1313 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1316 disk_space_label.set_text (buf);
1320 ARDOUR_UI::update_wall_clock ()
1327 tm_now = localtime (&now);
1329 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1330 wall_clock_label.set_text (buf);
1336 ARDOUR_UI::toggle_recording_plugins ()
1338 /* XXX use toggle_some_session_state */
1344 session->set_recording_plugins (!session->get_recording_plugins());
1348 ARDOUR_UI::toggle_auto_play ()
1351 toggle_some_session_state (auto_play_button,
1352 &Session::get_auto_play,
1353 &Session::set_auto_play);
1357 ARDOUR_UI::toggle_auto_return ()
1360 toggle_some_session_state (auto_return_button,
1361 &Session::get_auto_return,
1362 &Session::set_auto_return);
1366 ARDOUR_UI::toggle_click ()
1368 toggle_some_session_state (click_button,
1369 &Session::get_clicking,
1370 &Session::set_clicking);
1374 ARDOUR_UI::toggle_session_auto_loop ()
1377 if (session->get_auto_loop()) {
1378 if (session->transport_rolling()) {
1382 session->request_auto_loop (false);
1386 session->request_auto_loop (true);
1392 ARDOUR_UI::toggle_session_punch_in ()
1395 session->set_punch_in (!session->get_punch_in());
1400 ARDOUR_UI::toggle_punch_out ()
1402 toggle_some_session_state (punch_out_button,
1403 &Session::get_punch_out,
1404 &Session::set_punch_out);
1408 ARDOUR_UI::toggle_punch_in ()
1410 toggle_some_session_state (punch_in_button,
1411 &Session::get_punch_in,
1412 &Session::set_punch_in);
1416 ARDOUR_UI::map_button_state ()
1419 map_some_session_state (auto_return_button,
1420 &Session::get_auto_return);
1421 map_some_session_state (auto_play_button,
1422 &Session::get_auto_play);
1423 map_some_session_state (auto_input_button,
1424 &Session::get_auto_input);
1425 map_some_session_state (punch_in_button,
1426 &Session::get_punch_in);
1427 map_some_session_state (punch_out_button,
1428 &Session::get_punch_out);
1429 map_some_session_state (click_button,
1430 &Session::get_clicking);
1434 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1436 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1440 ARDOUR_UI::map_control_change (Session::ControlType t)
1443 case Session::AutoPlay:
1444 map_some_session_state (auto_play_button, &Session::get_auto_play);
1447 case Session::AutoLoop:
1450 case Session::AutoReturn:
1451 map_some_session_state (auto_return_button, &Session::get_auto_return);
1454 case Session::AutoInput:
1455 map_some_session_state (auto_input_button, &Session::get_auto_input);
1458 case Session::PunchOut:
1459 map_some_session_state (punch_in_button, &Session::get_punch_out);
1462 case Session::PunchIn:
1463 map_some_session_state (punch_in_button, &Session::get_punch_in);
1466 case Session::Clicking:
1467 map_some_session_state (click_button, &Session::get_clicking);
1470 case Session::SlaveType:
1471 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1474 case Session::SendMTC:
1475 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1478 case Session::SendMMC:
1479 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1482 case Session::MMCControl:
1483 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1486 case Session::MidiFeedback:
1487 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1489 case Session::MidiControl:
1490 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1496 case Session::RecordingPlugins:
1499 case Session::CrossFadesActive:
1502 case Session::EditingMode:
1505 case Session::PlayRange:
1508 case Session::AlignChoice:
1509 /* don't care, this is handled by the options editor */
1511 case Session::SeamlessLoop:
1512 /* don't care, this is handled by the options editor */
1519 ARDOUR_UI::control_methods_adjusted ()
1524 which_method = (int) online_control_button->adjustment.get_value();
1525 switch (which_method) {
1527 allow_mmc_and_local ();
1533 allow_local_only ();
1536 fatal << _("programming error: impossible control method") << endmsg;
1542 ARDOUR_UI::mmc_device_id_adjusted ()
1547 int dev_id = (int) mmc_id_button->adjustment.get_value();
1548 mmc->set_device_id (dev_id);
1554 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1555 bool (Session::*get)() const)
1564 if (button.get_active() != (x = (session->*get)())) {
1565 button.set_active (x);
1570 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1571 bool (Session::*get)() const,
1572 void (Session::*set)(bool))
1582 button_state = button.get_active ();
1583 session_state = (session->*get)();
1585 if (button_state != session_state) {
1586 (session->*set) (button_state);
1589 /* check that it worked, and reverse
1590 the button state if it didn't
1593 if ((session->*get)() != button_state) {
1594 button->set_active (!button_state);
1602 ARDOUR_UI::session_menu (GdkEventButton *ev)
1604 session_popup_menu->popup (0, 0);
1609 ARDOUR_UI::redisplay_recent_sessions ()
1611 vector<string *> *sessions;
1612 vector<string *>::iterator i;
1613 RecentSessionsSorter cmp;
1615 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1616 recent_session_model->clear ();
1619 ARDOUR::read_recent_sessions (rs);
1622 recent_session_display.set_model (recent_session_model);
1626 /* sort them alphabetically */
1627 sort (rs.begin(), rs.end(), cmp);
1628 sessions = new vector<string*>;
1630 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1631 sessions->push_back (new string ((*i).second));
1634 for (i = sessions->begin(); i != sessions->end(); ++i) {
1636 vector<string*>* states;
1637 vector<const gchar*> item;
1638 string fullpath = *(*i);
1640 /* remove any trailing / */
1642 if (fullpath[fullpath.length()-1] == '/') {
1643 fullpath = fullpath.substr (0, fullpath.length()-1);
1646 /* now get available states for this session */
1648 if ((states = Session::possible_states (fullpath)) == 0) {
1649 /* no state file? */
1653 TreeModel::Row row = *(recent_session_model->append());
1655 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1656 row[recent_session_columns.fullpath] = fullpath;
1658 if (states->size() > 1) {
1660 /* add the children */
1662 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1664 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1666 child_row[recent_session_columns.visible_name] = **i2;
1667 child_row[recent_session_columns.fullpath] = fullpath;
1676 recent_session_display.set_model (recent_session_model);
1681 ARDOUR_UI::build_session_selector ()
1683 session_selector_window = new ArdourDialog ("session selector");
1685 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1687 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1688 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1690 recent_session_model = TreeStore::create (recent_session_columns);
1691 recent_session_display.set_model (recent_session_model);
1692 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1693 recent_session_display.set_headers_visible (false);
1695 scroller->add (recent_session_display);
1696 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1698 session_selector_window->set_name ("SessionSelectorWindow");
1699 session_selector_window->set_size_request (200, 400);
1700 session_selector_window->get_vbox()->pack_start (*scroller);
1701 session_selector_window->show_all_children();
1705 ARDOUR_UI::open_recent_session ()
1707 /* popup selector window */
1709 if (session_selector_window == 0) {
1710 build_session_selector ();
1713 redisplay_recent_sessions ();
1715 ResponseType r = (ResponseType) session_selector_window->run ();
1717 session_selector_window->hide();
1720 case RESPONSE_ACCEPT:
1726 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1728 if (i == recent_session_model->children().end()) {
1732 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1733 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1735 _session_is_new = false;
1737 load_session (path, state);
1741 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1743 struct stat statbuf;
1745 if (stat (info.filename.c_str(), &statbuf) != 0) {
1749 if (!S_ISDIR(statbuf.st_mode)) {
1753 string session_file = info.filename;
1754 session_file += '/';
1755 session_file += PBD::basename (info.filename);
1756 session_file += ".ardour";
1758 if (stat (session_file.c_str(), &statbuf) != 0) {
1762 return S_ISREG (statbuf.st_mode);
1766 ARDOUR_UI::open_session ()
1768 /* popup selector window */
1770 if (open_session_selector == 0) {
1772 /* ardour sessions are folders */
1774 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1775 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1776 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1778 FileFilter session_filter;
1779 session_filter.add_pattern ("*.ardour");
1780 session_filter.set_name (_("Ardour sessions"));
1781 open_session_selector->add_filter (session_filter);
1782 open_session_selector->set_filter (session_filter);
1785 int response = open_session_selector->run();
1786 open_session_selector->hide ();
1789 case RESPONSE_ACCEPT:
1792 open_session_selector->hide();
1796 open_session_selector->hide();
1797 string session_path = open_session_selector->get_filename();
1801 if (session_path.length() > 0) {
1802 if (Session::find_session (session_path, path, name, isnew) == 0) {
1803 _session_is_new = isnew;
1804 load_session (path, name);
1811 ARDOUR_UI::session_add_midi_track ()
1813 cerr << _("Patience is a virtue.\n");
1817 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1822 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1828 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1829 error << _("could not create new audio track") << endmsg;
1832 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1833 error << _("could not create new audio bus") << endmsg;
1838 if (need_control_room_outs) {
1844 route->set_stereo_control_outs (control_lr_channels);
1845 route->control_outs()->set_stereo_pan (pans, this);
1847 #endif /* CONTROLOUTS */
1851 ArdourMessage msg (editor, X_("noport dialog"),
1852 _("There are insufficient JACK ports available\n\
1853 to create a new track or bus.\n\
1854 You should save Ardour, exit and\n\
1855 restart JACK with more ports."));
1860 ARDOUR_UI::diskstream_added (DiskStream* ds)
1865 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1867 jack_nframes_t _preroll;
1870 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1872 if (new_position > _preroll) {
1873 new_position -= _preroll;
1878 session->request_locate (new_position);
1883 ARDOUR_UI::transport_goto_start ()
1886 session->request_locate (0);
1889 /* force displayed area in editor to start no matter
1890 what "follow playhead" setting is.
1894 editor->reposition_x_origin (0);
1900 ARDOUR_UI::transport_goto_end ()
1903 jack_nframes_t frame = session->current_end_frame();
1904 session->request_locate (frame);
1906 /* force displayed area in editor to start no matter
1907 what "follow playhead" setting is.
1911 editor->reposition_x_origin (frame);
1917 ARDOUR_UI::transport_stop ()
1923 if (session->is_auditioning()) {
1924 session->cancel_audition ();
1928 if (session->get_auto_loop()) {
1929 session->request_auto_loop (false);
1932 session->request_stop ();
1936 ARDOUR_UI::transport_stop_and_forget_capture ()
1939 session->request_stop (true);
1944 ARDOUR_UI::remove_last_capture()
1947 editor->remove_last_capture();
1952 ARDOUR_UI::transport_record ()
1955 switch (session->record_status()) {
1956 case Session::Disabled:
1957 if (session->ntracks() == 0) {
1958 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1959 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1962 session->maybe_enable_record ();
1964 case Session::Recording:
1965 case Session::Enabled:
1966 session->disable_record ();
1972 ARDOUR_UI::transport_roll ()
1980 rolling = session->transport_rolling ();
1982 if (session->get_auto_loop()) {
1983 session->request_auto_loop (false);
1984 auto_loop_button.set_active (false);
1985 roll_button.set_active (true);
1986 } else if (session->get_play_range ()) {
1987 session->request_play_range (false);
1988 play_selection_button.set_active (false);
1989 } else if (rolling) {
1990 session->request_locate (session->last_transport_start(), true);
1993 session->request_transport_speed (1.0f);
1997 ARDOUR_UI::transport_loop()
2000 if (session->get_auto_loop()) {
2001 if (session->transport_rolling()) {
2002 Location * looploc = session->locations()->auto_loop_location();
2004 session->request_locate (looploc->start(), true);
2009 session->request_auto_loop (true);
2015 ARDOUR_UI::transport_play_selection ()
2021 if (!session->get_play_range()) {
2022 session->request_stop ();
2025 editor->play_selection ();
2029 ARDOUR_UI::transport_rewind (int option)
2031 float current_transport_speed;
2034 current_transport_speed = session->transport_speed();
2036 if (current_transport_speed >= 0.0f) {
2039 session->request_transport_speed (-1.0f);
2042 session->request_transport_speed (-4.0f);
2045 session->request_transport_speed (-0.5f);
2050 session->request_transport_speed (current_transport_speed * 1.5f);
2056 ARDOUR_UI::transport_forward (int option)
2058 float current_transport_speed;
2061 current_transport_speed = session->transport_speed();
2063 if (current_transport_speed <= 0.0f) {
2066 session->request_transport_speed (1.0f);
2069 session->request_transport_speed (4.0f);
2072 session->request_transport_speed (0.5f);
2077 session->request_transport_speed (current_transport_speed * 1.5f);
2083 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2091 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2092 Port *port = ds->io()->input (0);
2093 port->request_monitor_input (!port->monitoring_input());
2098 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2106 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2107 ds->set_record_enabled (!ds->record_enabled(), this);
2112 ARDOUR_UI::queue_transport_change ()
2114 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2118 ARDOUR_UI::map_transport_state ()
2120 float sp = session->transport_speed();
2123 transport_rolling ();
2124 } else if (sp < 0.0f) {
2125 transport_rewinding ();
2126 } else if (sp > 0.0f) {
2127 transport_forwarding ();
2129 transport_stopped ();
2134 ARDOUR_UI::send_all_midi_feedback ()
2137 session->send_all_midi_feedback();
2142 ARDOUR_UI::allow_local_only ()
2148 ARDOUR_UI::allow_mmc_only ()
2154 ARDOUR_UI::allow_mmc_and_local ()
2160 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2162 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2163 (int) adj.get_value()].c_str());
2167 ARDOUR_UI::engine_stopped ()
2169 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2170 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2171 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2176 ARDOUR_UI::engine_running ()
2178 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2179 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2180 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2184 ARDOUR_UI::engine_halted ()
2186 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2188 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2189 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2191 update_sample_rate (0);
2193 ArdourMessage msg (editor, X_("halted"),
2195 JACK has either been shutdown or it\n\
2196 disconnected Ardour because Ardour\n\
2197 was not fast enough. You can save the\n\
2198 session and/or try to reconnect to JACK ."));
2202 ARDOUR_UI::do_engine_start ()
2208 catch (AudioEngine::PortRegistrationFailure& err) {
2210 error << _("Unable to create all required ports")
2218 error << _("Unable to start the session running")
2228 ARDOUR_UI::start_engine ()
2230 if (do_engine_start () == 0) {
2231 if (session && _session_is_new) {
2232 /* we need to retain initial visual
2233 settings for a new session
2235 session->save_state ("");
2238 /* there is too much going on, in too many threads, for us to
2239 end up with a clean session. So wait 1 second after loading,
2240 and fix it up. its ugly, but until i come across a better
2241 solution, its what we have.
2244 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2251 ARDOUR_UI::update_clocks ()
2253 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2257 ARDOUR_UI::start_clocking ()
2259 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2263 ARDOUR_UI::stop_clocking ()
2265 clock_signal_connection.disconnect ();
2269 ARDOUR_UI::toggle_clocking ()
2272 if (clock_button.get_active()) {
2281 ARDOUR_UI::_blink (void *arg)
2284 ((ARDOUR_UI *) arg)->blink ();
2291 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2295 ARDOUR_UI::start_blinking ()
2297 /* Start the blink signal. Everybody with a blinking widget
2298 uses Blink to drive the widget's state.
2301 if (blink_timeout_tag < 0) {
2303 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2308 ARDOUR_UI::stop_blinking ()
2310 if (blink_timeout_tag >= 0) {
2311 gtk_timeout_remove (blink_timeout_tag);
2312 blink_timeout_tag = -1;
2318 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2320 using namespace Gtk;
2321 using namespace Menu_Helpers;
2323 if (dstream.hidden()) {
2327 MenuList& items = diskstream_menu->items();
2328 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2332 ARDOUR_UI::diskstream_selected (gint32 id)
2334 selected_dstream = id;
2339 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2341 using namespace Gtk;
2342 using namespace Menu_Helpers;
2348 diskstream_menu = new Menu();
2349 diskstream_menu->set_name ("ArdourContextMenu");
2350 using namespace Gtk;
2351 using namespace Menu_Helpers;
2353 MenuList& items = diskstream_menu->items();
2354 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2356 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2359 diskstream_menu->popup (ev->button, ev->time);
2361 diskstream_menu->popup (0, 0);
2364 selected_dstream = -1;
2368 delete diskstream_menu;
2370 return selected_dstream;
2374 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2380 if (io.n_inputs() == 0) {
2385 /* XXX we're not handling multiple ports yet. */
2387 const char **connections = io.input(0)->get_connections();
2389 if (connections == 0 || connections[0] == '\0') {
2392 buf = connections[0];
2399 if (io.n_outputs() == 0) {
2404 /* XXX we're not handling multiple ports yet. */
2406 const char **connections = io.output(0)->get_connections();
2408 if (connections == 0 || connections[0] == '\0') {
2411 buf = connections[0];
2419 ARDOUR_UI::snapshot_session ()
2421 ArdourPrompter prompter (true);
2428 now = now.substr (0, now.length() - 1);
2430 prompter.set_name ("Prompter");
2431 prompter.set_prompt (_("Name for snapshot"));
2432 prompter.set_initial_text (now);
2434 switch (prompter.run()) {
2435 case RESPONSE_ACCEPT:
2436 prompter.get_result (snapname);
2437 if (snapname.length()){
2438 save_state (snapname);
2448 ARDOUR_UI::save_state (const string & name)
2450 (void) save_state_canfail (name);
2454 ARDOUR_UI::save_state_canfail (string name)
2459 if (name.length() == 0) {
2460 name = session->snap_name();
2463 if ((ret = session->save_state (name)) != 0) {
2467 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2472 ARDOUR_UI::restore_state (string name)
2475 if (name.length() == 0) {
2476 name = session->name();
2478 session->restore_state (name);
2483 ARDOUR_UI::primary_clock_value_changed ()
2486 session->request_locate (primary_clock.current_time ());
2491 ARDOUR_UI::secondary_clock_value_changed ()
2494 session->request_locate (secondary_clock.current_time ());
2499 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2501 if (session && dstream && dstream->record_enabled()) {
2503 Session::RecordState rs;
2505 rs = session->record_status ();
2508 case Session::Disabled:
2509 case Session::Enabled:
2510 if (w->get_state() != STATE_SELECTED) {
2511 w->set_state (STATE_SELECTED);
2515 case Session::Recording:
2516 if (w->get_state() != STATE_ACTIVE) {
2517 w->set_state (STATE_ACTIVE);
2523 if (w->get_state() != STATE_NORMAL) {
2524 w->set_state (STATE_NORMAL);
2530 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2536 switch (session->record_status()) {
2537 case Session::Enabled:
2539 rec_button.set_state (1);
2541 rec_button.set_state (0);
2545 case Session::Recording:
2546 rec_button.set_state (2);
2550 rec_button.set_state (0);
2556 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2564 ARDOUR_UI::start_keyboard_prefix ()
2566 keyboard->start_prefix();
2570 ARDOUR_UI::save_template ()
2573 ArdourPrompter prompter (true);
2576 prompter.set_name (X_("Prompter"));
2577 prompter.set_prompt (_("Name for mix template:"));
2578 prompter.set_initial_text(session->name() + _("-template"));
2580 switch (prompter.run()) {
2581 case RESPONSE_ACCEPT:
2582 prompter.get_result (name);
2584 if (name.length()) {
2585 session->save_template (name);
2595 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2597 m_new_session_dialog->show_all();
2598 m_new_session_dialog->set_transient_for(*editor);
2599 m_new_session_dialog->set_name(predetermined_path);
2601 int response = Gtk::RESPONSE_CANCEL;
2604 response = m_new_session_dialog->run ();
2606 if(response == Gtk::RESPONSE_OK) {
2608 _session_is_new = true;
2610 std::string session_name = m_new_session_dialog->session_name();
2611 std::string session_path = m_new_session_dialog->session_folder();
2614 XXX This is needed because session constructor wants a
2615 non-existant path. hopefully this will be fixed at some point.
2617 session_path = Glib::build_filename(session_path, session_name);
2619 std::string template_name = m_new_session_dialog->session_template_name();
2621 if (m_new_session_dialog->use_session_template()) {
2623 load_session (session_path, session_name, &template_name);
2629 Session::AutoConnectOption iconnect;
2630 Session::AutoConnectOption oconnect;
2632 if (m_new_session_dialog->create_control_bus()) {
2633 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2638 if (m_new_session_dialog->create_master_bus()) {
2639 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2644 if (m_new_session_dialog->connect_inputs()) {
2645 iconnect = Session::AutoConnectPhysical;
2647 iconnect = Session::AutoConnectOption (0);
2650 /// @todo some minor tweaks.
2652 if (m_new_session_dialog->connect_outs_to_master()) {
2653 oconnect = Session::AutoConnectMaster;
2654 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2655 oconnect = Session::AutoConnectPhysical;
2657 oconnect = Session::AutoConnectOption (0);
2660 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2661 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2663 build_session (session_path,
2671 engine->frame_rate() * 60 * 5);
2675 } while(response == Gtk::RESPONSE_HELP);
2676 m_new_session_dialog->hide_all();
2680 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2682 Session *new_session;
2684 session_loaded = false;
2685 x = unload_session ();
2693 /* if it already exists, we must have write access */
2695 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2696 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2697 You do not have write access to this session.\n\
2698 This prevents the session from being loaded."));
2703 new_session = new Session (*engine, path, snap_name, mix_template);
2708 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2712 connect_to_session (new_session);
2714 //if (engine->running()) {
2715 //mixer->show_window();
2717 session_loaded = true;
2722 ARDOUR_UI::make_session_clean ()
2725 session->set_clean ();
2732 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2733 uint32_t control_channels,
2734 uint32_t master_channels,
2735 Session::AutoConnectOption input_connect,
2736 Session::AutoConnectOption output_connect,
2739 jack_nframes_t initial_length)
2741 Session *new_session;
2744 session_loaded = false;
2745 x = unload_session ();
2752 _session_is_new = true;
2755 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2756 control_channels, master_channels, nphysin, nphysout, initial_length);
2761 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2765 connect_to_session (new_session);
2767 //if (engine->running()) {
2768 //mixer->show_window();
2770 session_loaded = true;
2778 editor->show_window ();
2782 if (session && mixer) {
2783 // mixer->show_window ();
2792 ARDOUR_UI::show_splash ()
2795 about = new About();
2801 ARDOUR_UI::hide_splash ()
2809 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2813 removed = rep.paths.size();
2816 ArdourMessage msg (editor, X_("cleanupresults"),
2818 No audio files were ready for cleanup\n\n\
2819 If this seems suprising, check for any existing\n\
2820 snapshots. These may still include regions that\n\
2821 require some unused files to continue to exist."));
2825 ArdourDialog results (_("ardour: cleanup"), true);
2827 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2828 CleanupResultsModelColumns() {
2832 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2833 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2837 Glib::RefPtr<Gtk::ListStore> results_model;
2838 CleanupResultsModelColumns results_columns;
2839 Gtk::TreeView results_display;
2841 results_model = ListStore::create (results_columns);
2842 results_display.set_model (results_model);
2843 results_display.append_column (list_title, results_columns.visible_name);
2844 results_display.set_headers_visible (true);
2846 Gtk::ScrolledWindow list_scroller;
2849 if (rep.space < 1048576.0f) {
2851 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2853 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2857 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2859 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2863 results.get_vbox()->pack_start (txt, false, false);
2865 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2866 TreeModel::Row row = *(results_model->append());
2867 row[results_columns.visible_name] = *i;
2868 row[results_columns.fullpath] = *i;
2871 list_scroller.add (results_display);
2872 list_scroller.set_size_request (-1, 250);
2873 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2875 results.get_vbox()->pack_start (list_scroller, true, true);
2876 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2877 results.set_position (Gtk::WIN_POS_MOUSE);
2883 ARDOUR_UI::cleanup ()
2886 /* shouldn't happen: menu item is insensitive */
2890 ArdourDialog checker (_("ardour cleanup"));
2891 Gtk::Label label (_("\
2892 Cleanup is a destructive operation.\n\
2893 ALL undo/redo information will be lost if you cleanup.\n\
2894 Unused audio files will be moved to a \"dead sounds\" location."));
2896 checker.get_vbox()->pack_start (label, false, false);
2897 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2898 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2900 checker.set_name (_("CleanupDialog"));
2901 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2902 checker.set_position (Gtk::WIN_POS_MOUSE);
2904 switch (checker.run()) {
2905 case RESPONSE_ACCEPT:
2911 Session::cleanup_report rep;
2913 editor->prepare_for_cleanup ();
2915 if (session->cleanup_sources (rep)) {
2919 display_cleanup_results (rep,
2922 The following %1 %2 were not in use.\n\
2923 The next time you flush the wastebasket\n\
2924 it will release an additional %3 %4bytes\n\
2930 ARDOUR_UI::flush_trash ()
2933 /* shouldn't happen: menu item is insensitive */
2937 Session::cleanup_report rep;
2939 if (session->cleanup_trash_sources (rep)) {
2943 display_cleanup_results (rep,
2945 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2949 ARDOUR_UI::add_route ()
2957 if (add_route_dialog == 0) {
2958 add_route_dialog = new AddRouteDialog;
2959 editor->ensure_float (*add_route_dialog);
2962 if (add_route_dialog->is_visible()) {
2963 /* we're already doing this */
2967 ResponseType r = (ResponseType) add_route_dialog->run ();
2969 add_route_dialog->hide();
2972 case RESPONSE_ACCEPT:
2979 if ((count = add_route_dialog->count()) <= 0) {
2983 uint32_t input_chan = add_route_dialog->channels ();
2984 uint32_t output_chan;
2985 string name_template = add_route_dialog->name_template ();
2986 bool track = add_route_dialog->track ();
2988 Session::AutoConnectOption oac = session->get_output_auto_connect();
2990 if (oac & Session::AutoConnectMaster) {
2991 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2993 output_chan = input_chan;
2996 /* XXX do something with name template */
3000 session_add_audio_track (input_chan, output_chan);
3002 session_add_audio_bus (input_chan, output_chan);
3006 while (Main::events_pending()) {
3013 ARDOUR_UI::mixer_settings () const
3018 node = session->instant_xml(X_("Mixer"), session->path());
3020 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3024 node = new XMLNode (X_("Mixer"));
3031 ARDOUR_UI::editor_settings () const
3036 node = session->instant_xml(X_("Editor"), session->path());
3038 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3042 node = new XMLNode (X_("Editor"));
3048 ARDOUR_UI::keyboard_settings () const
3052 node = Config->extra_xml(X_("Keyboard"));
3055 node = new XMLNode (X_("Keyboard"));
3061 ARDOUR_UI::halt_on_xrun_message ()
3063 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3065 ArdourMessage msg (editor, X_("haltonxrun"),
3066 _("Recording was stopped because your system could not keep up."));
3070 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3072 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3074 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3078 delete deletion_list;
3082 ARDOUR_UI::disk_overrun_handler ()
3084 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3086 if (!have_disk_overrun_displayed) {
3087 have_disk_overrun_displayed = true;
3088 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3089 The disk system on your computer\n\
3090 was not able to keep up with Ardour.\n\
3092 Specifically, it failed to write data to disk\n\
3093 quickly enough to keep up with recording.\n"));
3094 have_disk_overrun_displayed = false;
3099 ARDOUR_UI::disk_underrun_handler ()
3101 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3103 if (!have_disk_underrun_displayed) {
3104 have_disk_underrun_displayed = true;
3105 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3106 (_("The disk system on your computer\n\
3107 was not able to keep up with Ardour.\n\
3109 Specifically, it failed to read data from disk\n\
3110 quickly enough to keep up with playback.\n")));
3111 have_disk_underrun_displayed = false;
3116 ARDOUR_UI::disk_underrun_message_gone ()
3118 have_disk_underrun_displayed = false;
3122 ARDOUR_UI::disk_overrun_message_gone ()
3124 have_disk_underrun_displayed = false;
3128 ARDOUR_UI::pending_state_dialog ()
3130 ArdourDialog dialog ("pending state dialog");
3132 This session appears to have been in\n\
3133 middle of recording when ardour or\n\
3134 the computer was shutdown.\n\
3136 Ardour can recover any captured audio for\n\
3137 you, or it can ignore it. Please decide\n\
3138 what you would like to do.\n"));
3140 dialog.get_vbox()->pack_start (message);
3141 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3142 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3144 dialog.set_position (WIN_POS_CENTER);
3147 switch (dialog.run ()) {
3148 case RESPONSE_ACCEPT:
3159 ARDOUR_UI::disconnect_from_jack ()
3162 if( engine->disconnect_from_jack ()) {
3163 ArdourMessage msg (editor, X_("nojack dialog"),
3164 _("Could not disconnect from JACK"));
3167 update_sample_rate (0);
3172 ARDOUR_UI::reconnect_to_jack ()
3175 if (engine->reconnect_to_jack ()) {
3176 ArdourMessage msg (editor, X_("nojack dialog"),
3177 _("Could not reconnect to JACK"));
3180 update_sample_rate (0);
3185 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3187 engine->request_buffer_size (nframes);
3188 update_sample_rate (0);
3192 ARDOUR_UI::cmdline_new_session (string path)
3194 if (path[0] != '/') {
3195 char buf[PATH_MAX+1];
3198 getcwd (buf, sizeof (buf));
3205 new_session (false, path);
3207 _will_create_new_session_automatically = false; /* done it */
3208 return FALSE; /* don't call it again */