2 Copyright (C) 1999-2007 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.
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
39 #include <pbd/basename.h>
40 #include <pbd/compose.h>
41 #include <pbd/pathscanner.h>
42 #include <pbd/failed_constructor.h>
43 #include <pbd/enumwriter.h>
44 #include <pbd/stacktrace.h>
45 #include <gtkmm2ext/gtk_ui.h>
46 #include <gtkmm2ext/utils.h>
47 #include <gtkmm2ext/click_box.h>
48 #include <gtkmm2ext/fastmeter.h>
49 #include <gtkmm2ext/stop_signal.h>
50 #include <gtkmm2ext/popup.h>
51 #include <gtkmm2ext/window_title.h>
53 #include <midi++/port.h>
54 #include <midi++/mmc.h>
56 #include <ardour/ardour.h>
57 #include <ardour/profile.h>
58 #include <ardour/session_route.h>
59 #include <ardour/port.h>
60 #include <ardour/audioengine.h>
61 #include <ardour/playlist.h>
62 #include <ardour/utils.h>
63 #include <ardour/plugin.h>
64 #include <ardour/audio_diskstream.h>
65 #include <ardour/audiofilesource.h>
66 #include <ardour/recent_sessions.h>
67 #include <ardour/port.h>
68 #include <ardour/audio_track.h>
69 #include <ardour/control_protocol_manager.h>
71 typedef uint64_t microseconds_t
;
74 #include "ardour_ui.h"
75 #include "public_editor.h"
76 #include "audio_clock.h"
81 #include "add_route_dialog.h"
82 #include "new_session_dialog.h"
87 #include "gui_thread.h"
88 #include "theme_manager.h"
89 #include "engine_dialog.h"
90 #include "gain_meter.h"
91 #include "route_time_axis.h"
95 using namespace ARDOUR
;
97 using namespace Gtkmm2ext
;
101 ARDOUR_UI
*ARDOUR_UI::theArdourUI
= 0;
102 UIConfiguration
*ARDOUR_UI::ui_config
= 0;
104 sigc::signal
<void,bool> ARDOUR_UI::Blink
;
105 sigc::signal
<void> ARDOUR_UI::RapidScreenUpdate
;
106 sigc::signal
<void> ARDOUR_UI::SuperRapidScreenUpdate
;
107 sigc::signal
<void,nframes_t
, bool, nframes_t
> ARDOUR_UI::Clock
;
109 ARDOUR_UI::ARDOUR_UI (int *argcp
, char **argvp
[])
111 : Gtkmm2ext::UI (PROGRAM_NAME
, argcp
, argvp
),
113 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
114 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
115 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
116 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
120 preroll_button (_("pre\nroll")),
121 postroll_button (_("post\nroll")),
125 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
129 roll_controllable ("transport roll", *this, TransportControllable::Roll
),
130 stop_controllable ("transport stop", *this, TransportControllable::Stop
),
131 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart
),
132 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd
),
133 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop
),
134 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection
),
135 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable
),
136 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl
),
137 shuttle_controller_binding_proxy (shuttle_controllable
),
139 roll_button (&roll_controllable
),
140 stop_button (&stop_controllable
),
141 goto_start_button (&goto_start_controllable
),
142 goto_end_button (&goto_end_controllable
),
143 auto_loop_button (&auto_loop_controllable
),
144 play_selection_button (&play_selection_controllable
),
145 rec_button (&rec_controllable
),
147 shuttle_units_button (_("% ")),
149 punch_in_button (_("Punch In")),
150 punch_out_button (_("Punch Out")),
151 auto_return_button (_("Auto Return")),
152 auto_play_button (_("Auto Play")),
153 auto_input_button (_("Auto Input")),
154 click_button (_("Click")),
155 time_master_button (_("time\nmaster")),
157 auditioning_alert_button (_("AUDITION")),
158 solo_alert_button (_("SOLO")),
160 error_log_button (_("Errors"))
162 using namespace Gtk::Menu_Helpers
;
167 _auto_display_errors
= false;
173 if (ARDOUR_COMMAND_LINE::session_name
.length()) {
174 /* only show this if we're not going to post the new session dialog */
178 if (theArdourUI
== 0) {
182 ui_config
= new UIConfiguration();
183 theme_manager
= new ThemeManager();
189 _session_is_new
= false;
190 big_clock_window
= 0;
191 session_selector_window
= 0;
192 new_session_dialog
= 0;
193 last_key_press_time
= 0;
194 connection_editor
= 0;
195 add_route_dialog
= 0;
200 open_session_selector
= 0;
201 have_configure_timeout
= false;
202 have_disk_speed_dialog_displayed
= false;
203 _will_create_new_session_automatically
= false;
204 session_loaded
= false;
205 last_speed_displayed
= -1.0f
;
206 ignore_dual_punch
= false;
207 _mixer_on_top
= false;
209 roll_button
.unset_flags (Gtk::CAN_FOCUS
);
210 stop_button
.unset_flags (Gtk::CAN_FOCUS
);
211 goto_start_button
.unset_flags (Gtk::CAN_FOCUS
);
212 goto_end_button
.unset_flags (Gtk::CAN_FOCUS
);
213 auto_loop_button
.unset_flags (Gtk::CAN_FOCUS
);
214 play_selection_button
.unset_flags (Gtk::CAN_FOCUS
);
215 rec_button
.unset_flags (Gtk::CAN_FOCUS
);
217 last_configure_time
= 0;
219 shuttle_grabbed
= false;
221 shuttle_max_speed
= 8.0f
;
223 shuttle_style_menu
= 0;
224 shuttle_unit_menu
= 0;
226 // We do not have jack linked in yet so;
228 last_shuttle_request
= last_peak_grab
= 0; // get_microseconds();
230 ARDOUR::Diskstream::DiskOverrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
231 ARDOUR::Diskstream::DiskUnderrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
233 ARDOUR::Plugin::PresetFileExists
.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler
));
235 /* handle dialog requests */
237 ARDOUR::Session::Dialog
.connect (mem_fun(*this, &ARDOUR_UI::session_dialog
));
239 /* handle pending state with a dialog */
241 ARDOUR::Session::AskAboutPendingState
.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog
));
243 /* handle sr mismatch with a dialog */
245 ARDOUR::Session::AskAboutSampleRateMismatch
.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog
));
247 /* lets get this party started */
250 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst
, ARDOUR_COMMAND_LINE::try_hw_optimization
)) {
251 throw failed_constructor ();
254 setup_gtk_ardour_enums ();
255 Config
->set_current_owner (ConfigVariableBase::Interface
);
258 GainMeter::setup_slider_pix ();
259 RouteTimeAxisView::setup_slider_pix ();
261 } catch (failed_constructor
& err
) {
262 error
<< string_compose (_("could not initialize %1."), PROGRAM_NAME
) << endmsg
;
267 /* we like keyboards */
269 keyboard
= new Keyboard
;
273 starting
.connect (mem_fun(*this, &ARDOUR_UI::startup
));
274 stopping
.connect (mem_fun(*this, &ARDOUR_UI::shutdown
));
280 ARDOUR_UI::create_engine ()
282 // this gets called every time by new_session()
288 loading_message (_("Starting audio engine"));
291 engine
= new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name
);
298 engine
->Stopped
.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
299 engine
->Running
.connect (mem_fun(*this, &ARDOUR_UI::engine_running
));
300 engine
->Halted
.connect (bind (mem_fun(*this, &ARDOUR_UI::engine_halted
), false));
301 engine
->SampleRateChanged
.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate
));
309 ARDOUR_UI::post_engine ()
311 /* Things to be done once we create the AudioEngine
314 check_memory_locking();
316 ActionManager::init ();
319 if (setup_windows ()) {
320 throw failed_constructor ();
323 /* this is the first point at which all the keybindings are available */
325 if (ARDOUR_COMMAND_LINE::show_key_actions
) {
326 vector
<string
> names
;
327 vector
<string
> paths
;
329 vector
<AccelKey
> bindings
;
331 ActionManager::get_all_actions (names
, paths
, keys
, bindings
);
333 vector
<string
>::iterator n
;
334 vector
<string
>::iterator k
;
335 for (n
= names
.begin(), k
= keys
.begin(); n
!= names
.end(); ++n
, ++k
) {
336 cerr
<< "Action: " << (*n
) << " bound to " << (*k
) << endl
;
342 blink_timeout_tag
= -1;
344 /* the global configuration object is now valid */
348 /* this being a GUI and all, we want peakfiles */
350 AudioFileSource::set_build_peakfiles (true);
351 AudioFileSource::set_build_missing_peakfiles (true);
353 /* set default clock modes */
355 if (Profile
->get_sae()) {
356 primary_clock
.set_mode (AudioClock::BBT
);
357 secondary_clock
.set_mode (AudioClock::MinSec
);
359 primary_clock
.set_mode (AudioClock::SMPTE
);
360 secondary_clock
.set_mode (AudioClock::BBT
);
363 /* start the time-of-day-clock */
366 /* OS X provides an always visible wallclock, so don't be stupid */
367 update_wall_clock ();
368 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock
), 60000);
371 update_disk_space ();
373 update_sample_rate (engine
->frame_rate());
375 platform_specific ();
377 /* now start and maybe save state */
379 if (do_engine_start () == 0) {
380 if (session
&& _session_is_new
) {
381 /* we need to retain initial visual
382 settings for a new session
384 session
->save_state ("");
389 ARDOUR_UI::~ARDOUR_UI ()
391 save_ardour_state ();
405 if (add_route_dialog
) {
406 delete add_route_dialog
;
409 if (new_session_dialog
) {
410 delete new_session_dialog
;
415 ARDOUR_UI::pop_back_splash ()
417 if (Splash::instance()) {
418 // Splash::instance()->pop_back();
419 Splash::instance()->hide ();
424 ARDOUR_UI::configure_timeout ()
426 if (last_configure_time
== 0) {
427 /* no configure events yet */
431 /* force a gap of 0.5 seconds since the last configure event
434 if (get_microseconds() - last_configure_time
< 500000) {
437 have_configure_timeout
= false;
438 save_ardour_state ();
444 ARDOUR_UI::configure_handler (GdkEventConfigure
* conf
)
446 if (have_configure_timeout
) {
447 last_configure_time
= get_microseconds();
449 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout
), 100);
450 have_configure_timeout
= true;
457 ARDOUR_UI::set_transport_controllable_state (const XMLNode
& node
)
459 const XMLProperty
* prop
;
461 if ((prop
= node
.property ("roll")) != 0) {
462 roll_controllable
.set_id (prop
->value());
464 if ((prop
= node
.property ("stop")) != 0) {
465 stop_controllable
.set_id (prop
->value());
467 if ((prop
= node
.property ("goto_start")) != 0) {
468 goto_start_controllable
.set_id (prop
->value());
470 if ((prop
= node
.property ("goto_end")) != 0) {
471 goto_end_controllable
.set_id (prop
->value());
473 if ((prop
= node
.property ("auto_loop")) != 0) {
474 auto_loop_controllable
.set_id (prop
->value());
476 if ((prop
= node
.property ("play_selection")) != 0) {
477 play_selection_controllable
.set_id (prop
->value());
479 if ((prop
= node
.property ("rec")) != 0) {
480 rec_controllable
.set_id (prop
->value());
482 if ((prop
= node
.property ("shuttle")) != 0) {
483 shuttle_controllable
.set_id (prop
->value());
488 ARDOUR_UI::get_transport_controllable_state ()
490 XMLNode
* node
= new XMLNode(X_("TransportControllables"));
493 roll_controllable
.id().print (buf
, sizeof (buf
));
494 node
->add_property (X_("roll"), buf
);
495 stop_controllable
.id().print (buf
, sizeof (buf
));
496 node
->add_property (X_("stop"), buf
);
497 goto_start_controllable
.id().print (buf
, sizeof (buf
));
498 node
->add_property (X_("goto_start"), buf
);
499 goto_end_controllable
.id().print (buf
, sizeof (buf
));
500 node
->add_property (X_("goto_end"), buf
);
501 auto_loop_controllable
.id().print (buf
, sizeof (buf
));
502 node
->add_property (X_("auto_loop"), buf
);
503 play_selection_controllable
.id().print (buf
, sizeof (buf
));
504 node
->add_property (X_("play_selection"), buf
);
505 rec_controllable
.id().print (buf
, sizeof (buf
));
506 node
->add_property (X_("rec"), buf
);
507 shuttle_controllable
.id().print (buf
, sizeof (buf
));
508 node
->add_property (X_("shuttle"), buf
);
514 ARDOUR_UI::save_ardour_state ()
516 if (!keyboard
|| !mixer
|| !editor
) {
520 /* XXX this is all a bit dubious. add_extra_xml() uses
521 a different lifetime model from add_instant_xml().
524 XMLNode
* node
= new XMLNode (keyboard
->get_state());
525 Config
->add_extra_xml (*node
);
526 Config
->add_extra_xml (get_transport_controllable_state());
527 if (new_session_dialog
) {
528 if (new_session_dialog
->engine_control
.was_used()) {
529 Config
->add_extra_xml (new_session_dialog
->engine_control
.get_state());
532 Config
->save_state();
533 ui_config
->save_state ();
535 XMLNode
enode(static_cast<Stateful
*>(editor
)->get_state());
536 XMLNode
mnode(mixer
->get_state());
539 session
->add_instant_xml (enode
, session
->path());
540 session
->add_instant_xml (mnode
, session
->path());
542 Config
->add_instant_xml (enode
, get_user_ardour_path());
543 Config
->add_instant_xml (mnode
, get_user_ardour_path());
546 Keyboard::save_keybindings ();
550 ARDOUR_UI::autosave_session ()
552 if (g_main_depth() > 1) {
553 /* inside a recursive main loop,
554 give up because we may not be able to
560 if (!Config
->get_periodic_safety_backups())
564 session
->maybe_write_autosave();
571 ARDOUR_UI::update_autosave ()
573 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave
));
575 if (session
&& session
->dirty()) {
576 if (_autosave_connection
.connected()) {
577 _autosave_connection
.disconnect();
580 _autosave_connection
= Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session
),
581 Config
->get_periodic_safety_backup_interval() * 1000);
584 if (_autosave_connection
.connected()) {
585 _autosave_connection
.disconnect();
591 ARDOUR_UI::backend_audio_error (bool we_set_params
, Gtk::Window
* toplevel
)
595 title
= string_compose (_("%1 could not start JACK"), PROGRAM_NAME
);
597 title
= string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME
);
600 MessageDialog
win (title
,
606 win
.set_secondary_text(_("There are several possible reasons:\n\
608 1) You requested audio parameters that are not supported..\n\
609 2) JACK is running as another user.\n\
611 Please consider the possibilities, and perhaps try different parameters."));
613 win
.set_secondary_text(_("There are several possible reasons:\n\
615 1) JACK is not running.\n\
616 2) JACK is running as another user, perhaps root.\n\
617 3) There is already another client called \"ardour\".\n\
619 Please consider the possibilities, and perhaps (re)start JACK."));
623 win
.set_transient_for (*toplevel
);
627 win
.add_button (Stock::OK
, RESPONSE_CLOSE
);
629 win
.add_button (Stock::QUIT
, RESPONSE_CLOSE
);
632 win
.set_default_response (RESPONSE_CLOSE
);
635 win
.set_position (Gtk::WIN_POS_CENTER
);
638 /* we just don't care about the result, but we want to block */
644 ARDOUR_UI::startup ()
648 new_session_dialog
= new NewSessionDialog();
650 bool backend_audio_is_running
= EngineControl::engine_running();
651 XMLNode
* audio_setup
= Config
->extra_xml ("AudioSetup");
654 new_session_dialog
->engine_control
.set_state (*audio_setup
);
657 if (!get_session_parameters (backend_audio_is_running
, ARDOUR_COMMAND_LINE::new_session
)) {
661 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME
));
666 ARDOUR_UI::no_memory_warning ()
668 XMLNode
node (X_("no-memory-warning"));
669 Config
->add_instant_xml (node
, get_user_ardour_path());
673 ARDOUR_UI::check_memory_locking ()
676 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
680 XMLNode
* memory_warning_node
= Config
->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
682 if (engine
->is_realtime() && memory_warning_node
== 0) {
684 struct rlimit limits
;
686 long pages
, page_size
;
688 if ((page_size
= sysconf (_SC_PAGESIZE
)) < 0 ||(pages
= sysconf (_SC_PHYS_PAGES
)) < 0) {
691 ram
= (int64_t) pages
* (int64_t) page_size
;
694 if (getrlimit (RLIMIT_MEMLOCK
, &limits
)) {
698 if (limits
.rlim_cur
!= RLIM_INFINITY
) {
700 if (ram
== 0 || ((double) limits
.rlim_cur
/ ram
) < 0.75) {
703 MessageDialog
msg (string_compose (_("WARNING: Your system has a limit for maximum amount of locked memory. "
704 "This might cause %1 to run out of memory before your system "
705 "runs out of memory. \n\n"
706 "You can view the memory limit with 'ulimit -l', "
707 "and it is normally controlled by /etc/security/limits.conf"), PROGRAM_NAME
));
709 VBox
* vbox
= msg
.get_vbox();
711 CheckButton
cb (_("Do not show this window again"));
713 cb
.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning
));
715 hbox
.pack_start (cb
, true, false);
716 vbox
->pack_start (hbox
);
729 ARDOUR_UI::queue_finish ()
731 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish
));
735 ARDOUR_UI::idle_finish ()
738 return false; /* do not call again */
748 while (session
->transport_rolling() && (++tries
< 8)) {
749 /* stop but do not abort capture */
750 session
->request_stop (false, true);
754 if (session
->dirty()) {
755 switch (ask_about_saving_session(_("quit"))) {
760 /* use the default name */
761 if (save_state_canfail ("")) {
762 /* failed - don't quit */
763 MessageDialog
msg (*editor
,
765 Ardour was unable to save your session.\n\n\
766 If you still wish to quit, please use the\n\n\
767 \"Just quit\" option."));
778 session
->set_clean();
779 session
->set_deletion_in_progress ();
780 unload_session(true);
783 ArdourDialog::close_all_dialogs ();
785 save_ardour_state ();
790 ARDOUR_UI::ask_about_saving_session (const string
& what
)
792 ArdourDialog
window (_("ardour: save session?"));
793 Gtk::HBox dhbox
; // the hbox for the image and text
794 Gtk::Label prompt_label
;
795 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_WARNING
, Gtk::ICON_SIZE_DIALOG
));
799 msg
= string_compose(_("Don't %1"), what
);
800 window
.add_button (msg
, RESPONSE_REJECT
);
801 msg
= string_compose(_("Just %1"), what
);
802 window
.add_button (msg
, RESPONSE_APPLY
);
803 msg
= string_compose(_("Save and %1"), what
);
804 window
.add_button (msg
, RESPONSE_ACCEPT
);
806 window
.set_default_response (RESPONSE_ACCEPT
);
808 Gtk::Button
noquit_button (msg
);
809 noquit_button
.set_name ("EditorGTKButton");
814 if (session
->snap_name() == session
->name()) {
817 type
= _("snapshot");
819 prompt
= string_compose(_("The %1\"%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?"),
820 type
, session
->snap_name());
822 prompt_label
.set_text (prompt
);
823 prompt_label
.set_name (X_("PrompterLabel"));
824 prompt_label
.set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
826 dimage
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
)
828 dhbox
.set_homogeneous (false);
829 dhbox
.pack_start (*dimage
, false, false, 5);
830 dhbox
.pack_start (prompt_label
, true, false, 5);
831 window
.get_vbox()->pack_start (dhbox
);
833 window
.set_name (_("Prompter"));
834 window
.set_position (Gtk::WIN_POS_MOUSE
);
835 window
.set_modal (true);
836 window
.set_resizable (false);
839 window
.set_keep_above (true);
842 ResponseType r
= (ResponseType
) window
.run();
847 case RESPONSE_ACCEPT
: // save and get out of here
849 case RESPONSE_APPLY
: // get out of here
859 ARDOUR_UI::every_second ()
862 update_buffer_load ();
863 update_disk_space ();
868 ARDOUR_UI::every_point_one_seconds ()
870 update_speed_display ();
871 RapidScreenUpdate(); /* EMIT_SIGNAL */
876 ARDOUR_UI::every_point_zero_one_seconds ()
878 // august 2007: actual update frequency: 40Hz, not 100Hz
880 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
885 ARDOUR_UI::update_sample_rate (nframes_t ignored
)
889 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate
), ignored
));
891 if (!engine
->connected()) {
893 snprintf (buf
, sizeof (buf
), _("disconnected"));
897 nframes_t rate
= engine
->frame_rate();
899 if (fmod (rate
, 1000.0) != 0.0) {
900 snprintf (buf
, sizeof (buf
), _("%.1f kHz / %4.1f ms"),
901 (float) rate
/1000.0f
,
902 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
904 snprintf (buf
, sizeof (buf
), _("%u kHz / %4.1f ms"),
906 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
910 sample_rate_label
.set_text (buf
);
914 ARDOUR_UI::update_cpu_load ()
917 snprintf (buf
, sizeof (buf
), _("DSP: %5.1f%%"), engine
->get_cpu_load());
918 cpu_load_label
.set_text (buf
);
922 ARDOUR_UI::update_buffer_load ()
928 c
= session
->capture_load ();
929 p
= session
->playback_load ();
931 snprintf (buf
, sizeof (buf
), _("Buffers p:%" PRIu32
"%% c:%" PRIu32
"%%"),
932 session
->playback_load(), session
->capture_load());
933 buffer_load_label
.set_text (buf
);
935 buffer_load_label
.set_text ("");
940 ARDOUR_UI::count_recenabled_streams (Route
& route
)
942 Track
* track
= dynamic_cast<Track
*>(&route
);
943 if (track
&& track
->diskstream()->record_enabled()) {
944 rec_enabled_streams
+= track
->n_inputs();
949 ARDOUR_UI::update_disk_space()
955 nframes_t frames
= session
->available_capture_duration();
958 if (frames
== max_frames
) {
959 strcpy (buf
, _("Disk: 24hrs+"));
964 nframes_t fr
= session
->frame_rate();
966 rec_enabled_streams
= 0;
967 session
->foreach_route (this, &ARDOUR_UI::count_recenabled_streams
);
969 if (rec_enabled_streams
) {
970 frames
/= rec_enabled_streams
;
973 hrs
= frames
/ (fr
* 3600);
974 frames
-= hrs
* fr
* 3600;
975 mins
= frames
/ (fr
* 60);
976 frames
-= mins
* fr
* 60;
979 snprintf (buf
, sizeof(buf
), _("Disk: %02dh:%02dm:%02ds"), hrs
, mins
, secs
);
982 disk_space_label
.set_text (buf
);
986 ARDOUR_UI::update_wall_clock ()
993 tm_now
= localtime (&now
);
995 sprintf (buf
, "%02d:%02d", tm_now
->tm_hour
, tm_now
->tm_min
);
996 wall_clock_label
.set_text (buf
);
1002 ARDOUR_UI::session_menu (GdkEventButton
*ev
)
1004 session_popup_menu
->popup (0, 0);
1009 ARDOUR_UI::redisplay_recent_sessions ()
1011 vector
<string
*> *sessions
;
1012 vector
<string
*>::iterator i
;
1013 RecentSessionsSorter cmp
;
1015 recent_session_display
.set_model (Glib::RefPtr
<TreeModel
>(0));
1016 recent_session_model
->clear ();
1019 ARDOUR::read_recent_sessions (rs
);
1022 recent_session_display
.set_model (recent_session_model
);
1026 /* sort them alphabetically */
1027 sort (rs
.begin(), rs
.end(), cmp
);
1028 sessions
= new vector
<string
*>;
1030 for (RecentSessions::iterator i
= rs
.begin(); i
!= rs
.end(); ++i
) {
1031 sessions
->push_back (new string ((*i
).second
));
1034 for (i
= sessions
->begin(); i
!= sessions
->end(); ++i
) {
1036 vector
<string
*>* states
;
1037 vector
<const gchar
*> item
;
1038 string fullpath
= *(*i
);
1040 /* remove any trailing / */
1042 if (fullpath
[fullpath
.length()-1] == G_DIR_SEPARATOR
) {
1043 fullpath
= fullpath
.substr (0, fullpath
.length()-1);
1046 /* check whether session still exists */
1047 if (!Glib::file_test(fullpath
.c_str(), Glib::FILE_TEST_EXISTS
)) {
1048 /* session doesn't exist */
1049 cerr
<< "skipping non-existent session " << fullpath
<< endl
;
1053 /* now get available states for this session */
1055 if ((states
= Session::possible_states (fullpath
)) == 0) {
1056 /* no state file? */
1060 TreeModel::Row row
= *(recent_session_model
->append());
1062 row
[recent_session_columns
.visible_name
] = Glib::path_get_basename (fullpath
);
1063 row
[recent_session_columns
.fullpath
] = fullpath
;
1065 if (states
->size() > 1) {
1067 /* add the children */
1069 for (vector
<string
*>::iterator i2
= states
->begin(); i2
!= states
->end(); ++i2
) {
1071 TreeModel::Row child_row
= *(recent_session_model
->append (row
.children()));
1073 child_row
[recent_session_columns
.visible_name
] = **i2
;
1074 child_row
[recent_session_columns
.fullpath
] = fullpath
;
1083 recent_session_display
.set_model (recent_session_model
);
1088 ARDOUR_UI::build_session_selector ()
1090 session_selector_window
= new ArdourDialog ("session selector");
1092 Gtk::ScrolledWindow
*scroller
= manage (new Gtk::ScrolledWindow
);
1094 session_selector_window
->add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
1095 session_selector_window
->add_button (Stock::OPEN
, RESPONSE_ACCEPT
);
1096 session_selector_window
->set_default_response (RESPONSE_ACCEPT
);
1097 recent_session_model
= TreeStore::create (recent_session_columns
);
1098 recent_session_display
.set_model (recent_session_model
);
1099 recent_session_display
.append_column (_("Recent Sessions"), recent_session_columns
.visible_name
);
1100 recent_session_display
.set_headers_visible (false);
1101 recent_session_display
.get_selection()->set_mode (SELECTION_BROWSE
);
1102 recent_session_display
.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated
));
1104 scroller
->add (recent_session_display
);
1105 scroller
->set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
1107 session_selector_window
->set_name ("SessionSelectorWindow");
1108 session_selector_window
->set_size_request (200, 400);
1109 session_selector_window
->get_vbox()->pack_start (*scroller
);
1110 session_selector_window
->show_all_children();
1114 ARDOUR_UI::recent_session_row_activated (const TreePath
& path
, TreeViewColumn
* col
)
1116 session_selector_window
->response (RESPONSE_ACCEPT
);
1120 ARDOUR_UI::open_recent_session ()
1122 bool can_return
= (session
!= 0);
1124 if (session_selector_window
== 0) {
1125 build_session_selector ();
1128 redisplay_recent_sessions ();
1132 session_selector_window
->set_position (WIN_POS_MOUSE
);
1134 ResponseType r
= (ResponseType
) session_selector_window
->run ();
1137 case RESPONSE_ACCEPT
:
1141 session_selector_window
->hide();
1148 if (recent_session_display
.get_selection()->count_selected_rows() == 0) {
1152 session_selector_window
->hide();
1154 Gtk::TreeModel::iterator i
= recent_session_display
.get_selection()->get_selected();
1156 if (i
== recent_session_model
->children().end()) {
1160 Glib::ustring path
= (*i
)[recent_session_columns
.fullpath
];
1161 Glib::ustring state
= (*i
)[recent_session_columns
.visible_name
];
1163 _session_is_new
= false;
1165 if (load_session (path
, state
) == 0) {
1174 ARDOUR_UI::check_audioengine ()
1177 if (!engine
->connected()) {
1178 MessageDialog
msg (string_compose (_("%1 is not connected to JACK\n"
1179 "You cannot open or close sessions in this condition"), PROGRAM_NAME
));
1181 msg
.set_position (WIN_POS_CENTER
);
1192 ARDOUR_UI::open_session ()
1194 if (!check_audioengine()) {
1198 /* popup selector window */
1200 if (open_session_selector
== 0) {
1202 /* ardour sessions are folders */
1204 open_session_selector
= new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN
);
1205 open_session_selector
->add_button (Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
1206 open_session_selector
->add_button (Gtk::Stock::OPEN
, Gtk::RESPONSE_ACCEPT
);
1207 open_session_selector
->set_default_response(Gtk::RESPONSE_ACCEPT
);
1209 FileFilter session_filter
;
1210 session_filter
.add_pattern ("*.ardour");
1211 session_filter
.set_name (_("Ardour sessions"));
1212 open_session_selector
->add_filter (session_filter
);
1213 open_session_selector
->set_filter (session_filter
);
1216 int response
= open_session_selector
->run();
1217 open_session_selector
->hide ();
1220 case RESPONSE_ACCEPT
:
1223 open_session_selector
->hide();
1227 open_session_selector
->hide();
1228 string session_path
= open_session_selector
->get_filename();
1232 if (session_path
.length() > 0) {
1233 if (Session::find_session (session_path
, path
, name
, isnew
) == 0) {
1234 _session_is_new
= isnew
;
1235 load_session (path
, name
);
1242 ARDOUR_UI::session_add_midi_track ()
1244 cerr
<< _("Patience is a virtue.\n");
1248 ARDOUR_UI::session_add_audio_route (bool track
, int32_t input_channels
, int32_t output_channels
, ARDOUR::TrackMode mode
, uint32_t how_many
)
1250 list
<boost::shared_ptr
<AudioTrack
> > tracks
;
1251 Session::RouteList routes
;
1254 warning
<< _("You cannot add a track or bus without a session already loaded.") << endmsg
;
1260 tracks
= session
->new_audio_track (input_channels
, output_channels
, mode
, how_many
);
1262 if (tracks
.size() != how_many
) {
1263 if (how_many
== 1) {
1264 error
<< _("could not create a new audio track") << endmsg
;
1266 error
<< string_compose (_("could only create %1 of %2 new audio %3"),
1267 tracks
.size(), how_many
, (track
? _("tracks") : _("busses"))) << endmsg
;
1273 routes
= session
->new_audio_route (input_channels
, output_channels
, how_many
);
1275 if (routes
.size() != how_many
) {
1276 if (how_many
== 1) {
1277 error
<< _("could not create a new audio track") << endmsg
;
1279 error
<< string_compose (_("could not create %1 new audio tracks"), how_many
) << endmsg
;
1285 if (need_control_room_outs
) {
1291 route
->set_stereo_control_outs (control_lr_channels
);
1292 route
->control_outs()->set_stereo_pan (pans
, this);
1294 #endif /* CONTROLOUTS */
1298 MessageDialog
msg (*editor
,
1299 _("There are insufficient JACK ports available\n\
1300 to create a new track or bus.\n\
1301 You should save Ardour, exit and\n\
1302 restart JACK with more ports."));
1309 ARDOUR_UI::do_transport_locate (nframes_t new_position
)
1311 nframes_t _preroll
= 0;
1314 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1315 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1317 if (new_position
> _preroll
) {
1318 new_position
-= _preroll
;
1323 session
->request_locate (new_position
);
1328 ARDOUR_UI::transport_goto_start ()
1331 session
->goto_start();
1334 /* force displayed area in editor to start no matter
1335 what "follow playhead" setting is.
1339 editor
->reset_x_origin (session
->current_start_frame());
1345 ARDOUR_UI::transport_goto_zero ()
1348 session
->request_locate (0);
1351 /* force displayed area in editor to start no matter
1352 what "follow playhead" setting is.
1356 editor
->reset_x_origin (0);
1362 ARDOUR_UI::transport_goto_wallclock ()
1364 if (session
&& editor
) {
1371 localtime_r (&now
, &tmnow
);
1373 frames
= tmnow
.tm_hour
* (60 * 60 * session
->frame_rate());
1374 frames
+= tmnow
.tm_min
* (60 * session
->frame_rate());
1375 frames
+= tmnow
.tm_sec
* session
->frame_rate();
1377 session
->request_locate (frames
);
1379 /* force displayed area in editor to start no matter
1380 what "follow playhead" setting is.
1384 editor
->reset_x_origin (frames
- (editor
->current_page_frames()/2));
1390 ARDOUR_UI::transport_goto_end ()
1393 nframes_t frame
= session
->current_end_frame();
1394 session
->request_locate (frame
);
1396 /* force displayed area in editor to start no matter
1397 what "follow playhead" setting is.
1401 editor
->reset_x_origin (frame
);
1407 ARDOUR_UI::transport_stop ()
1413 if (session
->is_auditioning()) {
1414 session
->cancel_audition ();
1418 session
->request_stop (false, true);
1422 ARDOUR_UI::transport_stop_and_forget_capture ()
1425 session
->request_stop (true, true);
1430 ARDOUR_UI::remove_last_capture()
1433 editor
->remove_last_capture();
1438 ARDOUR_UI::transport_record (bool roll
)
1442 switch (session
->record_status()) {
1443 case Session::Disabled
:
1444 if (session
->ntracks() == 0) {
1445 MessageDialog
msg (*editor
, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1449 session
->maybe_enable_record ();
1454 case Session::Recording
:
1456 session
->request_stop();
1458 session
->disable_record (false, true);
1462 case Session::Enabled
:
1463 session
->disable_record (false, true);
1466 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1470 ARDOUR_UI::transport_roll ()
1476 if (session
->is_auditioning()) {
1480 switch (Config
->get_slave_source()) {
1485 /* transport controlled by the master */
1489 bool rolling
= session
->transport_rolling();
1491 if (session
->get_play_loop()) {
1492 /* XXX it is not possible to just leave seamless loop and keep
1493 playing at present (nov 4th 2009)
1495 if (!Config
->get_seamless_loop()) {
1497 session
->request_play_loop (false, true);
1501 } else if (session
->get_play_range ()) {
1502 session
->request_play_range (0, true);
1506 session
->request_transport_speed (1.0f
);
1509 map_transport_state ();
1513 ARDOUR_UI::toggle_roll (bool with_abort
, bool roll_out_of_bounded_mode
)
1520 if (session
->is_auditioning()) {
1521 session
->cancel_audition ();
1525 switch (Config
->get_slave_source()) {
1530 /* transport controlled by the master */
1534 bool rolling
= session
->transport_rolling();
1535 bool affect_transport
= true;
1537 if (rolling
&& roll_out_of_bounded_mode
) {
1538 /* drop out of loop/range playback but leave transport rolling */
1539 if (session
->get_play_loop()) {
1540 if (Config
->get_seamless_loop()) {
1541 /* the disk buffers contain copies of the loop - we can't
1542 just keep playing, so stop the transport. the user
1543 can restart as they wish.
1545 affect_transport
= true;
1547 /* disk buffers are normal, so we can keep playing */
1548 affect_transport
= false;
1550 session
->request_play_loop (false, true);
1551 } else if (session
->get_play_range ()) {
1552 affect_transport
= false;
1553 session
->request_play_range (0, true);
1557 if (affect_transport
) {
1559 session
->request_stop (with_abort
, true);
1561 session
->request_transport_speed (1.0f
);
1565 map_transport_state ();
1569 ARDOUR_UI::toggle_session_auto_loop ()
1572 if (session
->get_play_loop()) {
1573 if (session
->transport_rolling()) {
1574 Location
* looploc
= session
->locations()->auto_loop_location();
1576 session
->request_locate (looploc
->start(), true);
1579 session
->request_play_loop (false);
1582 Location
* looploc
= session
->locations()->auto_loop_location();
1584 session
->request_play_loop (true);
1591 ARDOUR_UI::transport_play_selection ()
1597 editor
->play_selection ();
1601 ARDOUR_UI::transport_rewind (int option
)
1603 float current_transport_speed
;
1606 current_transport_speed
= session
->transport_speed();
1608 if (current_transport_speed
>= 0.0f
) {
1611 session
->request_transport_speed (-1.0f
);
1614 session
->request_transport_speed (-4.0f
);
1617 session
->request_transport_speed (-0.5f
);
1622 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1628 ARDOUR_UI::transport_forward (int option
)
1630 float current_transport_speed
;
1633 current_transport_speed
= session
->transport_speed();
1635 if (current_transport_speed
<= 0.0f
) {
1638 session
->request_transport_speed (1.0f
);
1641 session
->request_transport_speed (4.0f
);
1644 session
->request_transport_speed (0.5f
);
1649 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1655 ARDOUR_UI::toggle_record_enable (uint32_t dstream
)
1661 boost::shared_ptr
<Route
> r
;
1663 if ((r
= session
->route_by_remote_id (dstream
)) != 0) {
1667 if ((t
= dynamic_cast<Track
*>(r
.get())) != 0) {
1668 t
->diskstream()->set_record_enabled (!t
->diskstream()->record_enabled());
1674 ARDOUR_UI::queue_transport_change ()
1676 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state
));
1680 ARDOUR_UI::map_transport_state ()
1683 auto_loop_button
.set_visual_state (0);
1684 play_selection_button
.set_visual_state (0);
1685 roll_button
.set_visual_state (0);
1686 stop_button
.set_visual_state (1);
1690 float sp
= session
->transport_speed();
1693 shuttle_fract
= SHUTTLE_FRACT_SPEED1
; /* speed = 1.0, believe it or not */
1694 shuttle_box
.queue_draw ();
1695 } else if (sp
== 0.0f
) {
1697 shuttle_box
.queue_draw ();
1698 update_disk_space ();
1703 if (session
->get_play_range()) {
1705 play_selection_button
.set_visual_state (1);
1706 roll_button
.set_visual_state (0);
1707 auto_loop_button
.set_visual_state (0);
1709 } else if (session
->get_play_loop ()) {
1711 auto_loop_button
.set_visual_state (1);
1712 play_selection_button
.set_visual_state (0);
1713 roll_button
.set_visual_state (0);
1717 roll_button
.set_visual_state (1);
1718 play_selection_button
.set_visual_state (0);
1719 auto_loop_button
.set_visual_state (0);
1722 stop_button
.set_visual_state (0);
1726 stop_button
.set_visual_state (1);
1727 roll_button
.set_visual_state (0);
1728 play_selection_button
.set_visual_state (0);
1729 auto_loop_button
.set_visual_state (0);
1735 ARDOUR_UI::GlobalClickBox::printer (char buf
[32], Adjustment
&adj
, void *arg
)
1737 snprintf (buf
, sizeof(buf
), "%s", ((GlobalClickBox
*) arg
)->strings
[
1738 (int) adj
.get_value()].c_str());
1742 ARDOUR_UI::engine_stopped ()
1744 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
1745 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1746 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1750 ARDOUR_UI::engine_running ()
1752 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running
));
1753 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, true);
1754 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, false);
1756 Glib::RefPtr
<Action
> action
;
1757 const char* action_name
= 0;
1759 switch (engine
->frames_per_cycle()) {
1761 action_name
= X_("JACKLatency32");
1764 action_name
= X_("JACKLatency64");
1767 action_name
= X_("JACKLatency128");
1770 action_name
= X_("JACKLatency512");
1773 action_name
= X_("JACKLatency1024");
1776 action_name
= X_("JACKLatency2048");
1779 action_name
= X_("JACKLatency4096");
1782 action_name
= X_("JACKLatency8192");
1785 /* XXX can we do anything useful ? */
1791 action
= ActionManager::get_action (X_("JACK"), action_name
);
1794 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic (action
);
1795 ract
->set_active ();
1801 ARDOUR_UI::engine_halted (const char* reason
, bool free_reason
)
1803 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
1804 /* we can't rely on the original string continuing to exist when we are called
1805 again in the GUI thread, so make a copy and note that we need to
1808 char *copy
= strdup (reason
);
1809 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &ARDOUR_UI::engine_halted
), copy
, true));
1813 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1814 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1816 update_sample_rate (0);
1820 /* if the reason is a non-empty string, it means that the backend was shutdown
1821 rather than just Ardour.
1824 if (strlen (reason
)) {
1825 msgstr
= string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason
);
1828 JACK has either been shutdown or it\n\
1829 disconnected Ardour because Ardour\n\
1830 was not fast enough. Try to restart\n\
1831 JACK, reconnect and save the session.");
1834 MessageDialog
msg (*editor
, msgstr
);
1839 free ((char *) reason
);
1844 ARDOUR_UI::do_engine_start ()
1852 error
<< _("Unable to start the session running")
1862 ARDOUR_UI::setup_theme ()
1864 theme_manager
->setup_theme();
1868 ARDOUR_UI::update_clocks ()
1870 if (!editor
|| !editor
->dragging_playhead()) {
1871 Clock (session
->audible_frame(), false, editor
->get_preferred_edit_position()); /* EMIT_SIGNAL */
1876 ARDOUR_UI::start_clocking ()
1878 clock_signal_connection
= RapidScreenUpdate
.connect (mem_fun(*this, &ARDOUR_UI::update_clocks
));
1882 ARDOUR_UI::stop_clocking ()
1884 clock_signal_connection
.disconnect ();
1888 ARDOUR_UI::toggle_clocking ()
1891 if (clock_button
.get_active()) {
1900 ARDOUR_UI::_blink (void *arg
)
1903 ((ARDOUR_UI
*) arg
)->blink ();
1910 Blink (blink_on
= !blink_on
); /* EMIT_SIGNAL */
1914 ARDOUR_UI::start_blinking ()
1916 /* Start the blink signal. Everybody with a blinking widget
1917 uses Blink to drive the widget's state.
1920 if (blink_timeout_tag
< 0) {
1922 blink_timeout_tag
= g_timeout_add (240, _blink
, this);
1927 ARDOUR_UI::stop_blinking ()
1929 if (blink_timeout_tag
>= 0) {
1930 g_source_remove (blink_timeout_tag
);
1931 blink_timeout_tag
= -1;
1936 ARDOUR_UI::name_io_setup (AudioEngine
& engine
,
1942 if (io
.n_inputs() == 0) {
1947 /* XXX we're not handling multiple ports yet. */
1949 const char **connections
= io
.input(0)->get_connections();
1951 if (connections
== 0 || connections
[0] == '\0') {
1954 buf
= connections
[0];
1961 if (io
.n_outputs() == 0) {
1966 /* XXX we're not handling multiple ports yet. */
1968 const char **connections
= io
.output(0)->get_connections();
1970 if (connections
== 0 || connections
[0] == '\0') {
1973 buf
= connections
[0];
1980 /** Ask the user for the name of a new shapshot and then take it.
1983 ARDOUR_UI::snapshot_session (bool switch_to_it
)
1985 ArdourPrompter
prompter (true);
1988 prompter
.set_name ("Prompter");
1989 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
1990 prompter
.set_title (_("Take Snapshot"));
1991 prompter
.set_prompt (_("Name of New Snapshot"));
1993 if (!switch_to_it
) {
1996 struct tm local_time
;
1999 localtime_r (&n
, &local_time
);
2000 strftime (timebuf
, sizeof(timebuf
), "%FT%T", &local_time
);
2002 prompter
.set_initial_text (timebuf
);
2006 switch (prompter
.run()) {
2007 case RESPONSE_ACCEPT
:
2008 prompter
.get_result (snapname
);
2009 if (snapname
.length()){
2010 if (snapname
.find ('/') != string::npos
) {
2011 MessageDialog
msg (_("To ensure compatibility with various systems\n"
2012 "snapshot names may not contain a '/' character"));
2016 if (snapname
.find ('\\') != string::npos
) {
2017 MessageDialog
msg (_("To ensure compatibility with various systems\n"
2018 "snapshot names may not contain a '\\' character"));
2022 save_state (snapname
, switch_to_it
);
2032 ARDOUR_UI::save_state (const string
& name
, bool switch_to_it
)
2034 (void) save_state_canfail (name
, switch_to_it
);
2038 ARDOUR_UI::save_state_canfail (string name
, bool switch_to_it
)
2043 if (name
.length() == 0) {
2044 name
= session
->snap_name();
2047 if ((ret
= session
->save_state (name
, false, switch_to_it
)) != 0) {
2051 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2056 ARDOUR_UI::primary_clock_value_changed ()
2059 session
->request_locate (primary_clock
.current_time ());
2064 ARDOUR_UI::big_clock_value_changed ()
2067 session
->request_locate (big_clock
.current_time ());
2072 ARDOUR_UI::secondary_clock_value_changed ()
2075 session
->request_locate (secondary_clock
.current_time ());
2080 ARDOUR_UI::transport_rec_enable_blink (bool onoff
)
2086 switch (session
->record_status()) {
2087 case Session::Enabled
:
2089 rec_button
.set_visual_state (2);
2091 rec_button
.set_visual_state (0);
2095 case Session::Recording
:
2096 rec_button
.set_visual_state (1);
2100 rec_button
.set_visual_state (0);
2106 ARDOUR_UI::save_template ()
2108 ArdourPrompter
prompter (true);
2111 if (!check_audioengine()) {
2115 prompter
.set_name (X_("Prompter"));
2116 prompter
.set_title (_("Save Mix Template"));
2117 prompter
.set_prompt (_("Name for mix template:"));
2118 prompter
.set_initial_text(session
->name() + _("-template"));
2119 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
2121 switch (prompter
.run()) {
2122 case RESPONSE_ACCEPT
:
2123 prompter
.get_result (name
);
2125 if (name
.length()) {
2126 session
->save_template (name
);
2136 ARDOUR_UI::fontconfig_dialog ()
2139 /* this issue seems to have gone away with changes to font handling in GTK/Quartz
2142 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2143 may not and it can take a while to build it. Warn them.
2146 Glib::ustring fontconfig
= Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2148 if (!Glib::file_test (fontconfig
, Glib::FILE_TEST_EXISTS
|Glib::FILE_TEST_IS_DIR
)) {
2149 MessageDialog
msg (*new_session_dialog
,
2150 string_compose (_("Welcome to %1.\n\n"
2151 "The program will take a bit longer to start up\n"
2152 "while the system fonts are checked.\n\n"
2153 "This will only be done once, and you will\n"
2154 "not see this message again\n"), PROGRAM_NAME
),
2168 ARDOUR_UI::parse_cmdline_path (const Glib::ustring
& cmdline_path
, Glib::ustring
& session_name
, Glib::ustring
& session_path
, bool& existing_session
)
2170 existing_session
= false;
2172 if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_DIR
)) {
2173 session_path
= cmdline_path
;
2174 existing_session
= true;
2175 } else if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_REGULAR
)) {
2176 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2177 existing_session
= true;
2179 /* it doesn't exist, assume the best */
2180 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2183 session_name
= basename_nosuffix (string (cmdline_path
));
2187 ARDOUR_UI::load_cmdline_session (const Glib::ustring
& session_name
, const Glib::ustring
& session_path
, bool& existing_session
)
2189 /* when this is called, the backend audio system must be running */
2191 /* the main idea here is to deal with the fact that a cmdline argument for the session
2192 can be interpreted in different ways - it could be a directory or a file, and before
2193 we load, we need to know both the session directory and the snapshot (statefile) within it
2194 that we are supposed to use.
2197 if (session_name
.length() == 0 || session_path
.length() == 0) {
2201 if (Glib::file_test (session_path
, Glib::FILE_TEST_IS_DIR
)) {
2203 Glib::ustring predicted_session_file
;
2205 predicted_session_file
= Glib::build_filename (session_path
, session_name
+ Session::statefile_suffix());
2207 if (Glib::file_test (predicted_session_file
, Glib::FILE_TEST_EXISTS
)) {
2208 existing_session
= true;
2211 } else if (Glib::file_test (session_path
, Glib::FILE_TEST_EXISTS
)) {
2213 if (session_path
.find (Session::statefile_suffix()) == session_path
.length() - 7) {
2214 /* existing .ardour file */
2215 existing_session
= true;
2219 existing_session
= false;
2222 /* lets just try to load it */
2224 if (create_engine ()) {
2225 backend_audio_error (false, new_session_dialog
);
2229 return load_session (session_path
, session_name
);
2233 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring
& session_path
)
2235 Glib::ustring str
= string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path
);
2237 MessageDialog
msg (str
,
2239 Gtk::MESSAGE_WARNING
,
2240 Gtk::BUTTONS_YES_NO
,
2244 msg
.set_name (X_("CleanupDialog"));
2245 msg
.set_title (_("Cleanup Unused Sources"));
2246 msg
.set_wmclass (X_("existing_session"), PROGRAM_NAME
);
2247 msg
.set_position (Gtk::WIN_POS_MOUSE
);
2250 switch (msg
.run()) {
2259 ARDOUR_UI::build_session_from_nsd (const Glib::ustring
& session_path
, const Glib::ustring
& session_name
)
2264 AutoConnectOption iconnect
;
2265 AutoConnectOption oconnect
;
2269 if (Profile
->get_sae()) {
2273 iconnect
= AutoConnectPhysical
;
2274 oconnect
= AutoConnectMaster
;
2275 nphysin
= 0; // use all available
2276 nphysout
= 0; // use all available
2280 /* get settings from advanced section of NSD */
2282 if (new_session_dialog
->create_control_bus()) {
2283 cchns
= (uint32_t) new_session_dialog
->control_channel_count();
2288 if (new_session_dialog
->create_master_bus()) {
2289 mchns
= (uint32_t) new_session_dialog
->master_channel_count();
2294 if (new_session_dialog
->connect_inputs()) {
2295 iconnect
= AutoConnectPhysical
;
2297 iconnect
= AutoConnectOption (0);
2300 /// @todo some minor tweaks.
2302 oconnect
= AutoConnectOption (0);
2304 if (new_session_dialog
->connect_outputs()) {
2305 if (new_session_dialog
->connect_outs_to_master()) {
2306 oconnect
= AutoConnectMaster
;
2307 } else if (new_session_dialog
->connect_outs_to_physical()) {
2308 oconnect
= AutoConnectPhysical
;
2312 nphysin
= (uint32_t) new_session_dialog
->input_limit_count();
2313 nphysout
= (uint32_t) new_session_dialog
->output_limit_count();
2316 if (build_session (session_path
,
2324 engine
->frame_rate() * 60 * 5)) {
2333 ARDOUR_UI::end_loading_messages ()
2339 ARDOUR_UI::loading_message (const std::string
& msg
)
2342 splash
->message (msg
);
2347 ARDOUR_UI::idle_load (const Glib::ustring
& path
)
2350 if (Glib::file_test (path
, Glib::FILE_TEST_IS_DIR
)) {
2351 /* /path/to/foo => /path/to/foo, foo */
2352 load_session (path
, basename_nosuffix (path
));
2354 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2355 load_session (Glib::path_get_dirname (path
), basename_nosuffix (path
));
2359 ARDOUR_COMMAND_LINE::session_name
= path
;
2361 if (new_session_dialog
) {
2364 /* make it break out of Dialog::run() and
2368 new_session_dialog
->response (1);
2374 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running
, bool should_be_new
)
2376 bool existing_session
= false;
2377 Glib::ustring session_name
;
2378 Glib::ustring session_path
;
2379 Glib::ustring template_name
;
2383 response
= Gtk::RESPONSE_NONE
;
2385 if (!ARDOUR_COMMAND_LINE::session_name
.empty()) {
2387 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name
, session_name
, session_path
, existing_session
);
2389 /* don't ever reuse this */
2391 ARDOUR_COMMAND_LINE::session_name
= string();
2393 if (existing_session
&& backend_audio_is_running
) {
2395 /* just load the thing already */
2397 if (load_cmdline_session (session_name
, session_path
, existing_session
) == 0) {
2402 /* make the NSD use whatever information we have */
2404 new_session_dialog
->set_session_name (session_name
);
2405 new_session_dialog
->set_session_folder (session_path
);
2408 /* loading failed, or we need the NSD for something */
2410 new_session_dialog
->set_modal (false);
2411 new_session_dialog
->set_position (WIN_POS_CENTER
);
2412 new_session_dialog
->set_current_page (0);
2413 new_session_dialog
->set_existing_session (existing_session
);
2414 new_session_dialog
->reset_recent();
2417 new_session_dialog
->set_have_engine (backend_audio_is_running
);
2418 new_session_dialog
->present ();
2419 response
= new_session_dialog
->run ();
2421 _session_is_new
= false;
2423 /* handle possible negative responses */
2427 /* sent by idle_load, meaning restart the whole process again */
2428 new_session_dialog
->hide();
2429 new_session_dialog
->reset();
2433 case Gtk::RESPONSE_CANCEL
:
2434 case Gtk::RESPONSE_DELETE_EVENT
:
2436 if (engine
&& engine
->running()) {
2437 engine
->stop (true);
2441 new_session_dialog
->hide ();
2444 case Gtk::RESPONSE_NONE
:
2445 /* "Clear" was pressed */
2449 fontconfig_dialog();
2451 if (!backend_audio_is_running
) {
2452 int ret
= new_session_dialog
->engine_control
.setup_engine ();
2455 } else if (ret
> 0) {
2456 response
= Gtk::RESPONSE_REJECT
;
2460 /* hide the NSD while we start up the engine */
2462 new_session_dialog
->hide ();
2466 if (create_engine ()) {
2468 backend_audio_error (!backend_audio_is_running
, new_session_dialog
);
2471 new_session_dialog
->set_existing_session (false);
2472 new_session_dialog
->set_current_page (0); // new engine page
2473 new_session_dialog
->engine_control
.unset_interface_chosen ();
2475 response
= Gtk::RESPONSE_NONE
;
2479 backend_audio_is_running
= true;
2481 if (response
== Gtk::RESPONSE_OK
) {
2483 session_name
= new_session_dialog
->session_name();
2485 if (session_name
.empty()) {
2486 response
= Gtk::RESPONSE_NONE
;
2490 /* if the user mistakenly typed path information into the session filename entry,
2491 convert what they typed into a path & a name
2494 if (Glib::path_is_absolute (session_name
) ||
2495 (session_name
.length() > 2 && session_name
[0] == '.' && session_name
[1] == G_DIR_SEPARATOR
) ||
2496 (session_name
.length() > 3 && session_name
[0] == '.' && session_name
[1] == '.' && session_name
[2] == G_DIR_SEPARATOR
)) {
2498 session_path
= Glib::path_get_dirname (session_name
);
2499 session_name
= Glib::path_get_basename (session_name
);
2503 session_path
= new_session_dialog
->session_folder();
2507 template_name
= Glib::ustring();
2508 switch (new_session_dialog
->which_page()) {
2510 case NewSessionDialog::OpenPage
:
2514 case NewSessionDialog::EnginePage
:
2515 if (new_session_dialog
->engine_control
.interface_chosen() && !session_path
.empty()) {
2522 case NewSessionDialog::NewPage
: /* nominally the "new" session creator, but could be in use for an old session */
2524 should_be_new
= true;
2526 if (session_name
.find ('/') != Glib::ustring::npos
) {
2527 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2528 "session names may not contain a '/' character"));
2530 response
= RESPONSE_NONE
;
2534 if (session_name
.find ('\\') != Glib::ustring::npos
) {
2535 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2536 "session names may not contain a '\\' character"));
2538 response
= RESPONSE_NONE
;
2542 //XXX This is needed because session constructor wants a
2543 //non-existant path. hopefully this will be fixed at some point.
2545 session_path
= Glib::build_filename (session_path
, session_name
);
2547 if (Glib::file_test (session_path
, Glib::FileTest (G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))) {
2549 new_session_dialog
->hide ();
2551 if (ask_about_loading_existing_session (session_path
)) {
2554 response
= RESPONSE_NONE
;
2559 _session_is_new
= true;
2561 if (new_session_dialog
->use_session_template()) {
2563 template_name
= new_session_dialog
->session_template_name();
2567 if (build_session_from_nsd (session_path
, session_name
)) {
2568 response
= RESPONSE_NONE
;
2580 new_session_dialog
->hide ();
2582 if (load_session (session_path
, session_name
, template_name
)) {
2584 response
= Gtk::RESPONSE_NONE
;
2588 if (response
== Gtk::RESPONSE_NONE
) {
2589 new_session_dialog
->set_existing_session (false);
2590 new_session_dialog
->reset ();
2594 } while (response
== Gtk::RESPONSE_NONE
|| response
== Gtk::RESPONSE_REJECT
);
2598 new_session_dialog
->hide();
2599 new_session_dialog
->reset();
2600 goto_editor_window ();
2605 ARDOUR_UI::close_session ()
2607 if (!check_audioengine()) {
2611 if (unload_session (true)) {
2615 get_session_parameters (true, false);
2619 ARDOUR_UI::load_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
, Glib::ustring mix_template
)
2621 Session
*new_session
;
2625 session_loaded
= false;
2627 if (!check_audioengine()) {
2631 unload_status
= unload_session ();
2633 if (unload_status
< 0) {
2635 } else if (unload_status
> 0) {
2640 loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME
));
2643 new_session
= new Session (*engine
, path
, snap_name
, mix_template
);
2646 /* this one is special */
2648 catch (AudioEngine::PortRegistrationFailure
& err
) {
2650 MessageDialog
msg (err
.what(),
2653 Gtk::BUTTONS_CLOSE
);
2655 msg
.set_title (_("Port Registration Error"));
2656 msg
.set_secondary_text (_("Click the Close button to try again."));
2657 msg
.set_position (Gtk::WIN_POS_CENTER
);
2661 int response
= msg
.run ();
2666 case RESPONSE_CANCEL
:
2674 /* this exception is also special */
2676 catch (Session::SRMismatchRejected
& err
) {
2677 goto out
; /* just go back and reload something else, etc. */
2682 MessageDialog
msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path
, snap_name
),
2685 Gtk::BUTTONS_CLOSE
);
2687 msg
.set_title (_("Loading Error"));
2688 msg
.set_secondary_text (_("Click the Close button to try again."));
2689 msg
.set_position (Gtk::WIN_POS_CENTER
);
2693 int response
= msg
.run ();
2698 case RESPONSE_CANCEL
:
2706 /* Now the session been created, add the transport controls */
2707 new_session
->add_controllable(&roll_controllable
);
2708 new_session
->add_controllable(&stop_controllable
);
2709 new_session
->add_controllable(&goto_start_controllable
);
2710 new_session
->add_controllable(&goto_end_controllable
);
2711 new_session
->add_controllable(&auto_loop_controllable
);
2712 new_session
->add_controllable(&play_selection_controllable
);
2713 new_session
->add_controllable(&rec_controllable
);
2715 /* Once the transport controlls have been added, the ControlProtocolManager
2716 is okay to instantiate the various protocols. */
2717 BootMessage (_("Reset Control Protocols"));
2718 ControlProtocolManager::instance().set_session (*new_session
);
2720 connect_to_session (new_session
);
2722 Config
->set_current_owner (ConfigVariableBase::Interface
);
2724 session_loaded
= true;
2726 goto_editor_window ();
2729 session
->set_clean ();
2740 ARDOUR_UI::build_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
,
2741 uint32_t control_channels
,
2742 uint32_t master_channels
,
2743 AutoConnectOption input_connect
,
2744 AutoConnectOption output_connect
,
2747 nframes_t initial_length
)
2749 Session
*new_session
;
2752 if (!check_audioengine()) {
2756 session_loaded
= false;
2758 x
= unload_session ();
2766 _session_is_new
= true;
2769 new_session
= new Session (*engine
, path
, snap_name
, input_connect
, output_connect
,
2770 control_channels
, master_channels
, nphysin
, nphysout
, initial_length
);
2775 MessageDialog
msg (string_compose(_("Could not create session in \"%1\""), path
));
2781 connect_to_session (new_session
);
2783 session_loaded
= true;
2785 new_session
->save_state(new_session
->name());
2794 editor
->show_window ();
2805 ARDOUR_UI::show_about ()
2809 about
->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response
) );
2812 about
->set_transient_for(*editor
);
2818 ARDOUR_UI::launch_chat ()
2821 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2823 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2828 ARDOUR_UI::launch_manual ()
2830 NagScreen::open_uri("http://ardour.org/flossmanual");
2834 ARDOUR_UI::launch_reference ()
2836 NagScreen::open_uri("http://ardour.org/refmanual");
2840 ARDOUR_UI::hide_about ()
2843 about
->get_window()->set_cursor ();
2849 ARDOUR_UI::about_signal_response(int response
)
2855 ARDOUR_UI::show_splash ()
2859 splash
= new Splash
;
2867 splash
->queue_draw ();
2868 splash
->get_window()->process_updates (true);
2873 ARDOUR_UI::hide_splash ()
2881 ARDOUR_UI::display_cleanup_results (Session::cleanup_report
& rep
, const gchar
* list_title
,
2882 const string
& plural_msg
, const string
& singular_msg
)
2886 removed
= rep
.paths
.size();
2889 MessageDialog
msgd (*editor
,
2890 _("No audio files were ready for cleanup"),
2893 (Gtk::ButtonsType
)(Gtk::BUTTONS_OK
) );
2894 msgd
.set_secondary_text (_("If this seems suprising, \n\
2895 check for any existing snapshots.\n\
2896 These may still include regions that\n\
2897 require some unused files to continue to exist."));
2903 ArdourDialog
results (_("ardour: cleanup"), true, false);
2905 struct CleanupResultsModelColumns
: public Gtk::TreeModel::ColumnRecord
{
2906 CleanupResultsModelColumns() {
2910 Gtk::TreeModelColumn
<Glib::ustring
> visible_name
;
2911 Gtk::TreeModelColumn
<Glib::ustring
> fullpath
;
2915 CleanupResultsModelColumns results_columns
;
2916 Glib::RefPtr
<Gtk::ListStore
> results_model
;
2917 Gtk::TreeView results_display
;
2919 results_model
= ListStore::create (results_columns
);
2920 results_display
.set_model (results_model
);
2921 results_display
.append_column (list_title
, results_columns
.visible_name
);
2923 results_display
.set_name ("CleanupResultsList");
2924 results_display
.set_headers_visible (true);
2925 results_display
.set_headers_clickable (false);
2926 results_display
.set_reorderable (false);
2928 Gtk::ScrolledWindow list_scroller
;
2931 Gtk::HBox dhbox
; // the hbox for the image and text
2932 Gtk::HBox ddhbox
; // the hbox we eventually pack into the dialog's vbox
2933 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_INFO
, Gtk::ICON_SIZE_DIALOG
));
2935 dimage
->set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
2939 %1 - number of files removed
2940 %2 - location of "dead_sounds"
2941 %3 - size of files affected
2942 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2945 const char* bprefix
;
2946 float space_adjusted
;
2948 if (rep
.space
< 1000000.0f
) {
2949 bprefix
= X_("kilo");
2950 space_adjusted
= truncf((float)rep
.space
/ 1000.0f
);
2951 } else if (rep
.space
< (1000000.0f
* 1000)) {
2952 bprefix
= X_("mega");
2953 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
));
2955 bprefix
= X_("giga");
2956 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
* 1000));
2960 txt
.set_text (string_compose (plural_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2962 txt
.set_text (string_compose (singular_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2965 dhbox
.pack_start (*dimage
, true, false, 5);
2966 dhbox
.pack_start (txt
, true, false, 5);
2968 for (vector
<string
>::iterator i
= rep
.paths
.begin(); i
!= rep
.paths
.end(); ++i
) {
2969 TreeModel::Row row
= *(results_model
->append());
2970 row
[results_columns
.visible_name
] = *i
;
2971 row
[results_columns
.fullpath
] = *i
;
2974 list_scroller
.add (results_display
);
2975 list_scroller
.set_size_request (-1, 150);
2976 list_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
2978 dvbox
.pack_start (dhbox
, true, false, 5);
2979 dvbox
.pack_start (list_scroller
, true, false, 5);
2980 ddhbox
.pack_start (dvbox
, true, false, 5);
2982 results
.get_vbox()->pack_start (ddhbox
, true, false, 5);
2983 results
.add_button (Stock::CLOSE
, RESPONSE_CLOSE
);
2984 results
.set_default_response (RESPONSE_CLOSE
);
2985 results
.set_position (Gtk::WIN_POS_MOUSE
);
2986 results
.show_all_children ();
2987 results
.set_resizable (false);
2994 ARDOUR_UI::cleanup ()
2997 /* shouldn't happen: menu item is insensitive */
3002 MessageDialog
checker (_("Are you sure you want to cleanup?"),
3004 Gtk::MESSAGE_QUESTION
,
3005 (Gtk::ButtonsType
)(Gtk::BUTTONS_NONE
));
3007 checker
.set_secondary_text(_("Cleanup is a destructive operation.\n\
3008 ALL undo/redo information will be lost if you cleanup.\n\
3009 After cleanup, unused audio files will be moved to a \
3010 \"dead sounds\" location."));
3012 checker
.add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
3013 checker
.add_button (_("Clean Up"), RESPONSE_ACCEPT
);
3014 checker
.set_default_response (RESPONSE_CANCEL
);
3016 checker
.set_name (_("CleanupDialog"));
3017 checker
.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME
);
3018 checker
.set_position (Gtk::WIN_POS_MOUSE
);
3020 switch (checker
.run()) {
3021 case RESPONSE_ACCEPT
:
3027 Session::cleanup_report rep
;
3029 editor
->prepare_for_cleanup ();
3031 /* do not allow flush until a session is reloaded */
3033 Glib::RefPtr
<Action
> act
= ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3035 act
->set_sensitive (false);
3038 if (session
->cleanup_sources (rep
)) {
3039 editor
->finish_cleanup ();
3043 editor
->finish_cleanup ();
3046 display_cleanup_results (rep
,
3049 The following %1 files were not in use and \n\
3050 have been moved to:\n\
3052 Flushing the wastebasket will \n\
3053 release an additional\n\
3054 %3 %4bytes of disk space.\n"),
3056 The following file was not in use and \n \
3057 has been moved to:\n \
3059 Flushing the wastebasket will \n\
3060 release an additional\n\
3061 %3 %4bytes of disk space.\n"
3067 ARDOUR_UI::flush_trash ()
3070 /* shouldn't happen: menu item is insensitive */
3074 Session::cleanup_report rep
;
3076 if (session
->cleanup_trash_sources (rep
)) {
3080 display_cleanup_results (rep
,
3082 _("The following %1 files were deleted from\n\
3084 releasing %3 %4bytes of disk space"),
3085 _("The following file was deleted from\n\
3087 releasing %3 %4bytes of disk space"));
3091 ARDOUR_UI::add_route (Gtk::Window
* float_window
)
3099 if (add_route_dialog
== 0) {
3100 add_route_dialog
= new AddRouteDialog
;
3102 add_route_dialog
->set_transient_for (*float_window
);
3106 if (add_route_dialog
->is_visible()) {
3107 /* we're already doing this */
3111 ResponseType r
= (ResponseType
) add_route_dialog
->run ();
3113 add_route_dialog
->hide();
3116 case RESPONSE_ACCEPT
:
3123 if ((count
= add_route_dialog
->count()) <= 0) {
3127 string template_path
= add_route_dialog
->track_template();
3129 if (!template_path
.empty()) {
3130 session
->new_route_from_template (count
, template_path
);
3134 uint32_t input_chan
= add_route_dialog
->channels ();
3135 uint32_t output_chan
;
3136 string name_template
= add_route_dialog
->name_template ();
3137 bool track
= add_route_dialog
->track ();
3139 AutoConnectOption oac
= Config
->get_output_auto_connect();
3141 if (oac
& AutoConnectMaster
) {
3142 output_chan
= (session
->master_out() ? session
->master_out()->n_inputs() : input_chan
);
3144 output_chan
= input_chan
;
3147 /* XXX do something with name template */
3150 session_add_audio_track (input_chan
, output_chan
, add_route_dialog
->mode(), count
);
3152 session_add_audio_bus (input_chan
, output_chan
, count
);
3157 ARDOUR_UI::mixer_settings () const
3162 node
= session
->instant_xml(X_("Mixer"), session
->path());
3164 node
= Config
->instant_xml(X_("Mixer"), get_user_ardour_path());
3168 node
= new XMLNode (X_("Mixer"));
3175 ARDOUR_UI::editor_settings () const
3180 node
= session
->instant_xml(X_("Editor"), session
->path());
3182 node
= Config
->instant_xml(X_("Editor"), get_user_ardour_path());
3186 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3187 node
= Config
->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3192 node
= new XMLNode (X_("Editor"));
3198 ARDOUR_UI::keyboard_settings () const
3202 node
= Config
->extra_xml(X_("Keyboard"));
3205 node
= new XMLNode (X_("Keyboard"));
3211 ARDOUR_UI::create_xrun_marker(nframes_t where
)
3213 editor
->mouse_add_new_marker (where
, false, true);
3217 ARDOUR_UI::halt_on_xrun_message ()
3219 MessageDialog
msg (*editor
,
3220 _("Recording was stopped because your system could not keep up."));
3225 ARDOUR_UI::xrun_handler(nframes_t where
)
3231 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler
), where
));
3233 if (session
&& Config
->get_create_xrun_marker() && session
->actively_recording()) {
3234 create_xrun_marker(where
);
3237 if (session
&& Config
->get_stop_recording_on_xrun() && session
->actively_recording()) {
3238 halt_on_xrun_message ();
3243 ARDOUR_UI::preset_file_exists_handler ()
3245 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3248 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3252 HBox
* hbox
= new HBox();
3253 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3254 Gtk::Dialog
dialog (_("Preset Exists"), true, false);
3256 A preset with this name already exists for this plugin.\n\
3258 What you would like to do?\n"));
3259 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3260 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3261 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3262 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3263 dialog
.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT
);
3264 dialog
.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT
);
3265 dialog
.set_default_response (RESPONSE_ACCEPT
);
3266 dialog
.set_position (WIN_POS_MOUSE
);
3267 dialog
.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY
); // need to make it float above the preset name dialog
3273 switch (dialog
.run ()) {
3274 case RESPONSE_ACCEPT
:
3282 ARDOUR_UI::disk_overrun_handler ()
3285 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
3287 if (!have_disk_speed_dialog_displayed
) {
3288 have_disk_speed_dialog_displayed
= true;
3289 MessageDialog
* msg
= new MessageDialog (*editor
, _("\
3290 The disk system on your computer\n\
3291 was not able to keep up with Ardour.\n\
3293 Specifically, it failed to write data to disk\n\
3294 quickly enough to keep up with recording.\n"));
3295 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3301 ARDOUR_UI::disk_underrun_handler ()
3304 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
3306 if (!have_disk_speed_dialog_displayed
) {
3307 have_disk_speed_dialog_displayed
= true;
3308 MessageDialog
* msg
= new MessageDialog (*editor
,
3309 _("The disk system on your computer\n\
3310 was not able to keep up with Ardour.\n\
3312 Specifically, it failed to read data from disk\n\
3313 quickly enough to keep up with playback.\n"));
3314 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3320 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response
, MessageDialog
* msg
)
3322 have_disk_speed_dialog_displayed
= false;
3327 ARDOUR_UI::session_dialog (std::string msg
)
3329 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog
), msg
));
3334 d
= new MessageDialog (*editor
, msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3336 d
= new MessageDialog (msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3345 ARDOUR_UI::pending_state_dialog ()
3347 HBox
* hbox
= new HBox();
3348 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3349 ArdourDialog
dialog (_("Crash Recovery"), true);
3351 This session appears to have been in\n\
3352 middle of recording when ardour or\n\
3353 the computer was shutdown.\n\
3355 Ardour can recover any captured audio for\n\
3356 you, or it can ignore it. Please decide\n\
3357 what you would like to do.\n"));
3358 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3359 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3360 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3361 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3362 dialog
.add_button (_("Ignore crash data"), RESPONSE_REJECT
);
3363 dialog
.add_button (_("Recover from crash"), RESPONSE_ACCEPT
);
3364 dialog
.set_default_response (RESPONSE_ACCEPT
);
3365 dialog
.set_position (WIN_POS_CENTER
);
3372 switch (dialog
.run ()) {
3373 case RESPONSE_ACCEPT
:
3381 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired
, nframes_t actual
)
3383 HBox
* hbox
= new HBox();
3384 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3385 ArdourDialog
dialog (_("Sample Rate Mismatch"), true);
3386 Label
message (string_compose (_("\
3387 This session was created with a sample rate of %1 Hz\n\
3389 The audioengine is currently running at %2 Hz\n"), desired
, actual
));
3391 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3392 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3393 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3394 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3395 dialog
.add_button (_("Do not load session"), RESPONSE_REJECT
);
3396 dialog
.add_button (_("Load session anyway"), RESPONSE_ACCEPT
);
3397 dialog
.set_default_response (RESPONSE_ACCEPT
);
3398 dialog
.set_position (WIN_POS_CENTER
);
3403 switch (dialog
.run ()) {
3404 case RESPONSE_ACCEPT
:
3413 ARDOUR_UI::disconnect_from_jack ()
3416 if( engine
->disconnect_from_jack ()) {
3417 MessageDialog
msg (*editor
, _("Could not disconnect from JACK"));
3421 update_sample_rate (0);
3426 ARDOUR_UI::reconnect_to_jack ()
3429 if (engine
->reconnect_to_jack ()) {
3430 MessageDialog
msg (*editor
, _("Could not reconnect to JACK"));
3434 update_sample_rate (0);
3439 ARDOUR_UI::use_config ()
3441 Glib::RefPtr
<Action
> act
;
3443 switch (Config
->get_native_file_data_format ()) {
3445 act
= ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3448 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3451 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3456 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3457 ract
->set_active ();
3460 switch (Config
->get_native_file_header_format ()) {
3462 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3465 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3468 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3471 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3474 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3477 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3480 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3485 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3486 ract
->set_active ();
3489 XMLNode
* node
= Config
->extra_xml (X_("TransportControllables"));
3491 set_transport_controllable_state (*node
);
3496 ARDOUR_UI::update_transport_clocks (nframes_t pos
)
3498 if (Config
->get_primary_clock_delta_edit_cursor()) {
3499 primary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 1);
3501 primary_clock
.set (pos
, 0, true);
3504 if (Config
->get_secondary_clock_delta_edit_cursor()) {
3505 secondary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 2);
3507 secondary_clock
.set (pos
);
3510 if (big_clock_window
) {
3511 big_clock
.set (pos
);
3516 ARDOUR_UI::record_state_changed ()
3518 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed
));
3520 if (!session
|| !big_clock_window
) {
3521 /* why bother - the clock isn't visible */
3525 switch (session
->record_status()) {
3526 case Session::Recording
:
3527 big_clock
.set_widget_name ("BigClockRecording");
3530 big_clock
.set_widget_name ("BigClockNonRecording");
3536 ARDOUR_UI::first_idle ()
3539 session
->allow_auto_play (true);
3543 editor
->first_idle();
3546 Keyboard::set_can_save_keybindings (true);
3551 ARDOUR_UI::store_clock_modes ()
3553 XMLNode
* node
= new XMLNode(X_("ClockModes"));
3555 for (vector
<AudioClock
*>::iterator x
= AudioClock::clocks
.begin(); x
!= AudioClock::clocks
.end(); ++x
) {
3556 node
->add_property ((*x
)->name().c_str(), enum_2_string ((*x
)->mode()));
3559 session
->add_extra_xml (*node
);
3560 session
->set_dirty ();
3565 ARDOUR_UI::TransportControllable::TransportControllable (std::string name
, ARDOUR_UI
& u
, ToggleType tp
)
3566 : Controllable (name
), ui (u
), type(tp
)
3572 ARDOUR_UI::TransportControllable::set_value (float val
)
3574 if (type
== ShuttleControl
) {
3581 fract
= -((0.5f
- val
)/0.5f
);
3583 fract
= ((val
- 0.5f
)/0.5f
);
3587 ui
.set_shuttle_fract (fract
);
3592 /* do nothing: these are radio-style actions */
3596 const char *action
= 0;
3600 action
= X_("Roll");
3603 action
= X_("Stop");
3606 action
= X_("Goto Start");
3609 action
= X_("Goto End");
3612 action
= X_("Loop");
3615 action
= X_("Play Selection");
3618 action
= X_("Record");
3628 Glib::RefPtr
<Action
> act
= ActionManager::get_action ("Transport", action
);
3636 ARDOUR_UI::TransportControllable::get_value (void) const
3655 case ShuttleControl
:
3665 ARDOUR_UI::TransportControllable::set_id (const string
& str
)
3671 ARDOUR_UI::setup_profile ()
3673 if (gdk_screen_width() < 1200) {
3674 Profile
->set_small_screen ();
3677 if (getenv ("ARDOUR_SAE")) {
3678 Profile
->set_sae ();
3679 Profile
->set_single_package ();
3685 ARDOUR_UI::toggle_translations ()
3687 using namespace Glib
;
3689 RefPtr
<Action
> act
= ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3691 RefPtr
<ToggleAction
> ract
= RefPtr
<ToggleAction
>::cast_dynamic (act
);
3694 string i18n_killer
= ARDOUR::translation_kill_path();
3696 bool already_enabled
= !ARDOUR::translations_are_disabled ();
3698 if (ract
->get_active ()) {
3699 /* we don't care about errors */
3700 int fd
= ::open (i18n_killer
.c_str(), O_RDONLY
|O_CREAT
, 0644);
3703 /* we don't care about errors */
3704 unlink (i18n_killer
.c_str());
3707 if (already_enabled
!= ract
->get_active()) {
3708 MessageDialog
win (already_enabled
? _("Translations disabled") : _("Translations enabled"),
3710 Gtk::MESSAGE_WARNING
,
3712 win
.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME
));
3713 win
.set_position (Gtk::WIN_POS_CENTER
);