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.
32 #include <sys/resource.h>
34 #include <gtkmm/messagedialog.h>
35 #include <gtkmm/accelmap.h>
37 #include <pbd/error.h>
38 #include <pbd/basename.h>
39 #include <pbd/compose.h>
40 #include <pbd/pathscanner.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/stacktrace.h>
44 #include <gtkmm2ext/gtk_ui.h>
45 #include <gtkmm2ext/utils.h>
46 #include <gtkmm2ext/click_box.h>
47 #include <gtkmm2ext/fastmeter.h>
48 #include <gtkmm2ext/stop_signal.h>
49 #include <gtkmm2ext/popup.h>
50 #include <gtkmm2ext/window_title.h>
52 #include <midi++/port.h>
53 #include <midi++/mmc.h>
55 #include <ardour/ardour.h>
56 #include <ardour/profile.h>
57 #include <ardour/session_route.h>
58 #include <ardour/port.h>
59 #include <ardour/audioengine.h>
60 #include <ardour/playlist.h>
61 #include <ardour/utils.h>
62 #include <ardour/plugin.h>
63 #include <ardour/audio_diskstream.h>
64 #include <ardour/audiofilesource.h>
65 #include <ardour/recent_sessions.h>
66 #include <ardour/port.h>
67 #include <ardour/audio_track.h>
69 typedef uint64_t microseconds_t
;
72 #include "ardour_ui.h"
73 #include "public_editor.h"
74 #include "audio_clock.h"
79 #include "add_route_dialog.h"
80 #include "new_session_dialog.h"
85 #include "gui_thread.h"
86 #include "theme_manager.h"
87 #include "engine_dialog.h"
88 #include "gain_meter.h"
89 #include "route_time_axis.h"
93 using namespace ARDOUR
;
95 using namespace Gtkmm2ext
;
99 ARDOUR_UI
*ARDOUR_UI::theArdourUI
= 0;
100 UIConfiguration
*ARDOUR_UI::ui_config
= 0;
102 sigc::signal
<void,bool> ARDOUR_UI::Blink
;
103 sigc::signal
<void> ARDOUR_UI::RapidScreenUpdate
;
104 sigc::signal
<void> ARDOUR_UI::SuperRapidScreenUpdate
;
105 sigc::signal
<void,nframes_t
, bool, nframes_t
> ARDOUR_UI::Clock
;
107 ARDOUR_UI::ARDOUR_UI (int *argcp
, char **argvp
[])
109 : Gtkmm2ext::UI (X_("Ardour"), argcp
, argvp
),
111 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
112 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
113 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
114 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
118 preroll_button (_("pre\nroll")),
119 postroll_button (_("post\nroll")),
123 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
127 roll_controllable ("transport roll", *this, TransportControllable::Roll
),
128 stop_controllable ("transport stop", *this, TransportControllable::Stop
),
129 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart
),
130 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd
),
131 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop
),
132 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection
),
133 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable
),
134 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl
),
135 shuttle_controller_binding_proxy (shuttle_controllable
),
137 roll_button (&roll_controllable
),
138 stop_button (&stop_controllable
),
139 goto_start_button (&goto_start_controllable
),
140 goto_end_button (&goto_end_controllable
),
141 auto_loop_button (&auto_loop_controllable
),
142 play_selection_button (&play_selection_controllable
),
143 rec_button (&rec_controllable
),
145 shuttle_units_button (_("% ")),
147 punch_in_button (_("Punch In")),
148 punch_out_button (_("Punch Out")),
149 auto_return_button (_("Auto Return")),
150 auto_play_button (_("Auto Play")),
151 auto_input_button (_("Auto Input")),
152 click_button (_("Click")),
153 time_master_button (_("time\nmaster")),
155 auditioning_alert_button (_("AUDITION")),
156 solo_alert_button (_("SOLO")),
158 error_log_button (_("Errors"))
160 using namespace Gtk::Menu_Helpers
;
165 _auto_display_errors
= false;
171 if (ARDOUR_COMMAND_LINE::session_name
.length()) {
172 /* only show this if we're not going to post the new session dialog */
176 if (theArdourUI
== 0) {
180 ui_config
= new UIConfiguration();
181 theme_manager
= new ThemeManager();
187 _session_is_new
= false;
188 big_clock_window
= 0;
189 session_selector_window
= 0;
190 new_session_dialog
= 0;
191 last_key_press_time
= 0;
192 connection_editor
= 0;
193 add_route_dialog
= 0;
198 open_session_selector
= 0;
199 have_configure_timeout
= false;
200 have_disk_speed_dialog_displayed
= false;
201 _will_create_new_session_automatically
= false;
202 session_loaded
= false;
203 last_speed_displayed
= -1.0f
;
204 ignore_dual_punch
= false;
205 _mixer_on_top
= false;
207 roll_button
.unset_flags (Gtk::CAN_FOCUS
);
208 stop_button
.unset_flags (Gtk::CAN_FOCUS
);
209 goto_start_button
.unset_flags (Gtk::CAN_FOCUS
);
210 goto_end_button
.unset_flags (Gtk::CAN_FOCUS
);
211 auto_loop_button
.unset_flags (Gtk::CAN_FOCUS
);
212 play_selection_button
.unset_flags (Gtk::CAN_FOCUS
);
213 rec_button
.unset_flags (Gtk::CAN_FOCUS
);
215 last_configure_time
= 0;
217 shuttle_grabbed
= false;
219 shuttle_max_speed
= 8.0f
;
221 shuttle_style_menu
= 0;
222 shuttle_unit_menu
= 0;
224 // We do not have jack linked in yet so;
226 last_shuttle_request
= last_peak_grab
= 0; // get_microseconds();
228 ARDOUR::Diskstream::DiskOverrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
229 ARDOUR::Diskstream::DiskUnderrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
231 ARDOUR::Plugin::PresetFileExists
.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler
));
233 /* handle dialog requests */
235 ARDOUR::Session::Dialog
.connect (mem_fun(*this, &ARDOUR_UI::session_dialog
));
237 /* handle pending state with a dialog */
239 ARDOUR::Session::AskAboutPendingState
.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog
));
241 /* handle sr mismatch with a dialog */
243 ARDOUR::Session::AskAboutSampleRateMismatch
.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog
));
245 /* lets get this party started */
248 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst
, ARDOUR_COMMAND_LINE::try_hw_optimization
)) {
249 throw failed_constructor ();
252 setup_gtk_ardour_enums ();
253 Config
->set_current_owner (ConfigVariableBase::Interface
);
256 GainMeter::setup_slider_pix ();
257 RouteTimeAxisView::setup_slider_pix ();
259 } catch (failed_constructor
& err
) {
260 error
<< _("could not initialize Ardour.") << endmsg
;
265 /* we like keyboards */
267 keyboard
= new Keyboard
;
271 starting
.connect (mem_fun(*this, &ARDOUR_UI::startup
));
272 stopping
.connect (mem_fun(*this, &ARDOUR_UI::shutdown
));
278 ARDOUR_UI::create_engine ()
280 // this gets called every time by new_session()
286 loading_message (_("Starting audio engine"));
289 engine
= new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name
);
296 engine
->Stopped
.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
297 engine
->Running
.connect (mem_fun(*this, &ARDOUR_UI::engine_running
));
298 engine
->Halted
.connect (mem_fun(*this, &ARDOUR_UI::engine_halted
));
299 engine
->SampleRateChanged
.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate
));
307 ARDOUR_UI::post_engine ()
309 /* Things to be done once we create the AudioEngine
312 check_memory_locking();
314 ActionManager::init ();
317 if (setup_windows ()) {
318 throw failed_constructor ();
321 /* this is the first point at which all the keybindings are available */
323 if (ARDOUR_COMMAND_LINE::show_key_actions
) {
324 vector
<string
> names
;
325 vector
<string
> paths
;
327 vector
<AccelKey
> bindings
;
329 ActionManager::get_all_actions (names
, paths
, keys
, bindings
);
331 vector
<string
>::iterator n
;
332 vector
<string
>::iterator k
;
333 for (n
= names
.begin(), k
= keys
.begin(); n
!= names
.end(); ++n
, ++k
) {
334 cerr
<< "Action: " << (*n
) << " bound to " << (*k
) << endl
;
340 blink_timeout_tag
= -1;
342 /* the global configuration object is now valid */
346 /* this being a GUI and all, we want peakfiles */
348 AudioFileSource::set_build_peakfiles (true);
349 AudioFileSource::set_build_missing_peakfiles (true);
351 /* set default clock modes */
353 if (Profile
->get_sae()) {
354 primary_clock
.set_mode (AudioClock::BBT
);
355 secondary_clock
.set_mode (AudioClock::MinSec
);
357 primary_clock
.set_mode (AudioClock::SMPTE
);
358 secondary_clock
.set_mode (AudioClock::BBT
);
361 /* start the time-of-day-clock */
364 /* OS X provides an always visible wallclock, so don't be stupid */
365 update_wall_clock ();
366 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock
), 60000);
369 update_disk_space ();
371 update_sample_rate (engine
->frame_rate());
373 platform_specific ();
375 /* now start and maybe save state */
377 if (do_engine_start () == 0) {
378 if (session
&& _session_is_new
) {
379 /* we need to retain initial visual
380 settings for a new session
382 session
->save_state ("");
387 ARDOUR_UI::~ARDOUR_UI ()
389 save_ardour_state ();
403 if (add_route_dialog
) {
404 delete add_route_dialog
;
407 if (new_session_dialog
) {
408 delete new_session_dialog
;
413 ARDOUR_UI::pop_back_splash ()
415 if (Splash::instance()) {
416 // Splash::instance()->pop_back();
417 Splash::instance()->hide ();
422 ARDOUR_UI::configure_timeout ()
424 if (last_configure_time
== 0) {
425 /* no configure events yet */
429 /* force a gap of 0.5 seconds since the last configure event
432 if (get_microseconds() - last_configure_time
< 500000) {
435 have_configure_timeout
= false;
436 save_ardour_state ();
442 ARDOUR_UI::configure_handler (GdkEventConfigure
* conf
)
444 if (have_configure_timeout
) {
445 last_configure_time
= get_microseconds();
447 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout
), 100);
448 have_configure_timeout
= true;
455 ARDOUR_UI::set_transport_controllable_state (const XMLNode
& node
)
457 const XMLProperty
* prop
;
459 if ((prop
= node
.property ("roll")) != 0) {
460 roll_controllable
.set_id (prop
->value());
462 if ((prop
= node
.property ("stop")) != 0) {
463 stop_controllable
.set_id (prop
->value());
465 if ((prop
= node
.property ("goto_start")) != 0) {
466 goto_start_controllable
.set_id (prop
->value());
468 if ((prop
= node
.property ("goto_end")) != 0) {
469 goto_end_controllable
.set_id (prop
->value());
471 if ((prop
= node
.property ("auto_loop")) != 0) {
472 auto_loop_controllable
.set_id (prop
->value());
474 if ((prop
= node
.property ("play_selection")) != 0) {
475 play_selection_controllable
.set_id (prop
->value());
477 if ((prop
= node
.property ("rec")) != 0) {
478 rec_controllable
.set_id (prop
->value());
480 if ((prop
= node
.property ("shuttle")) != 0) {
481 shuttle_controllable
.set_id (prop
->value());
486 ARDOUR_UI::get_transport_controllable_state ()
488 XMLNode
* node
= new XMLNode(X_("TransportControllables"));
491 roll_controllable
.id().print (buf
, sizeof (buf
));
492 node
->add_property (X_("roll"), buf
);
493 stop_controllable
.id().print (buf
, sizeof (buf
));
494 node
->add_property (X_("stop"), buf
);
495 goto_start_controllable
.id().print (buf
, sizeof (buf
));
496 node
->add_property (X_("goto_start"), buf
);
497 goto_end_controllable
.id().print (buf
, sizeof (buf
));
498 node
->add_property (X_("goto_end"), buf
);
499 auto_loop_controllable
.id().print (buf
, sizeof (buf
));
500 node
->add_property (X_("auto_loop"), buf
);
501 play_selection_controllable
.id().print (buf
, sizeof (buf
));
502 node
->add_property (X_("play_selection"), buf
);
503 rec_controllable
.id().print (buf
, sizeof (buf
));
504 node
->add_property (X_("rec"), buf
);
505 shuttle_controllable
.id().print (buf
, sizeof (buf
));
506 node
->add_property (X_("shuttle"), buf
);
512 ARDOUR_UI::save_ardour_state ()
514 if (!keyboard
|| !mixer
|| !editor
) {
518 /* XXX this is all a bit dubious. add_extra_xml() uses
519 a different lifetime model from add_instant_xml().
522 XMLNode
* node
= new XMLNode (keyboard
->get_state());
523 Config
->add_extra_xml (*node
);
524 Config
->add_extra_xml (get_transport_controllable_state());
525 if (new_session_dialog
) {
526 if (new_session_dialog
->engine_control
.was_used()) {
527 Config
->add_extra_xml (new_session_dialog
->engine_control
.get_state());
530 Config
->save_state();
531 ui_config
->save_state ();
533 XMLNode
enode(static_cast<Stateful
*>(editor
)->get_state());
534 XMLNode
mnode(mixer
->get_state());
537 session
->add_instant_xml (enode
, session
->path());
538 session
->add_instant_xml (mnode
, session
->path());
540 Config
->add_instant_xml (enode
, get_user_ardour_path());
541 Config
->add_instant_xml (mnode
, get_user_ardour_path());
544 Keyboard::save_keybindings ();
548 ARDOUR_UI::autosave_session ()
550 if (g_main_depth() > 1) {
551 /* inside a recursive main loop,
552 give up because we may not be able to
558 if (!Config
->get_periodic_safety_backups())
562 session
->maybe_write_autosave();
569 ARDOUR_UI::update_autosave ()
571 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave
));
573 if (session
->dirty()) {
574 if (_autosave_connection
.connected()) {
575 _autosave_connection
.disconnect();
578 _autosave_connection
= Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session
),
579 Config
->get_periodic_safety_backup_interval() * 1000);
582 if (_autosave_connection
.connected()) {
583 _autosave_connection
.disconnect();
589 ARDOUR_UI::backend_audio_error (bool we_set_params
, Gtk::Window
* toplevel
)
593 title
= _("Ardour could not start JACK");
595 title
= _("Ardour could not connect to JACK.");
598 MessageDialog
win (title
,
604 win
.set_secondary_text(_("There are several possible reasons:\n\
606 1) You requested audio parameters that are not supported..\n\
607 2) JACK is running as another user.\n\
609 Please consider the possibilities, and perhaps try different parameters."));
611 win
.set_secondary_text(_("There are several possible reasons:\n\
613 1) JACK is not running.\n\
614 2) JACK is running as another user, perhaps root.\n\
615 3) There is already another client called \"ardour\".\n\
617 Please consider the possibilities, and perhaps (re)start JACK."));
621 win
.set_transient_for (*toplevel
);
625 win
.add_button (Stock::OK
, RESPONSE_CLOSE
);
627 win
.add_button (Stock::QUIT
, RESPONSE_CLOSE
);
630 win
.set_default_response (RESPONSE_CLOSE
);
633 win
.set_position (Gtk::WIN_POS_CENTER
);
636 /* we just don't care about the result, but we want to block */
642 ARDOUR_UI::startup ()
646 new_session_dialog
= new NewSessionDialog();
648 bool backend_audio_is_running
= EngineControl::engine_running();
649 XMLNode
* audio_setup
= Config
->extra_xml ("AudioSetup");
652 new_session_dialog
->engine_control
.set_state (*audio_setup
);
655 if (!get_session_parameters (backend_audio_is_running
, ARDOUR_COMMAND_LINE::new_session
)) {
659 BootMessage (_("Ardour is ready for use"));
664 ARDOUR_UI::no_memory_warning ()
666 XMLNode
node (X_("no-memory-warning"));
667 Config
->add_instant_xml (node
, get_user_ardour_path());
671 ARDOUR_UI::check_memory_locking ()
674 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
678 XMLNode
* memory_warning_node
= Config
->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
680 if (engine
->is_realtime() && memory_warning_node
== 0) {
682 struct rlimit limits
;
684 long pages
, page_size
;
686 if ((page_size
= sysconf (_SC_PAGESIZE
)) < 0 ||(pages
= sysconf (_SC_PHYS_PAGES
)) < 0) {
689 ram
= (int64_t) pages
* (int64_t) page_size
;
692 if (getrlimit (RLIMIT_MEMLOCK
, &limits
)) {
696 if (limits
.rlim_cur
!= RLIM_INFINITY
) {
698 if (ram
== 0 || ((double) limits
.rlim_cur
/ ram
) < 0.75) {
701 MessageDialog
msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
702 "This might cause Ardour to run out of memory before your system "
703 "runs out of memory. \n\n"
704 "You can view the memory limit with 'ulimit -l', "
705 "and it is normally controlled by /etc/security/limits.conf"));
707 VBox
* vbox
= msg
.get_vbox();
709 CheckButton
cb (_("Do not show this window again"));
711 cb
.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning
));
713 hbox
.pack_start (cb
, true, false);
714 vbox
->pack_start (hbox
);
732 if (session
->transport_rolling()) {
733 session
->request_stop ();
737 if (session
->dirty()) {
738 switch (ask_about_saving_session(_("quit"))) {
743 /* use the default name */
744 if (save_state_canfail ("")) {
745 /* failed - don't quit */
746 MessageDialog
msg (*editor
,
748 Ardour was unable to save your session.\n\n\
749 If you still wish to quit, please use the\n\n\
750 \"Just quit\" option."));
761 session
->set_deletion_in_progress ();
764 ArdourDialog::close_all_dialogs ();
766 save_ardour_state ();
771 ARDOUR_UI::ask_about_saving_session (const string
& what
)
773 ArdourDialog
window (_("ardour: save session?"));
774 Gtk::HBox dhbox
; // the hbox for the image and text
775 Gtk::Label prompt_label
;
776 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_WARNING
, Gtk::ICON_SIZE_DIALOG
));
780 msg
= string_compose(_("Don't %1"), what
);
781 window
.add_button (msg
, RESPONSE_REJECT
);
782 msg
= string_compose(_("Just %1"), what
);
783 window
.add_button (msg
, RESPONSE_APPLY
);
784 msg
= string_compose(_("Save and %1"), what
);
785 window
.add_button (msg
, RESPONSE_ACCEPT
);
787 window
.set_default_response (RESPONSE_ACCEPT
);
789 Gtk::Button
noquit_button (msg
);
790 noquit_button
.set_name ("EditorGTKButton");
795 if (session
->snap_name() == session
->name()) {
798 type
= _("snapshot");
800 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?"),
801 type
, session
->snap_name());
803 prompt_label
.set_text (prompt
);
804 prompt_label
.set_name (X_("PrompterLabel"));
805 prompt_label
.set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
807 dimage
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
)
809 dhbox
.set_homogeneous (false);
810 dhbox
.pack_start (*dimage
, false, false, 5);
811 dhbox
.pack_start (prompt_label
, true, false, 5);
812 window
.get_vbox()->pack_start (dhbox
);
814 window
.set_name (_("Prompter"));
815 window
.set_position (Gtk::WIN_POS_MOUSE
);
816 window
.set_modal (true);
817 window
.set_resizable (false);
820 window
.set_keep_above (true);
823 ResponseType r
= (ResponseType
) window
.run();
828 case RESPONSE_ACCEPT
: // save and get out of here
830 case RESPONSE_APPLY
: // get out of here
840 ARDOUR_UI::every_second ()
843 update_buffer_load ();
844 update_disk_space ();
849 ARDOUR_UI::every_point_one_seconds ()
851 update_speed_display ();
852 RapidScreenUpdate(); /* EMIT_SIGNAL */
857 ARDOUR_UI::every_point_zero_one_seconds ()
859 // august 2007: actual update frequency: 40Hz, not 100Hz
861 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
866 ARDOUR_UI::update_sample_rate (nframes_t ignored
)
870 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate
), ignored
));
872 if (!engine
->connected()) {
874 snprintf (buf
, sizeof (buf
), _("disconnected"));
878 nframes_t rate
= engine
->frame_rate();
880 if (fmod (rate
, 1000.0) != 0.0) {
881 snprintf (buf
, sizeof (buf
), _("%.1f kHz / %4.1f ms"),
882 (float) rate
/1000.0f
,
883 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
885 snprintf (buf
, sizeof (buf
), _("%u kHz / %4.1f ms"),
887 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
891 sample_rate_label
.set_text (buf
);
895 ARDOUR_UI::update_cpu_load ()
898 snprintf (buf
, sizeof (buf
), _("DSP: %5.1f%%"), engine
->get_cpu_load());
899 cpu_load_label
.set_text (buf
);
903 ARDOUR_UI::update_buffer_load ()
909 c
= session
->capture_load ();
910 p
= session
->playback_load ();
912 push_buffer_stats (c
, p
);
914 snprintf (buf
, sizeof (buf
), _("Buffers p:%" PRIu32
"%% c:%" PRIu32
"%%"),
915 session
->playback_load(), session
->capture_load());
916 buffer_load_label
.set_text (buf
);
918 buffer_load_label
.set_text ("");
923 ARDOUR_UI::count_recenabled_streams (Route
& route
)
925 Track
* track
= dynamic_cast<Track
*>(&route
);
926 if (track
&& track
->diskstream()->record_enabled()) {
927 rec_enabled_streams
+= track
->n_inputs();
932 ARDOUR_UI::update_disk_space()
938 nframes_t frames
= session
->available_capture_duration();
941 if (frames
== max_frames
) {
942 strcpy (buf
, _("Disk: 24hrs+"));
947 nframes_t fr
= session
->frame_rate();
949 rec_enabled_streams
= 0;
950 session
->foreach_route (this, &ARDOUR_UI::count_recenabled_streams
);
952 if (rec_enabled_streams
) {
953 frames
/= rec_enabled_streams
;
956 hrs
= frames
/ (fr
* 3600);
957 frames
-= hrs
* fr
* 3600;
958 mins
= frames
/ (fr
* 60);
959 frames
-= mins
* fr
* 60;
962 snprintf (buf
, sizeof(buf
), _("Disk: %02dh:%02dm:%02ds"), hrs
, mins
, secs
);
965 disk_space_label
.set_text (buf
);
969 ARDOUR_UI::update_wall_clock ()
976 tm_now
= localtime (&now
);
978 sprintf (buf
, "%02d:%02d", tm_now
->tm_hour
, tm_now
->tm_min
);
979 wall_clock_label
.set_text (buf
);
985 ARDOUR_UI::session_menu (GdkEventButton
*ev
)
987 session_popup_menu
->popup (0, 0);
992 ARDOUR_UI::redisplay_recent_sessions ()
994 vector
<string
*> *sessions
;
995 vector
<string
*>::iterator i
;
996 RecentSessionsSorter cmp
;
998 recent_session_display
.set_model (Glib::RefPtr
<TreeModel
>(0));
999 recent_session_model
->clear ();
1002 ARDOUR::read_recent_sessions (rs
);
1005 recent_session_display
.set_model (recent_session_model
);
1009 /* sort them alphabetically */
1010 sort (rs
.begin(), rs
.end(), cmp
);
1011 sessions
= new vector
<string
*>;
1013 for (RecentSessions::iterator i
= rs
.begin(); i
!= rs
.end(); ++i
) {
1014 sessions
->push_back (new string ((*i
).second
));
1017 for (i
= sessions
->begin(); i
!= sessions
->end(); ++i
) {
1019 vector
<string
*>* states
;
1020 vector
<const gchar
*> item
;
1021 string fullpath
= *(*i
);
1023 /* remove any trailing / */
1025 if (fullpath
[fullpath
.length()-1] == '/') {
1026 fullpath
= fullpath
.substr (0, fullpath
.length()-1);
1029 /* check whether session still exists */
1030 if (!Glib::file_test(fullpath
.c_str(), Glib::FILE_TEST_EXISTS
)) {
1031 /* session doesn't exist */
1032 cerr
<< "skipping non-existent session " << fullpath
<< endl
;
1036 /* now get available states for this session */
1038 if ((states
= Session::possible_states (fullpath
)) == 0) {
1039 /* no state file? */
1043 TreeModel::Row row
= *(recent_session_model
->append());
1045 row
[recent_session_columns
.visible_name
] = Glib::path_get_basename (fullpath
);
1046 row
[recent_session_columns
.fullpath
] = fullpath
;
1048 if (states
->size() > 1) {
1050 /* add the children */
1052 for (vector
<string
*>::iterator i2
= states
->begin(); i2
!= states
->end(); ++i2
) {
1054 TreeModel::Row child_row
= *(recent_session_model
->append (row
.children()));
1056 child_row
[recent_session_columns
.visible_name
] = **i2
;
1057 child_row
[recent_session_columns
.fullpath
] = fullpath
;
1066 recent_session_display
.set_model (recent_session_model
);
1071 ARDOUR_UI::build_session_selector ()
1073 session_selector_window
= new ArdourDialog ("session selector");
1075 Gtk::ScrolledWindow
*scroller
= manage (new Gtk::ScrolledWindow
);
1077 session_selector_window
->add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
1078 session_selector_window
->add_button (Stock::OPEN
, RESPONSE_ACCEPT
);
1079 session_selector_window
->set_default_response (RESPONSE_ACCEPT
);
1080 recent_session_model
= TreeStore::create (recent_session_columns
);
1081 recent_session_display
.set_model (recent_session_model
);
1082 recent_session_display
.append_column (_("Recent Sessions"), recent_session_columns
.visible_name
);
1083 recent_session_display
.set_headers_visible (false);
1084 recent_session_display
.get_selection()->set_mode (SELECTION_BROWSE
);
1085 recent_session_display
.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated
));
1087 scroller
->add (recent_session_display
);
1088 scroller
->set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
1090 session_selector_window
->set_name ("SessionSelectorWindow");
1091 session_selector_window
->set_size_request (200, 400);
1092 session_selector_window
->get_vbox()->pack_start (*scroller
);
1093 session_selector_window
->show_all_children();
1097 ARDOUR_UI::recent_session_row_activated (const TreePath
& path
, TreeViewColumn
* col
)
1099 session_selector_window
->response (RESPONSE_ACCEPT
);
1103 ARDOUR_UI::open_recent_session ()
1105 bool can_return
= (session
!= 0);
1107 if (session_selector_window
== 0) {
1108 build_session_selector ();
1111 redisplay_recent_sessions ();
1115 session_selector_window
->set_position (WIN_POS_MOUSE
);
1117 ResponseType r
= (ResponseType
) session_selector_window
->run ();
1120 case RESPONSE_ACCEPT
:
1124 session_selector_window
->hide();
1131 if (recent_session_display
.get_selection()->count_selected_rows() == 0) {
1135 session_selector_window
->hide();
1137 Gtk::TreeModel::iterator i
= recent_session_display
.get_selection()->get_selected();
1139 if (i
== recent_session_model
->children().end()) {
1143 Glib::ustring path
= (*i
)[recent_session_columns
.fullpath
];
1144 Glib::ustring state
= (*i
)[recent_session_columns
.visible_name
];
1146 _session_is_new
= false;
1148 if (load_session (path
, state
) == 0) {
1157 ARDOUR_UI::check_audioengine ()
1160 if (!engine
->connected()) {
1161 MessageDialog
msg (_("Ardour is not connected to JACK\n"
1162 "You cannot open or close sessions in this condition"));
1164 msg
.set_position (WIN_POS_CENTER
);
1175 ARDOUR_UI::open_session ()
1177 if (!check_audioengine()) {
1181 /* popup selector window */
1183 if (open_session_selector
== 0) {
1185 /* ardour sessions are folders */
1187 open_session_selector
= new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN
);
1188 open_session_selector
->add_button (Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
1189 open_session_selector
->add_button (Gtk::Stock::OPEN
, Gtk::RESPONSE_ACCEPT
);
1190 open_session_selector
->set_default_response(Gtk::RESPONSE_ACCEPT
);
1192 FileFilter session_filter
;
1193 session_filter
.add_pattern ("*.ardour");
1194 session_filter
.set_name (_("Ardour sessions"));
1195 open_session_selector
->add_filter (session_filter
);
1196 open_session_selector
->set_filter (session_filter
);
1199 int response
= open_session_selector
->run();
1200 open_session_selector
->hide ();
1203 case RESPONSE_ACCEPT
:
1206 open_session_selector
->hide();
1210 open_session_selector
->hide();
1211 string session_path
= open_session_selector
->get_filename();
1215 if (session_path
.length() > 0) {
1216 if (Session::find_session (session_path
, path
, name
, isnew
) == 0) {
1217 _session_is_new
= isnew
;
1218 load_session (path
, name
);
1225 ARDOUR_UI::session_add_midi_track ()
1227 cerr
<< _("Patience is a virtue.\n");
1231 ARDOUR_UI::session_add_audio_route (bool track
, int32_t input_channels
, int32_t output_channels
, ARDOUR::TrackMode mode
, uint32_t how_many
)
1233 list
<boost::shared_ptr
<AudioTrack
> > tracks
;
1234 Session::RouteList routes
;
1237 warning
<< _("You cannot add a track or bus without a session already loaded.") << endmsg
;
1243 tracks
= session
->new_audio_track (input_channels
, output_channels
, mode
, how_many
);
1245 if (tracks
.size() != how_many
) {
1246 if (how_many
== 1) {
1247 error
<< _("could not create a new audio track") << endmsg
;
1249 error
<< string_compose (_("could only create %1 of %2 new audio %3"),
1250 tracks
.size(), how_many
, (track
? _("tracks") : _("busses"))) << endmsg
;
1256 routes
= session
->new_audio_route (input_channels
, output_channels
, how_many
);
1258 if (routes
.size() != how_many
) {
1259 if (how_many
== 1) {
1260 error
<< _("could not create a new audio track") << endmsg
;
1262 error
<< string_compose (_("could not create %1 new audio tracks"), how_many
) << endmsg
;
1268 if (need_control_room_outs
) {
1274 route
->set_stereo_control_outs (control_lr_channels
);
1275 route
->control_outs()->set_stereo_pan (pans
, this);
1277 #endif /* CONTROLOUTS */
1281 MessageDialog
msg (*editor
,
1282 _("There are insufficient JACK ports available\n\
1283 to create a new track or bus.\n\
1284 You should save Ardour, exit and\n\
1285 restart JACK with more ports."));
1292 ARDOUR_UI::do_transport_locate (nframes_t new_position
)
1294 nframes_t _preroll
= 0;
1297 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1298 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1300 if (new_position
> _preroll
) {
1301 new_position
-= _preroll
;
1306 session
->request_locate (new_position
);
1311 ARDOUR_UI::transport_goto_start ()
1314 session
->goto_start();
1317 /* force displayed area in editor to start no matter
1318 what "follow playhead" setting is.
1322 editor
->reset_x_origin (session
->current_start_frame());
1328 ARDOUR_UI::transport_goto_zero ()
1331 session
->request_locate (0);
1334 /* force displayed area in editor to start no matter
1335 what "follow playhead" setting is.
1339 editor
->reset_x_origin (0);
1345 ARDOUR_UI::transport_goto_wallclock ()
1347 if (session
&& editor
) {
1354 localtime_r (&now
, &tmnow
);
1356 frames
= tmnow
.tm_hour
* (60 * 60 * session
->frame_rate());
1357 frames
+= tmnow
.tm_min
* (60 * session
->frame_rate());
1358 frames
+= tmnow
.tm_sec
* session
->frame_rate();
1360 session
->request_locate (frames
);
1362 /* force displayed area in editor to start no matter
1363 what "follow playhead" setting is.
1367 editor
->reset_x_origin (frames
- (editor
->current_page_frames()/2));
1373 ARDOUR_UI::transport_goto_end ()
1376 nframes_t frame
= session
->current_end_frame();
1377 session
->request_locate (frame
);
1379 /* force displayed area in editor to start no matter
1380 what "follow playhead" setting is.
1384 editor
->reset_x_origin (frame
);
1390 ARDOUR_UI::transport_stop ()
1396 if (session
->is_auditioning()) {
1397 session
->cancel_audition ();
1401 if (session
->get_play_loop ()) {
1402 session
->request_play_loop (false);
1405 session
->request_stop ();
1409 ARDOUR_UI::transport_stop_and_forget_capture ()
1412 session
->request_stop (true);
1417 ARDOUR_UI::remove_last_capture()
1420 editor
->remove_last_capture();
1425 ARDOUR_UI::transport_record (bool roll
)
1429 switch (session
->record_status()) {
1430 case Session::Disabled
:
1431 if (session
->ntracks() == 0) {
1432 MessageDialog
msg (*editor
, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1436 session
->maybe_enable_record ();
1441 case Session::Recording
:
1443 session
->request_stop();
1445 session
->disable_record (false, true);
1449 case Session::Enabled
:
1450 session
->disable_record (false, true);
1453 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1457 ARDOUR_UI::transport_roll ()
1465 rolling
= session
->transport_rolling ();
1467 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1469 if (session
->get_play_loop()) {
1470 session
->request_play_loop (false);
1471 auto_loop_button
.set_visual_state (1);
1472 roll_button
.set_visual_state (1);
1473 } else if (session
->get_play_range ()) {
1474 session
->request_play_range (false);
1475 play_selection_button
.set_visual_state (0);
1476 } else if (rolling
) {
1477 session
->request_locate (session
->last_transport_start(), true);
1480 session
->request_transport_speed (1.0f
);
1484 ARDOUR_UI::transport_loop()
1487 if (session
->get_play_loop()) {
1488 if (session
->transport_rolling()) {
1489 Location
* looploc
= session
->locations()->auto_loop_location();
1491 session
->request_locate (looploc
->start(), true);
1496 session
->request_play_loop (true);
1502 ARDOUR_UI::transport_play_selection ()
1508 if (!session
->get_play_range()) {
1509 session
->request_stop ();
1512 editor
->play_selection ();
1516 ARDOUR_UI::transport_rewind (int option
)
1518 float current_transport_speed
;
1521 current_transport_speed
= session
->transport_speed();
1523 if (current_transport_speed
>= 0.0f
) {
1526 session
->request_transport_speed (-1.0f
);
1529 session
->request_transport_speed (-4.0f
);
1532 session
->request_transport_speed (-0.5f
);
1537 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1543 ARDOUR_UI::transport_forward (int option
)
1545 float current_transport_speed
;
1548 current_transport_speed
= session
->transport_speed();
1550 if (current_transport_speed
<= 0.0f
) {
1553 session
->request_transport_speed (1.0f
);
1556 session
->request_transport_speed (4.0f
);
1559 session
->request_transport_speed (0.5f
);
1564 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1570 ARDOUR_UI::toggle_record_enable (uint32_t dstream
)
1576 boost::shared_ptr
<Route
> r
;
1578 if ((r
= session
->route_by_remote_id (dstream
)) != 0) {
1582 if ((t
= dynamic_cast<Track
*>(r
.get())) != 0) {
1583 t
->diskstream()->set_record_enabled (!t
->diskstream()->record_enabled());
1592 ARDOUR_UI::queue_transport_change ()
1594 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state
));
1598 ARDOUR_UI::map_transport_state ()
1600 float sp
= session
->transport_speed();
1603 transport_rolling ();
1604 } else if (sp
< 0.0f
) {
1605 transport_rewinding ();
1606 } else if (sp
> 0.0f
) {
1607 transport_forwarding ();
1609 transport_stopped ();
1614 ARDOUR_UI::GlobalClickBox::printer (char buf
[32], Adjustment
&adj
, void *arg
)
1616 snprintf (buf
, sizeof(buf
), "%s", ((GlobalClickBox
*) arg
)->strings
[
1617 (int) adj
.get_value()].c_str());
1621 ARDOUR_UI::engine_stopped ()
1623 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
1624 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1625 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1629 ARDOUR_UI::engine_running ()
1631 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running
));
1632 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, true);
1633 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, false);
1635 Glib::RefPtr
<Action
> action
;
1636 const char* action_name
= 0;
1638 switch (engine
->frames_per_cycle()) {
1640 action_name
= X_("JACKLatency32");
1643 action_name
= X_("JACKLatency64");
1646 action_name
= X_("JACKLatency128");
1649 action_name
= X_("JACKLatency512");
1652 action_name
= X_("JACKLatency1024");
1655 action_name
= X_("JACKLatency2048");
1658 action_name
= X_("JACKLatency4096");
1661 action_name
= X_("JACKLatency8192");
1664 /* XXX can we do anything useful ? */
1670 action
= ActionManager::get_action (X_("JACK"), action_name
);
1673 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic (action
);
1674 ract
->set_active ();
1680 ARDOUR_UI::engine_halted ()
1682 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted
));
1684 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1685 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1687 update_sample_rate (0);
1689 MessageDialog
msg (*editor
,
1691 JACK has either been shutdown or it\n\
1692 disconnected Ardour because Ardour\n\
1693 was not fast enough. Try to restart\n\
1694 JACK, reconnect and save the session."));
1700 ARDOUR_UI::do_engine_start ()
1708 error
<< _("Unable to start the session running")
1718 ARDOUR_UI::setup_theme ()
1720 theme_manager
->setup_theme();
1724 ARDOUR_UI::update_clocks ()
1726 if (!editor
|| !editor
->dragging_playhead()) {
1727 Clock (session
->audible_frame(), false, editor
->get_preferred_edit_position()); /* EMIT_SIGNAL */
1732 ARDOUR_UI::start_clocking ()
1734 clock_signal_connection
= RapidScreenUpdate
.connect (mem_fun(*this, &ARDOUR_UI::update_clocks
));
1738 ARDOUR_UI::stop_clocking ()
1740 clock_signal_connection
.disconnect ();
1744 ARDOUR_UI::toggle_clocking ()
1747 if (clock_button
.get_active()) {
1756 ARDOUR_UI::_blink (void *arg
)
1759 ((ARDOUR_UI
*) arg
)->blink ();
1766 Blink (blink_on
= !blink_on
); /* EMIT_SIGNAL */
1770 ARDOUR_UI::start_blinking ()
1772 /* Start the blink signal. Everybody with a blinking widget
1773 uses Blink to drive the widget's state.
1776 if (blink_timeout_tag
< 0) {
1778 blink_timeout_tag
= g_timeout_add (240, _blink
, this);
1783 ARDOUR_UI::stop_blinking ()
1785 if (blink_timeout_tag
>= 0) {
1786 g_source_remove (blink_timeout_tag
);
1787 blink_timeout_tag
= -1;
1792 ARDOUR_UI::name_io_setup (AudioEngine
& engine
,
1798 if (io
.n_inputs() == 0) {
1803 /* XXX we're not handling multiple ports yet. */
1805 const char **connections
= io
.input(0)->get_connections();
1807 if (connections
== 0 || connections
[0] == '\0') {
1810 buf
= connections
[0];
1817 if (io
.n_outputs() == 0) {
1822 /* XXX we're not handling multiple ports yet. */
1824 const char **connections
= io
.output(0)->get_connections();
1826 if (connections
== 0 || connections
[0] == '\0') {
1829 buf
= connections
[0];
1836 /** Ask the user for the name of a new shapshot and then take it.
1839 ARDOUR_UI::snapshot_session ()
1841 ArdourPrompter
prompter (true);
1845 struct tm local_time
;
1848 localtime_r (&n
, &local_time
);
1849 strftime (timebuf
, sizeof(timebuf
), "%FT%T", &local_time
);
1851 prompter
.set_name ("Prompter");
1852 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
1853 prompter
.set_prompt (_("Name of New Snapshot"));
1854 prompter
.set_initial_text (timebuf
);
1857 switch (prompter
.run()) {
1858 case RESPONSE_ACCEPT
:
1859 prompter
.get_result (snapname
);
1860 if (snapname
.length()){
1861 if (snapname
.find ('/') != string::npos
) {
1862 MessageDialog
msg (_("To ensure compatibility with various systems\n"
1863 "snapshot names may not contain a '/' character"));
1867 if (snapname
.find ('\\') != string::npos
) {
1868 MessageDialog
msg (_("To ensure compatibility with various systems\n"
1869 "snapshot names may not contain a '\\' character"));
1873 save_state (snapname
);
1883 ARDOUR_UI::save_state (const string
& name
)
1885 (void) save_state_canfail (name
);
1889 ARDOUR_UI::save_state_canfail (string name
)
1894 if (name
.length() == 0) {
1895 name
= session
->snap_name();
1898 if ((ret
= session
->save_state (name
)) != 0) {
1902 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1907 ARDOUR_UI::primary_clock_value_changed ()
1910 session
->request_locate (primary_clock
.current_time ());
1915 ARDOUR_UI::big_clock_value_changed ()
1918 session
->request_locate (big_clock
.current_time ());
1923 ARDOUR_UI::secondary_clock_value_changed ()
1926 session
->request_locate (secondary_clock
.current_time ());
1931 ARDOUR_UI::transport_rec_enable_blink (bool onoff
)
1937 switch (session
->record_status()) {
1938 case Session::Enabled
:
1940 rec_button
.set_visual_state (2);
1942 rec_button
.set_visual_state (0);
1946 case Session::Recording
:
1947 rec_button
.set_visual_state (1);
1951 rec_button
.set_visual_state (0);
1957 ARDOUR_UI::save_template ()
1960 ArdourPrompter
prompter (true);
1963 if (!check_audioengine()) {
1967 prompter
.set_name (X_("Prompter"));
1968 prompter
.set_prompt (_("Name for mix template:"));
1969 prompter
.set_initial_text(session
->name() + _("-template"));
1970 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
1972 switch (prompter
.run()) {
1973 case RESPONSE_ACCEPT
:
1974 prompter
.get_result (name
);
1976 if (name
.length()) {
1977 session
->save_template (name
);
1987 ARDOUR_UI::fontconfig_dialog ()
1990 /* this issue seems to have gone away with changes to font handling in GTK/Quartz
1993 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1994 may not and it can take a while to build it. Warn them.
1997 Glib::ustring fontconfig
= Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1999 if (!Glib::file_test (fontconfig
, Glib::FILE_TEST_EXISTS
|Glib::FILE_TEST_IS_DIR
)) {
2000 MessageDialog
msg (*new_session_dialog
,
2001 _("Welcome to Ardour.\n\n"
2002 "The program will take a bit longer to start up\n"
2003 "while the system fonts are checked.\n\n"
2004 "This will only be done once, and you will\n"
2005 "not see this message again\n"),
2019 ARDOUR_UI::parse_cmdline_path (const Glib::ustring
& cmdline_path
, Glib::ustring
& session_name
, Glib::ustring
& session_path
, bool& existing_session
)
2021 existing_session
= false;
2023 if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_DIR
)) {
2024 session_path
= cmdline_path
;
2025 existing_session
= true;
2026 } else if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_REGULAR
)) {
2027 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2028 existing_session
= true;
2030 /* it doesn't exist, assume the best */
2031 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2034 session_name
= basename_nosuffix (string (cmdline_path
));
2038 ARDOUR_UI::load_cmdline_session (const Glib::ustring
& session_name
, const Glib::ustring
& session_path
, bool& existing_session
)
2040 /* when this is called, the backend audio system must be running */
2042 /* the main idea here is to deal with the fact that a cmdline argument for the session
2043 can be interpreted in different ways - it could be a directory or a file, and before
2044 we load, we need to know both the session directory and the snapshot (statefile) within it
2045 that we are supposed to use.
2048 if (session_name
.length() == 0 || session_path
.length() == 0) {
2052 if (Glib::file_test (session_path
, Glib::FILE_TEST_IS_DIR
)) {
2054 Glib::ustring predicted_session_file
;
2056 predicted_session_file
= session_path
;
2057 predicted_session_file
+= '/';
2058 predicted_session_file
+= session_name
;
2059 predicted_session_file
+= Session::statefile_suffix();
2061 if (Glib::file_test (predicted_session_file
, Glib::FILE_TEST_EXISTS
)) {
2062 existing_session
= true;
2065 } else if (Glib::file_test (session_path
, Glib::FILE_TEST_EXISTS
)) {
2067 if (session_path
.find (Session::statefile_suffix()) == session_path
.length() - 7) {
2068 /* existing .ardour file */
2069 existing_session
= true;
2073 existing_session
= false;
2076 /* lets just try to load it */
2078 if (create_engine ()) {
2079 backend_audio_error (false, new_session_dialog
);
2083 return load_session (session_path
, session_name
);
2087 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring
& session_path
)
2089 Glib::ustring str
= string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path
);
2091 MessageDialog
msg (str
,
2093 Gtk::MESSAGE_WARNING
,
2094 Gtk::BUTTONS_YES_NO
,
2098 msg
.set_name (X_("CleanupDialog"));
2099 msg
.set_wmclass (X_("existing_session"), "Ardour");
2100 msg
.set_position (Gtk::WIN_POS_MOUSE
);
2103 switch (msg
.run()) {
2112 ARDOUR_UI::build_session_from_nsd (const Glib::ustring
& session_path
, const Glib::ustring
& session_name
)
2117 AutoConnectOption iconnect
;
2118 AutoConnectOption oconnect
;
2122 if (Profile
->get_sae()) {
2126 iconnect
= AutoConnectPhysical
;
2127 oconnect
= AutoConnectMaster
;
2128 nphysin
= 0; // use all available
2129 nphysout
= 0; // use all available
2133 /* get settings from advanced section of NSD */
2135 if (new_session_dialog
->create_control_bus()) {
2136 cchns
= (uint32_t) new_session_dialog
->control_channel_count();
2141 if (new_session_dialog
->create_master_bus()) {
2142 mchns
= (uint32_t) new_session_dialog
->master_channel_count();
2147 if (new_session_dialog
->connect_inputs()) {
2148 iconnect
= AutoConnectPhysical
;
2150 iconnect
= AutoConnectOption (0);
2153 /// @todo some minor tweaks.
2155 if (new_session_dialog
->connect_outs_to_master()) {
2156 oconnect
= AutoConnectMaster
;
2157 } else if (new_session_dialog
->connect_outs_to_physical()) {
2158 oconnect
= AutoConnectPhysical
;
2160 oconnect
= AutoConnectOption (0);
2163 nphysin
= (uint32_t) new_session_dialog
->input_limit_count();
2164 nphysout
= (uint32_t) new_session_dialog
->output_limit_count();
2167 if (build_session (session_path
,
2175 engine
->frame_rate() * 60 * 5)) {
2184 ARDOUR_UI::end_loading_messages ()
2190 ARDOUR_UI::loading_message (const std::string
& msg
)
2193 splash
->message (msg
);
2198 ARDOUR_UI::idle_load (const Glib::ustring
& path
)
2201 if (Glib::file_test (path
, Glib::FILE_TEST_IS_DIR
)) {
2202 /* /path/to/foo => /path/to/foo, foo */
2203 load_session (path
, basename_nosuffix (path
));
2205 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2206 load_session (Glib::path_get_dirname (path
), basename_nosuffix (path
));
2210 ARDOUR_COMMAND_LINE::session_name
= path
;
2212 if (new_session_dialog
) {
2215 /* make it break out of Dialog::run() and
2219 new_session_dialog
->response (1);
2225 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running
, bool should_be_new
)
2227 bool existing_session
= false;
2228 Glib::ustring session_name
;
2229 Glib::ustring session_path
;
2230 Glib::ustring template_name
;
2234 response
= Gtk::RESPONSE_NONE
;
2236 if (!ARDOUR_COMMAND_LINE::session_name
.empty()) {
2238 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name
, session_name
, session_path
, existing_session
);
2240 /* don't ever reuse this */
2242 ARDOUR_COMMAND_LINE::session_name
= string();
2244 if (existing_session
&& backend_audio_is_running
) {
2246 /* just load the thing already */
2248 if (load_cmdline_session (session_name
, session_path
, existing_session
) == 0) {
2253 /* make the NSD use whatever information we have */
2255 new_session_dialog
->set_session_name (session_name
);
2256 new_session_dialog
->set_session_folder (session_path
);
2259 /* loading failed, or we need the NSD for something */
2261 new_session_dialog
->set_modal (false);
2262 new_session_dialog
->set_position (WIN_POS_CENTER
);
2263 new_session_dialog
->set_current_page (0);
2264 new_session_dialog
->set_existing_session (existing_session
);
2265 new_session_dialog
->reset_recent();
2268 new_session_dialog
->set_have_engine (backend_audio_is_running
);
2269 new_session_dialog
->present ();
2270 response
= new_session_dialog
->run ();
2272 _session_is_new
= false;
2274 /* handle possible negative responses */
2278 /* sent by idle_load, meaning restart the whole process again */
2279 new_session_dialog
->hide();
2280 new_session_dialog
->reset();
2284 case Gtk::RESPONSE_CANCEL
:
2285 case Gtk::RESPONSE_DELETE_EVENT
:
2287 if (engine
&& engine
->running()) {
2288 engine
->stop (true);
2292 new_session_dialog
->hide ();
2295 case Gtk::RESPONSE_NONE
:
2296 /* "Clear" was pressed */
2300 fontconfig_dialog();
2302 if (!backend_audio_is_running
) {
2303 int ret
= new_session_dialog
->engine_control
.setup_engine ();
2306 } else if (ret
> 0) {
2307 response
= Gtk::RESPONSE_REJECT
;
2311 /* hide the NSD while we start up the engine */
2313 new_session_dialog
->hide ();
2317 if (create_engine ()) {
2319 backend_audio_error (!backend_audio_is_running
, new_session_dialog
);
2322 new_session_dialog
->set_existing_session (false);
2323 new_session_dialog
->set_current_page (0); // new engine page
2324 new_session_dialog
->engine_control
.unset_interface_chosen ();
2326 response
= Gtk::RESPONSE_NONE
;
2330 backend_audio_is_running
= true;
2332 if (response
== Gtk::RESPONSE_OK
) {
2334 session_name
= new_session_dialog
->session_name();
2336 if (session_name
.empty()) {
2337 response
= Gtk::RESPONSE_NONE
;
2341 /* if the user mistakenly typed path information into the session filename entry,
2342 convert what they typed into a path & a name
2345 if (session_name
[0] == '/' ||
2346 (session_name
.length() > 2 && session_name
[0] == '.' && session_name
[1] == '/') ||
2347 (session_name
.length() > 3 && session_name
[0] == '.' && session_name
[1] == '.' && session_name
[2] == '/')) {
2349 session_path
= Glib::path_get_dirname (session_name
);
2350 session_name
= Glib::path_get_basename (session_name
);
2354 session_path
= new_session_dialog
->session_folder();
2358 template_name
= Glib::ustring();
2359 switch (new_session_dialog
->which_page()) {
2361 case NewSessionDialog::OpenPage
:
2365 case NewSessionDialog::EnginePage
:
2366 if (new_session_dialog
->engine_control
.interface_chosen() && !session_path
.empty()) {
2373 case NewSessionDialog::NewPage
: /* nominally the "new" session creator, but could be in use for an old session */
2375 should_be_new
= true;
2377 if (session_name
.find ('/') != Glib::ustring::npos
) {
2378 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2379 "session names may not contain a '/' character"));
2381 response
= RESPONSE_NONE
;
2385 if (session_name
.find ('\\') != Glib::ustring::npos
) {
2386 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2387 "session names may not contain a '\\' character"));
2389 response
= RESPONSE_NONE
;
2393 //XXX This is needed because session constructor wants a
2394 //non-existant path. hopefully this will be fixed at some point.
2396 session_path
= Glib::build_filename (session_path
, session_name
);
2398 if (Glib::file_test (session_path
, Glib::FileTest (G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))) {
2400 new_session_dialog
->hide ();
2402 if (ask_about_loading_existing_session (session_path
)) {
2405 response
= RESPONSE_NONE
;
2410 _session_is_new
= true;
2412 if (new_session_dialog
->use_session_template()) {
2414 template_name
= new_session_dialog
->session_template_name();
2418 if (build_session_from_nsd (session_path
, session_name
)) {
2419 response
= RESPONSE_NONE
;
2431 new_session_dialog
->hide ();
2433 if (load_session (session_path
, session_name
, template_name
)) {
2435 response
= Gtk::RESPONSE_NONE
;
2439 if (response
== Gtk::RESPONSE_NONE
) {
2440 new_session_dialog
->set_existing_session (false);
2441 new_session_dialog
->reset ();
2445 } while (response
== Gtk::RESPONSE_NONE
|| response
== Gtk::RESPONSE_REJECT
);
2449 new_session_dialog
->hide();
2450 new_session_dialog
->reset();
2451 goto_editor_window ();
2456 ARDOUR_UI::close_session ()
2458 if (!check_audioengine()) {
2462 if (unload_session (true)) {
2466 get_session_parameters (true, false);
2470 ARDOUR_UI::load_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
, Glib::ustring mix_template
)
2472 Session
*new_session
;
2476 session_loaded
= false;
2478 if (!check_audioengine()) {
2482 unload_status
= unload_session ();
2484 if (unload_status
< 0) {
2486 } else if (unload_status
> 0) {
2491 loading_message (_("Please wait while Ardour loads your session"));
2494 new_session
= new Session (*engine
, path
, snap_name
, mix_template
);
2497 /* this one is special */
2499 catch (AudioEngine::PortRegistrationFailure
& err
) {
2501 MessageDialog
msg (err
.what(),
2504 Gtk::BUTTONS_CLOSE
);
2506 msg
.set_title (_("Port Registration Error"));
2507 msg
.set_secondary_text (_("Click the Close button to try again."));
2508 msg
.set_position (Gtk::WIN_POS_CENTER
);
2512 int response
= msg
.run ();
2517 case RESPONSE_CANCEL
:
2525 /* this exception is also special */
2527 catch (Session::SRMismatchRejected
& err
) {
2528 goto out
; /* just go back and reload something else, etc. */
2533 MessageDialog
msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path
, snap_name
),
2536 Gtk::BUTTONS_CLOSE
);
2538 msg
.set_title (_("Loading Error"));
2539 msg
.set_secondary_text (_("Click the Close button to try again."));
2540 msg
.set_position (Gtk::WIN_POS_CENTER
);
2544 int response
= msg
.run ();
2549 case RESPONSE_CANCEL
:
2557 connect_to_session (new_session
);
2559 Config
->set_current_owner (ConfigVariableBase::Interface
);
2561 session_loaded
= true;
2563 goto_editor_window ();
2566 session
->set_clean ();
2577 ARDOUR_UI::build_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
,
2578 uint32_t control_channels
,
2579 uint32_t master_channels
,
2580 AutoConnectOption input_connect
,
2581 AutoConnectOption output_connect
,
2584 nframes_t initial_length
)
2586 Session
*new_session
;
2589 if (!check_audioengine()) {
2593 session_loaded
= false;
2595 x
= unload_session ();
2603 _session_is_new
= true;
2606 new_session
= new Session (*engine
, path
, snap_name
, input_connect
, output_connect
,
2607 control_channels
, master_channels
, nphysin
, nphysout
, initial_length
);
2612 MessageDialog
msg (string_compose(_("Could not create session in \"%1\""), path
));
2618 connect_to_session (new_session
);
2620 session_loaded
= true;
2622 new_session
->save_state(new_session
->name());
2631 editor
->show_window ();
2642 ARDOUR_UI::show_about ()
2646 about
->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response
) );
2649 about
->set_transient_for(*editor
);
2655 ARDOUR_UI::launch_chat ()
2658 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2660 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2665 ARDOUR_UI::hide_about ()
2668 about
->get_window()->set_cursor ();
2674 ARDOUR_UI::about_signal_response(int response
)
2680 ARDOUR_UI::show_splash ()
2684 splash
= new Splash
;
2692 splash
->queue_draw ();
2693 splash
->get_window()->process_updates (true);
2698 ARDOUR_UI::hide_splash ()
2706 ARDOUR_UI::display_cleanup_results (Session::cleanup_report
& rep
, const gchar
* list_title
,
2707 const string
& plural_msg
, const string
& singular_msg
)
2711 removed
= rep
.paths
.size();
2714 MessageDialog
msgd (*editor
,
2715 _("No audio files were ready for cleanup"),
2718 (Gtk::ButtonsType
)(Gtk::BUTTONS_OK
) );
2719 msgd
.set_secondary_text (_("If this seems suprising, \n\
2720 check for any existing snapshots.\n\
2721 These may still include regions that\n\
2722 require some unused files to continue to exist."));
2728 ArdourDialog
results (_("ardour: cleanup"), true, false);
2730 struct CleanupResultsModelColumns
: public Gtk::TreeModel::ColumnRecord
{
2731 CleanupResultsModelColumns() {
2735 Gtk::TreeModelColumn
<Glib::ustring
> visible_name
;
2736 Gtk::TreeModelColumn
<Glib::ustring
> fullpath
;
2740 CleanupResultsModelColumns results_columns
;
2741 Glib::RefPtr
<Gtk::ListStore
> results_model
;
2742 Gtk::TreeView results_display
;
2744 results_model
= ListStore::create (results_columns
);
2745 results_display
.set_model (results_model
);
2746 results_display
.append_column (list_title
, results_columns
.visible_name
);
2748 results_display
.set_name ("CleanupResultsList");
2749 results_display
.set_headers_visible (true);
2750 results_display
.set_headers_clickable (false);
2751 results_display
.set_reorderable (false);
2753 Gtk::ScrolledWindow list_scroller
;
2756 Gtk::HBox dhbox
; // the hbox for the image and text
2757 Gtk::HBox ddhbox
; // the hbox we eventually pack into the dialog's vbox
2758 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_INFO
, Gtk::ICON_SIZE_DIALOG
));
2760 dimage
->set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
2764 %1 - number of files removed
2765 %2 - location of "dead_sounds"
2766 %3 - size of files affected
2767 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2770 const char* bprefix
;
2771 float space_adjusted
;
2773 if (rep
.space
< 1000000.0f
) {
2774 bprefix
= X_("kilo");
2775 space_adjusted
= truncf((float)rep
.space
/ 1000.0f
);
2776 } else if (rep
.space
< (1000000.0f
* 1000)) {
2777 bprefix
= X_("mega");
2778 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
));
2780 bprefix
= X_("giga");
2781 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
* 1000));
2785 txt
.set_text (string_compose (plural_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2787 txt
.set_text (string_compose (singular_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2790 dhbox
.pack_start (*dimage
, true, false, 5);
2791 dhbox
.pack_start (txt
, true, false, 5);
2793 for (vector
<string
>::iterator i
= rep
.paths
.begin(); i
!= rep
.paths
.end(); ++i
) {
2794 TreeModel::Row row
= *(results_model
->append());
2795 row
[results_columns
.visible_name
] = *i
;
2796 row
[results_columns
.fullpath
] = *i
;
2799 list_scroller
.add (results_display
);
2800 list_scroller
.set_size_request (-1, 150);
2801 list_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
2803 dvbox
.pack_start (dhbox
, true, false, 5);
2804 dvbox
.pack_start (list_scroller
, true, false, 5);
2805 ddhbox
.pack_start (dvbox
, true, false, 5);
2807 results
.get_vbox()->pack_start (ddhbox
, true, false, 5);
2808 results
.add_button (Stock::CLOSE
, RESPONSE_CLOSE
);
2809 results
.set_default_response (RESPONSE_CLOSE
);
2810 results
.set_position (Gtk::WIN_POS_MOUSE
);
2811 results
.show_all_children ();
2812 results
.set_resizable (false);
2819 ARDOUR_UI::cleanup ()
2822 /* shouldn't happen: menu item is insensitive */
2827 MessageDialog
checker (_("Are you sure you want to cleanup?"),
2829 Gtk::MESSAGE_QUESTION
,
2830 (Gtk::ButtonsType
)(Gtk::BUTTONS_NONE
));
2832 checker
.set_secondary_text(_("Cleanup is a destructive operation.\n\
2833 ALL undo/redo information will be lost if you cleanup.\n\
2834 After cleanup, unused audio files will be moved to a \
2835 \"dead sounds\" location."));
2837 checker
.add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
2838 checker
.add_button (_("Clean Up"), RESPONSE_ACCEPT
);
2839 checker
.set_default_response (RESPONSE_CANCEL
);
2841 checker
.set_name (_("CleanupDialog"));
2842 checker
.set_wmclass (X_("ardour_cleanup"), "Ardour");
2843 checker
.set_position (Gtk::WIN_POS_MOUSE
);
2845 switch (checker
.run()) {
2846 case RESPONSE_ACCEPT
:
2852 Session::cleanup_report rep
;
2854 editor
->prepare_for_cleanup ();
2856 /* do not allow flush until a session is reloaded */
2858 Glib::RefPtr
<Action
> act
= ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2860 act
->set_sensitive (false);
2863 if (session
->cleanup_sources (rep
)) {
2864 editor
->finish_cleanup ();
2868 editor
->finish_cleanup ();
2871 display_cleanup_results (rep
,
2874 The following %1 files were not in use and \n\
2875 have been moved to:\n\
2877 Flushing the wastebasket will \n\
2878 release an additional\n\
2879 %3 %4bytes of disk space.\n"),
2881 The following file was not in use and \n \
2882 has been moved to:\n \
2884 Flushing the wastebasket will \n\
2885 release an additional\n\
2886 %3 %4bytes of disk space.\n"
2892 ARDOUR_UI::flush_trash ()
2895 /* shouldn't happen: menu item is insensitive */
2899 Session::cleanup_report rep
;
2901 if (session
->cleanup_trash_sources (rep
)) {
2905 display_cleanup_results (rep
,
2907 _("The following %1 files were deleted from\n\
2909 releasing %3 %4bytes of disk space"),
2910 _("The following file was deleted from\n\
2912 releasing %3 %4bytes of disk space"));
2916 ARDOUR_UI::add_route (Gtk::Window
* float_window
)
2924 if (add_route_dialog
== 0) {
2925 add_route_dialog
= new AddRouteDialog
;
2927 add_route_dialog
->set_transient_for (*float_window
);
2931 if (add_route_dialog
->is_visible()) {
2932 /* we're already doing this */
2936 ResponseType r
= (ResponseType
) add_route_dialog
->run ();
2938 add_route_dialog
->hide();
2941 case RESPONSE_ACCEPT
:
2948 if ((count
= add_route_dialog
->count()) <= 0) {
2952 string template_path
= add_route_dialog
->track_template();
2954 if (!template_path
.empty()) {
2955 session
->new_route_from_template (count
, template_path
);
2959 uint32_t input_chan
= add_route_dialog
->channels ();
2960 uint32_t output_chan
;
2961 string name_template
= add_route_dialog
->name_template ();
2962 bool track
= add_route_dialog
->track ();
2964 AutoConnectOption oac
= Config
->get_output_auto_connect();
2966 if (oac
& AutoConnectMaster
) {
2967 output_chan
= (session
->master_out() ? session
->master_out()->n_inputs() : input_chan
);
2969 output_chan
= input_chan
;
2972 /* XXX do something with name template */
2975 session_add_audio_track (input_chan
, output_chan
, add_route_dialog
->mode(), count
);
2977 session_add_audio_bus (input_chan
, output_chan
, count
);
2982 ARDOUR_UI::mixer_settings () const
2987 node
= session
->instant_xml(X_("Mixer"), session
->path());
2989 node
= Config
->instant_xml(X_("Mixer"), get_user_ardour_path());
2993 node
= new XMLNode (X_("Mixer"));
3000 ARDOUR_UI::editor_settings () const
3005 node
= session
->instant_xml(X_("Editor"), session
->path());
3007 node
= Config
->instant_xml(X_("Editor"), get_user_ardour_path());
3011 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3012 node
= Config
->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3017 node
= new XMLNode (X_("Editor"));
3023 ARDOUR_UI::keyboard_settings () const
3027 node
= Config
->extra_xml(X_("Keyboard"));
3030 node
= new XMLNode (X_("Keyboard"));
3036 ARDOUR_UI::create_xrun_marker(nframes_t where
)
3038 editor
->mouse_add_new_marker (where
, false, true);
3042 ARDOUR_UI::halt_on_xrun_message ()
3044 MessageDialog
msg (*editor
,
3045 _("Recording was stopped because your system could not keep up."));
3050 ARDOUR_UI::xrun_handler(nframes_t where
)
3056 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler
), where
));
3058 if (session
&& Config
->get_create_xrun_marker() && session
->actively_recording()) {
3059 create_xrun_marker(where
);
3062 if (session
&& Config
->get_stop_recording_on_xrun() && session
->actively_recording()) {
3063 halt_on_xrun_message ();
3068 ARDOUR_UI::preset_file_exists_handler ()
3070 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3073 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3077 HBox
* hbox
= new HBox();
3078 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3079 Gtk::Dialog
dialog (_("Preset Exists"), true, false);
3081 A preset with this name already exists for this plugin.\n\
3083 What you would like to do?\n"));
3084 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3085 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3086 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3087 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3088 dialog
.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT
);
3089 dialog
.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT
);
3090 dialog
.set_default_response (RESPONSE_ACCEPT
);
3091 dialog
.set_position (WIN_POS_MOUSE
);
3092 dialog
.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY
); // need to make it float above the preset name dialog
3098 switch (dialog
.run ()) {
3099 case RESPONSE_ACCEPT
:
3107 ARDOUR_UI::push_buffer_stats (uint32_t capture
, uint32_t playback
)
3112 while (disk_buffer_stats
.size() > 60) {
3113 disk_buffer_stats
.pop_front ();
3116 disk_buffer_stats
.push_back (DiskBufferStat (now
, capture
, playback
));
3120 ARDOUR_UI::write_buffer_stats ()
3125 char path
[PATH_MAX
+1]; int fd
;
3127 strcpy (path
, "ardourBufferingXXXXXX");
3129 if ((fd
= mkstemp (path
)) < 0) {
3130 cerr
<< X_("cannot find temporary name for ardour buffer stats") << endl
;
3138 cerr
<< string_compose (X_("cannot open file %1 for ardour buffer stats"), path
) << endl
;
3142 for (list
<DiskBufferStat
>::iterator i
= disk_buffer_stats
.begin(); i
!= disk_buffer_stats
.end(); ++i
) {
3143 localtime_r (&(*i
).when
, &tm
);
3144 strftime (buf
, sizeof (buf
), "%T", &tm
);
3145 fout
<< buf
<< ' ' << (*i
).capture
<< ' ' << (*i
).playback
<< endl
;
3148 disk_buffer_stats
.clear ();
3152 cerr
<< "Ardour buffering statistics can be found in: " << path
<< endl
;
3157 ARDOUR_UI::disk_overrun_handler ()
3160 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
3162 write_buffer_stats ();
3164 if (!have_disk_speed_dialog_displayed
) {
3165 have_disk_speed_dialog_displayed
= true;
3166 MessageDialog
* msg
= new MessageDialog (*editor
, _("\
3167 The disk system on your computer\n\
3168 was not able to keep up with Ardour.\n\
3170 Specifically, it failed to write data to disk\n\
3171 quickly enough to keep up with recording.\n"));
3172 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3178 ARDOUR_UI::disk_underrun_handler ()
3181 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
3183 write_buffer_stats ();
3185 if (!have_disk_speed_dialog_displayed
) {
3186 have_disk_speed_dialog_displayed
= true;
3187 MessageDialog
* msg
= new MessageDialog (*editor
,
3188 _("The disk system on your computer\n\
3189 was not able to keep up with Ardour.\n\
3191 Specifically, it failed to read data from disk\n\
3192 quickly enough to keep up with playback.\n"));
3193 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3199 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response
, MessageDialog
* msg
)
3201 have_disk_speed_dialog_displayed
= false;
3206 ARDOUR_UI::session_dialog (std::string msg
)
3208 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog
), msg
));
3213 d
= new MessageDialog (*editor
, msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3215 d
= new MessageDialog (msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3224 ARDOUR_UI::pending_state_dialog ()
3226 HBox
* hbox
= new HBox();
3227 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3228 ArdourDialog
dialog (_("Crash Recovery"), true);
3230 This session appears to have been in\n\
3231 middle of recording when ardour or\n\
3232 the computer was shutdown.\n\
3234 Ardour can recover any captured audio for\n\
3235 you, or it can ignore it. Please decide\n\
3236 what you would like to do.\n"));
3237 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3238 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3239 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3240 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3241 dialog
.add_button (_("Ignore crash data"), RESPONSE_REJECT
);
3242 dialog
.add_button (_("Recover from crash"), RESPONSE_ACCEPT
);
3243 dialog
.set_default_response (RESPONSE_ACCEPT
);
3244 dialog
.set_position (WIN_POS_CENTER
);
3251 switch (dialog
.run ()) {
3252 case RESPONSE_ACCEPT
:
3260 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired
, nframes_t actual
)
3262 HBox
* hbox
= new HBox();
3263 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3264 ArdourDialog
dialog (_("Sample Rate Mismatch"), true);
3265 Label
message (string_compose (_("\
3266 This session was created with a sample rate of %1 Hz\n\
3268 The audioengine is currently running at %2 Hz\n"), desired
, actual
));
3270 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3271 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3272 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3273 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3274 dialog
.add_button (_("Do not load session"), RESPONSE_REJECT
);
3275 dialog
.add_button (_("Load session anyway"), RESPONSE_ACCEPT
);
3276 dialog
.set_default_response (RESPONSE_ACCEPT
);
3277 dialog
.set_position (WIN_POS_CENTER
);
3282 switch (dialog
.run ()) {
3283 case RESPONSE_ACCEPT
:
3292 ARDOUR_UI::disconnect_from_jack ()
3295 if( engine
->disconnect_from_jack ()) {
3296 MessageDialog
msg (*editor
, _("Could not disconnect from JACK"));
3300 update_sample_rate (0);
3305 ARDOUR_UI::reconnect_to_jack ()
3308 if (engine
->reconnect_to_jack ()) {
3309 MessageDialog
msg (*editor
, _("Could not reconnect to JACK"));
3313 update_sample_rate (0);
3318 ARDOUR_UI::use_config ()
3320 Glib::RefPtr
<Action
> act
;
3322 switch (Config
->get_native_file_data_format ()) {
3324 act
= ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3327 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3330 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3335 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3336 ract
->set_active ();
3339 switch (Config
->get_native_file_header_format ()) {
3341 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3344 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3347 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3350 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3353 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3356 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3359 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3364 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3365 ract
->set_active ();
3368 XMLNode
* node
= Config
->extra_xml (X_("TransportControllables"));
3370 set_transport_controllable_state (*node
);
3375 ARDOUR_UI::update_transport_clocks (nframes_t pos
)
3377 if (Config
->get_primary_clock_delta_edit_cursor()) {
3378 primary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 1);
3380 primary_clock
.set (pos
, 0, true);
3383 if (Config
->get_secondary_clock_delta_edit_cursor()) {
3384 secondary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 2);
3386 secondary_clock
.set (pos
);
3389 if (big_clock_window
) {
3390 big_clock
.set (pos
);
3395 ARDOUR_UI::record_state_changed ()
3397 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed
));
3399 if (!session
|| !big_clock_window
) {
3400 /* why bother - the clock isn't visible */
3404 switch (session
->record_status()) {
3405 case Session::Recording
:
3406 big_clock
.set_widget_name ("BigClockRecording");
3409 big_clock
.set_widget_name ("BigClockNonRecording");
3415 ARDOUR_UI::first_idle ()
3418 session
->allow_auto_play (true);
3422 editor
->first_idle();
3425 Keyboard::set_can_save_keybindings (true);
3430 ARDOUR_UI::store_clock_modes ()
3432 XMLNode
* node
= new XMLNode(X_("ClockModes"));
3434 for (vector
<AudioClock
*>::iterator x
= AudioClock::clocks
.begin(); x
!= AudioClock::clocks
.end(); ++x
) {
3435 node
->add_property ((*x
)->name().c_str(), enum_2_string ((*x
)->mode()));
3438 session
->add_extra_xml (*node
);
3439 session
->set_dirty ();
3444 ARDOUR_UI::TransportControllable::TransportControllable (std::string name
, ARDOUR_UI
& u
, ToggleType tp
)
3445 : Controllable (name
), ui (u
), type(tp
)
3451 ARDOUR_UI::TransportControllable::set_value (float val
)
3453 if (type
== ShuttleControl
) {
3460 fract
= -((0.5f
- val
)/0.5f
);
3462 fract
= ((val
- 0.5f
)/0.5f
);
3466 ui
.set_shuttle_fract (fract
);
3471 /* do nothing: these are radio-style actions */
3475 const char *action
= 0;
3479 action
= X_("Roll");
3482 action
= X_("Stop");
3485 action
= X_("Goto Start");
3488 action
= X_("Goto End");
3491 action
= X_("Loop");
3494 action
= X_("Play Selection");
3497 action
= X_("Record");
3507 Glib::RefPtr
<Action
> act
= ActionManager::get_action ("Transport", action
);
3515 ARDOUR_UI::TransportControllable::get_value (void) const
3534 case ShuttleControl
:
3544 ARDOUR_UI::TransportControllable::set_id (const string
& str
)
3550 ARDOUR_UI::setup_profile ()
3552 if (gdk_screen_width() < 1200) {
3553 Profile
->set_small_screen ();
3556 if (getenv ("ARDOUR_SAE")) {
3557 Profile
->set_sae ();
3558 Profile
->set_single_package ();