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>
70 typedef uint64_t microseconds_t
;
73 #include "ardour_ui.h"
74 #include "public_editor.h"
75 #include "audio_clock.h"
80 #include "add_route_dialog.h"
81 #include "new_session_dialog.h"
86 #include "gui_thread.h"
87 #include "theme_manager.h"
88 #include "engine_dialog.h"
89 #include "gain_meter.h"
90 #include "route_time_axis.h"
94 using namespace ARDOUR
;
96 using namespace Gtkmm2ext
;
100 ARDOUR_UI
*ARDOUR_UI::theArdourUI
= 0;
101 UIConfiguration
*ARDOUR_UI::ui_config
= 0;
103 sigc::signal
<void,bool> ARDOUR_UI::Blink
;
104 sigc::signal
<void> ARDOUR_UI::RapidScreenUpdate
;
105 sigc::signal
<void> ARDOUR_UI::SuperRapidScreenUpdate
;
106 sigc::signal
<void,nframes_t
, bool, nframes_t
> ARDOUR_UI::Clock
;
108 ARDOUR_UI::ARDOUR_UI (int *argcp
, char **argvp
[])
110 : Gtkmm2ext::UI (PROGRAM_NAME
, argcp
, argvp
),
112 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
113 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
114 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
115 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
119 preroll_button (_("pre\nroll")),
120 postroll_button (_("post\nroll")),
124 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
128 roll_controllable ("transport roll", *this, TransportControllable::Roll
),
129 stop_controllable ("transport stop", *this, TransportControllable::Stop
),
130 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart
),
131 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd
),
132 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop
),
133 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection
),
134 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable
),
135 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl
),
136 shuttle_controller_binding_proxy (shuttle_controllable
),
138 roll_button (&roll_controllable
),
139 stop_button (&stop_controllable
),
140 goto_start_button (&goto_start_controllable
),
141 goto_end_button (&goto_end_controllable
),
142 auto_loop_button (&auto_loop_controllable
),
143 play_selection_button (&play_selection_controllable
),
144 rec_button (&rec_controllable
),
146 shuttle_units_button (_("% ")),
148 punch_in_button (_("Punch In")),
149 punch_out_button (_("Punch Out")),
150 auto_return_button (_("Auto Return")),
151 auto_play_button (_("Auto Play")),
152 auto_input_button (_("Auto Input")),
153 click_button (_("Click")),
154 time_master_button (_("time\nmaster")),
156 auditioning_alert_button (_("AUDITION")),
157 solo_alert_button (_("SOLO")),
159 error_log_button (_("Errors"))
161 using namespace Gtk::Menu_Helpers
;
166 _auto_display_errors
= false;
172 if (ARDOUR_COMMAND_LINE::session_name
.length()) {
173 /* only show this if we're not going to post the new session dialog */
177 if (theArdourUI
== 0) {
181 ui_config
= new UIConfiguration();
182 theme_manager
= new ThemeManager();
188 _session_is_new
= false;
189 big_clock_window
= 0;
190 session_selector_window
= 0;
191 new_session_dialog
= 0;
192 last_key_press_time
= 0;
193 connection_editor
= 0;
194 add_route_dialog
= 0;
199 open_session_selector
= 0;
200 have_configure_timeout
= false;
201 have_disk_speed_dialog_displayed
= false;
202 _will_create_new_session_automatically
= false;
203 session_loaded
= false;
204 last_speed_displayed
= -1.0f
;
205 ignore_dual_punch
= false;
206 _mixer_on_top
= false;
208 roll_button
.unset_flags (Gtk::CAN_FOCUS
);
209 stop_button
.unset_flags (Gtk::CAN_FOCUS
);
210 goto_start_button
.unset_flags (Gtk::CAN_FOCUS
);
211 goto_end_button
.unset_flags (Gtk::CAN_FOCUS
);
212 auto_loop_button
.unset_flags (Gtk::CAN_FOCUS
);
213 play_selection_button
.unset_flags (Gtk::CAN_FOCUS
);
214 rec_button
.unset_flags (Gtk::CAN_FOCUS
);
216 last_configure_time
= 0;
218 shuttle_grabbed
= false;
220 shuttle_max_speed
= 8.0f
;
222 shuttle_style_menu
= 0;
223 shuttle_unit_menu
= 0;
225 // We do not have jack linked in yet so;
227 last_shuttle_request
= last_peak_grab
= 0; // get_microseconds();
229 ARDOUR::Diskstream::DiskOverrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
230 ARDOUR::Diskstream::DiskUnderrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
232 ARDOUR::Plugin::PresetFileExists
.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler
));
234 /* handle dialog requests */
236 ARDOUR::Session::Dialog
.connect (mem_fun(*this, &ARDOUR_UI::session_dialog
));
238 /* handle pending state with a dialog */
240 ARDOUR::Session::AskAboutPendingState
.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog
));
242 /* handle sr mismatch with a dialog */
244 ARDOUR::Session::AskAboutSampleRateMismatch
.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog
));
246 /* lets get this party started */
249 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst
, ARDOUR_COMMAND_LINE::try_hw_optimization
)) {
250 throw failed_constructor ();
253 setup_gtk_ardour_enums ();
254 Config
->set_current_owner (ConfigVariableBase::Interface
);
257 GainMeter::setup_slider_pix ();
258 RouteTimeAxisView::setup_slider_pix ();
260 } catch (failed_constructor
& err
) {
261 error
<< string_compose (_("could not initialize %1."), PROGRAM_NAME
) << endmsg
;
266 /* we like keyboards */
268 keyboard
= new Keyboard
;
272 starting
.connect (mem_fun(*this, &ARDOUR_UI::startup
));
273 stopping
.connect (mem_fun(*this, &ARDOUR_UI::shutdown
));
279 ARDOUR_UI::create_engine ()
281 // this gets called every time by new_session()
287 loading_message (_("Starting audio engine"));
290 engine
= new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name
);
297 engine
->Stopped
.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
298 engine
->Running
.connect (mem_fun(*this, &ARDOUR_UI::engine_running
));
299 engine
->Halted
.connect (bind (mem_fun(*this, &ARDOUR_UI::engine_halted
), false));
300 engine
->SampleRateChanged
.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate
));
308 ARDOUR_UI::post_engine ()
310 /* Things to be done once we create the AudioEngine
313 check_memory_locking();
315 ActionManager::init ();
318 if (setup_windows ()) {
319 throw failed_constructor ();
322 /* this is the first point at which all the keybindings are available */
324 if (ARDOUR_COMMAND_LINE::show_key_actions
) {
325 vector
<string
> names
;
326 vector
<string
> paths
;
328 vector
<AccelKey
> bindings
;
330 ActionManager::get_all_actions (names
, paths
, keys
, bindings
);
332 vector
<string
>::iterator n
;
333 vector
<string
>::iterator k
;
334 for (n
= names
.begin(), k
= keys
.begin(); n
!= names
.end(); ++n
, ++k
) {
335 cerr
<< "Action: " << (*n
) << " bound to " << (*k
) << endl
;
341 blink_timeout_tag
= -1;
343 /* the global configuration object is now valid */
347 /* this being a GUI and all, we want peakfiles */
349 AudioFileSource::set_build_peakfiles (true);
350 AudioFileSource::set_build_missing_peakfiles (true);
352 /* set default clock modes */
354 if (Profile
->get_sae()) {
355 primary_clock
.set_mode (AudioClock::BBT
);
356 secondary_clock
.set_mode (AudioClock::MinSec
);
358 primary_clock
.set_mode (AudioClock::SMPTE
);
359 secondary_clock
.set_mode (AudioClock::BBT
);
362 /* start the time-of-day-clock */
365 /* OS X provides an always visible wallclock, so don't be stupid */
366 update_wall_clock ();
367 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock
), 60000);
370 update_disk_space ();
372 update_sample_rate (engine
->frame_rate());
374 platform_specific ();
376 /* now start and maybe save state */
378 if (do_engine_start () == 0) {
379 if (session
&& _session_is_new
) {
380 /* we need to retain initial visual
381 settings for a new session
383 session
->save_state ("");
388 ARDOUR_UI::~ARDOUR_UI ()
390 save_ardour_state ();
404 if (add_route_dialog
) {
405 delete add_route_dialog
;
408 if (new_session_dialog
) {
409 delete new_session_dialog
;
414 ARDOUR_UI::pop_back_splash ()
416 if (Splash::instance()) {
417 // Splash::instance()->pop_back();
418 Splash::instance()->hide ();
423 ARDOUR_UI::configure_timeout ()
425 if (last_configure_time
== 0) {
426 /* no configure events yet */
430 /* force a gap of 0.5 seconds since the last configure event
433 if (get_microseconds() - last_configure_time
< 500000) {
436 have_configure_timeout
= false;
437 save_ardour_state ();
443 ARDOUR_UI::configure_handler (GdkEventConfigure
* conf
)
445 if (have_configure_timeout
) {
446 last_configure_time
= get_microseconds();
448 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout
), 100);
449 have_configure_timeout
= true;
456 ARDOUR_UI::set_transport_controllable_state (const XMLNode
& node
)
458 const XMLProperty
* prop
;
460 if ((prop
= node
.property ("roll")) != 0) {
461 roll_controllable
.set_id (prop
->value());
463 if ((prop
= node
.property ("stop")) != 0) {
464 stop_controllable
.set_id (prop
->value());
466 if ((prop
= node
.property ("goto_start")) != 0) {
467 goto_start_controllable
.set_id (prop
->value());
469 if ((prop
= node
.property ("goto_end")) != 0) {
470 goto_end_controllable
.set_id (prop
->value());
472 if ((prop
= node
.property ("auto_loop")) != 0) {
473 auto_loop_controllable
.set_id (prop
->value());
475 if ((prop
= node
.property ("play_selection")) != 0) {
476 play_selection_controllable
.set_id (prop
->value());
478 if ((prop
= node
.property ("rec")) != 0) {
479 rec_controllable
.set_id (prop
->value());
481 if ((prop
= node
.property ("shuttle")) != 0) {
482 shuttle_controllable
.set_id (prop
->value());
487 ARDOUR_UI::get_transport_controllable_state ()
489 XMLNode
* node
= new XMLNode(X_("TransportControllables"));
492 roll_controllable
.id().print (buf
, sizeof (buf
));
493 node
->add_property (X_("roll"), buf
);
494 stop_controllable
.id().print (buf
, sizeof (buf
));
495 node
->add_property (X_("stop"), buf
);
496 goto_start_controllable
.id().print (buf
, sizeof (buf
));
497 node
->add_property (X_("goto_start"), buf
);
498 goto_end_controllable
.id().print (buf
, sizeof (buf
));
499 node
->add_property (X_("goto_end"), buf
);
500 auto_loop_controllable
.id().print (buf
, sizeof (buf
));
501 node
->add_property (X_("auto_loop"), buf
);
502 play_selection_controllable
.id().print (buf
, sizeof (buf
));
503 node
->add_property (X_("play_selection"), buf
);
504 rec_controllable
.id().print (buf
, sizeof (buf
));
505 node
->add_property (X_("rec"), buf
);
506 shuttle_controllable
.id().print (buf
, sizeof (buf
));
507 node
->add_property (X_("shuttle"), buf
);
513 ARDOUR_UI::save_ardour_state ()
515 if (!keyboard
|| !mixer
|| !editor
) {
519 /* XXX this is all a bit dubious. add_extra_xml() uses
520 a different lifetime model from add_instant_xml().
523 XMLNode
* node
= new XMLNode (keyboard
->get_state());
524 Config
->add_extra_xml (*node
);
525 Config
->add_extra_xml (get_transport_controllable_state());
526 if (new_session_dialog
) {
527 if (new_session_dialog
->engine_control
.was_used()) {
528 Config
->add_extra_xml (new_session_dialog
->engine_control
.get_state());
531 Config
->save_state();
532 ui_config
->save_state ();
534 XMLNode
enode(static_cast<Stateful
*>(editor
)->get_state());
535 XMLNode
mnode(mixer
->get_state());
538 session
->add_instant_xml (enode
, session
->path());
539 session
->add_instant_xml (mnode
, session
->path());
541 Config
->add_instant_xml (enode
, get_user_ardour_path());
542 Config
->add_instant_xml (mnode
, get_user_ardour_path());
545 Keyboard::save_keybindings ();
549 ARDOUR_UI::autosave_session ()
551 if (g_main_depth() > 1) {
552 /* inside a recursive main loop,
553 give up because we may not be able to
559 if (!Config
->get_periodic_safety_backups())
563 session
->maybe_write_autosave();
570 ARDOUR_UI::update_autosave ()
572 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave
));
574 if (session
&& session
->dirty()) {
575 if (_autosave_connection
.connected()) {
576 _autosave_connection
.disconnect();
579 _autosave_connection
= Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session
),
580 Config
->get_periodic_safety_backup_interval() * 1000);
583 if (_autosave_connection
.connected()) {
584 _autosave_connection
.disconnect();
590 ARDOUR_UI::backend_audio_error (bool we_set_params
, Gtk::Window
* toplevel
)
594 title
= string_compose (_("%1 could not start JACK"), PROGRAM_NAME
);
596 title
= string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME
);
599 MessageDialog
win (title
,
605 win
.set_secondary_text(_("There are several possible reasons:\n\
607 1) You requested audio parameters that are not supported..\n\
608 2) JACK is running as another user.\n\
610 Please consider the possibilities, and perhaps try different parameters."));
612 win
.set_secondary_text(_("There are several possible reasons:\n\
614 1) JACK is not running.\n\
615 2) JACK is running as another user, perhaps root.\n\
616 3) There is already another client called \"ardour\".\n\
618 Please consider the possibilities, and perhaps (re)start JACK."));
622 win
.set_transient_for (*toplevel
);
626 win
.add_button (Stock::OK
, RESPONSE_CLOSE
);
628 win
.add_button (Stock::QUIT
, RESPONSE_CLOSE
);
631 win
.set_default_response (RESPONSE_CLOSE
);
634 win
.set_position (Gtk::WIN_POS_CENTER
);
637 /* we just don't care about the result, but we want to block */
643 ARDOUR_UI::startup ()
647 new_session_dialog
= new NewSessionDialog();
649 bool backend_audio_is_running
= EngineControl::engine_running();
650 XMLNode
* audio_setup
= Config
->extra_xml ("AudioSetup");
653 new_session_dialog
->engine_control
.set_state (*audio_setup
);
656 if (!get_session_parameters (backend_audio_is_running
, ARDOUR_COMMAND_LINE::new_session
)) {
660 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME
));
665 ARDOUR_UI::no_memory_warning ()
667 XMLNode
node (X_("no-memory-warning"));
668 Config
->add_instant_xml (node
, get_user_ardour_path());
672 ARDOUR_UI::check_memory_locking ()
675 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
679 XMLNode
* memory_warning_node
= Config
->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
681 if (engine
->is_realtime() && memory_warning_node
== 0) {
683 struct rlimit limits
;
685 long pages
, page_size
;
687 if ((page_size
= sysconf (_SC_PAGESIZE
)) < 0 ||(pages
= sysconf (_SC_PHYS_PAGES
)) < 0) {
690 ram
= (int64_t) pages
* (int64_t) page_size
;
693 if (getrlimit (RLIMIT_MEMLOCK
, &limits
)) {
697 if (limits
.rlim_cur
!= RLIM_INFINITY
) {
699 if (ram
== 0 || ((double) limits
.rlim_cur
/ ram
) < 0.75) {
702 MessageDialog
msg (string_compose (_("WARNING: Your system has a limit for maximum amount of locked memory. "
703 "This might cause %1 to run out of memory before your system "
704 "runs out of memory. \n\n"
705 "You can view the memory limit with 'ulimit -l', "
706 "and it is normally controlled by /etc/security/limits.conf"), PROGRAM_NAME
));
708 VBox
* vbox
= msg
.get_vbox();
710 CheckButton
cb (_("Do not show this window again"));
712 cb
.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning
));
714 hbox
.pack_start (cb
, true, false);
715 vbox
->pack_start (hbox
);
728 ARDOUR_UI::queue_finish ()
730 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish
));
734 ARDOUR_UI::idle_finish ()
737 return false; /* do not call again */
747 while (session
->transport_rolling() && (++tries
< 8)) {
748 /* stop but do not abort capture */
749 session
->request_stop (false, true);
753 if (session
->dirty()) {
754 switch (ask_about_saving_session(_("quit"))) {
759 /* use the default name */
760 if (save_state_canfail ("")) {
761 /* failed - don't quit */
762 MessageDialog
msg (*editor
,
764 Ardour was unable to save your session.\n\n\
765 If you still wish to quit, please use the\n\n\
766 \"Just quit\" option."));
777 session
->set_clean();
778 session
->set_deletion_in_progress ();
779 unload_session(true);
782 ArdourDialog::close_all_dialogs ();
784 save_ardour_state ();
789 ARDOUR_UI::ask_about_saving_session (const string
& what
)
791 ArdourDialog
window (_("ardour: save session?"));
792 Gtk::HBox dhbox
; // the hbox for the image and text
793 Gtk::Label prompt_label
;
794 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_WARNING
, Gtk::ICON_SIZE_DIALOG
));
798 msg
= string_compose(_("Don't %1"), what
);
799 window
.add_button (msg
, RESPONSE_REJECT
);
800 msg
= string_compose(_("Just %1"), what
);
801 window
.add_button (msg
, RESPONSE_APPLY
);
802 msg
= string_compose(_("Save and %1"), what
);
803 window
.add_button (msg
, RESPONSE_ACCEPT
);
805 window
.set_default_response (RESPONSE_ACCEPT
);
807 Gtk::Button
noquit_button (msg
);
808 noquit_button
.set_name ("EditorGTKButton");
813 if (session
->snap_name() == session
->name()) {
816 type
= _("snapshot");
818 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?"),
819 type
, session
->snap_name());
821 prompt_label
.set_text (prompt
);
822 prompt_label
.set_name (X_("PrompterLabel"));
823 prompt_label
.set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
825 dimage
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
)
827 dhbox
.set_homogeneous (false);
828 dhbox
.pack_start (*dimage
, false, false, 5);
829 dhbox
.pack_start (prompt_label
, true, false, 5);
830 window
.get_vbox()->pack_start (dhbox
);
832 window
.set_name (_("Prompter"));
833 window
.set_position (Gtk::WIN_POS_MOUSE
);
834 window
.set_modal (true);
835 window
.set_resizable (false);
838 window
.set_keep_above (true);
841 ResponseType r
= (ResponseType
) window
.run();
846 case RESPONSE_ACCEPT
: // save and get out of here
848 case RESPONSE_APPLY
: // get out of here
858 ARDOUR_UI::every_second ()
861 update_buffer_load ();
862 update_disk_space ();
867 ARDOUR_UI::every_point_one_seconds ()
869 update_speed_display ();
870 RapidScreenUpdate(); /* EMIT_SIGNAL */
875 ARDOUR_UI::every_point_zero_one_seconds ()
877 // august 2007: actual update frequency: 40Hz, not 100Hz
879 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
884 ARDOUR_UI::update_sample_rate (nframes_t ignored
)
888 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate
), ignored
));
890 if (!engine
->connected()) {
892 snprintf (buf
, sizeof (buf
), _("disconnected"));
896 nframes_t rate
= engine
->frame_rate();
898 if (fmod (rate
, 1000.0) != 0.0) {
899 snprintf (buf
, sizeof (buf
), _("%.1f kHz / %4.1f ms"),
900 (float) rate
/1000.0f
,
901 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
903 snprintf (buf
, sizeof (buf
), _("%u kHz / %4.1f ms"),
905 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
909 sample_rate_label
.set_text (buf
);
913 ARDOUR_UI::update_cpu_load ()
916 snprintf (buf
, sizeof (buf
), _("DSP: %5.1f%%"), engine
->get_cpu_load());
917 cpu_load_label
.set_text (buf
);
921 ARDOUR_UI::update_buffer_load ()
927 c
= session
->capture_load ();
928 p
= session
->playback_load ();
930 push_buffer_stats (c
, p
);
932 snprintf (buf
, sizeof (buf
), _("Buffers p:%" PRIu32
"%% c:%" PRIu32
"%%"),
933 session
->playback_load(), session
->capture_load());
934 buffer_load_label
.set_text (buf
);
936 buffer_load_label
.set_text ("");
941 ARDOUR_UI::count_recenabled_streams (Route
& route
)
943 Track
* track
= dynamic_cast<Track
*>(&route
);
944 if (track
&& track
->diskstream()->record_enabled()) {
945 rec_enabled_streams
+= track
->n_inputs();
950 ARDOUR_UI::update_disk_space()
956 nframes_t frames
= session
->available_capture_duration();
959 if (frames
== max_frames
) {
960 strcpy (buf
, _("Disk: 24hrs+"));
965 nframes_t fr
= session
->frame_rate();
967 rec_enabled_streams
= 0;
968 session
->foreach_route (this, &ARDOUR_UI::count_recenabled_streams
);
970 if (rec_enabled_streams
) {
971 frames
/= rec_enabled_streams
;
974 hrs
= frames
/ (fr
* 3600);
975 frames
-= hrs
* fr
* 3600;
976 mins
= frames
/ (fr
* 60);
977 frames
-= mins
* fr
* 60;
980 snprintf (buf
, sizeof(buf
), _("Disk: %02dh:%02dm:%02ds"), hrs
, mins
, secs
);
983 disk_space_label
.set_text (buf
);
987 ARDOUR_UI::update_wall_clock ()
994 tm_now
= localtime (&now
);
996 sprintf (buf
, "%02d:%02d", tm_now
->tm_hour
, tm_now
->tm_min
);
997 wall_clock_label
.set_text (buf
);
1003 ARDOUR_UI::session_menu (GdkEventButton
*ev
)
1005 session_popup_menu
->popup (0, 0);
1010 ARDOUR_UI::redisplay_recent_sessions ()
1012 vector
<string
*> *sessions
;
1013 vector
<string
*>::iterator i
;
1014 RecentSessionsSorter cmp
;
1016 recent_session_display
.set_model (Glib::RefPtr
<TreeModel
>(0));
1017 recent_session_model
->clear ();
1020 ARDOUR::read_recent_sessions (rs
);
1023 recent_session_display
.set_model (recent_session_model
);
1027 /* sort them alphabetically */
1028 sort (rs
.begin(), rs
.end(), cmp
);
1029 sessions
= new vector
<string
*>;
1031 for (RecentSessions::iterator i
= rs
.begin(); i
!= rs
.end(); ++i
) {
1032 sessions
->push_back (new string ((*i
).second
));
1035 for (i
= sessions
->begin(); i
!= sessions
->end(); ++i
) {
1037 vector
<string
*>* states
;
1038 vector
<const gchar
*> item
;
1039 string fullpath
= *(*i
);
1041 /* remove any trailing / */
1043 if (fullpath
[fullpath
.length()-1] == '/') {
1044 fullpath
= fullpath
.substr (0, fullpath
.length()-1);
1047 /* check whether session still exists */
1048 if (!Glib::file_test(fullpath
.c_str(), Glib::FILE_TEST_EXISTS
)) {
1049 /* session doesn't exist */
1050 cerr
<< "skipping non-existent session " << fullpath
<< endl
;
1054 /* now get available states for this session */
1056 if ((states
= Session::possible_states (fullpath
)) == 0) {
1057 /* no state file? */
1061 TreeModel::Row row
= *(recent_session_model
->append());
1063 row
[recent_session_columns
.visible_name
] = Glib::path_get_basename (fullpath
);
1064 row
[recent_session_columns
.fullpath
] = fullpath
;
1066 if (states
->size() > 1) {
1068 /* add the children */
1070 for (vector
<string
*>::iterator i2
= states
->begin(); i2
!= states
->end(); ++i2
) {
1072 TreeModel::Row child_row
= *(recent_session_model
->append (row
.children()));
1074 child_row
[recent_session_columns
.visible_name
] = **i2
;
1075 child_row
[recent_session_columns
.fullpath
] = fullpath
;
1084 recent_session_display
.set_model (recent_session_model
);
1089 ARDOUR_UI::build_session_selector ()
1091 session_selector_window
= new ArdourDialog ("session selector");
1093 Gtk::ScrolledWindow
*scroller
= manage (new Gtk::ScrolledWindow
);
1095 session_selector_window
->add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
1096 session_selector_window
->add_button (Stock::OPEN
, RESPONSE_ACCEPT
);
1097 session_selector_window
->set_default_response (RESPONSE_ACCEPT
);
1098 recent_session_model
= TreeStore::create (recent_session_columns
);
1099 recent_session_display
.set_model (recent_session_model
);
1100 recent_session_display
.append_column (_("Recent Sessions"), recent_session_columns
.visible_name
);
1101 recent_session_display
.set_headers_visible (false);
1102 recent_session_display
.get_selection()->set_mode (SELECTION_BROWSE
);
1103 recent_session_display
.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated
));
1105 scroller
->add (recent_session_display
);
1106 scroller
->set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
1108 session_selector_window
->set_name ("SessionSelectorWindow");
1109 session_selector_window
->set_size_request (200, 400);
1110 session_selector_window
->get_vbox()->pack_start (*scroller
);
1111 session_selector_window
->show_all_children();
1115 ARDOUR_UI::recent_session_row_activated (const TreePath
& path
, TreeViewColumn
* col
)
1117 session_selector_window
->response (RESPONSE_ACCEPT
);
1121 ARDOUR_UI::open_recent_session ()
1123 bool can_return
= (session
!= 0);
1125 if (session_selector_window
== 0) {
1126 build_session_selector ();
1129 redisplay_recent_sessions ();
1133 session_selector_window
->set_position (WIN_POS_MOUSE
);
1135 ResponseType r
= (ResponseType
) session_selector_window
->run ();
1138 case RESPONSE_ACCEPT
:
1142 session_selector_window
->hide();
1149 if (recent_session_display
.get_selection()->count_selected_rows() == 0) {
1153 session_selector_window
->hide();
1155 Gtk::TreeModel::iterator i
= recent_session_display
.get_selection()->get_selected();
1157 if (i
== recent_session_model
->children().end()) {
1161 Glib::ustring path
= (*i
)[recent_session_columns
.fullpath
];
1162 Glib::ustring state
= (*i
)[recent_session_columns
.visible_name
];
1164 _session_is_new
= false;
1166 if (load_session (path
, state
) == 0) {
1175 ARDOUR_UI::check_audioengine ()
1178 if (!engine
->connected()) {
1179 MessageDialog
msg (string_compose (_("%1 is not connected to JACK\n"
1180 "You cannot open or close sessions in this condition"), PROGRAM_NAME
));
1182 msg
.set_position (WIN_POS_CENTER
);
1193 ARDOUR_UI::open_session ()
1195 if (!check_audioengine()) {
1199 /* popup selector window */
1201 if (open_session_selector
== 0) {
1203 /* ardour sessions are folders */
1205 open_session_selector
= new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN
);
1206 open_session_selector
->add_button (Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
1207 open_session_selector
->add_button (Gtk::Stock::OPEN
, Gtk::RESPONSE_ACCEPT
);
1208 open_session_selector
->set_default_response(Gtk::RESPONSE_ACCEPT
);
1210 FileFilter session_filter
;
1211 session_filter
.add_pattern ("*.ardour");
1212 session_filter
.set_name (_("Ardour sessions"));
1213 open_session_selector
->add_filter (session_filter
);
1214 open_session_selector
->set_filter (session_filter
);
1217 int response
= open_session_selector
->run();
1218 open_session_selector
->hide ();
1221 case RESPONSE_ACCEPT
:
1224 open_session_selector
->hide();
1228 open_session_selector
->hide();
1229 string session_path
= open_session_selector
->get_filename();
1233 if (session_path
.length() > 0) {
1234 if (Session::find_session (session_path
, path
, name
, isnew
) == 0) {
1235 _session_is_new
= isnew
;
1236 load_session (path
, name
);
1243 ARDOUR_UI::session_add_midi_track ()
1245 cerr
<< _("Patience is a virtue.\n");
1249 ARDOUR_UI::session_add_audio_route (bool track
, int32_t input_channels
, int32_t output_channels
, ARDOUR::TrackMode mode
, uint32_t how_many
)
1251 list
<boost::shared_ptr
<AudioTrack
> > tracks
;
1252 Session::RouteList routes
;
1255 warning
<< _("You cannot add a track or bus without a session already loaded.") << endmsg
;
1261 tracks
= session
->new_audio_track (input_channels
, output_channels
, mode
, how_many
);
1263 if (tracks
.size() != how_many
) {
1264 if (how_many
== 1) {
1265 error
<< _("could not create a new audio track") << endmsg
;
1267 error
<< string_compose (_("could only create %1 of %2 new audio %3"),
1268 tracks
.size(), how_many
, (track
? _("tracks") : _("busses"))) << endmsg
;
1274 routes
= session
->new_audio_route (input_channels
, output_channels
, how_many
);
1276 if (routes
.size() != how_many
) {
1277 if (how_many
== 1) {
1278 error
<< _("could not create a new audio track") << endmsg
;
1280 error
<< string_compose (_("could not create %1 new audio tracks"), how_many
) << endmsg
;
1286 if (need_control_room_outs
) {
1292 route
->set_stereo_control_outs (control_lr_channels
);
1293 route
->control_outs()->set_stereo_pan (pans
, this);
1295 #endif /* CONTROLOUTS */
1299 MessageDialog
msg (*editor
,
1300 _("There are insufficient JACK ports available\n\
1301 to create a new track or bus.\n\
1302 You should save Ardour, exit and\n\
1303 restart JACK with more ports."));
1310 ARDOUR_UI::do_transport_locate (nframes_t new_position
)
1312 nframes_t _preroll
= 0;
1315 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1316 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1318 if (new_position
> _preroll
) {
1319 new_position
-= _preroll
;
1324 session
->request_locate (new_position
);
1329 ARDOUR_UI::transport_goto_start ()
1332 session
->goto_start();
1335 /* force displayed area in editor to start no matter
1336 what "follow playhead" setting is.
1340 editor
->reset_x_origin (session
->current_start_frame());
1346 ARDOUR_UI::transport_goto_zero ()
1349 session
->request_locate (0);
1352 /* force displayed area in editor to start no matter
1353 what "follow playhead" setting is.
1357 editor
->reset_x_origin (0);
1363 ARDOUR_UI::transport_goto_wallclock ()
1365 if (session
&& editor
) {
1372 localtime_r (&now
, &tmnow
);
1374 frames
= tmnow
.tm_hour
* (60 * 60 * session
->frame_rate());
1375 frames
+= tmnow
.tm_min
* (60 * session
->frame_rate());
1376 frames
+= tmnow
.tm_sec
* session
->frame_rate();
1378 session
->request_locate (frames
);
1380 /* force displayed area in editor to start no matter
1381 what "follow playhead" setting is.
1385 editor
->reset_x_origin (frames
- (editor
->current_page_frames()/2));
1391 ARDOUR_UI::transport_goto_end ()
1394 nframes_t frame
= session
->current_end_frame();
1395 session
->request_locate (frame
);
1397 /* force displayed area in editor to start no matter
1398 what "follow playhead" setting is.
1402 editor
->reset_x_origin (frame
);
1408 ARDOUR_UI::transport_stop ()
1414 if (session
->is_auditioning()) {
1415 session
->cancel_audition ();
1419 session
->request_stop (false, true);
1423 ARDOUR_UI::transport_stop_and_forget_capture ()
1426 session
->request_stop (true, true);
1431 ARDOUR_UI::remove_last_capture()
1434 editor
->remove_last_capture();
1439 ARDOUR_UI::transport_record (bool roll
)
1443 switch (session
->record_status()) {
1444 case Session::Disabled
:
1445 if (session
->ntracks() == 0) {
1446 MessageDialog
msg (*editor
, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1450 session
->maybe_enable_record ();
1455 case Session::Recording
:
1457 session
->request_stop();
1459 session
->disable_record (false, true);
1463 case Session::Enabled
:
1464 session
->disable_record (false, true);
1467 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1471 ARDOUR_UI::transport_roll ()
1477 if (session
->is_auditioning()) {
1481 switch (Config
->get_slave_source()) {
1486 /* transport controlled by the master */
1490 bool rolling
= session
->transport_rolling();
1492 if (session
->get_play_loop()) {
1493 /* XXX it is not possible to just leave seamless loop and keep
1494 playing at present (nov 4th 2009)
1496 if (!Config
->get_seamless_loop()) {
1498 session
->request_play_loop (false, true);
1502 } else if (session
->get_play_range ()) {
1503 session
->request_play_range (0, true);
1507 session
->request_transport_speed (1.0f
);
1510 map_transport_state ();
1514 ARDOUR_UI::toggle_roll (bool with_abort
, bool roll_out_of_bounded_mode
)
1521 if (session
->is_auditioning()) {
1522 session
->cancel_audition ();
1526 switch (Config
->get_slave_source()) {
1531 /* transport controlled by the master */
1535 bool rolling
= session
->transport_rolling();
1536 bool affect_transport
= true;
1538 if (rolling
&& roll_out_of_bounded_mode
) {
1539 /* drop out of loop/range playback but leave transport rolling */
1540 if (session
->get_play_loop()) {
1541 if (Config
->get_seamless_loop()) {
1542 /* the disk buffers contain copies of the loop - we can't
1543 just keep playing, so stop the transport. the user
1544 can restart as they wish.
1546 affect_transport
= true;
1548 /* disk buffers are normal, so we can keep playing */
1549 affect_transport
= false;
1551 session
->request_play_loop (false, true);
1552 } else if (session
->get_play_range ()) {
1553 affect_transport
= false;
1554 session
->request_play_range (0, true);
1558 if (affect_transport
) {
1560 session
->request_stop (with_abort
, true);
1562 session
->request_transport_speed (1.0f
);
1566 map_transport_state ();
1570 ARDOUR_UI::toggle_session_auto_loop ()
1573 if (session
->get_play_loop()) {
1574 if (session
->transport_rolling()) {
1575 Location
* looploc
= session
->locations()->auto_loop_location();
1577 session
->request_locate (looploc
->start(), true);
1580 session
->request_play_loop (false);
1583 Location
* looploc
= session
->locations()->auto_loop_location();
1585 session
->request_play_loop (true);
1592 ARDOUR_UI::transport_play_selection ()
1598 editor
->play_selection ();
1602 ARDOUR_UI::transport_rewind (int option
)
1604 float current_transport_speed
;
1607 current_transport_speed
= session
->transport_speed();
1609 if (current_transport_speed
>= 0.0f
) {
1612 session
->request_transport_speed (-1.0f
);
1615 session
->request_transport_speed (-4.0f
);
1618 session
->request_transport_speed (-0.5f
);
1623 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1629 ARDOUR_UI::transport_forward (int option
)
1631 float current_transport_speed
;
1634 current_transport_speed
= session
->transport_speed();
1636 if (current_transport_speed
<= 0.0f
) {
1639 session
->request_transport_speed (1.0f
);
1642 session
->request_transport_speed (4.0f
);
1645 session
->request_transport_speed (0.5f
);
1650 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1656 ARDOUR_UI::toggle_record_enable (uint32_t dstream
)
1662 boost::shared_ptr
<Route
> r
;
1664 if ((r
= session
->route_by_remote_id (dstream
)) != 0) {
1668 if ((t
= dynamic_cast<Track
*>(r
.get())) != 0) {
1669 t
->diskstream()->set_record_enabled (!t
->diskstream()->record_enabled());
1678 ARDOUR_UI::queue_transport_change ()
1680 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state
));
1684 ARDOUR_UI::map_transport_state ()
1687 auto_loop_button
.set_visual_state (0);
1688 play_selection_button
.set_visual_state (0);
1689 roll_button
.set_visual_state (0);
1690 stop_button
.set_visual_state (1);
1694 float sp
= session
->transport_speed();
1697 shuttle_fract
= SHUTTLE_FRACT_SPEED1
; /* speed = 1.0, believe it or not */
1698 shuttle_box
.queue_draw ();
1699 } else if (sp
== 0.0f
) {
1701 shuttle_box
.queue_draw ();
1702 update_disk_space ();
1707 if (session
->get_play_range()) {
1709 play_selection_button
.set_visual_state (1);
1710 roll_button
.set_visual_state (0);
1711 auto_loop_button
.set_visual_state (0);
1713 } else if (session
->get_play_loop ()) {
1715 auto_loop_button
.set_visual_state (1);
1716 play_selection_button
.set_visual_state (0);
1717 roll_button
.set_visual_state (0);
1721 roll_button
.set_visual_state (1);
1722 play_selection_button
.set_visual_state (0);
1723 auto_loop_button
.set_visual_state (0);
1726 stop_button
.set_visual_state (0);
1730 stop_button
.set_visual_state (1);
1731 roll_button
.set_visual_state (0);
1732 play_selection_button
.set_visual_state (0);
1733 auto_loop_button
.set_visual_state (0);
1739 ARDOUR_UI::GlobalClickBox::printer (char buf
[32], Adjustment
&adj
, void *arg
)
1741 snprintf (buf
, sizeof(buf
), "%s", ((GlobalClickBox
*) arg
)->strings
[
1742 (int) adj
.get_value()].c_str());
1746 ARDOUR_UI::engine_stopped ()
1748 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
1749 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1750 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1754 ARDOUR_UI::engine_running ()
1756 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running
));
1757 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, true);
1758 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, false);
1760 Glib::RefPtr
<Action
> action
;
1761 const char* action_name
= 0;
1763 switch (engine
->frames_per_cycle()) {
1765 action_name
= X_("JACKLatency32");
1768 action_name
= X_("JACKLatency64");
1771 action_name
= X_("JACKLatency128");
1774 action_name
= X_("JACKLatency512");
1777 action_name
= X_("JACKLatency1024");
1780 action_name
= X_("JACKLatency2048");
1783 action_name
= X_("JACKLatency4096");
1786 action_name
= X_("JACKLatency8192");
1789 /* XXX can we do anything useful ? */
1795 action
= ActionManager::get_action (X_("JACK"), action_name
);
1798 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic (action
);
1799 ract
->set_active ();
1805 ARDOUR_UI::engine_halted (const char* reason
, bool free_reason
)
1807 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
1808 /* we can't rely on the original string continuing to exist when we are called
1809 again in the GUI thread, so make a copy and note that we need to
1812 char *copy
= strdup (reason
);
1813 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &ARDOUR_UI::engine_halted
), copy
, true));
1817 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1818 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1820 update_sample_rate (0);
1824 /* if the reason is a non-empty string, it means that the backend was shutdown
1825 rather than just Ardour.
1828 if (strlen (reason
)) {
1829 msgstr
= string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason
);
1832 JACK has either been shutdown or it\n\
1833 disconnected Ardour because Ardour\n\
1834 was not fast enough. Try to restart\n\
1835 JACK, reconnect and save the session.");
1838 MessageDialog
msg (*editor
, msgstr
);
1843 free ((char *) reason
);
1848 ARDOUR_UI::do_engine_start ()
1856 error
<< _("Unable to start the session running")
1866 ARDOUR_UI::setup_theme ()
1868 theme_manager
->setup_theme();
1872 ARDOUR_UI::update_clocks ()
1874 if (!editor
|| !editor
->dragging_playhead()) {
1875 Clock (session
->audible_frame(), false, editor
->get_preferred_edit_position()); /* EMIT_SIGNAL */
1880 ARDOUR_UI::start_clocking ()
1882 clock_signal_connection
= RapidScreenUpdate
.connect (mem_fun(*this, &ARDOUR_UI::update_clocks
));
1886 ARDOUR_UI::stop_clocking ()
1888 clock_signal_connection
.disconnect ();
1892 ARDOUR_UI::toggle_clocking ()
1895 if (clock_button
.get_active()) {
1904 ARDOUR_UI::_blink (void *arg
)
1907 ((ARDOUR_UI
*) arg
)->blink ();
1914 Blink (blink_on
= !blink_on
); /* EMIT_SIGNAL */
1918 ARDOUR_UI::start_blinking ()
1920 /* Start the blink signal. Everybody with a blinking widget
1921 uses Blink to drive the widget's state.
1924 if (blink_timeout_tag
< 0) {
1926 blink_timeout_tag
= g_timeout_add (240, _blink
, this);
1931 ARDOUR_UI::stop_blinking ()
1933 if (blink_timeout_tag
>= 0) {
1934 g_source_remove (blink_timeout_tag
);
1935 blink_timeout_tag
= -1;
1940 ARDOUR_UI::name_io_setup (AudioEngine
& engine
,
1946 if (io
.n_inputs() == 0) {
1951 /* XXX we're not handling multiple ports yet. */
1953 const char **connections
= io
.input(0)->get_connections();
1955 if (connections
== 0 || connections
[0] == '\0') {
1958 buf
= connections
[0];
1965 if (io
.n_outputs() == 0) {
1970 /* XXX we're not handling multiple ports yet. */
1972 const char **connections
= io
.output(0)->get_connections();
1974 if (connections
== 0 || connections
[0] == '\0') {
1977 buf
= connections
[0];
1984 /** Ask the user for the name of a new shapshot and then take it.
1987 ARDOUR_UI::snapshot_session (bool switch_to_it
)
1989 ArdourPrompter
prompter (true);
1992 prompter
.set_name ("Prompter");
1993 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
1994 prompter
.set_title (_("Take Snapshot"));
1995 prompter
.set_prompt (_("Name of New Snapshot"));
1997 if (!switch_to_it
) {
2000 struct tm local_time
;
2003 localtime_r (&n
, &local_time
);
2004 strftime (timebuf
, sizeof(timebuf
), "%FT%T", &local_time
);
2006 prompter
.set_initial_text (timebuf
);
2010 switch (prompter
.run()) {
2011 case RESPONSE_ACCEPT
:
2012 prompter
.get_result (snapname
);
2013 if (snapname
.length()){
2014 if (snapname
.find ('/') != string::npos
) {
2015 MessageDialog
msg (_("To ensure compatibility with various systems\n"
2016 "snapshot names may not contain a '/' character"));
2020 if (snapname
.find ('\\') != string::npos
) {
2021 MessageDialog
msg (_("To ensure compatibility with various systems\n"
2022 "snapshot names may not contain a '\\' character"));
2026 save_state (snapname
, switch_to_it
);
2036 ARDOUR_UI::save_state (const string
& name
, bool switch_to_it
)
2038 (void) save_state_canfail (name
, switch_to_it
);
2042 ARDOUR_UI::save_state_canfail (string name
, bool switch_to_it
)
2047 if (name
.length() == 0) {
2048 name
= session
->snap_name();
2051 if ((ret
= session
->save_state (name
, false, switch_to_it
)) != 0) {
2055 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2060 ARDOUR_UI::primary_clock_value_changed ()
2063 session
->request_locate (primary_clock
.current_time ());
2068 ARDOUR_UI::big_clock_value_changed ()
2071 session
->request_locate (big_clock
.current_time ());
2076 ARDOUR_UI::secondary_clock_value_changed ()
2079 session
->request_locate (secondary_clock
.current_time ());
2084 ARDOUR_UI::transport_rec_enable_blink (bool onoff
)
2090 switch (session
->record_status()) {
2091 case Session::Enabled
:
2093 rec_button
.set_visual_state (2);
2095 rec_button
.set_visual_state (0);
2099 case Session::Recording
:
2100 rec_button
.set_visual_state (1);
2104 rec_button
.set_visual_state (0);
2110 ARDOUR_UI::save_template ()
2112 ArdourPrompter
prompter (true);
2115 if (!check_audioengine()) {
2119 prompter
.set_name (X_("Prompter"));
2120 prompter
.set_title (_("Save Mix Template"));
2121 prompter
.set_prompt (_("Name for mix template:"));
2122 prompter
.set_initial_text(session
->name() + _("-template"));
2123 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
2125 switch (prompter
.run()) {
2126 case RESPONSE_ACCEPT
:
2127 prompter
.get_result (name
);
2129 if (name
.length()) {
2130 session
->save_template (name
);
2140 ARDOUR_UI::fontconfig_dialog ()
2143 /* this issue seems to have gone away with changes to font handling in GTK/Quartz
2146 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2147 may not and it can take a while to build it. Warn them.
2150 Glib::ustring fontconfig
= Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2152 if (!Glib::file_test (fontconfig
, Glib::FILE_TEST_EXISTS
|Glib::FILE_TEST_IS_DIR
)) {
2153 MessageDialog
msg (*new_session_dialog
,
2154 string_compose (_("Welcome to %1.\n\n"
2155 "The program will take a bit longer to start up\n"
2156 "while the system fonts are checked.\n\n"
2157 "This will only be done once, and you will\n"
2158 "not see this message again\n"), PROGRAM_NAME
),
2172 ARDOUR_UI::parse_cmdline_path (const Glib::ustring
& cmdline_path
, Glib::ustring
& session_name
, Glib::ustring
& session_path
, bool& existing_session
)
2174 existing_session
= false;
2176 if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_DIR
)) {
2177 session_path
= cmdline_path
;
2178 existing_session
= true;
2179 } else if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_REGULAR
)) {
2180 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2181 existing_session
= true;
2183 /* it doesn't exist, assume the best */
2184 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2187 session_name
= basename_nosuffix (string (cmdline_path
));
2191 ARDOUR_UI::load_cmdline_session (const Glib::ustring
& session_name
, const Glib::ustring
& session_path
, bool& existing_session
)
2193 /* when this is called, the backend audio system must be running */
2195 /* the main idea here is to deal with the fact that a cmdline argument for the session
2196 can be interpreted in different ways - it could be a directory or a file, and before
2197 we load, we need to know both the session directory and the snapshot (statefile) within it
2198 that we are supposed to use.
2201 if (session_name
.length() == 0 || session_path
.length() == 0) {
2205 if (Glib::file_test (session_path
, Glib::FILE_TEST_IS_DIR
)) {
2207 Glib::ustring predicted_session_file
;
2209 predicted_session_file
= session_path
;
2210 predicted_session_file
+= '/';
2211 predicted_session_file
+= session_name
;
2212 predicted_session_file
+= Session::statefile_suffix();
2214 if (Glib::file_test (predicted_session_file
, Glib::FILE_TEST_EXISTS
)) {
2215 existing_session
= true;
2218 } else if (Glib::file_test (session_path
, Glib::FILE_TEST_EXISTS
)) {
2220 if (session_path
.find (Session::statefile_suffix()) == session_path
.length() - 7) {
2221 /* existing .ardour file */
2222 existing_session
= true;
2226 existing_session
= false;
2229 /* lets just try to load it */
2231 if (create_engine ()) {
2232 backend_audio_error (false, new_session_dialog
);
2236 return load_session (session_path
, session_name
);
2240 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring
& session_path
)
2242 Glib::ustring str
= string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path
);
2244 MessageDialog
msg (str
,
2246 Gtk::MESSAGE_WARNING
,
2247 Gtk::BUTTONS_YES_NO
,
2251 msg
.set_name (X_("CleanupDialog"));
2252 msg
.set_title (_("Cleanup Unused Sources"));
2253 msg
.set_wmclass (X_("existing_session"), PROGRAM_NAME
);
2254 msg
.set_position (Gtk::WIN_POS_MOUSE
);
2257 switch (msg
.run()) {
2266 ARDOUR_UI::build_session_from_nsd (const Glib::ustring
& session_path
, const Glib::ustring
& session_name
)
2271 AutoConnectOption iconnect
;
2272 AutoConnectOption oconnect
;
2276 if (Profile
->get_sae()) {
2280 iconnect
= AutoConnectPhysical
;
2281 oconnect
= AutoConnectMaster
;
2282 nphysin
= 0; // use all available
2283 nphysout
= 0; // use all available
2287 /* get settings from advanced section of NSD */
2289 if (new_session_dialog
->create_control_bus()) {
2290 cchns
= (uint32_t) new_session_dialog
->control_channel_count();
2295 if (new_session_dialog
->create_master_bus()) {
2296 mchns
= (uint32_t) new_session_dialog
->master_channel_count();
2301 if (new_session_dialog
->connect_inputs()) {
2302 iconnect
= AutoConnectPhysical
;
2304 iconnect
= AutoConnectOption (0);
2307 /// @todo some minor tweaks.
2309 oconnect
= AutoConnectOption (0);
2311 if (new_session_dialog
->connect_outputs()) {
2312 if (new_session_dialog
->connect_outs_to_master()) {
2313 oconnect
= AutoConnectMaster
;
2314 } else if (new_session_dialog
->connect_outs_to_physical()) {
2315 oconnect
= AutoConnectPhysical
;
2319 nphysin
= (uint32_t) new_session_dialog
->input_limit_count();
2320 nphysout
= (uint32_t) new_session_dialog
->output_limit_count();
2323 if (build_session (session_path
,
2331 engine
->frame_rate() * 60 * 5)) {
2340 ARDOUR_UI::end_loading_messages ()
2346 ARDOUR_UI::loading_message (const std::string
& msg
)
2349 splash
->message (msg
);
2354 ARDOUR_UI::idle_load (const Glib::ustring
& path
)
2357 if (Glib::file_test (path
, Glib::FILE_TEST_IS_DIR
)) {
2358 /* /path/to/foo => /path/to/foo, foo */
2359 load_session (path
, basename_nosuffix (path
));
2361 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2362 load_session (Glib::path_get_dirname (path
), basename_nosuffix (path
));
2366 ARDOUR_COMMAND_LINE::session_name
= path
;
2368 if (new_session_dialog
) {
2371 /* make it break out of Dialog::run() and
2375 new_session_dialog
->response (1);
2381 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running
, bool should_be_new
)
2383 bool existing_session
= false;
2384 Glib::ustring session_name
;
2385 Glib::ustring session_path
;
2386 Glib::ustring template_name
;
2390 response
= Gtk::RESPONSE_NONE
;
2392 if (!ARDOUR_COMMAND_LINE::session_name
.empty()) {
2394 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name
, session_name
, session_path
, existing_session
);
2396 /* don't ever reuse this */
2398 ARDOUR_COMMAND_LINE::session_name
= string();
2400 if (existing_session
&& backend_audio_is_running
) {
2402 /* just load the thing already */
2404 if (load_cmdline_session (session_name
, session_path
, existing_session
) == 0) {
2409 /* make the NSD use whatever information we have */
2411 new_session_dialog
->set_session_name (session_name
);
2412 new_session_dialog
->set_session_folder (session_path
);
2415 /* loading failed, or we need the NSD for something */
2417 new_session_dialog
->set_modal (false);
2418 new_session_dialog
->set_position (WIN_POS_CENTER
);
2419 new_session_dialog
->set_current_page (0);
2420 new_session_dialog
->set_existing_session (existing_session
);
2421 new_session_dialog
->reset_recent();
2424 new_session_dialog
->set_have_engine (backend_audio_is_running
);
2425 new_session_dialog
->present ();
2426 response
= new_session_dialog
->run ();
2428 _session_is_new
= false;
2430 /* handle possible negative responses */
2434 /* sent by idle_load, meaning restart the whole process again */
2435 new_session_dialog
->hide();
2436 new_session_dialog
->reset();
2440 case Gtk::RESPONSE_CANCEL
:
2441 case Gtk::RESPONSE_DELETE_EVENT
:
2443 if (engine
&& engine
->running()) {
2444 engine
->stop (true);
2448 new_session_dialog
->hide ();
2451 case Gtk::RESPONSE_NONE
:
2452 /* "Clear" was pressed */
2456 fontconfig_dialog();
2458 if (!backend_audio_is_running
) {
2459 int ret
= new_session_dialog
->engine_control
.setup_engine ();
2462 } else if (ret
> 0) {
2463 response
= Gtk::RESPONSE_REJECT
;
2467 /* hide the NSD while we start up the engine */
2469 new_session_dialog
->hide ();
2473 if (create_engine ()) {
2475 backend_audio_error (!backend_audio_is_running
, new_session_dialog
);
2478 new_session_dialog
->set_existing_session (false);
2479 new_session_dialog
->set_current_page (0); // new engine page
2480 new_session_dialog
->engine_control
.unset_interface_chosen ();
2482 response
= Gtk::RESPONSE_NONE
;
2486 backend_audio_is_running
= true;
2488 if (response
== Gtk::RESPONSE_OK
) {
2490 session_name
= new_session_dialog
->session_name();
2492 if (session_name
.empty()) {
2493 response
= Gtk::RESPONSE_NONE
;
2497 /* if the user mistakenly typed path information into the session filename entry,
2498 convert what they typed into a path & a name
2501 if (session_name
[0] == '/' ||
2502 (session_name
.length() > 2 && session_name
[0] == '.' && session_name
[1] == '/') ||
2503 (session_name
.length() > 3 && session_name
[0] == '.' && session_name
[1] == '.' && session_name
[2] == '/')) {
2505 session_path
= Glib::path_get_dirname (session_name
);
2506 session_name
= Glib::path_get_basename (session_name
);
2510 session_path
= new_session_dialog
->session_folder();
2514 template_name
= Glib::ustring();
2515 switch (new_session_dialog
->which_page()) {
2517 case NewSessionDialog::OpenPage
:
2521 case NewSessionDialog::EnginePage
:
2522 if (new_session_dialog
->engine_control
.interface_chosen() && !session_path
.empty()) {
2529 case NewSessionDialog::NewPage
: /* nominally the "new" session creator, but could be in use for an old session */
2531 should_be_new
= true;
2533 if (session_name
.find ('/') != Glib::ustring::npos
) {
2534 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2535 "session names may not contain a '/' character"));
2537 response
= RESPONSE_NONE
;
2541 if (session_name
.find ('\\') != Glib::ustring::npos
) {
2542 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2543 "session names may not contain a '\\' character"));
2545 response
= RESPONSE_NONE
;
2549 //XXX This is needed because session constructor wants a
2550 //non-existant path. hopefully this will be fixed at some point.
2552 session_path
= Glib::build_filename (session_path
, session_name
);
2554 if (Glib::file_test (session_path
, Glib::FileTest (G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))) {
2556 new_session_dialog
->hide ();
2558 if (ask_about_loading_existing_session (session_path
)) {
2561 response
= RESPONSE_NONE
;
2566 _session_is_new
= true;
2568 if (new_session_dialog
->use_session_template()) {
2570 template_name
= new_session_dialog
->session_template_name();
2574 if (build_session_from_nsd (session_path
, session_name
)) {
2575 response
= RESPONSE_NONE
;
2587 new_session_dialog
->hide ();
2589 if (load_session (session_path
, session_name
, template_name
)) {
2591 response
= Gtk::RESPONSE_NONE
;
2595 if (response
== Gtk::RESPONSE_NONE
) {
2596 new_session_dialog
->set_existing_session (false);
2597 new_session_dialog
->reset ();
2601 } while (response
== Gtk::RESPONSE_NONE
|| response
== Gtk::RESPONSE_REJECT
);
2605 new_session_dialog
->hide();
2606 new_session_dialog
->reset();
2607 goto_editor_window ();
2612 ARDOUR_UI::close_session ()
2614 if (!check_audioengine()) {
2618 if (unload_session (true)) {
2622 get_session_parameters (true, false);
2626 ARDOUR_UI::load_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
, Glib::ustring mix_template
)
2628 Session
*new_session
;
2632 session_loaded
= false;
2634 if (!check_audioengine()) {
2638 unload_status
= unload_session ();
2640 if (unload_status
< 0) {
2642 } else if (unload_status
> 0) {
2647 loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME
));
2650 new_session
= new Session (*engine
, path
, snap_name
, mix_template
);
2653 /* this one is special */
2655 catch (AudioEngine::PortRegistrationFailure
& err
) {
2657 MessageDialog
msg (err
.what(),
2660 Gtk::BUTTONS_CLOSE
);
2662 msg
.set_title (_("Port Registration Error"));
2663 msg
.set_secondary_text (_("Click the Close button to try again."));
2664 msg
.set_position (Gtk::WIN_POS_CENTER
);
2668 int response
= msg
.run ();
2673 case RESPONSE_CANCEL
:
2681 /* this exception is also special */
2683 catch (Session::SRMismatchRejected
& err
) {
2684 goto out
; /* just go back and reload something else, etc. */
2689 MessageDialog
msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path
, snap_name
),
2692 Gtk::BUTTONS_CLOSE
);
2694 msg
.set_title (_("Loading Error"));
2695 msg
.set_secondary_text (_("Click the Close button to try again."));
2696 msg
.set_position (Gtk::WIN_POS_CENTER
);
2700 int response
= msg
.run ();
2705 case RESPONSE_CANCEL
:
2713 connect_to_session (new_session
);
2715 Config
->set_current_owner (ConfigVariableBase::Interface
);
2717 session_loaded
= true;
2719 goto_editor_window ();
2722 session
->set_clean ();
2733 ARDOUR_UI::build_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
,
2734 uint32_t control_channels
,
2735 uint32_t master_channels
,
2736 AutoConnectOption input_connect
,
2737 AutoConnectOption output_connect
,
2740 nframes_t initial_length
)
2742 Session
*new_session
;
2745 if (!check_audioengine()) {
2749 session_loaded
= false;
2751 x
= unload_session ();
2759 _session_is_new
= true;
2762 new_session
= new Session (*engine
, path
, snap_name
, input_connect
, output_connect
,
2763 control_channels
, master_channels
, nphysin
, nphysout
, initial_length
);
2768 MessageDialog
msg (string_compose(_("Could not create session in \"%1\""), path
));
2774 connect_to_session (new_session
);
2776 session_loaded
= true;
2778 new_session
->save_state(new_session
->name());
2787 editor
->show_window ();
2798 ARDOUR_UI::show_about ()
2802 about
->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response
) );
2805 about
->set_transient_for(*editor
);
2811 ARDOUR_UI::launch_chat ()
2814 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2816 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2821 ARDOUR_UI::hide_about ()
2824 about
->get_window()->set_cursor ();
2830 ARDOUR_UI::about_signal_response(int response
)
2836 ARDOUR_UI::show_splash ()
2840 splash
= new Splash
;
2848 splash
->queue_draw ();
2849 splash
->get_window()->process_updates (true);
2854 ARDOUR_UI::hide_splash ()
2862 ARDOUR_UI::display_cleanup_results (Session::cleanup_report
& rep
, const gchar
* list_title
,
2863 const string
& plural_msg
, const string
& singular_msg
)
2867 removed
= rep
.paths
.size();
2870 MessageDialog
msgd (*editor
,
2871 _("No audio files were ready for cleanup"),
2874 (Gtk::ButtonsType
)(Gtk::BUTTONS_OK
) );
2875 msgd
.set_secondary_text (_("If this seems suprising, \n\
2876 check for any existing snapshots.\n\
2877 These may still include regions that\n\
2878 require some unused files to continue to exist."));
2884 ArdourDialog
results (_("ardour: cleanup"), true, false);
2886 struct CleanupResultsModelColumns
: public Gtk::TreeModel::ColumnRecord
{
2887 CleanupResultsModelColumns() {
2891 Gtk::TreeModelColumn
<Glib::ustring
> visible_name
;
2892 Gtk::TreeModelColumn
<Glib::ustring
> fullpath
;
2896 CleanupResultsModelColumns results_columns
;
2897 Glib::RefPtr
<Gtk::ListStore
> results_model
;
2898 Gtk::TreeView results_display
;
2900 results_model
= ListStore::create (results_columns
);
2901 results_display
.set_model (results_model
);
2902 results_display
.append_column (list_title
, results_columns
.visible_name
);
2904 results_display
.set_name ("CleanupResultsList");
2905 results_display
.set_headers_visible (true);
2906 results_display
.set_headers_clickable (false);
2907 results_display
.set_reorderable (false);
2909 Gtk::ScrolledWindow list_scroller
;
2912 Gtk::HBox dhbox
; // the hbox for the image and text
2913 Gtk::HBox ddhbox
; // the hbox we eventually pack into the dialog's vbox
2914 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_INFO
, Gtk::ICON_SIZE_DIALOG
));
2916 dimage
->set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
2920 %1 - number of files removed
2921 %2 - location of "dead_sounds"
2922 %3 - size of files affected
2923 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2926 const char* bprefix
;
2927 float space_adjusted
;
2929 if (rep
.space
< 1000000.0f
) {
2930 bprefix
= X_("kilo");
2931 space_adjusted
= truncf((float)rep
.space
/ 1000.0f
);
2932 } else if (rep
.space
< (1000000.0f
* 1000)) {
2933 bprefix
= X_("mega");
2934 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
));
2936 bprefix
= X_("giga");
2937 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
* 1000));
2941 txt
.set_text (string_compose (plural_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2943 txt
.set_text (string_compose (singular_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2946 dhbox
.pack_start (*dimage
, true, false, 5);
2947 dhbox
.pack_start (txt
, true, false, 5);
2949 for (vector
<string
>::iterator i
= rep
.paths
.begin(); i
!= rep
.paths
.end(); ++i
) {
2950 TreeModel::Row row
= *(results_model
->append());
2951 row
[results_columns
.visible_name
] = *i
;
2952 row
[results_columns
.fullpath
] = *i
;
2955 list_scroller
.add (results_display
);
2956 list_scroller
.set_size_request (-1, 150);
2957 list_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
2959 dvbox
.pack_start (dhbox
, true, false, 5);
2960 dvbox
.pack_start (list_scroller
, true, false, 5);
2961 ddhbox
.pack_start (dvbox
, true, false, 5);
2963 results
.get_vbox()->pack_start (ddhbox
, true, false, 5);
2964 results
.add_button (Stock::CLOSE
, RESPONSE_CLOSE
);
2965 results
.set_default_response (RESPONSE_CLOSE
);
2966 results
.set_position (Gtk::WIN_POS_MOUSE
);
2967 results
.show_all_children ();
2968 results
.set_resizable (false);
2975 ARDOUR_UI::cleanup ()
2978 /* shouldn't happen: menu item is insensitive */
2983 MessageDialog
checker (_("Are you sure you want to cleanup?"),
2985 Gtk::MESSAGE_QUESTION
,
2986 (Gtk::ButtonsType
)(Gtk::BUTTONS_NONE
));
2988 checker
.set_secondary_text(_("Cleanup is a destructive operation.\n\
2989 ALL undo/redo information will be lost if you cleanup.\n\
2990 After cleanup, unused audio files will be moved to a \
2991 \"dead sounds\" location."));
2993 checker
.add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
2994 checker
.add_button (_("Clean Up"), RESPONSE_ACCEPT
);
2995 checker
.set_default_response (RESPONSE_CANCEL
);
2997 checker
.set_name (_("CleanupDialog"));
2998 checker
.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME
);
2999 checker
.set_position (Gtk::WIN_POS_MOUSE
);
3001 switch (checker
.run()) {
3002 case RESPONSE_ACCEPT
:
3008 Session::cleanup_report rep
;
3010 editor
->prepare_for_cleanup ();
3012 /* do not allow flush until a session is reloaded */
3014 Glib::RefPtr
<Action
> act
= ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3016 act
->set_sensitive (false);
3019 if (session
->cleanup_sources (rep
)) {
3020 editor
->finish_cleanup ();
3024 editor
->finish_cleanup ();
3027 display_cleanup_results (rep
,
3030 The following %1 files were not in use and \n\
3031 have been moved to:\n\
3033 Flushing the wastebasket will \n\
3034 release an additional\n\
3035 %3 %4bytes of disk space.\n"),
3037 The following file was not in use and \n \
3038 has been moved to:\n \
3040 Flushing the wastebasket will \n\
3041 release an additional\n\
3042 %3 %4bytes of disk space.\n"
3048 ARDOUR_UI::flush_trash ()
3051 /* shouldn't happen: menu item is insensitive */
3055 Session::cleanup_report rep
;
3057 if (session
->cleanup_trash_sources (rep
)) {
3061 display_cleanup_results (rep
,
3063 _("The following %1 files were deleted from\n\
3065 releasing %3 %4bytes of disk space"),
3066 _("The following file was deleted from\n\
3068 releasing %3 %4bytes of disk space"));
3072 ARDOUR_UI::add_route (Gtk::Window
* float_window
)
3080 if (add_route_dialog
== 0) {
3081 add_route_dialog
= new AddRouteDialog
;
3083 add_route_dialog
->set_transient_for (*float_window
);
3087 if (add_route_dialog
->is_visible()) {
3088 /* we're already doing this */
3092 ResponseType r
= (ResponseType
) add_route_dialog
->run ();
3094 add_route_dialog
->hide();
3097 case RESPONSE_ACCEPT
:
3104 if ((count
= add_route_dialog
->count()) <= 0) {
3108 string template_path
= add_route_dialog
->track_template();
3110 if (!template_path
.empty()) {
3111 session
->new_route_from_template (count
, template_path
);
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 AutoConnectOption oac
= Config
->get_output_auto_connect();
3122 if (oac
& 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 */
3131 session_add_audio_track (input_chan
, output_chan
, add_route_dialog
->mode(), count
);
3133 session_add_audio_bus (input_chan
, output_chan
, count
);
3138 ARDOUR_UI::mixer_settings () const
3143 node
= session
->instant_xml(X_("Mixer"), session
->path());
3145 node
= Config
->instant_xml(X_("Mixer"), get_user_ardour_path());
3149 node
= new XMLNode (X_("Mixer"));
3156 ARDOUR_UI::editor_settings () const
3161 node
= session
->instant_xml(X_("Editor"), session
->path());
3163 node
= Config
->instant_xml(X_("Editor"), get_user_ardour_path());
3167 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3168 node
= Config
->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3173 node
= new XMLNode (X_("Editor"));
3179 ARDOUR_UI::keyboard_settings () const
3183 node
= Config
->extra_xml(X_("Keyboard"));
3186 node
= new XMLNode (X_("Keyboard"));
3192 ARDOUR_UI::create_xrun_marker(nframes_t where
)
3194 editor
->mouse_add_new_marker (where
, false, true);
3198 ARDOUR_UI::halt_on_xrun_message ()
3200 MessageDialog
msg (*editor
,
3201 _("Recording was stopped because your system could not keep up."));
3206 ARDOUR_UI::xrun_handler(nframes_t where
)
3212 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler
), where
));
3214 if (session
&& Config
->get_create_xrun_marker() && session
->actively_recording()) {
3215 create_xrun_marker(where
);
3218 if (session
&& Config
->get_stop_recording_on_xrun() && session
->actively_recording()) {
3219 halt_on_xrun_message ();
3224 ARDOUR_UI::preset_file_exists_handler ()
3226 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3229 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3233 HBox
* hbox
= new HBox();
3234 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3235 Gtk::Dialog
dialog (_("Preset Exists"), true, false);
3237 A preset with this name already exists for this plugin.\n\
3239 What you would like to do?\n"));
3240 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3241 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3242 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3243 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3244 dialog
.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT
);
3245 dialog
.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT
);
3246 dialog
.set_default_response (RESPONSE_ACCEPT
);
3247 dialog
.set_position (WIN_POS_MOUSE
);
3248 dialog
.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY
); // need to make it float above the preset name dialog
3254 switch (dialog
.run ()) {
3255 case RESPONSE_ACCEPT
:
3263 ARDOUR_UI::push_buffer_stats (uint32_t capture
, uint32_t playback
)
3268 while (disk_buffer_stats
.size() > 60) {
3269 disk_buffer_stats
.pop_front ();
3272 disk_buffer_stats
.push_back (DiskBufferStat (now
, capture
, playback
));
3276 ARDOUR_UI::write_buffer_stats ()
3281 char path
[PATH_MAX
+1]; int fd
;
3283 strcpy (path
, "ardourBufferingXXXXXX");
3285 if ((fd
= mkstemp (path
)) < 0) {
3286 cerr
<< X_("cannot find temporary name for ardour buffer stats") << endl
;
3294 cerr
<< string_compose (X_("cannot open file %1 for ardour buffer stats"), path
) << endl
;
3298 for (list
<DiskBufferStat
>::iterator i
= disk_buffer_stats
.begin(); i
!= disk_buffer_stats
.end(); ++i
) {
3299 localtime_r (&(*i
).when
, &tm
);
3300 strftime (buf
, sizeof (buf
), "%T", &tm
);
3301 fout
<< buf
<< ' ' << (*i
).capture
<< ' ' << (*i
).playback
<< endl
;
3304 disk_buffer_stats
.clear ();
3308 cerr
<< "buffering statistics can be found in: " << path
<< endl
;
3312 ARDOUR_UI::disk_overrun_handler ()
3315 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
3317 write_buffer_stats ();
3319 if (!have_disk_speed_dialog_displayed
) {
3320 have_disk_speed_dialog_displayed
= true;
3321 MessageDialog
* msg
= new MessageDialog (*editor
, _("\
3322 The disk system on your computer\n\
3323 was not able to keep up with Ardour.\n\
3325 Specifically, it failed to write data to disk\n\
3326 quickly enough to keep up with recording.\n"));
3327 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3333 ARDOUR_UI::disk_underrun_handler ()
3336 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
3338 write_buffer_stats ();
3340 if (!have_disk_speed_dialog_displayed
) {
3341 have_disk_speed_dialog_displayed
= true;
3342 MessageDialog
* msg
= new MessageDialog (*editor
,
3343 _("The disk system on your computer\n\
3344 was not able to keep up with Ardour.\n\
3346 Specifically, it failed to read data from disk\n\
3347 quickly enough to keep up with playback.\n"));
3348 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3354 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response
, MessageDialog
* msg
)
3356 have_disk_speed_dialog_displayed
= false;
3361 ARDOUR_UI::session_dialog (std::string msg
)
3363 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog
), msg
));
3368 d
= new MessageDialog (*editor
, msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3370 d
= new MessageDialog (msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3379 ARDOUR_UI::pending_state_dialog ()
3381 HBox
* hbox
= new HBox();
3382 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3383 ArdourDialog
dialog (_("Crash Recovery"), true);
3385 This session appears to have been in\n\
3386 middle of recording when ardour or\n\
3387 the computer was shutdown.\n\
3389 Ardour can recover any captured audio for\n\
3390 you, or it can ignore it. Please decide\n\
3391 what you would like to do.\n"));
3392 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3393 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3394 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3395 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3396 dialog
.add_button (_("Ignore crash data"), RESPONSE_REJECT
);
3397 dialog
.add_button (_("Recover from crash"), RESPONSE_ACCEPT
);
3398 dialog
.set_default_response (RESPONSE_ACCEPT
);
3399 dialog
.set_position (WIN_POS_CENTER
);
3406 switch (dialog
.run ()) {
3407 case RESPONSE_ACCEPT
:
3415 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired
, nframes_t actual
)
3417 HBox
* hbox
= new HBox();
3418 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3419 ArdourDialog
dialog (_("Sample Rate Mismatch"), true);
3420 Label
message (string_compose (_("\
3421 This session was created with a sample rate of %1 Hz\n\
3423 The audioengine is currently running at %2 Hz\n"), desired
, actual
));
3425 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3426 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3427 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3428 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3429 dialog
.add_button (_("Do not load session"), RESPONSE_REJECT
);
3430 dialog
.add_button (_("Load session anyway"), RESPONSE_ACCEPT
);
3431 dialog
.set_default_response (RESPONSE_ACCEPT
);
3432 dialog
.set_position (WIN_POS_CENTER
);
3437 switch (dialog
.run ()) {
3438 case RESPONSE_ACCEPT
:
3447 ARDOUR_UI::disconnect_from_jack ()
3450 if( engine
->disconnect_from_jack ()) {
3451 MessageDialog
msg (*editor
, _("Could not disconnect from JACK"));
3455 update_sample_rate (0);
3460 ARDOUR_UI::reconnect_to_jack ()
3463 if (engine
->reconnect_to_jack ()) {
3464 MessageDialog
msg (*editor
, _("Could not reconnect to JACK"));
3468 update_sample_rate (0);
3473 ARDOUR_UI::use_config ()
3475 Glib::RefPtr
<Action
> act
;
3477 switch (Config
->get_native_file_data_format ()) {
3479 act
= ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3482 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3485 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3490 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3491 ract
->set_active ();
3494 switch (Config
->get_native_file_header_format ()) {
3496 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3499 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3502 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3505 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3508 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3511 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3514 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3519 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3520 ract
->set_active ();
3523 XMLNode
* node
= Config
->extra_xml (X_("TransportControllables"));
3525 set_transport_controllable_state (*node
);
3530 ARDOUR_UI::update_transport_clocks (nframes_t pos
)
3532 if (Config
->get_primary_clock_delta_edit_cursor()) {
3533 primary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 1);
3535 primary_clock
.set (pos
, 0, true);
3538 if (Config
->get_secondary_clock_delta_edit_cursor()) {
3539 secondary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 2);
3541 secondary_clock
.set (pos
);
3544 if (big_clock_window
) {
3545 big_clock
.set (pos
);
3550 ARDOUR_UI::record_state_changed ()
3552 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed
));
3554 if (!session
|| !big_clock_window
) {
3555 /* why bother - the clock isn't visible */
3559 switch (session
->record_status()) {
3560 case Session::Recording
:
3561 big_clock
.set_widget_name ("BigClockRecording");
3564 big_clock
.set_widget_name ("BigClockNonRecording");
3570 ARDOUR_UI::first_idle ()
3573 session
->allow_auto_play (true);
3577 editor
->first_idle();
3580 Keyboard::set_can_save_keybindings (true);
3585 ARDOUR_UI::store_clock_modes ()
3587 XMLNode
* node
= new XMLNode(X_("ClockModes"));
3589 for (vector
<AudioClock
*>::iterator x
= AudioClock::clocks
.begin(); x
!= AudioClock::clocks
.end(); ++x
) {
3590 node
->add_property ((*x
)->name().c_str(), enum_2_string ((*x
)->mode()));
3593 session
->add_extra_xml (*node
);
3594 session
->set_dirty ();
3599 ARDOUR_UI::TransportControllable::TransportControllable (std::string name
, ARDOUR_UI
& u
, ToggleType tp
)
3600 : Controllable (name
), ui (u
), type(tp
)
3606 ARDOUR_UI::TransportControllable::set_value (float val
)
3608 if (type
== ShuttleControl
) {
3615 fract
= -((0.5f
- val
)/0.5f
);
3617 fract
= ((val
- 0.5f
)/0.5f
);
3621 ui
.set_shuttle_fract (fract
);
3626 /* do nothing: these are radio-style actions */
3630 const char *action
= 0;
3634 action
= X_("Roll");
3637 action
= X_("Stop");
3640 action
= X_("Goto Start");
3643 action
= X_("Goto End");
3646 action
= X_("Loop");
3649 action
= X_("Play Selection");
3652 action
= X_("Record");
3662 Glib::RefPtr
<Action
> act
= ActionManager::get_action ("Transport", action
);
3670 ARDOUR_UI::TransportControllable::get_value (void) const
3689 case ShuttleControl
:
3699 ARDOUR_UI::TransportControllable::set_id (const string
& str
)
3705 ARDOUR_UI::setup_profile ()
3707 if (gdk_screen_width() < 1200) {
3708 Profile
->set_small_screen ();
3711 if (getenv ("ARDOUR_SAE")) {
3712 Profile
->set_sae ();
3713 Profile
->set_single_package ();
3719 ARDOUR_UI::toggle_translations ()
3721 using namespace Glib
;
3723 RefPtr
<Action
> act
= ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3725 RefPtr
<ToggleAction
> ract
= RefPtr
<ToggleAction
>::cast_dynamic (act
);
3728 string i18n_killer
= ARDOUR::translation_kill_path();
3730 bool already_enabled
= !ARDOUR::translations_are_disabled ();
3732 if (ract
->get_active ()) {
3733 /* we don't care about errors */
3734 int fd
= ::open (i18n_killer
.c_str(), O_RDONLY
|O_CREAT
, 0644);
3737 /* we don't care about errors */
3738 unlink (i18n_killer
.c_str());
3741 if (already_enabled
!= ract
->get_active()) {
3742 MessageDialog
win (already_enabled
? _("Translations disabled") : _("Translations enabled"),
3744 Gtk::MESSAGE_WARNING
,
3746 win
.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME
));
3747 win
.set_position (Gtk::WIN_POS_CENTER
);