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.
31 #include <sys/resource.h>
33 #include <gtkmm/messagedialog.h>
34 #include <gtkmm/accelmap.h>
36 #include <pbd/error.h>
37 #include <pbd/basename.h>
38 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/plugin.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/audiofilesource.h>
64 #include <ardour/recent_sessions.h>
65 #include <ardour/port.h>
66 #include <ardour/audio_track.h>
68 typedef uint64_t microseconds_t
;
71 #include "ardour_ui.h"
72 #include "public_editor.h"
73 #include "audio_clock.h"
78 #include "add_route_dialog.h"
79 #include "new_session_dialog.h"
84 #include "gui_thread.h"
85 #include "theme_manager.h"
86 #include "engine_dialog.h"
87 #include "gain_meter.h"
88 #include "route_time_axis.h"
92 using namespace ARDOUR
;
94 using namespace Gtkmm2ext
;
98 ARDOUR_UI
*ARDOUR_UI::theArdourUI
= 0;
99 UIConfiguration
*ARDOUR_UI::ui_config
= 0;
101 sigc::signal
<void,bool> ARDOUR_UI::Blink
;
102 sigc::signal
<void> ARDOUR_UI::RapidScreenUpdate
;
103 sigc::signal
<void> ARDOUR_UI::SuperRapidScreenUpdate
;
104 sigc::signal
<void,nframes_t
, bool, nframes_t
> ARDOUR_UI::Clock
;
106 ARDOUR_UI::ARDOUR_UI (int *argcp
, char **argvp
[])
108 : Gtkmm2ext::UI (X_("Ardour"), argcp
, argvp
),
110 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
111 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
112 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
113 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
117 preroll_button (_("pre\nroll")),
118 postroll_button (_("post\nroll")),
122 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
126 roll_controllable ("transport roll", *this, TransportControllable::Roll
),
127 stop_controllable ("transport stop", *this, TransportControllable::Stop
),
128 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart
),
129 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd
),
130 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop
),
131 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection
),
132 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable
),
133 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl
),
134 shuttle_controller_binding_proxy (shuttle_controllable
),
136 roll_button (&roll_controllable
),
137 stop_button (&stop_controllable
),
138 goto_start_button (&goto_start_controllable
),
139 goto_end_button (&goto_end_controllable
),
140 auto_loop_button (&auto_loop_controllable
),
141 play_selection_button (&play_selection_controllable
),
142 rec_button (&rec_controllable
),
144 shuttle_units_button (_("% ")),
146 punch_in_button (_("Punch In")),
147 punch_out_button (_("Punch Out")),
148 auto_return_button (_("Auto Return")),
149 auto_play_button (_("Auto Play")),
150 auto_input_button (_("Auto Input")),
151 click_button (_("Click")),
152 time_master_button (_("time\nmaster")),
154 auditioning_alert_button (_("AUDITION")),
155 solo_alert_button (_("SOLO")),
157 error_log_button (_("Errors"))
159 using namespace Gtk::Menu_Helpers
;
164 _auto_display_errors
= false;
170 if (ARDOUR_COMMAND_LINE::session_name
.length()) {
171 /* only show this if we're not going to post the new session dialog */
175 if (theArdourUI
== 0) {
179 ui_config
= new UIConfiguration();
180 theme_manager
= new ThemeManager();
186 _session_is_new
= false;
187 big_clock_window
= 0;
188 session_selector_window
= 0;
189 new_session_dialog
= 0;
190 last_key_press_time
= 0;
191 connection_editor
= 0;
192 add_route_dialog
= 0;
197 open_session_selector
= 0;
198 have_configure_timeout
= false;
199 have_disk_speed_dialog_displayed
= false;
200 _will_create_new_session_automatically
= false;
201 session_loaded
= false;
202 last_speed_displayed
= -1.0f
;
203 ignore_dual_punch
= false;
204 _mixer_on_top
= false;
206 roll_button
.unset_flags (Gtk::CAN_FOCUS
);
207 stop_button
.unset_flags (Gtk::CAN_FOCUS
);
208 goto_start_button
.unset_flags (Gtk::CAN_FOCUS
);
209 goto_end_button
.unset_flags (Gtk::CAN_FOCUS
);
210 auto_loop_button
.unset_flags (Gtk::CAN_FOCUS
);
211 play_selection_button
.unset_flags (Gtk::CAN_FOCUS
);
212 rec_button
.unset_flags (Gtk::CAN_FOCUS
);
214 last_configure_time
= 0;
216 shuttle_grabbed
= false;
218 shuttle_max_speed
= 8.0f
;
220 shuttle_style_menu
= 0;
221 shuttle_unit_menu
= 0;
223 // We do not have jack linked in yet so;
225 last_shuttle_request
= last_peak_grab
= 0; // get_microseconds();
227 ARDOUR::Diskstream::DiskOverrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
228 ARDOUR::Diskstream::DiskUnderrun
.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
230 ARDOUR::Plugin::PresetFileExists
.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler
));
232 /* handle dialog requests */
234 ARDOUR::Session::Dialog
.connect (mem_fun(*this, &ARDOUR_UI::session_dialog
));
236 /* handle pending state with a dialog */
238 ARDOUR::Session::AskAboutPendingState
.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog
));
240 /* handle sr mismatch with a dialog */
242 ARDOUR::Session::AskAboutSampleRateMismatch
.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog
));
244 /* lets get this party started */
247 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst
, ARDOUR_COMMAND_LINE::try_hw_optimization
)) {
248 throw failed_constructor ();
251 setup_gtk_ardour_enums ();
252 Config
->set_current_owner (ConfigVariableBase::Interface
);
255 GainMeter::setup_slider_pix ();
256 RouteTimeAxisView::setup_slider_pix ();
258 } catch (failed_constructor
& err
) {
259 error
<< _("could not initialize Ardour.") << endmsg
;
264 /* we like keyboards */
266 keyboard
= new Keyboard
;
270 starting
.connect (mem_fun(*this, &ARDOUR_UI::startup
));
271 stopping
.connect (mem_fun(*this, &ARDOUR_UI::shutdown
));
277 ARDOUR_UI::create_engine ()
279 // this gets called every time by new_session()
285 loading_message (_("Starting audio engine"));
288 engine
= new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name
);
295 engine
->Stopped
.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
296 engine
->Running
.connect (mem_fun(*this, &ARDOUR_UI::engine_running
));
297 engine
->Halted
.connect (mem_fun(*this, &ARDOUR_UI::engine_halted
));
298 engine
->SampleRateChanged
.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate
));
306 ARDOUR_UI::post_engine ()
308 /* Things to be done once we create the AudioEngine
311 check_memory_locking();
313 ActionManager::init ();
316 if (setup_windows ()) {
317 throw failed_constructor ();
320 /* this is the first point at which all the keybindings are available */
322 if (ARDOUR_COMMAND_LINE::show_key_actions
) {
323 vector
<string
> names
;
324 vector
<string
> paths
;
326 vector
<AccelKey
> bindings
;
328 ActionManager::get_all_actions (names
, paths
, keys
, bindings
);
330 vector
<string
>::iterator n
;
331 vector
<string
>::iterator k
;
332 for (n
= names
.begin(), k
= keys
.begin(); n
!= names
.end(); ++n
, ++k
) {
333 cerr
<< "Action: " << (*n
) << " bound to " << (*k
) << endl
;
339 blink_timeout_tag
= -1;
341 /* the global configuration object is now valid */
345 /* this being a GUI and all, we want peakfiles */
347 AudioFileSource::set_build_peakfiles (true);
348 AudioFileSource::set_build_missing_peakfiles (true);
350 /* set default clock modes */
352 if (Profile
->get_sae()) {
353 primary_clock
.set_mode (AudioClock::BBT
);
354 secondary_clock
.set_mode (AudioClock::MinSec
);
356 primary_clock
.set_mode (AudioClock::SMPTE
);
357 secondary_clock
.set_mode (AudioClock::BBT
);
360 /* start the time-of-day-clock */
363 /* OS X provides an always visible wallclock, so don't be stupid */
364 update_wall_clock ();
365 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock
), 60000);
368 update_disk_space ();
370 update_sample_rate (engine
->frame_rate());
372 platform_specific ();
374 /* now start and maybe save state */
376 if (do_engine_start () == 0) {
377 if (session
&& _session_is_new
) {
378 /* we need to retain initial visual
379 settings for a new session
381 session
->save_state ("");
386 ARDOUR_UI::~ARDOUR_UI ()
388 save_ardour_state ();
402 if (add_route_dialog
) {
403 delete add_route_dialog
;
406 if (new_session_dialog
) {
407 delete new_session_dialog
;
412 ARDOUR_UI::pop_back_splash ()
414 if (Splash::instance()) {
415 // Splash::instance()->pop_back();
416 Splash::instance()->hide ();
421 ARDOUR_UI::configure_timeout ()
423 if (last_configure_time
== 0) {
424 /* no configure events yet */
428 /* force a gap of 0.5 seconds since the last configure event
431 if (get_microseconds() - last_configure_time
< 500000) {
434 have_configure_timeout
= false;
435 save_ardour_state ();
441 ARDOUR_UI::configure_handler (GdkEventConfigure
* conf
)
443 if (have_configure_timeout
) {
444 last_configure_time
= get_microseconds();
446 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout
), 100);
447 have_configure_timeout
= true;
454 ARDOUR_UI::set_transport_controllable_state (const XMLNode
& node
)
456 const XMLProperty
* prop
;
458 if ((prop
= node
.property ("roll")) != 0) {
459 roll_controllable
.set_id (prop
->value());
461 if ((prop
= node
.property ("stop")) != 0) {
462 stop_controllable
.set_id (prop
->value());
464 if ((prop
= node
.property ("goto_start")) != 0) {
465 goto_start_controllable
.set_id (prop
->value());
467 if ((prop
= node
.property ("goto_end")) != 0) {
468 goto_end_controllable
.set_id (prop
->value());
470 if ((prop
= node
.property ("auto_loop")) != 0) {
471 auto_loop_controllable
.set_id (prop
->value());
473 if ((prop
= node
.property ("play_selection")) != 0) {
474 play_selection_controllable
.set_id (prop
->value());
476 if ((prop
= node
.property ("rec")) != 0) {
477 rec_controllable
.set_id (prop
->value());
479 if ((prop
= node
.property ("shuttle")) != 0) {
480 shuttle_controllable
.set_id (prop
->value());
485 ARDOUR_UI::get_transport_controllable_state ()
487 XMLNode
* node
= new XMLNode(X_("TransportControllables"));
490 roll_controllable
.id().print (buf
, sizeof (buf
));
491 node
->add_property (X_("roll"), buf
);
492 stop_controllable
.id().print (buf
, sizeof (buf
));
493 node
->add_property (X_("stop"), buf
);
494 goto_start_controllable
.id().print (buf
, sizeof (buf
));
495 node
->add_property (X_("goto_start"), buf
);
496 goto_end_controllable
.id().print (buf
, sizeof (buf
));
497 node
->add_property (X_("goto_end"), buf
);
498 auto_loop_controllable
.id().print (buf
, sizeof (buf
));
499 node
->add_property (X_("auto_loop"), buf
);
500 play_selection_controllable
.id().print (buf
, sizeof (buf
));
501 node
->add_property (X_("play_selection"), buf
);
502 rec_controllable
.id().print (buf
, sizeof (buf
));
503 node
->add_property (X_("rec"), buf
);
504 shuttle_controllable
.id().print (buf
, sizeof (buf
));
505 node
->add_property (X_("shuttle"), buf
);
511 ARDOUR_UI::save_ardour_state ()
513 if (!keyboard
|| !mixer
|| !editor
) {
517 /* XXX this is all a bit dubious. add_extra_xml() uses
518 a different lifetime model from add_instant_xml().
521 XMLNode
* node
= new XMLNode (keyboard
->get_state());
522 Config
->add_extra_xml (*node
);
523 Config
->add_extra_xml (get_transport_controllable_state());
524 if (new_session_dialog
) {
525 if (new_session_dialog
->engine_control
.was_used()) {
526 Config
->add_extra_xml (new_session_dialog
->engine_control
.get_state());
529 Config
->save_state();
530 ui_config
->save_state ();
532 XMLNode
enode(static_cast<Stateful
*>(editor
)->get_state());
533 XMLNode
mnode(mixer
->get_state());
536 session
->add_instant_xml (enode
, session
->path());
537 session
->add_instant_xml (mnode
, session
->path());
539 Config
->add_instant_xml (enode
, get_user_ardour_path());
540 Config
->add_instant_xml (mnode
, get_user_ardour_path());
543 Keyboard::save_keybindings ();
547 ARDOUR_UI::autosave_session ()
549 if (g_main_depth() > 1) {
550 /* inside a recursive main loop,
551 give up because we may not be able to
557 if (!Config
->get_periodic_safety_backups())
561 session
->maybe_write_autosave();
568 ARDOUR_UI::update_autosave ()
570 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave
));
572 if (session
->dirty()) {
573 if (_autosave_connection
.connected()) {
574 _autosave_connection
.disconnect();
577 _autosave_connection
= Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session
),
578 Config
->get_periodic_safety_backup_interval() * 1000);
581 if (_autosave_connection
.connected()) {
582 _autosave_connection
.disconnect();
588 ARDOUR_UI::backend_audio_error (bool we_set_params
, Gtk::Window
* toplevel
)
592 title
= _("Ardour could not start JACK");
594 title
= _("Ardour could not connect to JACK.");
597 MessageDialog
win (title
,
603 win
.set_secondary_text(_("There are several possible reasons:\n\
605 1) You requested audio parameters that are not supported..\n\
606 2) JACK is running as another user.\n\
608 Please consider the possibilities, and perhaps try different parameters."));
610 win
.set_secondary_text(_("There are several possible reasons:\n\
612 1) JACK is not running.\n\
613 2) JACK is running as another user, perhaps root.\n\
614 3) There is already another client called \"ardour\".\n\
616 Please consider the possibilities, and perhaps (re)start JACK."));
620 win
.set_transient_for (*toplevel
);
624 win
.add_button (Stock::OK
, RESPONSE_CLOSE
);
626 win
.add_button (Stock::QUIT
, RESPONSE_CLOSE
);
629 win
.set_default_response (RESPONSE_CLOSE
);
632 win
.set_position (Gtk::WIN_POS_CENTER
);
635 /* we just don't care about the result, but we want to block */
641 ARDOUR_UI::startup ()
645 new_session_dialog
= new NewSessionDialog();
647 bool backend_audio_is_running
= EngineControl::engine_running();
648 XMLNode
* audio_setup
= Config
->extra_xml ("AudioSetup");
651 new_session_dialog
->engine_control
.set_state (*audio_setup
);
654 if (!get_session_parameters (backend_audio_is_running
, ARDOUR_COMMAND_LINE::new_session
)) {
658 BootMessage (_("Ardour is ready for use"));
663 ARDOUR_UI::no_memory_warning ()
665 XMLNode
node (X_("no-memory-warning"));
666 Config
->add_instant_xml (node
, get_user_ardour_path());
670 ARDOUR_UI::check_memory_locking ()
673 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
677 XMLNode
* memory_warning_node
= Config
->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
679 if (engine
->is_realtime() && memory_warning_node
== 0) {
681 struct rlimit limits
;
683 long pages
, page_size
;
685 if ((page_size
= sysconf (_SC_PAGESIZE
)) < 0 ||(pages
= sysconf (_SC_PHYS_PAGES
)) < 0) {
688 ram
= (int64_t) pages
* (int64_t) page_size
;
691 if (getrlimit (RLIMIT_MEMLOCK
, &limits
)) {
695 if (limits
.rlim_cur
!= RLIM_INFINITY
) {
697 if (ram
== 0 || ((double) limits
.rlim_cur
/ ram
) < 0.75) {
700 MessageDialog
msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
701 "This might cause Ardour to run out of memory before your system "
702 "runs out of memory. \n\n"
703 "You can view the memory limit with 'ulimit -l', "
704 "and it is normally controlled by /etc/security/limits.conf"));
706 VBox
* vbox
= msg
.get_vbox();
708 CheckButton
cb (_("Do not show this window again"));
710 cb
.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning
));
712 hbox
.pack_start (cb
, true, false);
713 vbox
->pack_start (hbox
);
731 if (session
->transport_rolling()) {
732 session
->request_stop ();
736 if (session
->dirty()) {
737 switch (ask_about_saving_session(_("quit"))) {
742 /* use the default name */
743 if (save_state_canfail ("")) {
744 /* failed - don't quit */
745 MessageDialog
msg (*editor
,
747 Ardour was unable to save your session.\n\n\
748 If you still wish to quit, please use the\n\n\
749 \"Just quit\" option."));
760 session
->set_deletion_in_progress ();
763 ArdourDialog::close_all_dialogs ();
765 save_ardour_state ();
770 ARDOUR_UI::ask_about_saving_session (const string
& what
)
772 ArdourDialog
window (_("ardour: save session?"));
773 Gtk::HBox dhbox
; // the hbox for the image and text
774 Gtk::Label prompt_label
;
775 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_WARNING
, Gtk::ICON_SIZE_DIALOG
));
779 msg
= string_compose(_("Don't %1"), what
);
780 window
.add_button (msg
, RESPONSE_REJECT
);
781 msg
= string_compose(_("Just %1"), what
);
782 window
.add_button (msg
, RESPONSE_APPLY
);
783 msg
= string_compose(_("Save and %1"), what
);
784 window
.add_button (msg
, RESPONSE_ACCEPT
);
786 window
.set_default_response (RESPONSE_ACCEPT
);
788 Gtk::Button
noquit_button (msg
);
789 noquit_button
.set_name ("EditorGTKButton");
794 if (session
->snap_name() == session
->name()) {
797 type
= _("snapshot");
799 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?"),
800 type
, session
->snap_name());
802 prompt_label
.set_text (prompt
);
803 prompt_label
.set_name (X_("PrompterLabel"));
804 prompt_label
.set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
806 dimage
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
)
808 dhbox
.set_homogeneous (false);
809 dhbox
.pack_start (*dimage
, false, false, 5);
810 dhbox
.pack_start (prompt_label
, true, false, 5);
811 window
.get_vbox()->pack_start (dhbox
);
813 window
.set_name (_("Prompter"));
814 window
.set_position (Gtk::WIN_POS_MOUSE
);
815 window
.set_modal (true);
816 window
.set_resizable (false);
819 window
.set_keep_above (true);
822 ResponseType r
= (ResponseType
) window
.run();
827 case RESPONSE_ACCEPT
: // save and get out of here
829 case RESPONSE_APPLY
: // get out of here
839 ARDOUR_UI::every_second ()
842 update_buffer_load ();
843 update_disk_space ();
848 ARDOUR_UI::every_point_one_seconds ()
850 update_speed_display ();
851 RapidScreenUpdate(); /* EMIT_SIGNAL */
856 ARDOUR_UI::every_point_zero_one_seconds ()
858 // august 2007: actual update frequency: 40Hz, not 100Hz
860 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
865 ARDOUR_UI::update_sample_rate (nframes_t ignored
)
869 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate
), ignored
));
871 if (!engine
->connected()) {
873 snprintf (buf
, sizeof (buf
), _("disconnected"));
877 nframes_t rate
= engine
->frame_rate();
879 if (fmod (rate
, 1000.0) != 0.0) {
880 snprintf (buf
, sizeof (buf
), _("%.1f kHz / %4.1f ms"),
881 (float) rate
/1000.0f
,
882 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
884 snprintf (buf
, sizeof (buf
), _("%u kHz / %4.1f ms"),
886 (engine
->frames_per_cycle() / (float) rate
) * 1000.0f
);
890 sample_rate_label
.set_text (buf
);
894 ARDOUR_UI::update_cpu_load ()
897 snprintf (buf
, sizeof (buf
), _("DSP: %5.1f%%"), engine
->get_cpu_load());
898 cpu_load_label
.set_text (buf
);
902 ARDOUR_UI::update_buffer_load ()
908 c
= session
->capture_load ();
909 p
= session
->playback_load ();
911 push_buffer_stats (c
, p
);
913 snprintf (buf
, sizeof (buf
), _("Buffers p:%" PRIu32
"%% c:%" PRIu32
"%%"),
914 session
->playback_load(), session
->capture_load());
915 buffer_load_label
.set_text (buf
);
917 buffer_load_label
.set_text ("");
922 ARDOUR_UI::count_recenabled_streams (Route
& route
)
924 Track
* track
= dynamic_cast<Track
*>(&route
);
925 if (track
&& track
->diskstream()->record_enabled()) {
926 rec_enabled_streams
+= track
->n_inputs();
931 ARDOUR_UI::update_disk_space()
937 nframes_t frames
= session
->available_capture_duration();
940 if (frames
== max_frames
) {
941 strcpy (buf
, _("Disk: 24hrs+"));
946 nframes_t fr
= session
->frame_rate();
948 rec_enabled_streams
= 0;
949 session
->foreach_route (this, &ARDOUR_UI::count_recenabled_streams
);
951 if (rec_enabled_streams
) {
952 frames
/= rec_enabled_streams
;
955 hrs
= frames
/ (fr
* 3600);
956 frames
-= hrs
* fr
* 3600;
957 mins
= frames
/ (fr
* 60);
958 frames
-= mins
* fr
* 60;
961 snprintf (buf
, sizeof(buf
), _("Disk: %02dh:%02dm:%02ds"), hrs
, mins
, secs
);
964 disk_space_label
.set_text (buf
);
968 ARDOUR_UI::update_wall_clock ()
975 tm_now
= localtime (&now
);
977 sprintf (buf
, "%02d:%02d", tm_now
->tm_hour
, tm_now
->tm_min
);
978 wall_clock_label
.set_text (buf
);
984 ARDOUR_UI::session_menu (GdkEventButton
*ev
)
986 session_popup_menu
->popup (0, 0);
991 ARDOUR_UI::redisplay_recent_sessions ()
993 vector
<string
*> *sessions
;
994 vector
<string
*>::iterator i
;
995 RecentSessionsSorter cmp
;
997 recent_session_display
.set_model (Glib::RefPtr
<TreeModel
>(0));
998 recent_session_model
->clear ();
1001 ARDOUR::read_recent_sessions (rs
);
1004 recent_session_display
.set_model (recent_session_model
);
1008 /* sort them alphabetically */
1009 sort (rs
.begin(), rs
.end(), cmp
);
1010 sessions
= new vector
<string
*>;
1012 for (RecentSessions::iterator i
= rs
.begin(); i
!= rs
.end(); ++i
) {
1013 sessions
->push_back (new string ((*i
).second
));
1016 for (i
= sessions
->begin(); i
!= sessions
->end(); ++i
) {
1018 vector
<string
*>* states
;
1019 vector
<const gchar
*> item
;
1020 string fullpath
= *(*i
);
1022 /* remove any trailing / */
1024 if (fullpath
[fullpath
.length()-1] == '/') {
1025 fullpath
= fullpath
.substr (0, fullpath
.length()-1);
1028 /* check whether session still exists */
1029 if (!Glib::file_test(fullpath
.c_str(), Glib::FILE_TEST_EXISTS
)) {
1030 /* session doesn't exist */
1031 cerr
<< "skipping non-existent session " << fullpath
<< endl
;
1035 /* now get available states for this session */
1037 if ((states
= Session::possible_states (fullpath
)) == 0) {
1038 /* no state file? */
1042 TreeModel::Row row
= *(recent_session_model
->append());
1044 row
[recent_session_columns
.visible_name
] = Glib::path_get_basename (fullpath
);
1045 row
[recent_session_columns
.fullpath
] = fullpath
;
1047 if (states
->size() > 1) {
1049 /* add the children */
1051 for (vector
<string
*>::iterator i2
= states
->begin(); i2
!= states
->end(); ++i2
) {
1053 TreeModel::Row child_row
= *(recent_session_model
->append (row
.children()));
1055 child_row
[recent_session_columns
.visible_name
] = **i2
;
1056 child_row
[recent_session_columns
.fullpath
] = fullpath
;
1065 recent_session_display
.set_model (recent_session_model
);
1070 ARDOUR_UI::build_session_selector ()
1072 session_selector_window
= new ArdourDialog ("session selector");
1074 Gtk::ScrolledWindow
*scroller
= manage (new Gtk::ScrolledWindow
);
1076 session_selector_window
->add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
1077 session_selector_window
->add_button (Stock::OPEN
, RESPONSE_ACCEPT
);
1078 session_selector_window
->set_default_response (RESPONSE_ACCEPT
);
1079 recent_session_model
= TreeStore::create (recent_session_columns
);
1080 recent_session_display
.set_model (recent_session_model
);
1081 recent_session_display
.append_column (_("Recent Sessions"), recent_session_columns
.visible_name
);
1082 recent_session_display
.set_headers_visible (false);
1083 recent_session_display
.get_selection()->set_mode (SELECTION_BROWSE
);
1084 recent_session_display
.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated
));
1086 scroller
->add (recent_session_display
);
1087 scroller
->set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
1089 session_selector_window
->set_name ("SessionSelectorWindow");
1090 session_selector_window
->set_size_request (200, 400);
1091 session_selector_window
->get_vbox()->pack_start (*scroller
);
1092 session_selector_window
->show_all_children();
1096 ARDOUR_UI::recent_session_row_activated (const TreePath
& path
, TreeViewColumn
* col
)
1098 session_selector_window
->response (RESPONSE_ACCEPT
);
1102 ARDOUR_UI::open_recent_session ()
1104 bool can_return
= (session
!= 0);
1106 if (session_selector_window
== 0) {
1107 build_session_selector ();
1110 redisplay_recent_sessions ();
1114 session_selector_window
->set_position (WIN_POS_MOUSE
);
1116 ResponseType r
= (ResponseType
) session_selector_window
->run ();
1119 case RESPONSE_ACCEPT
:
1123 session_selector_window
->hide();
1130 if (recent_session_display
.get_selection()->count_selected_rows() == 0) {
1134 session_selector_window
->hide();
1136 Gtk::TreeModel::iterator i
= recent_session_display
.get_selection()->get_selected();
1138 if (i
== recent_session_model
->children().end()) {
1142 Glib::ustring path
= (*i
)[recent_session_columns
.fullpath
];
1143 Glib::ustring state
= (*i
)[recent_session_columns
.visible_name
];
1145 _session_is_new
= false;
1147 if (load_session (path
, state
) == 0) {
1156 ARDOUR_UI::check_audioengine ()
1159 if (!engine
->connected()) {
1160 MessageDialog
msg (_("Ardour is not connected to JACK\n"
1161 "You cannot open or close sessions in this condition"));
1173 ARDOUR_UI::open_session ()
1175 if (!check_audioengine()) {
1179 /* popup selector window */
1181 if (open_session_selector
== 0) {
1183 /* ardour sessions are folders */
1185 open_session_selector
= new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN
);
1186 open_session_selector
->add_button (Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
1187 open_session_selector
->add_button (Gtk::Stock::OPEN
, Gtk::RESPONSE_ACCEPT
);
1188 open_session_selector
->set_default_response(Gtk::RESPONSE_ACCEPT
);
1190 FileFilter session_filter
;
1191 session_filter
.add_pattern ("*.ardour");
1192 session_filter
.set_name (_("Ardour sessions"));
1193 open_session_selector
->add_filter (session_filter
);
1194 open_session_selector
->set_filter (session_filter
);
1197 int response
= open_session_selector
->run();
1198 open_session_selector
->hide ();
1201 case RESPONSE_ACCEPT
:
1204 open_session_selector
->hide();
1208 open_session_selector
->hide();
1209 string session_path
= open_session_selector
->get_filename();
1213 if (session_path
.length() > 0) {
1214 if (Session::find_session (session_path
, path
, name
, isnew
) == 0) {
1215 _session_is_new
= isnew
;
1216 load_session (path
, name
);
1223 ARDOUR_UI::session_add_midi_track ()
1225 cerr
<< _("Patience is a virtue.\n");
1229 ARDOUR_UI::session_add_audio_route (bool track
, int32_t input_channels
, int32_t output_channels
, ARDOUR::TrackMode mode
, uint32_t how_many
)
1231 list
<boost::shared_ptr
<AudioTrack
> > tracks
;
1232 Session::RouteList routes
;
1235 warning
<< _("You cannot add a track or bus without a session already loaded.") << endmsg
;
1241 tracks
= session
->new_audio_track (input_channels
, output_channels
, mode
, how_many
);
1243 if (tracks
.size() != how_many
) {
1244 if (how_many
== 1) {
1245 error
<< _("could not create a new audio track") << endmsg
;
1247 error
<< string_compose (_("could only create %1 of %2 new audio %3"),
1248 tracks
.size(), how_many
, (track
? _("tracks") : _("busses"))) << endmsg
;
1254 routes
= session
->new_audio_route (input_channels
, output_channels
, how_many
);
1256 if (routes
.size() != how_many
) {
1257 if (how_many
== 1) {
1258 error
<< _("could not create a new audio track") << endmsg
;
1260 error
<< string_compose (_("could not create %1 new audio tracks"), how_many
) << endmsg
;
1266 if (need_control_room_outs
) {
1272 route
->set_stereo_control_outs (control_lr_channels
);
1273 route
->control_outs()->set_stereo_pan (pans
, this);
1275 #endif /* CONTROLOUTS */
1279 MessageDialog
msg (*editor
,
1280 _("There are insufficient JACK ports available\n\
1281 to create a new track or bus.\n\
1282 You should save Ardour, exit and\n\
1283 restart JACK with more ports."));
1290 ARDOUR_UI::do_transport_locate (nframes_t new_position
)
1292 nframes_t _preroll
= 0;
1295 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1296 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1298 if (new_position
> _preroll
) {
1299 new_position
-= _preroll
;
1304 session
->request_locate (new_position
);
1309 ARDOUR_UI::transport_goto_start ()
1312 session
->goto_start();
1315 /* force displayed area in editor to start no matter
1316 what "follow playhead" setting is.
1320 editor
->reset_x_origin (session
->current_start_frame());
1326 ARDOUR_UI::transport_goto_zero ()
1329 session
->request_locate (0);
1332 /* force displayed area in editor to start no matter
1333 what "follow playhead" setting is.
1337 editor
->reset_x_origin (0);
1343 ARDOUR_UI::transport_goto_wallclock ()
1345 if (session
&& editor
) {
1352 localtime_r (&now
, &tmnow
);
1354 frames
= tmnow
.tm_hour
* (60 * 60 * session
->frame_rate());
1355 frames
+= tmnow
.tm_min
* (60 * session
->frame_rate());
1356 frames
+= tmnow
.tm_sec
* session
->frame_rate();
1358 session
->request_locate (frames
);
1360 /* force displayed area in editor to start no matter
1361 what "follow playhead" setting is.
1365 editor
->reset_x_origin (frames
- (editor
->current_page_frames()/2));
1371 ARDOUR_UI::transport_goto_end ()
1374 nframes_t frame
= session
->current_end_frame();
1375 session
->request_locate (frame
);
1377 /* force displayed area in editor to start no matter
1378 what "follow playhead" setting is.
1382 editor
->reset_x_origin (frame
);
1388 ARDOUR_UI::transport_stop ()
1394 if (session
->is_auditioning()) {
1395 session
->cancel_audition ();
1399 if (session
->get_play_loop ()) {
1400 session
->request_play_loop (false);
1403 session
->request_stop ();
1407 ARDOUR_UI::transport_stop_and_forget_capture ()
1410 session
->request_stop (true);
1415 ARDOUR_UI::remove_last_capture()
1418 editor
->remove_last_capture();
1423 ARDOUR_UI::transport_record (bool roll
)
1427 switch (session
->record_status()) {
1428 case Session::Disabled
:
1429 if (session
->ntracks() == 0) {
1430 MessageDialog
msg (*editor
, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1434 session
->maybe_enable_record ();
1439 case Session::Recording
:
1441 session
->request_stop();
1443 session
->disable_record (false, true);
1447 case Session::Enabled
:
1448 session
->disable_record (false, true);
1451 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1455 ARDOUR_UI::transport_roll ()
1463 rolling
= session
->transport_rolling ();
1465 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1467 if (session
->get_play_loop()) {
1468 session
->request_play_loop (false);
1469 auto_loop_button
.set_visual_state (1);
1470 roll_button
.set_visual_state (1);
1471 } else if (session
->get_play_range ()) {
1472 session
->request_play_range (false);
1473 play_selection_button
.set_visual_state (0);
1474 } else if (rolling
) {
1475 session
->request_locate (session
->last_transport_start(), true);
1478 session
->request_transport_speed (1.0f
);
1482 ARDOUR_UI::transport_loop()
1485 if (session
->get_play_loop()) {
1486 if (session
->transport_rolling()) {
1487 Location
* looploc
= session
->locations()->auto_loop_location();
1489 session
->request_locate (looploc
->start(), true);
1494 session
->request_play_loop (true);
1500 ARDOUR_UI::transport_play_selection ()
1506 if (!session
->get_play_range()) {
1507 session
->request_stop ();
1510 editor
->play_selection ();
1514 ARDOUR_UI::transport_rewind (int option
)
1516 float current_transport_speed
;
1519 current_transport_speed
= session
->transport_speed();
1521 if (current_transport_speed
>= 0.0f
) {
1524 session
->request_transport_speed (-1.0f
);
1527 session
->request_transport_speed (-4.0f
);
1530 session
->request_transport_speed (-0.5f
);
1535 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1541 ARDOUR_UI::transport_forward (int option
)
1543 float current_transport_speed
;
1546 current_transport_speed
= session
->transport_speed();
1548 if (current_transport_speed
<= 0.0f
) {
1551 session
->request_transport_speed (1.0f
);
1554 session
->request_transport_speed (4.0f
);
1557 session
->request_transport_speed (0.5f
);
1562 session
->request_transport_speed (current_transport_speed
* 1.5f
);
1568 ARDOUR_UI::toggle_record_enable (uint32_t dstream
)
1574 boost::shared_ptr
<Route
> r
;
1576 if ((r
= session
->route_by_remote_id (dstream
)) != 0) {
1580 if ((t
= dynamic_cast<Track
*>(r
.get())) != 0) {
1581 t
->diskstream()->set_record_enabled (!t
->diskstream()->record_enabled());
1590 ARDOUR_UI::queue_transport_change ()
1592 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state
));
1596 ARDOUR_UI::map_transport_state ()
1598 float sp
= session
->transport_speed();
1601 transport_rolling ();
1602 } else if (sp
< 0.0f
) {
1603 transport_rewinding ();
1604 } else if (sp
> 0.0f
) {
1605 transport_forwarding ();
1607 transport_stopped ();
1612 ARDOUR_UI::GlobalClickBox::printer (char buf
[32], Adjustment
&adj
, void *arg
)
1614 snprintf (buf
, sizeof(buf
), "%s", ((GlobalClickBox
*) arg
)->strings
[
1615 (int) adj
.get_value()].c_str());
1619 ARDOUR_UI::engine_stopped ()
1621 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped
));
1622 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1623 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1627 ARDOUR_UI::engine_running ()
1629 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running
));
1630 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, true);
1631 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, false);
1633 Glib::RefPtr
<Action
> action
;
1634 const char* action_name
= 0;
1636 switch (engine
->frames_per_cycle()) {
1638 action_name
= X_("JACKLatency32");
1641 action_name
= X_("JACKLatency64");
1644 action_name
= X_("JACKLatency128");
1647 action_name
= X_("JACKLatency512");
1650 action_name
= X_("JACKLatency1024");
1653 action_name
= X_("JACKLatency2048");
1656 action_name
= X_("JACKLatency4096");
1659 action_name
= X_("JACKLatency8192");
1662 /* XXX can we do anything useful ? */
1668 action
= ActionManager::get_action (X_("JACK"), action_name
);
1671 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic (action
);
1672 ract
->set_active ();
1678 ARDOUR_UI::engine_halted ()
1680 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted
));
1682 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions
, false);
1683 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions
, true);
1685 update_sample_rate (0);
1687 MessageDialog
msg (*editor
,
1689 JACK has either been shutdown or it\n\
1690 disconnected Ardour because Ardour\n\
1691 was not fast enough. Try to restart\n\
1692 JACK, reconnect and save the session."));
1698 ARDOUR_UI::do_engine_start ()
1706 error
<< _("Unable to start the session running")
1716 ARDOUR_UI::setup_theme ()
1718 theme_manager
->setup_theme();
1722 ARDOUR_UI::update_clocks ()
1724 if (!editor
|| !editor
->dragging_playhead()) {
1725 Clock (session
->audible_frame(), false, editor
->get_preferred_edit_position()); /* EMIT_SIGNAL */
1730 ARDOUR_UI::start_clocking ()
1732 clock_signal_connection
= RapidScreenUpdate
.connect (mem_fun(*this, &ARDOUR_UI::update_clocks
));
1736 ARDOUR_UI::stop_clocking ()
1738 clock_signal_connection
.disconnect ();
1742 ARDOUR_UI::toggle_clocking ()
1745 if (clock_button
.get_active()) {
1754 ARDOUR_UI::_blink (void *arg
)
1757 ((ARDOUR_UI
*) arg
)->blink ();
1764 Blink (blink_on
= !blink_on
); /* EMIT_SIGNAL */
1768 ARDOUR_UI::start_blinking ()
1770 /* Start the blink signal. Everybody with a blinking widget
1771 uses Blink to drive the widget's state.
1774 if (blink_timeout_tag
< 0) {
1776 blink_timeout_tag
= g_timeout_add (240, _blink
, this);
1781 ARDOUR_UI::stop_blinking ()
1783 if (blink_timeout_tag
>= 0) {
1784 g_source_remove (blink_timeout_tag
);
1785 blink_timeout_tag
= -1;
1790 ARDOUR_UI::name_io_setup (AudioEngine
& engine
,
1796 if (io
.n_inputs() == 0) {
1801 /* XXX we're not handling multiple ports yet. */
1803 const char **connections
= io
.input(0)->get_connections();
1805 if (connections
== 0 || connections
[0] == '\0') {
1808 buf
= connections
[0];
1815 if (io
.n_outputs() == 0) {
1820 /* XXX we're not handling multiple ports yet. */
1822 const char **connections
= io
.output(0)->get_connections();
1824 if (connections
== 0 || connections
[0] == '\0') {
1827 buf
= connections
[0];
1834 /** Ask the user for the name of a new shapshot and then take it.
1837 ARDOUR_UI::snapshot_session ()
1839 ArdourPrompter
prompter (true);
1843 struct tm local_time
;
1846 localtime_r (&n
, &local_time
);
1847 strftime (timebuf
, sizeof(timebuf
), "%FT%T", &local_time
);
1849 prompter
.set_name ("Prompter");
1850 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
1851 prompter
.set_prompt (_("Name of New Snapshot"));
1852 prompter
.set_initial_text (timebuf
);
1855 switch (prompter
.run()) {
1856 case RESPONSE_ACCEPT
:
1857 prompter
.get_result (snapname
);
1858 if (snapname
.length()){
1859 if (snapname
.find ('/') != string::npos
) {
1860 MessageDialog
msg (_("To ensure compatibility with various systems\n"
1861 "snapshot names may not contain a '/' character"));
1865 if (snapname
.find ('\\') != string::npos
) {
1866 MessageDialog
msg (_("To ensure compatibility with various systems\n"
1867 "snapshot names may not contain a '\\' character"));
1871 save_state (snapname
);
1881 ARDOUR_UI::save_state (const string
& name
)
1883 (void) save_state_canfail (name
);
1887 ARDOUR_UI::save_state_canfail (string name
)
1892 if (name
.length() == 0) {
1893 name
= session
->snap_name();
1896 if ((ret
= session
->save_state (name
)) != 0) {
1900 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1905 ARDOUR_UI::primary_clock_value_changed ()
1908 session
->request_locate (primary_clock
.current_time ());
1913 ARDOUR_UI::big_clock_value_changed ()
1916 session
->request_locate (big_clock
.current_time ());
1921 ARDOUR_UI::secondary_clock_value_changed ()
1924 session
->request_locate (secondary_clock
.current_time ());
1929 ARDOUR_UI::transport_rec_enable_blink (bool onoff
)
1935 switch (session
->record_status()) {
1936 case Session::Enabled
:
1938 rec_button
.set_visual_state (2);
1940 rec_button
.set_visual_state (0);
1944 case Session::Recording
:
1945 rec_button
.set_visual_state (1);
1949 rec_button
.set_visual_state (0);
1955 ARDOUR_UI::save_template ()
1958 ArdourPrompter
prompter (true);
1961 if (!check_audioengine()) {
1965 prompter
.set_name (X_("Prompter"));
1966 prompter
.set_prompt (_("Name for mix template:"));
1967 prompter
.set_initial_text(session
->name() + _("-template"));
1968 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
1970 switch (prompter
.run()) {
1971 case RESPONSE_ACCEPT
:
1972 prompter
.get_result (name
);
1974 if (name
.length()) {
1975 session
->save_template (name
);
1985 ARDOUR_UI::fontconfig_dialog ()
1988 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1989 may not and it can take a while to build it. Warn them.
1992 Glib::ustring fontconfig
= Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1994 if (!Glib::file_test (fontconfig
, Glib::FILE_TEST_EXISTS
|Glib::FILE_TEST_IS_DIR
)) {
1995 MessageDialog
msg (*new_session_dialog
,
1996 _("Welcome to Ardour.\n\n"
1997 "The program will take a bit longer to start up\n"
1998 "while the system fonts are checked.\n\n"
1999 "This will only be done once, and you will\n"
2000 "not see this message again\n"),
2013 ARDOUR_UI::parse_cmdline_path (const Glib::ustring
& cmdline_path
, Glib::ustring
& session_name
, Glib::ustring
& session_path
, bool& existing_session
)
2015 existing_session
= false;
2017 if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_DIR
)) {
2018 session_path
= cmdline_path
;
2019 existing_session
= true;
2020 } else if (Glib::file_test (cmdline_path
, Glib::FILE_TEST_IS_REGULAR
)) {
2021 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2022 existing_session
= true;
2024 /* it doesn't exist, assume the best */
2025 session_path
= Glib::path_get_dirname (string (cmdline_path
));
2028 session_name
= basename_nosuffix (string (cmdline_path
));
2032 ARDOUR_UI::load_cmdline_session (const Glib::ustring
& session_name
, const Glib::ustring
& session_path
, bool& existing_session
)
2034 /* when this is called, the backend audio system must be running */
2036 /* the main idea here is to deal with the fact that a cmdline argument for the session
2037 can be interpreted in different ways - it could be a directory or a file, and before
2038 we load, we need to know both the session directory and the snapshot (statefile) within it
2039 that we are supposed to use.
2042 if (session_name
.length() == 0 || session_path
.length() == 0) {
2046 if (Glib::file_test (session_path
, Glib::FILE_TEST_IS_DIR
)) {
2048 Glib::ustring predicted_session_file
;
2050 predicted_session_file
= session_path
;
2051 predicted_session_file
+= '/';
2052 predicted_session_file
+= session_name
;
2053 predicted_session_file
+= Session::statefile_suffix();
2055 if (Glib::file_test (predicted_session_file
, Glib::FILE_TEST_EXISTS
)) {
2056 existing_session
= true;
2059 } else if (Glib::file_test (session_path
, Glib::FILE_TEST_EXISTS
)) {
2061 if (session_path
.find (Session::statefile_suffix()) == session_path
.length() - 7) {
2062 /* existing .ardour file */
2063 existing_session
= true;
2067 existing_session
= false;
2070 /* lets just try to load it */
2072 if (create_engine ()) {
2073 backend_audio_error (false, new_session_dialog
);
2077 return load_session (session_path
, session_name
);
2081 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring
& session_path
)
2083 Glib::ustring str
= string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path
);
2085 MessageDialog
msg (str
,
2087 Gtk::MESSAGE_WARNING
,
2088 Gtk::BUTTONS_YES_NO
,
2092 msg
.set_name (X_("CleanupDialog"));
2093 msg
.set_wmclass (X_("existing_session"), "Ardour");
2094 msg
.set_position (Gtk::WIN_POS_MOUSE
);
2097 switch (msg
.run()) {
2106 ARDOUR_UI::build_session_from_nsd (const Glib::ustring
& session_path
, const Glib::ustring
& session_name
)
2111 AutoConnectOption iconnect
;
2112 AutoConnectOption oconnect
;
2116 if (Profile
->get_sae()) {
2120 iconnect
= AutoConnectPhysical
;
2121 oconnect
= AutoConnectMaster
;
2122 nphysin
= 0; // use all available
2123 nphysout
= 0; // use all available
2127 /* get settings from advanced section of NSD */
2129 if (new_session_dialog
->create_control_bus()) {
2130 cchns
= (uint32_t) new_session_dialog
->control_channel_count();
2135 if (new_session_dialog
->create_master_bus()) {
2136 mchns
= (uint32_t) new_session_dialog
->master_channel_count();
2141 if (new_session_dialog
->connect_inputs()) {
2142 iconnect
= AutoConnectPhysical
;
2144 iconnect
= AutoConnectOption (0);
2147 /// @todo some minor tweaks.
2149 if (new_session_dialog
->connect_outs_to_master()) {
2150 oconnect
= AutoConnectMaster
;
2151 } else if (new_session_dialog
->connect_outs_to_physical()) {
2152 oconnect
= AutoConnectPhysical
;
2154 oconnect
= AutoConnectOption (0);
2157 nphysin
= (uint32_t) new_session_dialog
->input_limit_count();
2158 nphysout
= (uint32_t) new_session_dialog
->output_limit_count();
2161 if (build_session (session_path
,
2169 engine
->frame_rate() * 60 * 5)) {
2178 ARDOUR_UI::end_loading_messages ()
2184 ARDOUR_UI::loading_message (const std::string
& msg
)
2187 splash
->message (msg
);
2192 ARDOUR_UI::idle_load (const Glib::ustring
& path
)
2195 if (Glib::file_test (path
, Glib::FILE_TEST_IS_DIR
)) {
2196 /* /path/to/foo => /path/to/foo, foo */
2197 load_session (path
, basename_nosuffix (path
));
2199 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2200 load_session (Glib::path_get_dirname (path
), basename_nosuffix (path
));
2204 ARDOUR_COMMAND_LINE::session_name
= path
;
2206 if (new_session_dialog
) {
2209 /* make it break out of Dialog::run() and
2213 new_session_dialog
->response (1);
2219 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running
, bool should_be_new
)
2221 bool existing_session
= false;
2222 Glib::ustring session_name
;
2223 Glib::ustring session_path
;
2224 Glib::ustring template_name
;
2228 response
= Gtk::RESPONSE_NONE
;
2230 if (!ARDOUR_COMMAND_LINE::session_name
.empty()) {
2232 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name
, session_name
, session_path
, existing_session
);
2234 /* don't ever reuse this */
2236 ARDOUR_COMMAND_LINE::session_name
= string();
2238 if (existing_session
&& backend_audio_is_running
) {
2240 /* just load the thing already */
2242 if (load_cmdline_session (session_name
, session_path
, existing_session
) == 0) {
2247 /* make the NSD use whatever information we have */
2249 new_session_dialog
->set_session_name (session_name
);
2250 new_session_dialog
->set_session_folder (session_path
);
2253 /* loading failed, or we need the NSD for something */
2255 new_session_dialog
->set_modal (false);
2256 new_session_dialog
->set_position (WIN_POS_CENTER
);
2257 new_session_dialog
->set_current_page (0);
2258 new_session_dialog
->set_existing_session (existing_session
);
2259 new_session_dialog
->reset_recent();
2262 new_session_dialog
->set_have_engine (backend_audio_is_running
);
2263 new_session_dialog
->present ();
2264 response
= new_session_dialog
->run ();
2266 _session_is_new
= false;
2268 /* handle possible negative responses */
2272 /* sent by idle_load, meaning restart the whole process again */
2273 new_session_dialog
->hide();
2274 new_session_dialog
->reset();
2278 case Gtk::RESPONSE_CANCEL
:
2279 case Gtk::RESPONSE_DELETE_EVENT
:
2281 if (engine
&& engine
->running()) {
2282 engine
->stop (true);
2286 new_session_dialog
->hide ();
2289 case Gtk::RESPONSE_NONE
:
2290 /* "Clear" was pressed */
2294 fontconfig_dialog();
2296 if (!backend_audio_is_running
) {
2297 int ret
= new_session_dialog
->engine_control
.setup_engine ();
2300 } else if (ret
> 0) {
2301 response
= Gtk::RESPONSE_REJECT
;
2305 /* hide the NSD while we start up the engine */
2307 new_session_dialog
->hide ();
2311 if (create_engine ()) {
2313 backend_audio_error (!backend_audio_is_running
, new_session_dialog
);
2316 new_session_dialog
->set_existing_session (false);
2317 new_session_dialog
->set_current_page (2);
2319 response
= Gtk::RESPONSE_NONE
;
2323 backend_audio_is_running
= true;
2325 if (response
== Gtk::RESPONSE_OK
) {
2327 session_name
= new_session_dialog
->session_name();
2329 if (session_name
.empty()) {
2330 response
= Gtk::RESPONSE_NONE
;
2334 /* if the user mistakenly typed path information into the session filename entry,
2335 convert what they typed into a path & a name
2338 if (session_name
[0] == '/' ||
2339 (session_name
.length() > 2 && session_name
[0] == '.' && session_name
[1] == '/') ||
2340 (session_name
.length() > 3 && session_name
[0] == '.' && session_name
[1] == '.' && session_name
[2] == '/')) {
2342 session_path
= Glib::path_get_dirname (session_name
);
2343 session_name
= Glib::path_get_basename (session_name
);
2347 session_path
= new_session_dialog
->session_folder();
2350 template_name
= Glib::ustring();
2351 switch (new_session_dialog
->which_page()) {
2353 case NewSessionDialog::OpenPage
:
2357 case NewSessionDialog::EnginePage
:
2358 if (new_session_dialog
->engine_control
.interface_chosen() && !session_path
.empty()) {
2365 case NewSessionDialog::NewPage
: /* nominally the "new" session creator, but could be in use for an old session */
2367 should_be_new
= true;
2369 if (session_name
.find ('/') != Glib::ustring::npos
) {
2370 MessageDialog
msg (*new_session_dialog
, _("To ensure compatibility with various systems\n"
2371 "session names may not contain a '/' character"));
2373 response
= RESPONSE_NONE
;
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 //XXX This is needed because session constructor wants a
2386 //non-existant path. hopefully this will be fixed at some point.
2388 session_path
= Glib::build_filename (session_path
, session_name
);
2390 if (Glib::file_test (session_path
, Glib::FileTest (G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))) {
2392 if (ask_about_loading_existing_session (session_path
)) {
2395 response
= RESPONSE_NONE
;
2400 _session_is_new
= true;
2402 if (new_session_dialog
->use_session_template()) {
2404 template_name
= new_session_dialog
->session_template_name();
2408 if (build_session_from_nsd (session_path
, session_name
)) {
2409 response
= RESPONSE_NONE
;
2421 new_session_dialog
->hide ();
2423 if (load_session (session_path
, session_name
, template_name
)) {
2425 response
= Gtk::RESPONSE_NONE
;
2429 if (response
== Gtk::RESPONSE_NONE
) {
2430 new_session_dialog
->set_existing_session (false);
2431 new_session_dialog
->reset ();
2435 } while (response
== Gtk::RESPONSE_NONE
|| response
== Gtk::RESPONSE_REJECT
);
2439 new_session_dialog
->hide();
2440 new_session_dialog
->reset();
2441 goto_editor_window ();
2446 ARDOUR_UI::close_session ()
2448 if (!check_audioengine()) {
2452 if (unload_session (true)) {
2456 get_session_parameters (true, false);
2460 ARDOUR_UI::load_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
, Glib::ustring mix_template
)
2462 Session
*new_session
;
2466 session_loaded
= false;
2468 if (!check_audioengine()) {
2472 unload_status
= unload_session ();
2474 if (unload_status
< 0) {
2476 } else if (unload_status
> 0) {
2481 /* if it already exists, we must have write access */
2483 if (Glib::file_test (path
.c_str(), Glib::FILE_TEST_EXISTS
) && ::access (path
.c_str(), W_OK
)) {
2484 MessageDialog
msg (*editor
, _("You do not have write access to this session.\n"
2485 "This prevents the session from being loaded."));
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
:
2527 MessageDialog
msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path
, snap_name
),
2530 Gtk::BUTTONS_CLOSE
);
2532 msg
.set_title (_("Loading Error"));
2533 msg
.set_secondary_text (_("Click the Close button to try again."));
2534 msg
.set_position (Gtk::WIN_POS_CENTER
);
2538 int response
= msg
.run ();
2543 case RESPONSE_CANCEL
:
2551 connect_to_session (new_session
);
2553 Config
->set_current_owner (ConfigVariableBase::Interface
);
2555 session_loaded
= true;
2557 goto_editor_window ();
2560 session
->set_clean ();
2571 ARDOUR_UI::build_session (const Glib::ustring
& path
, const Glib::ustring
& snap_name
,
2572 uint32_t control_channels
,
2573 uint32_t master_channels
,
2574 AutoConnectOption input_connect
,
2575 AutoConnectOption output_connect
,
2578 nframes_t initial_length
)
2580 Session
*new_session
;
2583 if (!check_audioengine()) {
2587 session_loaded
= false;
2589 x
= unload_session ();
2597 _session_is_new
= true;
2600 new_session
= new Session (*engine
, path
, snap_name
, input_connect
, output_connect
,
2601 control_channels
, master_channels
, nphysin
, nphysout
, initial_length
);
2606 MessageDialog
msg (string_compose(_("Could not create session in \"%1\""), path
));
2612 connect_to_session (new_session
);
2614 session_loaded
= true;
2616 new_session
->save_state(new_session
->name());
2625 editor
->show_window ();
2636 ARDOUR_UI::show_about ()
2640 about
->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response
) );
2647 ARDOUR_UI::launch_chat ()
2650 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2652 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2657 ARDOUR_UI::hide_about ()
2660 about
->get_window()->set_cursor ();
2666 ARDOUR_UI::about_signal_response(int response
)
2672 ARDOUR_UI::show_splash ()
2676 splash
= new Splash
;
2684 splash
->queue_draw ();
2685 splash
->get_window()->process_updates (true);
2690 ARDOUR_UI::hide_splash ()
2698 ARDOUR_UI::display_cleanup_results (Session::cleanup_report
& rep
, const gchar
* list_title
,
2699 const string
& plural_msg
, const string
& singular_msg
)
2703 removed
= rep
.paths
.size();
2706 MessageDialog
msgd (*editor
,
2707 _("No audio files were ready for cleanup"),
2710 (Gtk::ButtonsType
)(Gtk::BUTTONS_OK
) );
2711 msgd
.set_secondary_text (_("If this seems suprising, \n\
2712 check for any existing snapshots.\n\
2713 These may still include regions that\n\
2714 require some unused files to continue to exist."));
2720 ArdourDialog
results (_("ardour: cleanup"), true, false);
2722 struct CleanupResultsModelColumns
: public Gtk::TreeModel::ColumnRecord
{
2723 CleanupResultsModelColumns() {
2727 Gtk::TreeModelColumn
<Glib::ustring
> visible_name
;
2728 Gtk::TreeModelColumn
<Glib::ustring
> fullpath
;
2732 CleanupResultsModelColumns results_columns
;
2733 Glib::RefPtr
<Gtk::ListStore
> results_model
;
2734 Gtk::TreeView results_display
;
2736 results_model
= ListStore::create (results_columns
);
2737 results_display
.set_model (results_model
);
2738 results_display
.append_column (list_title
, results_columns
.visible_name
);
2740 results_display
.set_name ("CleanupResultsList");
2741 results_display
.set_headers_visible (true);
2742 results_display
.set_headers_clickable (false);
2743 results_display
.set_reorderable (false);
2745 Gtk::ScrolledWindow list_scroller
;
2748 Gtk::HBox dhbox
; // the hbox for the image and text
2749 Gtk::HBox ddhbox
; // the hbox we eventually pack into the dialog's vbox
2750 Gtk::Image
* dimage
= manage (new Gtk::Image(Stock::DIALOG_INFO
, Gtk::ICON_SIZE_DIALOG
));
2752 dimage
->set_alignment(ALIGN_LEFT
, ALIGN_TOP
);
2756 %1 - number of files removed
2757 %2 - location of "dead_sounds"
2758 %3 - size of files affected
2759 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2762 const char* bprefix
;
2763 float space_adjusted
;
2765 if (rep
.space
< 1000000.0f
) {
2766 bprefix
= X_("kilo");
2767 space_adjusted
= truncf((float)rep
.space
/ 1000.0f
);
2768 } else if (rep
.space
< (1000000.0f
* 1000)) {
2769 bprefix
= X_("mega");
2770 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
));
2772 bprefix
= X_("giga");
2773 space_adjusted
= truncf((float)rep
.space
/ (1000000.0f
* 1000));
2777 txt
.set_text (string_compose (plural_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2779 txt
.set_text (string_compose (singular_msg
, removed
, session
->path() + "dead_sounds", space_adjusted
, bprefix
));
2782 dhbox
.pack_start (*dimage
, true, false, 5);
2783 dhbox
.pack_start (txt
, true, false, 5);
2785 for (vector
<string
>::iterator i
= rep
.paths
.begin(); i
!= rep
.paths
.end(); ++i
) {
2786 TreeModel::Row row
= *(results_model
->append());
2787 row
[results_columns
.visible_name
] = *i
;
2788 row
[results_columns
.fullpath
] = *i
;
2791 list_scroller
.add (results_display
);
2792 list_scroller
.set_size_request (-1, 150);
2793 list_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
2795 dvbox
.pack_start (dhbox
, true, false, 5);
2796 dvbox
.pack_start (list_scroller
, true, false, 5);
2797 ddhbox
.pack_start (dvbox
, true, false, 5);
2799 results
.get_vbox()->pack_start (ddhbox
, true, false, 5);
2800 results
.add_button (Stock::CLOSE
, RESPONSE_CLOSE
);
2801 results
.set_default_response (RESPONSE_CLOSE
);
2802 results
.set_position (Gtk::WIN_POS_MOUSE
);
2803 results
.show_all_children ();
2804 results
.set_resizable (false);
2811 ARDOUR_UI::cleanup ()
2814 /* shouldn't happen: menu item is insensitive */
2819 MessageDialog
checker (_("Are you sure you want to cleanup?"),
2821 Gtk::MESSAGE_QUESTION
,
2822 (Gtk::ButtonsType
)(Gtk::BUTTONS_NONE
));
2824 checker
.set_secondary_text(_("Cleanup is a destructive operation.\n\
2825 ALL undo/redo information will be lost if you cleanup.\n\
2826 After cleanup, unused audio files will be moved to a \
2827 \"dead sounds\" location."));
2829 checker
.add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
2830 checker
.add_button (_("Clean Up"), RESPONSE_ACCEPT
);
2831 checker
.set_default_response (RESPONSE_CANCEL
);
2833 checker
.set_name (_("CleanupDialog"));
2834 checker
.set_wmclass (X_("ardour_cleanup"), "Ardour");
2835 checker
.set_position (Gtk::WIN_POS_MOUSE
);
2837 switch (checker
.run()) {
2838 case RESPONSE_ACCEPT
:
2844 Session::cleanup_report rep
;
2846 editor
->prepare_for_cleanup ();
2848 /* do not allow flush until a session is reloaded */
2850 Glib::RefPtr
<Action
> act
= ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2852 act
->set_sensitive (false);
2855 if (session
->cleanup_sources (rep
)) {
2856 editor
->finish_cleanup ();
2860 editor
->finish_cleanup ();
2863 display_cleanup_results (rep
,
2866 The following %1 files were not in use and \n\
2867 have been moved to:\n\
2869 Flushing the wastebasket will \n\
2870 release an additional\n\
2871 %3 %4bytes of disk space.\n"),
2873 The following file was not in use and \n \
2874 has been moved to:\n \
2876 Flushing the wastebasket will \n\
2877 release an additional\n\
2878 %3 %4bytes of disk space.\n"
2884 ARDOUR_UI::flush_trash ()
2887 /* shouldn't happen: menu item is insensitive */
2891 Session::cleanup_report rep
;
2893 if (session
->cleanup_trash_sources (rep
)) {
2897 display_cleanup_results (rep
,
2899 _("The following %1 files were deleted from\n\
2901 releasing %3 %4bytes of disk space"),
2902 _("The following file was deleted from\n\
2904 releasing %3 %4bytes of disk space"));
2908 ARDOUR_UI::add_route (Gtk::Window
* float_window
)
2916 if (add_route_dialog
== 0) {
2917 add_route_dialog
= new AddRouteDialog
;
2919 add_route_dialog
->set_transient_for (*float_window
);
2923 if (add_route_dialog
->is_visible()) {
2924 /* we're already doing this */
2928 ResponseType r
= (ResponseType
) add_route_dialog
->run ();
2930 add_route_dialog
->hide();
2933 case RESPONSE_ACCEPT
:
2940 if ((count
= add_route_dialog
->count()) <= 0) {
2944 string template_path
= add_route_dialog
->track_template();
2946 if (!template_path
.empty()) {
2947 session
->new_route_from_template (count
, template_path
);
2951 uint32_t input_chan
= add_route_dialog
->channels ();
2952 uint32_t output_chan
;
2953 string name_template
= add_route_dialog
->name_template ();
2954 bool track
= add_route_dialog
->track ();
2956 AutoConnectOption oac
= Config
->get_output_auto_connect();
2958 if (oac
& AutoConnectMaster
) {
2959 output_chan
= (session
->master_out() ? session
->master_out()->n_inputs() : input_chan
);
2961 output_chan
= input_chan
;
2964 /* XXX do something with name template */
2967 session_add_audio_track (input_chan
, output_chan
, add_route_dialog
->mode(), count
);
2969 session_add_audio_bus (input_chan
, output_chan
, count
);
2974 ARDOUR_UI::mixer_settings () const
2979 node
= session
->instant_xml(X_("Mixer"), session
->path());
2981 node
= Config
->instant_xml(X_("Mixer"), get_user_ardour_path());
2985 node
= new XMLNode (X_("Mixer"));
2992 ARDOUR_UI::editor_settings () const
2997 node
= session
->instant_xml(X_("Editor"), session
->path());
2999 node
= Config
->instant_xml(X_("Editor"), get_user_ardour_path());
3003 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3004 node
= Config
->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3009 node
= new XMLNode (X_("Editor"));
3015 ARDOUR_UI::keyboard_settings () const
3019 node
= Config
->extra_xml(X_("Keyboard"));
3022 node
= new XMLNode (X_("Keyboard"));
3028 ARDOUR_UI::create_xrun_marker(nframes_t where
)
3030 editor
->mouse_add_new_marker (where
, false, true);
3034 ARDOUR_UI::halt_on_xrun_message ()
3036 MessageDialog
msg (*editor
,
3037 _("Recording was stopped because your system could not keep up."));
3042 ARDOUR_UI::xrun_handler(nframes_t where
)
3048 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler
), where
));
3050 if (session
&& Config
->get_create_xrun_marker() && session
->actively_recording()) {
3051 create_xrun_marker(where
);
3054 if (session
&& Config
->get_stop_recording_on_xrun() && session
->actively_recording()) {
3055 halt_on_xrun_message ();
3060 ARDOUR_UI::preset_file_exists_handler ()
3062 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3065 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3069 HBox
* hbox
= new HBox();
3070 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3071 Gtk::Dialog
dialog (_("Preset Exists"), true, false);
3073 A preset with this name already exists for this plugin.\n\
3075 What you would like to do?\n"));
3076 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3077 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3078 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3079 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3080 dialog
.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT
);
3081 dialog
.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT
);
3082 dialog
.set_default_response (RESPONSE_ACCEPT
);
3083 dialog
.set_position (WIN_POS_MOUSE
);
3084 dialog
.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY
); // need to make it float above the preset name dialog
3090 switch (dialog
.run ()) {
3091 case RESPONSE_ACCEPT
:
3099 ARDOUR_UI::push_buffer_stats (uint32_t capture
, uint32_t playback
)
3104 while (disk_buffer_stats
.size() > 60) {
3105 disk_buffer_stats
.pop_front ();
3108 disk_buffer_stats
.push_back (DiskBufferStat (now
, capture
, playback
));
3112 ARDOUR_UI::write_buffer_stats ()
3119 if ((path
= tempnam (0, "ardourBuffering")) == 0) {
3120 cerr
<< X_("cannot find temporary name for ardour buffer stats") << endl
;
3127 cerr
<< string_compose (X_("cannot open file %1 for ardour buffer stats"), path
) << endl
;
3131 for (list
<DiskBufferStat
>::iterator i
= disk_buffer_stats
.begin(); i
!= disk_buffer_stats
.end(); ++i
) {
3132 localtime_r (&(*i
).when
, &tm
);
3133 strftime (buf
, sizeof (buf
), "%T", &tm
);
3134 fout
<< buf
<< ' ' << (*i
).capture
<< ' ' << (*i
).playback
<< endl
;
3137 disk_buffer_stats
.clear ();
3141 cerr
<< "Ardour buffering statistics can be found in: " << path
<< endl
;
3146 ARDOUR_UI::disk_overrun_handler ()
3149 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler
));
3151 write_buffer_stats ();
3153 if (!have_disk_speed_dialog_displayed
) {
3154 have_disk_speed_dialog_displayed
= true;
3155 MessageDialog
* msg
= new MessageDialog (*editor
, _("\
3156 The disk system on your computer\n\
3157 was not able to keep up with Ardour.\n\
3159 Specifically, it failed to write data to disk\n\
3160 quickly enough to keep up with recording.\n"));
3161 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3167 ARDOUR_UI::disk_underrun_handler ()
3170 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler
));
3172 write_buffer_stats ();
3174 if (!have_disk_speed_dialog_displayed
) {
3175 have_disk_speed_dialog_displayed
= true;
3176 MessageDialog
* msg
= new MessageDialog (*editor
,
3177 _("The disk system on your computer\n\
3178 was not able to keep up with Ardour.\n\
3180 Specifically, it failed to read data from disk\n\
3181 quickly enough to keep up with playback.\n"));
3182 msg
->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone
), msg
));
3188 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response
, MessageDialog
* msg
)
3190 have_disk_speed_dialog_displayed
= false;
3195 ARDOUR_UI::session_dialog (std::string msg
)
3197 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog
), msg
));
3202 d
= new MessageDialog (*editor
, msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3204 d
= new MessageDialog (msg
, false, MESSAGE_INFO
, BUTTONS_OK
, true);
3213 ARDOUR_UI::pending_state_dialog ()
3215 HBox
* hbox
= new HBox();
3216 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3217 ArdourDialog
dialog (_("Crash Recovery"), true);
3219 This session appears to have been in\n\
3220 middle of recording when ardour or\n\
3221 the computer was shutdown.\n\
3223 Ardour can recover any captured audio for\n\
3224 you, or it can ignore it. Please decide\n\
3225 what you would like to do.\n"));
3226 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3227 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3228 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3229 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3230 dialog
.add_button (_("Ignore crash data"), RESPONSE_REJECT
);
3231 dialog
.add_button (_("Recover from crash"), RESPONSE_ACCEPT
);
3232 dialog
.set_default_response (RESPONSE_ACCEPT
);
3233 dialog
.set_position (WIN_POS_CENTER
);
3240 switch (dialog
.run ()) {
3241 case RESPONSE_ACCEPT
:
3249 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired
, nframes_t actual
)
3251 HBox
* hbox
= new HBox();
3252 Image
* image
= new Image (Stock::DIALOG_QUESTION
, ICON_SIZE_DIALOG
);
3253 ArdourDialog
dialog (_("Sample Rate Mismatch"), true);
3254 Label
message (string_compose (_("\
3255 This session was created with a sample rate of %1 Hz\n\
3257 The audioengine is currently running at %2 Hz\n"), desired
, actual
));
3259 image
->set_alignment(ALIGN_CENTER
, ALIGN_TOP
);
3260 hbox
->pack_start (*image
, PACK_EXPAND_WIDGET
, 12);
3261 hbox
->pack_end (message
, PACK_EXPAND_PADDING
, 12);
3262 dialog
.get_vbox()->pack_start(*hbox
, PACK_EXPAND_PADDING
, 6);
3263 dialog
.add_button (_("Do not load session"), RESPONSE_REJECT
);
3264 dialog
.add_button (_("Load session anyway"), RESPONSE_ACCEPT
);
3265 dialog
.set_default_response (RESPONSE_ACCEPT
);
3266 dialog
.set_position (WIN_POS_CENTER
);
3271 switch (dialog
.run ()) {
3272 case RESPONSE_ACCEPT
:
3281 ARDOUR_UI::disconnect_from_jack ()
3284 if( engine
->disconnect_from_jack ()) {
3285 MessageDialog
msg (*editor
, _("Could not disconnect from JACK"));
3289 update_sample_rate (0);
3294 ARDOUR_UI::reconnect_to_jack ()
3297 if (engine
->reconnect_to_jack ()) {
3298 MessageDialog
msg (*editor
, _("Could not reconnect to JACK"));
3302 update_sample_rate (0);
3307 ARDOUR_UI::use_config ()
3309 Glib::RefPtr
<Action
> act
;
3311 switch (Config
->get_native_file_data_format ()) {
3313 act
= ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3316 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3319 act
= ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3324 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3325 ract
->set_active ();
3328 switch (Config
->get_native_file_header_format ()) {
3330 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3333 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3336 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3339 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3342 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3345 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3348 act
= ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3353 Glib::RefPtr
<RadioAction
> ract
= Glib::RefPtr
<RadioAction
>::cast_dynamic(act
);
3354 ract
->set_active ();
3357 XMLNode
* node
= Config
->extra_xml (X_("TransportControllables"));
3359 set_transport_controllable_state (*node
);
3364 ARDOUR_UI::update_transport_clocks (nframes_t pos
)
3366 if (Config
->get_primary_clock_delta_edit_cursor()) {
3367 primary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 1);
3369 primary_clock
.set (pos
, 0, true);
3372 if (Config
->get_secondary_clock_delta_edit_cursor()) {
3373 secondary_clock
.set (pos
, false, editor
->get_preferred_edit_position(), 2);
3375 secondary_clock
.set (pos
);
3378 if (big_clock_window
) {
3379 big_clock
.set (pos
);
3384 ARDOUR_UI::record_state_changed ()
3386 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed
));
3388 if (!session
|| !big_clock_window
) {
3389 /* why bother - the clock isn't visible */
3393 switch (session
->record_status()) {
3394 case Session::Recording
:
3395 big_clock
.set_widget_name ("BigClockRecording");
3398 big_clock
.set_widget_name ("BigClockNonRecording");
3404 ARDOUR_UI::first_idle ()
3407 session
->allow_auto_play (true);
3411 editor
->first_idle();
3414 Keyboard::set_can_save_keybindings (true);
3419 ARDOUR_UI::store_clock_modes ()
3421 XMLNode
* node
= new XMLNode(X_("ClockModes"));
3423 for (vector
<AudioClock
*>::iterator x
= AudioClock::clocks
.begin(); x
!= AudioClock::clocks
.end(); ++x
) {
3424 node
->add_property ((*x
)->name().c_str(), enum_2_string ((*x
)->mode()));
3427 session
->add_extra_xml (*node
);
3428 session
->set_dirty ();
3433 ARDOUR_UI::TransportControllable::TransportControllable (std::string name
, ARDOUR_UI
& u
, ToggleType tp
)
3434 : Controllable (name
), ui (u
), type(tp
)
3440 ARDOUR_UI::TransportControllable::set_value (float val
)
3442 if (type
== ShuttleControl
) {
3449 fract
= -((0.5f
- val
)/0.5f
);
3451 fract
= ((val
- 0.5f
)/0.5f
);
3455 ui
.set_shuttle_fract (fract
);
3460 /* do nothing: these are radio-style actions */
3464 const char *action
= 0;
3468 action
= X_("Roll");
3471 action
= X_("Stop");
3474 action
= X_("Goto Start");
3477 action
= X_("Goto End");
3480 action
= X_("Loop");
3483 action
= X_("Play Selection");
3486 action
= X_("Record");
3496 Glib::RefPtr
<Action
> act
= ActionManager::get_action ("Transport", action
);
3504 ARDOUR_UI::TransportControllable::get_value (void) const
3523 case ShuttleControl
:
3533 ARDOUR_UI::TransportControllable::set_id (const string
& str
)
3539 ARDOUR_UI::setup_profile ()
3541 if (gdk_screen_width() < 1200) {
3542 Profile
->set_small_screen ();
3545 if (getenv ("ARDOUR_SAE")) {
3546 Profile
->set_sae ();
3547 Profile
->set_single_package ();