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>
59 #include "ardour_ui.h"
60 #include "ardour_message.h"
61 #include "public_editor.h"
62 #include "audio_clock.h"
67 #include "keyboard_target.h"
68 #include "add_route_dialog.h"
69 #include "new_session_dialog.h"
72 #include "gui_thread.h"
76 using namespace ARDOUR;
77 using namespace Gtkmm2ext;
81 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
83 sigc::signal<void,bool> ARDOUR_UI::Blink;
84 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
85 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
86 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
89 static const gchar *h_meter_strip_xpm[] = {
278 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 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.`. +.+",
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.`. +++"};
285 static const gchar * v_meter_strip_xpm[] = {
768 static const char* channel_setup_names[] = {
779 vector<string> channel_combo_strings;
781 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
783 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
785 primary_clock (X_("TransportClockDisplay"), true, false, true),
786 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
787 preroll_clock (X_("PreRollClock"), true, true),
788 postroll_clock (X_("PostRollClock"), true, true),
792 adjuster_table (3, 3),
796 preroll_button (_("pre\nroll")),
797 postroll_button (_("post\nroll")),
801 big_clock ("BigClockDisplay", true),
805 shuttle_units_button (_("% ")),
806 shuttle_style_button (_("spring")),
808 punch_in_button (_("punch\nin")),
809 punch_out_button (_("punch\nout")),
810 auto_return_button (_("auto\nreturn")),
811 auto_play_button (_("auto\nplay")),
812 auto_input_button (_("auto\ninput")),
813 click_button (_("click")),
814 follow_button (_("follow\nPH")),
815 auditioning_alert_button (_("AUDITIONING")),
816 solo_alert_button (_("SOLO")),
820 using namespace Gtk::Menu_Helpers;
824 /* actually, its already loaded, but ... */
826 cerr << "Loading UI configuration file " << rcfile << endl;
830 if (theArdourUI == 0) {
837 _session_is_new = false;
838 big_clock_window = 0;
839 session_selector_window = 0;
840 last_key_press_time = 0;
841 connection_editor = 0;
842 add_route_dialog = 0;
847 new_session_window = 0;
848 open_session_selector = 0;
849 have_configure_timeout = false;
850 have_disk_overrun_displayed = false;
851 have_disk_underrun_displayed = false;
852 _will_create_new_session_automatically = false;
853 session_loaded = false;
855 last_configure_time.tv_sec = 0;
856 last_configure_time.tv_usec = 0;
858 ui_manager = UIManager::create ();
860 shuttle_grabbed = false;
863 set_shuttle_units (Percentage);
864 set_shuttle_behaviour (Sprung);
866 Glib::RefPtr<ActionGroup> shuttle_actions = ActionGroup::create ("ShuttleActions");
868 shuttle_actions->add (Action::create (X_("SetShuttleUnitsPercentage"), _("Percentage")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_units), Percentage));
869 shuttle_actions->add (Action::create (X_("SetShuttleUnitsSemitones"), _("Semitones")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_units), Semitones));
870 shuttle_actions->add (Action::create (X_("SetShuttleActionSprung"), _("Sprung")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_behaviour), Sprung));
871 shuttle_actions->add (Action::create (X_("SetShuttleActionWheel"), _("Wheel")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_behaviour), Wheel));
873 ui_manager->insert_action_group (shuttle_actions);
875 shuttle_style_menu = dynamic_cast<Menu*> (ui_manager->get_widget ("ShuttleStylePopup"));
876 shuttle_unit_menu = dynamic_cast<Menu*> (ui_manager->get_widget ("ShuttleUnitPopup"));
878 gettimeofday (&last_peak_grab, 0);
879 gettimeofday (&last_shuttle_request, 0);
881 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
882 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
883 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
884 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
886 /* handle pending state with a dialog */
888 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
890 channel_combo_strings = internationalize (channel_setup_names);
892 /* have to wait for AudioEngine and Configuration before proceeding */
896 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
898 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
900 string msg = string_compose (_("\
901 You cannot record-enable\n\
903 because it has no input connections.\n\
904 You would be wasting space recording silence."),
907 ArdourMessage message (editor, X_("cannotrecord"), msg);
911 ARDOUR_UI::set_engine (AudioEngine& e)
915 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
916 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
917 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
918 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
922 keyboard = new Keyboard;
923 install_keybindings ();
925 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
926 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
928 if (setup_windows ()) {
929 throw failed_constructor ();
932 if (GTK_ARDOUR::show_key_actions) {
933 KeyboardTarget::show_all_actions ();
937 /* start with timecode, metering enabled
940 blink_timeout_tag = -1;
942 /* this being a GUI and all, we want peakfiles */
944 FileSource::set_build_peakfiles (true);
945 FileSource::set_build_missing_peakfiles (true);
947 if (Source::start_peak_thread ()) {
948 throw failed_constructor();
951 /* start the time-of-day-clock */
953 update_wall_clock ();
954 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
956 update_disk_space ();
958 update_sample_rate (engine->frame_rate());
960 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
961 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
964 ARDOUR_UI::~ARDOUR_UI ()
966 save_ardour_state ();
980 if (add_route_dialog) {
981 delete add_route_dialog;
984 Source::stop_peak_thread ();
988 ARDOUR_UI::configure_timeout ()
993 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
994 /* no configure events yet */
998 gettimeofday (&now, 0);
999 timersub (&now, &last_configure_time, &diff);
1001 /* force a gap of 0.5 seconds since the last configure event
1004 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1007 have_configure_timeout = false;
1008 save_ardour_state ();
1014 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1016 if (have_configure_timeout) {
1017 gettimeofday (&last_configure_time, 0);
1019 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1020 have_configure_timeout = true;
1027 ARDOUR_UI::save_ardour_state ()
1029 if (!keyboard || !mixer || !editor) {
1033 /* XXX this is all a bit dubious. add_extra_xml() uses
1034 a different lifetime model from add_instant_xml().
1037 XMLNode* node = new XMLNode (keyboard->get_state());
1038 Config->add_extra_xml (*node);
1039 Config->save_state();
1041 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1042 XMLNode& mnode (mixer->get_state());
1045 session->add_instant_xml(enode, session->path());
1046 session->add_instant_xml(mnode, session->path());
1048 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1049 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1054 ARDOUR_UI::startup ()
1056 /* Once the UI is up and running, start the audio engine. Doing
1057 this before the UI is up and running can cause problems
1058 when not running with SCHED_FIFO, because the amount of
1059 CPU and disk work needed to get the UI started can interfere
1060 with the scheduling of the audio thread.
1063 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1069 if (session && session->dirty()) {
1070 switch (ask_about_saving_session(_("quit"))) {
1075 /* use the default name */
1076 if (save_state_canfail ("")) {
1077 /* failed - don't quit */
1078 ArdourMessage (editor, X_("badsave dialog"),
1080 Ardour was unable to save your session.\n\n\
1081 If you still wish to quit, please use the\n\n\
1082 \"Just quit\" option."));
1095 ARDOUR_UI::ask_about_saving_session (string what)
1097 ArdourDialog window ("saving dialog");
1099 Gtk::Label prompt_label;
1100 Gtk::HBox button_packer;
1104 msg = string_compose(_("Save and %1"), what);
1106 Gtk::Button save_button (msg);
1107 save_button.set_name ("EditorGTKButton");
1109 msg = string_compose(_("Just %1"), what);
1111 Gtk::Button nosave_button (msg);
1112 nosave_button.set_name ("EditorGTKButton");
1114 msg = string_compose(_("Don't %1"), what);
1116 Gtk::Button noquit_button (msg);
1117 noquit_button.set_name ("EditorGTKButton");
1122 if (session->snap_name() == session->name()) {
1123 type = _("session");
1125 type = _("snapshot");
1127 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?"),
1128 type, session->snap_name());
1130 prompt_label.set_text (prompt);
1131 prompt_label.set_alignment (0.5, 0.5);
1132 prompt_label.set_name (X_("PrompterLabel"));
1134 save_button.signal_clicked().connect (bind(mem_fun(window,&ArdourDialog::stop), 1));
1135 nosave_button.signal_clicked().connect (bind(mem_fun(window,&ArdourDialog::stop), 0));
1136 noquit_button.signal_clicked().connect (bind(mem_fun(window,&ArdourDialog::stop), -1));
1138 button_packer.set_spacing (10);
1139 button_packer.pack_start (save_button);
1140 button_packer.pack_start (nosave_button);
1141 button_packer.pack_start (noquit_button);
1143 packer.set_spacing (10);
1144 packer.set_border_width (10);
1145 packer.pack_start (prompt_label);
1146 packer.pack_start (button_packer);
1148 window.set_name (_("Prompter"));
1149 window.set_title (_("ardour: save session?"));
1150 window.set_position (Gtk::WIN_POS_MOUSE);
1151 window.set_modal (true);
1152 window.add (packer);
1154 window.set_keyboard_input (true);
1156 save_the_session = 0;
1158 editor->ensure_float (window);
1162 return window.run_status();
1166 ARDOUR_UI::every_second ()
1169 update_buffer_load ();
1170 update_disk_space ();
1171 // update_disk_rate ();
1176 ARDOUR_UI::every_point_one_seconds ()
1179 struct timeval diff;
1181 /* do not attempt to grab peak power more than once per cycle.
1184 gettimeofday (&now, 0);
1185 timersub (&now, &last_peak_grab, &diff);
1187 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1188 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1189 last_peak_grab = now;
1192 update_speed_display ();
1193 RapidScreenUpdate(); /* EMIT_SIGNAL */
1198 ARDOUR_UI::every_point_zero_one_seconds ()
1200 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1205 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1209 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1211 if (!engine->connected()) {
1213 snprintf (buf, sizeof (buf), _("disconnected"));
1217 jack_nframes_t rate = engine->frame_rate();
1219 if (fmod (rate, 1000.0) != 0.0) {
1220 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1221 (float) rate/1000.0f,
1222 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1224 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1226 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1230 sample_rate_label.set_text (buf);
1234 ARDOUR_UI::update_cpu_load ()
1237 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1238 cpu_load_label.set_text (buf);
1242 ARDOUR_UI::update_disk_rate ()
1247 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1248 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1249 disk_rate_label.set_text (buf);
1251 disk_rate_label.set_text ("");
1256 ARDOUR_UI::update_buffer_load ()
1261 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1262 session->playback_load(), session->capture_load());
1263 buffer_load_label.set_text (buf);
1265 buffer_load_label.set_text ("");
1270 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1272 if (ds.record_enabled()) {
1273 rec_enabled_diskstreams++;
1278 ARDOUR_UI::update_disk_space()
1284 jack_nframes_t frames = session->available_capture_duration();
1287 if (frames == max_frames) {
1288 strcpy (buf, _("space: 24hrs+"));
1293 jack_nframes_t fr = session->frame_rate();
1295 if (session->actively_recording()){
1297 rec_enabled_diskstreams = 0;
1298 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1300 if (rec_enabled_diskstreams) {
1301 frames /= rec_enabled_diskstreams;
1306 /* hmmm. shall we divide by the route count? or the diskstream count?
1307 or what? for now, do nothing ...
1312 hrs = frames / (fr * 3600);
1313 frames -= hrs * fr * 3600;
1314 mins = frames / (fr * 60);
1315 frames -= mins * fr * 60;
1318 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1321 disk_space_label.set_text (buf);
1325 ARDOUR_UI::update_wall_clock ()
1332 tm_now = localtime (&now);
1334 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1335 wall_clock_label.set_text (buf);
1341 ARDOUR_UI::toggle_recording_plugins ()
1343 /* XXX use toggle_some_session_state */
1349 session->set_recording_plugins (!session->get_recording_plugins());
1353 ARDOUR_UI::toggle_auto_play ()
1356 toggle_some_session_state (auto_play_button,
1357 &Session::get_auto_play,
1358 &Session::set_auto_play);
1362 ARDOUR_UI::toggle_auto_return ()
1365 toggle_some_session_state (auto_return_button,
1366 &Session::get_auto_return,
1367 &Session::set_auto_return);
1371 ARDOUR_UI::toggle_click ()
1373 toggle_some_session_state (click_button,
1374 &Session::get_clicking,
1375 &Session::set_clicking);
1379 ARDOUR_UI::follow_changed ()
1387 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1388 follow_button.set_active (x);
1393 ARDOUR_UI::toggle_follow ()
1401 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1402 editor->set_follow_playhead (x);
1407 ARDOUR_UI::toggle_session_auto_loop ()
1410 if (session->get_auto_loop()) {
1411 if (session->transport_rolling()) {
1415 session->request_auto_loop (false);
1419 session->request_auto_loop (true);
1425 ARDOUR_UI::toggle_session_punch_in ()
1428 session->set_punch_in (!session->get_punch_in());
1433 ARDOUR_UI::toggle_punch_out ()
1435 toggle_some_session_state (punch_out_button,
1436 &Session::get_punch_out,
1437 &Session::set_punch_out);
1441 ARDOUR_UI::toggle_punch_in ()
1443 toggle_some_session_state (punch_in_button,
1444 &Session::get_punch_in,
1445 &Session::set_punch_in);
1449 ARDOUR_UI::map_button_state ()
1452 map_some_session_state (auto_return_button,
1453 &Session::get_auto_return);
1454 map_some_session_state (auto_play_button,
1455 &Session::get_auto_play);
1456 map_some_session_state (auto_input_button,
1457 &Session::get_auto_input);
1458 map_some_session_state (punch_in_button,
1459 &Session::get_punch_in);
1460 map_some_session_state (punch_out_button,
1461 &Session::get_punch_out);
1462 map_some_session_state (click_button,
1463 &Session::get_clicking);
1467 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1469 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1473 ARDOUR_UI::map_control_change (Session::ControlType t)
1476 case Session::AutoPlay:
1477 map_some_session_state (auto_play_button, &Session::get_auto_play);
1480 case Session::AutoLoop:
1483 case Session::AutoReturn:
1484 map_some_session_state (auto_return_button, &Session::get_auto_return);
1487 case Session::AutoInput:
1488 map_some_session_state (auto_input_button, &Session::get_auto_input);
1491 case Session::PunchOut:
1492 map_some_session_state (punch_in_button, &Session::get_punch_out);
1495 case Session::PunchIn:
1496 map_some_session_state (punch_in_button, &Session::get_punch_in);
1499 case Session::Clicking:
1500 map_some_session_state (click_button, &Session::get_clicking);
1503 case Session::SlaveType:
1504 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1507 case Session::SendMTC:
1508 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1511 case Session::SendMMC:
1512 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1515 case Session::MMCControl:
1516 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1519 case Session::MidiFeedback:
1520 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1522 case Session::MidiControl:
1523 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1529 case Session::RecordingPlugins:
1532 case Session::CrossFadesActive:
1535 case Session::EditingMode:
1538 case Session::PlayRange:
1541 case Session::AlignChoice:
1542 /* don't care, this is handled by the options editor */
1544 case Session::SeamlessLoop:
1545 /* don't care, this is handled by the options editor */
1552 ARDOUR_UI::control_methods_adjusted ()
1557 which_method = (int) online_control_button->adjustment.get_value();
1558 switch (which_method) {
1560 allow_mmc_and_local ();
1566 allow_local_only ();
1569 fatal << _("programming error: impossible control method") << endmsg;
1575 ARDOUR_UI::mmc_device_id_adjusted ()
1580 int dev_id = (int) mmc_id_button->adjustment.get_value();
1581 mmc->set_device_id (dev_id);
1587 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1588 bool (Session::*get)() const)
1597 if (button.get_active() != (x = (session->*get)())) {
1598 button.set_active (x);
1603 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1604 bool (Session::*get)() const,
1605 void (Session::*set)(bool))
1615 button_state = button.get_active ();
1616 session_state = (session->*get)();
1618 if (button_state != session_state) {
1619 (session->*set) (button_state);
1622 /* check that it worked, and reverse
1623 the button state if it didn't
1626 if ((session->*get)() != button_state) {
1627 button->set_active (!button_state);
1635 ARDOUR_UI::session_menu (GdkEventButton *ev)
1637 session_popup_menu->popup (0, 0);
1642 ARDOUR_UI::redisplay_recent_sessions ()
1644 vector<string *> *sessions;
1645 vector<string *>::iterator i;
1646 RecentSessionsSorter cmp;
1648 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1649 recent_session_model->clear ();
1652 ARDOUR::read_recent_sessions (rs);
1655 recent_session_display.set_model (recent_session_model);
1659 /* sort them alphabetically */
1660 sort (rs.begin(), rs.end(), cmp);
1661 sessions = new vector<string*>;
1663 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1664 sessions->push_back (new string ((*i).second));
1667 for (i = sessions->begin(); i != sessions->end(); ++i) {
1669 vector<string*>* states;
1670 vector<const gchar*> item;
1671 string fullpath = *(*i);
1673 /* remove any trailing / */
1675 if (fullpath[fullpath.length()-1] == '/') {
1676 fullpath = fullpath.substr (0, fullpath.length()-1);
1679 /* now get available states for this session */
1681 if ((states = Session::possible_states (fullpath)) == 0) {
1682 /* no state file? */
1686 TreeModel::Row row = *(recent_session_model->append());
1688 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1689 row[recent_session_columns.fullpath] = fullpath;
1691 if (states->size() > 1) {
1693 /* add the children */
1695 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1697 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1699 child_row[recent_session_columns.visible_name] = **i2;
1700 child_row[recent_session_columns.fullpath] = fullpath;
1709 recent_session_display.set_model (recent_session_model);
1714 ARDOUR_UI::build_session_selector ()
1716 session_selector_window = new ArdourDialog ("session selector");
1718 Gtk::VBox *vpacker = manage (new Gtk::VBox);
1719 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1720 Gtk::HBox *button_packer = manage (new Gtk::HBox);
1721 Gtk::Button *cancel_button = manage (new Gtk::Button (_("cancel")));
1722 Gtk::Button *rescan_button = manage (new Gtk::Button (_("rescan")));
1724 button_packer->pack_start (*rescan_button);
1725 button_packer->pack_start (*cancel_button);
1727 vpacker->pack_start (*scroller);
1728 vpacker->pack_start (*button_packer, false, false);
1730 recent_session_model = TreeStore::create (recent_session_columns);
1731 recent_session_display.set_model (recent_session_model);
1732 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1733 recent_session_display.set_headers_visible (false);
1735 scroller->add (recent_session_display);
1736 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1738 session_selector_window->add (*vpacker);
1739 session_selector_window->set_name ("SessionSelectorWindow");
1740 session_selector_window->set_size_request (200, 400);
1744 ARDOUR_UI::open_recent_session ()
1746 /* popup selector window */
1748 if (session_selector_window == 0) {
1749 build_session_selector ();
1752 redisplay_recent_sessions ();
1754 session_selector_window->run ();
1757 switch (session_selector_window->run_status()) {
1765 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1767 if (i == recent_session_model->children().end()) {
1771 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1772 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1774 session_selector_window->response (RESPONSE_ACCEPT);
1775 _session_is_new = false;
1777 load_session (path, state);
1782 ARDOUR_UI::fs_cancel_clicked (Gtk::FileSelection* fs)
1785 fs->get_selection_entry()->set_text("");
1786 allow_focus (false);
1790 ARDOUR_UI::fs_delete_event (GdkEventAny* ev, Gtk::FileSelection* fs)
1792 fs_cancel_clicked (fs);
1797 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1799 struct stat statbuf;
1801 if (stat (info.filename.c_str(), &statbuf) != 0) {
1805 if (!S_ISDIR(statbuf.st_mode)) {
1809 string session_file = info.filename;
1810 session_file += '/';
1811 session_file += PBD::basename (info.filename);
1812 session_file += ".ardour";
1814 if (stat (session_file.c_str(), &statbuf) != 0) {
1818 return S_ISREG (statbuf.st_mode);
1822 ARDOUR_UI::open_session ()
1824 /* popup selector window */
1826 if (open_session_selector == 0) {
1827 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1828 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1829 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1831 FileFilter filter_ardour;
1832 filter_ardour.set_name (_("Ardour sessions"));
1833 filter_ardour.add_custom (FILE_FILTER_FILENAME, mem_fun (*this, &ARDOUR_UI::filter_ardour_session_dirs));
1835 open_session_selector->add_filter (filter_ardour);
1838 switch (open_session_selector->run ()) {
1845 string session_path = open_session_selector->get_filename();
1849 if (session_path.length() > 0) {
1850 if (Session::find_session (session_path, path, name, isnew) == 0) {
1851 _session_is_new = isnew;
1852 load_session (path, name);
1859 ARDOUR_UI::session_add_midi_track ()
1861 cerr << _("Patience is a virtue.\n");
1865 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1870 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1876 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1877 error << _("could not create new audio track") << endmsg;
1880 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1881 error << _("could not create new audio bus") << endmsg;
1886 if (need_control_room_outs) {
1892 route->set_stereo_control_outs (control_lr_channels);
1893 route->control_outs()->set_stereo_pan (pans, this);
1895 #endif /* CONTROLOUTS */
1899 ArdourMessage msg (editor, X_("noport dialog"),
1900 _("There are insufficient JACK ports available\n\
1901 to create a new track or bus.\n\
1902 You should save Ardour, exit and\n\
1903 restart JACK with more ports."));
1908 ARDOUR_UI::diskstream_added (DiskStream* ds)
1910 // meter_bridge_dialog_check->set_sensitive (true);
1914 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1916 jack_nframes_t _preroll;
1919 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1921 if (new_position > _preroll) {
1922 new_position -= _preroll;
1927 session->request_locate (new_position);
1932 ARDOUR_UI::transport_goto_start ()
1935 session->request_locate (0);
1938 /* force displayed area in editor to start no matter
1939 what "follow playhead" setting is.
1943 editor->reposition_x_origin (0);
1949 ARDOUR_UI::transport_goto_end ()
1952 jack_nframes_t frame = session->current_end_frame();
1953 session->request_locate (frame);
1955 /* force displayed area in editor to start no matter
1956 what "follow playhead" setting is.
1960 editor->reposition_x_origin (frame);
1966 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1971 if (session->transport_stopped()) {
1972 session->request_locate (session->last_transport_start());
1974 if (session->get_auto_loop()) {
1975 session->request_auto_loop (false);
1978 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1979 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1987 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1994 ARDOUR_UI::transport_stop ()
2000 if (session->is_auditioning()) {
2001 session->cancel_audition ();
2005 if (session->get_auto_loop()) {
2006 session->request_auto_loop (false);
2009 session->request_stop ();
2013 ARDOUR_UI::transport_stop_and_forget_capture ()
2016 session->request_stop (true);
2021 ARDOUR_UI::remove_last_capture()
2024 editor->remove_last_capture();
2029 ARDOUR_UI::transport_record ()
2032 switch (session->record_status()) {
2033 case Session::Disabled:
2034 if (session->ntracks() == 0) {
2035 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
2036 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2039 session->maybe_enable_record ();
2041 case Session::Recording:
2042 case Session::Enabled:
2043 session->disable_record ();
2049 ARDOUR_UI::transport_roll ()
2057 rolling = session->transport_rolling ();
2059 if (session->get_auto_loop()) {
2060 session->request_auto_loop (false);
2061 auto_loop_button.set_active (false);
2062 roll_button.set_active (true);
2063 } else if (session->get_play_range ()) {
2064 session->request_play_range (false);
2065 play_selection_button.set_active (false);
2066 } else if (rolling) {
2067 session->request_locate (session->last_transport_start(), true);
2070 session->request_transport_speed (1.0f);
2074 ARDOUR_UI::transport_loop()
2077 if (session->get_auto_loop()) {
2078 if (session->transport_rolling()) {
2079 Location * looploc = session->locations()->auto_loop_location();
2081 session->request_locate (looploc->start(), true);
2086 session->request_auto_loop (true);
2092 ARDOUR_UI::transport_play_selection ()
2098 if (!session->get_play_range()) {
2099 session->request_stop ();
2102 editor->play_selection ();
2106 ARDOUR_UI::transport_rewind (int option)
2108 float current_transport_speed;
2111 current_transport_speed = session->transport_speed();
2113 if (current_transport_speed >= 0.0f) {
2116 session->request_transport_speed (-1.0f);
2119 session->request_transport_speed (-4.0f);
2122 session->request_transport_speed (-0.5f);
2127 session->request_transport_speed (current_transport_speed * 1.5f);
2133 ARDOUR_UI::transport_forward (int option)
2135 float current_transport_speed;
2138 current_transport_speed = session->transport_speed();
2140 if (current_transport_speed <= 0.0f) {
2143 session->request_transport_speed (1.0f);
2146 session->request_transport_speed (4.0f);
2149 session->request_transport_speed (0.5f);
2154 session->request_transport_speed (current_transport_speed * 1.5f);
2160 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2168 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2169 Port *port = ds->io()->input (0);
2170 port->request_monitor_input (!port->monitoring_input());
2175 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2183 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2184 ds->set_record_enabled (!ds->record_enabled(), this);
2189 ARDOUR_UI::queue_transport_change ()
2191 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2195 ARDOUR_UI::map_transport_state ()
2197 float sp = session->transport_speed();
2200 transport_rolling ();
2201 } else if (sp < 0.0f) {
2202 transport_rewinding ();
2203 } else if (sp > 0.0f) {
2204 transport_forwarding ();
2206 transport_stopped ();
2211 ARDOUR_UI::send_all_midi_feedback ()
2214 session->send_all_midi_feedback();
2219 ARDOUR_UI::allow_local_only ()
2225 ARDOUR_UI::allow_mmc_only ()
2231 ARDOUR_UI::allow_mmc_and_local ()
2237 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2239 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2240 (int) adj.get_value()].c_str());
2244 ARDOUR_UI::engine_stopped ()
2246 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2248 jack_disconnect_item->set_sensitive (false);
2249 jack_reconnect_item->set_sensitive (true);
2250 jack_bufsize_menu->set_sensitive (false);
2255 ARDOUR_UI::engine_running ()
2257 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2259 jack_disconnect_item->set_sensitive (true);
2260 jack_reconnect_item->set_sensitive (false);
2261 jack_bufsize_menu->set_sensitive (true);
2265 ARDOUR_UI::engine_halted ()
2267 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2269 jack_disconnect_item->set_sensitive (false);
2270 jack_reconnect_item->set_sensitive (true);
2271 jack_bufsize_menu->set_sensitive (false);
2273 update_sample_rate (0);
2275 ArdourMessage msg (editor, X_("halted"),
2277 JACK has either been shutdown or it\n\
2278 disconnected Ardour because Ardour\n\
2279 was not fast enough. You can save the\n\
2280 session and/or try to reconnect to JACK ."));
2284 ARDOUR_UI::do_engine_start ()
2290 catch (AudioEngine::PortRegistrationFailure& err) {
2292 error << _("Unable to create all required ports")
2300 error << _("Unable to start the session running")
2310 ARDOUR_UI::start_engine ()
2312 if (do_engine_start () == 0) {
2313 if (session && _session_is_new) {
2314 /* we need to retain initial visual
2315 settings for a new session
2317 session->save_state ("");
2320 /* there is too much going on, in too many threads, for us to
2321 end up with a clean session. So wait 1 second after loading,
2322 and fix it up. its ugly, but until i come across a better
2323 solution, its what we have.
2326 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2333 ARDOUR_UI::update_clocks ()
2335 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2339 ARDOUR_UI::start_clocking ()
2341 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2345 ARDOUR_UI::stop_clocking ()
2347 clock_signal_connection.disconnect ();
2351 ARDOUR_UI::toggle_clocking ()
2354 if (clock_button.get_active()) {
2363 ARDOUR_UI::_blink (void *arg)
2366 ((ARDOUR_UI *) arg)->blink ();
2373 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2377 ARDOUR_UI::start_blinking ()
2379 /* Start the blink signal. Everybody with a blinking widget
2380 uses Blink to drive the widget's state.
2383 if (blink_timeout_tag < 0) {
2385 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2390 ARDOUR_UI::stop_blinking ()
2392 if (blink_timeout_tag >= 0) {
2393 gtk_timeout_remove (blink_timeout_tag);
2394 blink_timeout_tag = -1;
2400 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2402 using namespace Gtk;
2403 using namespace Menu_Helpers;
2405 if (dstream.hidden()) {
2409 MenuList& items = diskstream_menu->items();
2410 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2414 ARDOUR_UI::diskstream_selected (gint32 id)
2416 selected_dstream = id;
2421 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2423 using namespace Gtk;
2424 using namespace Menu_Helpers;
2430 diskstream_menu = new Menu();
2431 diskstream_menu->set_name ("ArdourContextMenu");
2432 using namespace Gtk;
2433 using namespace Menu_Helpers;
2435 MenuList& items = diskstream_menu->items();
2436 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2438 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2441 diskstream_menu->popup (ev->button, ev->time);
2443 diskstream_menu->popup (0, 0);
2446 selected_dstream = -1;
2450 delete diskstream_menu;
2452 return selected_dstream;
2456 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2462 if (io.n_inputs() == 0) {
2467 /* XXX we're not handling multiple ports yet. */
2469 const char **connections = io.input(0)->get_connections();
2471 if (connections == 0 || connections[0] == '\0') {
2474 buf = connections[0];
2481 if (io.n_outputs() == 0) {
2486 /* XXX we're not handling multiple ports yet. */
2488 const char **connections = io.output(0)->get_connections();
2490 if (connections == 0 || connections[0] == '\0') {
2493 buf = connections[0];
2501 ARDOUR_UI::snapshot_session ()
2503 ArdourPrompter prompter (true);
2510 now = now.substr (0, now.length() - 1);
2512 prompter.set_name ("Prompter");
2513 prompter.set_prompt (_("Name for snapshot"));
2514 prompter.set_initial_text (now);
2516 switch (prompter.run()) {
2517 case RESPONSE_ACCEPT:
2518 prompter.get_result (snapname);
2519 if (snapname.length()){
2520 save_state (snapname);
2530 ARDOUR_UI::save_state (string name)
2532 (void) save_state_canfail (name);
2536 ARDOUR_UI::save_state_canfail (string name)
2541 if (name.length() == 0) {
2542 name = session->snap_name();
2545 if ((ret = session->save_state (name)) != 0) {
2549 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2554 ARDOUR_UI::restore_state (string name)
2557 if (name.length() == 0) {
2558 name = session->name();
2560 session->restore_state (name);
2565 ARDOUR_UI::allow_focus (bool yn)
2568 keyboard->allow_focus (yn);
2573 ARDOUR_UI::primary_clock_value_changed ()
2576 session->request_locate (primary_clock.current_time ());
2581 ARDOUR_UI::secondary_clock_value_changed ()
2584 session->request_locate (secondary_clock.current_time ());
2589 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2591 if (session && dstream && dstream->record_enabled()) {
2593 Session::RecordState rs;
2595 rs = session->record_status ();
2598 case Session::Disabled:
2599 case Session::Enabled:
2600 if (w->get_state() != STATE_SELECTED) {
2601 w->set_state (STATE_SELECTED);
2605 case Session::Recording:
2606 if (w->get_state() != STATE_ACTIVE) {
2607 w->set_state (STATE_ACTIVE);
2613 if (w->get_state() != STATE_NORMAL) {
2614 w->set_state (STATE_NORMAL);
2620 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2626 switch (session->record_status()) {
2627 case Session::Enabled:
2629 rec_button.set_state (STATE_ACTIVE);
2631 rec_button.set_state (STATE_NORMAL);
2635 case Session::Recording:
2636 rec_button.set_state (STATE_ACTIVE);
2640 rec_button.set_active (false);
2641 rec_button.set_state (STATE_NORMAL);
2647 ARDOUR_UI::generic_focus_in_event (GdkEventFocus *ev)
2649 ARDOUR_UI::instance()->allow_focus (true);
2654 ARDOUR_UI::generic_focus_out_event (GdkEventFocus *ev)
2656 ARDOUR_UI::instance()->allow_focus (false);
2661 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2669 ARDOUR_UI::start_keyboard_prefix ()
2671 keyboard->start_prefix();
2675 ARDOUR_UI::save_template ()
2678 ArdourPrompter prompter (true);
2681 prompter.set_name (X_("Prompter"));
2682 prompter.set_prompt (_("Name for mix template:"));
2683 prompter.set_initial_text(session->name() + _("-template"));
2685 switch (prompter.run()) {
2686 case RESPONSE_ACCEPT:
2687 prompter.get_result (name);
2689 if (name.length()) {
2690 session->save_template (name);
2700 ARDOUR_UI::new_session (bool startup, string predetermined_path)
2702 if (new_session_window == 0){
2703 new_session_window = new NewSessionDialog (*engine, startup, predetermined_path);
2704 editor->ensure_float (*new_session_window);
2707 new_session_window->run ();
2712 /* write favorites either way */
2713 Session::FavoriteDirs favs;
2714 new_session_window->file_selector.get_favorites (favs);
2715 Session::write_favorite_dirs (favs);
2717 if (new_session_window->run_status()) {
2722 string session_path = new_session_window->file_selector.get_filename ();
2723 string session_name = PBD::basename (session_path);
2725 // Check that it doesn't already exist.
2726 access(session_path.c_str(), R_OK);
2727 if (errno != ENOENT){
2728 error << string_compose(_("Session %1 already exists at %2"), session_name, session_path) << endmsg;
2732 _session_is_new = true;
2734 if (session_path[session_path.length()-1] != '/') {
2736 string template_name = new_session_window->get_template_name ();
2738 if (template_name.length()) {
2740 load_session (session_path, session_name, &template_name);
2746 Session::AutoConnectOption iconnect;
2747 Session::AutoConnectOption oconnect;
2749 if (new_session_window->use_control_button.get_active()) {
2750 cchns = (uint32_t) channel_combo_get_channel_count (new_session_window->control_out_channel_combo);
2754 if (new_session_window->use_master_button.get_active()) {
2755 mchns = (uint32_t) channel_combo_get_channel_count (new_session_window->master_out_channel_combo);
2760 if (new_session_window->connect_to_physical_inputs_button.get_active()) {
2761 iconnect = Session::AutoConnectPhysical;
2763 iconnect = Session::AutoConnectOption (0);
2766 if (new_session_window->connect_to_master_button.get_active ()) {
2767 oconnect = Session::AutoConnectMaster;
2768 } else if (new_session_window->connect_to_physical_outputs_button.get_active ()) {
2769 oconnect = Session::AutoConnectPhysical;
2771 oconnect = Session::AutoConnectOption (0);
2774 uint32_t nphysin = (uint32_t) new_session_window->in_count_adjustment.get_value();
2775 uint32_t nphysout = (uint32_t) new_session_window->out_count_adjustment.get_value();
2777 build_session (session_path, session_name, cchns, mchns, iconnect, oconnect, nphysin, nphysout,
2778 engine->frame_rate() * 60 * 5);
2784 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2786 Session *new_session;
2788 session_loaded = false;
2789 x = unload_session ();
2797 /* if it already exists, we must have write access */
2799 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2800 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2801 You do not have write access to this session.\n\
2802 This prevents the session from being loaded."));
2807 new_session = new Session (*engine, path, snap_name, mix_template);
2812 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2816 connect_to_session (new_session);
2818 //if (engine->running()) {
2819 //mixer->show_window();
2821 session_loaded = true;
2826 ARDOUR_UI::make_session_clean ()
2829 session->set_clean ();
2836 ARDOUR_UI::build_session (string path, string snap_name,
2837 uint32_t control_channels,
2838 uint32_t master_channels,
2839 Session::AutoConnectOption input_connect,
2840 Session::AutoConnectOption output_connect,
2843 jack_nframes_t initial_length)
2845 Session *new_session;
2848 session_loaded = false;
2849 x = unload_session ();
2856 _session_is_new = true;
2859 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2860 control_channels, master_channels, nphysin, nphysout, initial_length);
2865 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2869 connect_to_session (new_session);
2871 //if (engine->running()) {
2872 //mixer->show_window();
2874 session_loaded = true;
2879 ARDOUR_UI::hide_dialog (ArdourDialog *dialog)
2888 editor->show_window ();
2892 if (session && mixer) {
2893 mixer->show_window ();
2902 ARDOUR_UI::show_splash ()
2905 about = new About();
2911 ARDOUR_UI::hide_splash ()
2919 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2923 removed = rep.paths.size();
2926 ArdourMessage msg (editor, X_("cleanupresults"),
2928 No audio files were ready for cleanup\n\n\
2929 If this seems suprising, check for any existing\n\
2930 snapshots. These may still include regions that\n\
2931 require some unused files to continue to exist."));
2935 ArdourDialog results ("cleanup results");
2937 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2938 CleanupResultsModelColumns() {
2942 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2943 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2947 Glib::RefPtr<Gtk::ListStore> results_model;
2948 CleanupResultsModelColumns results_columns;
2949 Gtk::TreeView results_display;
2951 results_model = ListStore::create (results_columns);
2952 results_display.set_model (results_model);
2953 results_display.append_column (list_title, results_columns.visible_name);
2954 results_display.set_headers_visible (true);
2956 Gtk::ScrolledWindow list_scroller;
2958 Gtk::Button ok_button (_("OK"));
2961 vpacker.set_border_width (10);
2962 vpacker.set_spacing (10);
2964 if (rep.space < 1048576.0f) {
2966 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2968 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2972 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2974 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2978 vpacker.pack_start (txt, false, false);
2980 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2981 TreeModel::Row row = *(results_model->append());
2982 row[results_columns.visible_name] = *i;
2983 row[results_columns.fullpath] = *i;
2986 list_scroller.add (results_display);
2987 list_scroller.set_size_request (-1, 250);
2988 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2990 vpacker.pack_start (list_scroller, true, true);
2991 vpacker.pack_start (ok_button, false, false);
2993 results.add (vpacker);
2995 results.set_position (Gtk::WIN_POS_MOUSE);
2996 results.set_title (_("ardour: cleanup"));
2997 results.set_modal (true);
3003 ARDOUR_UI::cleanup ()
3006 /* shouldn't happen: menu item is insensitive */
3010 ArdourDialog checker (X_("cleanup confirm dialog"));
3011 Gtk::Label label (_("\
3012 Cleanup is a destructive operation.\n\
3013 ALL undo/redo information will be lost if you cleanup.\n\
3014 Unused audio files will be moved to a \"dead sounds\" location."));
3016 Gtk::Button ok_button (_("Proceed with cleanup"));
3017 Gtk::Button cancel_button (_("Cancel"));
3021 bbox.set_border_width (6);
3022 bbox.set_spacing (12);
3023 bbox.pack_start (ok_button, true, false);
3024 bbox.pack_start (cancel_button, true, false);
3026 vbox.set_border_width (6);
3027 vbox.set_spacing (12);
3028 vbox.pack_start (label, false, false);
3029 vbox.pack_start (bbox, false, false);
3032 checker.set_name (_("CleanupDialog"));
3033 checker.set_title (_("ardour cleanup"));
3034 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
3035 checker.set_position (Gtk::WIN_POS_MOUSE);
3037 ok_button.signal_clicked().connect (bind (mem_fun (checker, &ArdourDialog::stop), 1));
3038 cancel_button.signal_clicked().connect (bind (mem_fun (checker, &ArdourDialog::stop), 0));
3042 switch (checker.run_status()) {
3049 Session::cleanup_report rep;
3051 editor->prepare_for_cleanup ();
3053 if (session->cleanup_sources (rep)) {
3057 display_cleanup_results (rep,
3060 The following %1 %2 were not in use.\n\
3061 The next time you flush the wastebasket\n\
3062 it will release an additional %3 %4bytes\n\
3068 ARDOUR_UI::flush_trash ()
3071 /* shouldn't happen: menu item is insensitive */
3075 Session::cleanup_report rep;
3077 if (session->cleanup_trash_sources (rep)) {
3081 display_cleanup_results (rep,
3083 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
3087 ARDOUR_UI::add_route ()
3095 if (add_route_dialog == 0) {
3096 add_route_dialog = new AddRouteDialog;
3097 editor->ensure_float (*add_route_dialog);
3100 if (add_route_dialog->is_visible()) {
3101 /* we're already doing this */
3105 add_route_dialog->run ();
3107 if (add_route_dialog->run_status()) {
3111 if ((count = add_route_dialog->count()) <= 0) {
3115 uint32_t input_chan = add_route_dialog->channels ();
3116 uint32_t output_chan;
3117 string name_template = add_route_dialog->name_template ();
3118 bool track = add_route_dialog->track ();
3120 Session::AutoConnectOption oac = session->get_output_auto_connect();
3122 if (oac & Session::AutoConnectMaster) {
3123 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3125 output_chan = input_chan;
3128 /* XXX do something with name template */
3132 session_add_audio_track (input_chan, output_chan);
3134 session_add_audio_bus (input_chan, output_chan);
3138 while (Main::events_pending()) {
3145 ARDOUR_UI::mixer_settings () const
3150 node = session->instant_xml(X_("Mixer"), session->path());
3152 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3156 node = new XMLNode (X_("Mixer"));
3163 ARDOUR_UI::editor_settings () const
3168 node = session->instant_xml(X_("Editor"), session->path());
3170 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3174 node = new XMLNode (X_("Editor"));
3180 ARDOUR_UI::keyboard_settings () const
3184 node = Config->extra_xml(X_("Keyboard"));
3187 node = new XMLNode (X_("Keyboard"));
3193 ARDOUR_UI::halt_on_xrun_message ()
3195 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3197 ArdourMessage msg (editor, X_("haltonxrun"),
3198 _("Recording was stopped because your system could not keep up."));
3202 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3204 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3206 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3210 delete deletion_list;
3214 ARDOUR_UI::disk_overrun_handler ()
3216 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3218 if (!have_disk_overrun_displayed) {
3219 have_disk_overrun_displayed = true;
3220 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3221 The disk system on your computer\n\
3222 was not able to keep up with Ardour.\n\
3224 Specifically, it failed to write data to disk\n\
3225 quickly enough to keep up with recording.\n"));
3226 have_disk_overrun_displayed = false;
3231 ARDOUR_UI::disk_underrun_handler ()
3233 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3235 if (!have_disk_underrun_displayed) {
3236 have_disk_underrun_displayed = true;
3237 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3238 (_("The disk system on your computer\n\
3239 was not able to keep up with Ardour.\n\
3241 Specifically, it failed to read data from disk\n\
3242 quickly enough to keep up with playback.\n")));
3243 have_disk_underrun_displayed = false;
3248 ARDOUR_UI::disk_underrun_message_gone ()
3250 have_disk_underrun_displayed = false;
3254 ARDOUR_UI::disk_overrun_message_gone ()
3256 have_disk_underrun_displayed = false;
3260 ARDOUR_UI::pending_state_dialog ()
3262 ArdourDialog dialog ("pending state dialog");
3263 Button use_button (_("Recover from crash"));
3264 Button cancel_button (_("Ignore crash data"));
3266 This session appears to have been in\n\
3267 middle of recording when ardour or\n\
3268 the computer was shutdown.\n\
3270 Ardour can recover any captured audio for\n\
3271 you, or it can ignore it. Please decide\n\
3272 what you would like to do.\n"));
3276 vpacker.set_border_width (12);
3277 vpacker.set_spacing (7);
3278 vpacker.pack_start (message);
3279 vpacker.pack_start (hpacker);
3281 hpacker.set_spacing (7);
3282 hpacker.pack_start (use_button);
3283 hpacker.pack_start (cancel_button);
3285 use_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
3286 cancel_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
3288 dialog.add (vpacker);
3289 dialog.set_position (WIN_POS_CENTER);
3294 if (dialog.run_status () != 0) {
3303 ARDOUR_UI::disconnect_from_jack ()
3306 if( engine->disconnect_from_jack ()) {
3307 ArdourMessage msg (editor, X_("nojack dialog"),
3308 _("Could not disconnect from JACK"));
3311 update_sample_rate (0);
3316 ARDOUR_UI::reconnect_to_jack ()
3319 if (engine->reconnect_to_jack ()) {
3320 ArdourMessage msg (editor, X_("nojack dialog"),
3321 _("Could not reconnect to JACK"));
3324 update_sample_rate (0);
3329 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3331 engine->request_buffer_size (nframes);
3332 update_sample_rate (0);
3336 ARDOUR_UI::cmdline_new_session (string path)
3338 if (path[0] != '/') {
3339 char buf[PATH_MAX+1];
3342 getcwd (buf, sizeof (buf));
3349 new_session (false, path);
3351 _will_create_new_session_automatically = false; /* done it */
3352 return FALSE; /* don't call it again */