restore rec-enable, solo & mute functionality; remove all Global*Command cruft; reimp...
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2007 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #define __STDC_FORMAT_MACROS 1
21 #include <stdint.h>
22
23 #include <algorithm>
24 #include <cmath>
25 #include <fcntl.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <cerrno>
30 #include <fstream>
31
32 #include <iostream>
33
34 #include <sys/resource.h>
35
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
38
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
46
47 #include "gtkmm2ext/gtk_ui.h"
48 #include "gtkmm2ext/utils.h"
49 #include "gtkmm2ext/click_box.h"
50 #include "gtkmm2ext/fastmeter.h"
51 #include "gtkmm2ext/stop_signal.h"
52 #include "gtkmm2ext/popup.h"
53 #include "gtkmm2ext/window_title.h"
54
55 #include "midi++/manager.h"
56
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
75
76 typedef uint64_t microseconds_t;
77
78 #include "actions.h"
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
82 #include "keyboard.h"
83 #include "mixer_ui.h"
84 #include "prompter.h"
85 #include "opts.h"
86 #include "add_route_dialog.h"
87 #include "about.h"
88 #include "splash.h"
89 #include "utils.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
96 #include "startup.h"
97 #include "engine_dialog.h"
98 #include "processor_box.h"
99
100 #include "i18n.h"
101
102 using namespace ARDOUR;
103 using namespace PBD;
104 using namespace Gtkmm2ext;
105 using namespace Gtk;
106 using namespace sigc;
107
108 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
109 UIConfiguration *ARDOUR_UI::ui_config = 0;
110
111 sigc::signal<void,bool> ARDOUR_UI::Blink;
112 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
113 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
114 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115
116 void gui_rt_cleanup (SessionEvent* ev) 
117 {
118         /* a little helper function that makes sure we delete queued SessionEvents in the correct thread */
119         ENSURE_GUI_THREAD (bind (sigc::ptr_fun (&gui_rt_cleanup), ev));
120         delete ev;
121 }
122
123 /* wrap the above as a slot so that we can pass it to the session when queuing RT events */
124 const sigc::slot<void,SessionEvent*> gui_rt_cleanup_slot (sigc::ptr_fun (&gui_rt_cleanup));
125
126 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
127
128         : Gtkmm2ext::UI (X_("gui"), argcp, argvp),
129
130           primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true),
131           secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true),
132           preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, false, true),
133           postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, false, true),
134
135           /* preroll stuff */
136
137           preroll_button (_("pre\nroll")),
138           postroll_button (_("post\nroll")),
139
140           /* big clock */
141
142           big_clock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, true),
143
144           /* transport */
145
146           roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
147           stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
148           goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
149           goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
150           auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
151           play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
152           rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
153           shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
154           shuttle_controller_binding_proxy (shuttle_controllable),
155
156           roll_button (roll_controllable),
157           stop_button (stop_controllable),
158           goto_start_button (goto_start_controllable),
159           goto_end_button (goto_end_controllable),
160           auto_loop_button (auto_loop_controllable),
161           play_selection_button (play_selection_controllable),
162           rec_button (rec_controllable),
163
164           shuttle_units_button (_("% ")),
165
166           punch_in_button (_("Punch In")),
167           punch_out_button (_("Punch Out")),
168           auto_return_button (_("Auto Return")),
169           auto_play_button (_("Auto Play")),
170           auto_input_button (_("Auto Input")),
171           click_button (_("Click")),
172           time_master_button (_("time\nmaster")),
173
174           auditioning_alert_button (_("AUDITION")),
175           solo_alert_button (_("SOLO")),
176           shown_flag (false),
177           error_log_button (_("Errors"))
178
179 {
180         using namespace Gtk::Menu_Helpers;
181
182         Gtkmm2ext::init();
183
184
185 #ifdef TOP_MENUBAR
186         // _auto_display_errors = false;
187         /*
188          * This was commented out as it wasn't defined
189          * in A3 IIRC.  If this is not needed it should
190          * be completely removed.
191          */
192 #endif
193
194         about = 0;
195         splash = 0;
196         _startup = 0;
197
198         if (theArdourUI == 0) {
199                 theArdourUI = this;
200         }
201
202         ui_config = new UIConfiguration();
203         theme_manager = new ThemeManager();
204
205         editor = 0;
206         mixer = 0;
207         session = 0;
208         editor = 0;
209         engine = 0;
210         _session_is_new = false;
211         big_clock_window = 0;
212         session_selector_window = 0;
213         last_key_press_time = 0;
214         _will_create_new_session_automatically = false;
215         add_route_dialog = 0;
216         route_params = 0;
217         rc_option_editor = 0;
218         session_option_editor = 0;
219         location_ui = 0;
220         open_session_selector = 0;
221         have_configure_timeout = false;
222         have_disk_speed_dialog_displayed = false;
223         session_loaded = false;
224         last_speed_displayed = -1.0f;
225         ignore_dual_punch = false;
226         _mixer_on_top = false;
227
228         roll_button.unset_flags (Gtk::CAN_FOCUS);
229         stop_button.unset_flags (Gtk::CAN_FOCUS);
230         goto_start_button.unset_flags (Gtk::CAN_FOCUS);
231         goto_end_button.unset_flags (Gtk::CAN_FOCUS);
232         auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
233         play_selection_button.unset_flags (Gtk::CAN_FOCUS);
234         rec_button.unset_flags (Gtk::CAN_FOCUS);
235
236         last_configure_time= 0;
237
238         shuttle_grabbed = false;
239         shuttle_fract = 0.0;
240         shuttle_max_speed = 8.0f;
241
242         shuttle_style_menu = 0;
243         shuttle_unit_menu = 0;
244
245         // We do not have jack linked in yet so;
246
247         last_shuttle_request = last_peak_grab = 0; //  get_microseconds();
248
249         ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
250         ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
251
252         /* handle dialog requests */
253
254         ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
255
256         /* handle pending state with a dialog */
257
258         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
259
260         /* handle sr mismatch with a dialog */
261
262         ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
263
264         /* lets get this party started */
265
266         try {
267                 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
268                         throw failed_constructor ();
269                 }
270
271                 setup_gtk_ardour_enums ();
272                 setup_profile ();
273
274                 GainMeter::setup_slider_pix ();
275                 RouteTimeAxisView::setup_slider_pix ();
276                 SendProcessorEntry::setup_slider_pix ();
277                 SessionEvent::create_per_thread_pool ("GUI", 512);
278
279         } catch (failed_constructor& err) {
280                 error << _("could not initialize Ardour.") << endmsg;
281                 // pass it on up
282                 throw;
283         }
284
285         /* we like keyboards */
286
287         keyboard = new ArdourKeyboard;
288
289         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
290         if (node) {
291                 keyboard->set_state (*node, Stateful::loading_state_version);
292         }
293
294         reset_dpi();
295
296         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
297         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
298
299         platform_setup ();
300 }
301
302 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
303 bool
304 ARDOUR_UI::run_startup (bool should_be_new)
305 {
306         if (_startup == 0) {
307                 _startup = new ArdourStartup ();
308         }
309
310         _startup->set_new_only (should_be_new);
311         _startup->present ();
312
313         main().run();
314
315         _startup->hide ();
316
317         switch (_startup->response()) {
318         case RESPONSE_OK:
319                 return true;
320         default:
321                 return false;
322         }
323 }
324
325 int
326 ARDOUR_UI::create_engine ()
327 {
328         // this gets called every time by new_session()
329
330         if (engine) {
331                 return 0;
332         }
333
334         loading_message (_("Starting audio engine"));
335
336         try {
337                 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
338
339         } catch (...) {
340
341                 return -1;
342         }
343
344         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
345         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
346         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
347         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
348
349         post_engine ();
350
351         return 0;
352 }
353
354 void
355 ARDOUR_UI::post_engine ()
356 {
357         /* Things to be done once we create the AudioEngine
358          */
359
360         MIDI::Manager::instance()->set_api_data (engine->jack());
361         setup_midi ();
362         
363         ARDOUR::init_post_engine ();
364
365         ActionManager::init ();
366         _tooltips.enable();
367
368         if (setup_windows ()) {
369                 throw failed_constructor ();
370         }
371         
372         check_memory_locking();
373
374         /* this is the first point at which all the keybindings are available */
375
376         if (ARDOUR_COMMAND_LINE::show_key_actions) {
377                 vector<string> names;
378                 vector<string> paths;
379                 vector<string> keys;
380                 vector<AccelKey> bindings;
381
382                 ActionManager::get_all_actions (names, paths, keys, bindings);
383
384                 vector<string>::iterator n;
385                 vector<string>::iterator k;
386                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
387                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
388                 }
389
390                 exit (0);
391         }
392
393         blink_timeout_tag = -1;
394
395         /* this being a GUI and all, we want peakfiles */
396
397         AudioFileSource::set_build_peakfiles (true);
398         AudioFileSource::set_build_missing_peakfiles (true);
399
400         /* set default clock modes */
401
402         if (Profile->get_sae()) {
403                 primary_clock.set_mode (AudioClock::BBT);
404                 secondary_clock.set_mode (AudioClock::MinSec);
405         }  else {
406                 primary_clock.set_mode (AudioClock::Timecode);
407                 secondary_clock.set_mode (AudioClock::BBT);
408         }
409
410         /* start the time-of-day-clock */
411
412 #ifndef GTKOSX
413         /* OS X provides an always visible wallclock, so don't be stupid */
414         update_wall_clock ();
415         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
416 #endif
417
418         update_disk_space ();
419         update_cpu_load ();
420         update_sample_rate (engine->frame_rate());
421
422         Config->ParameterChanged.connect (mem_fun (*this, &ARDOUR_UI::parameter_changed));
423         Config->map_parameters (mem_fun (*this, &ARDOUR_UI::parameter_changed));
424
425         /* now start and maybe save state */
426
427         if (do_engine_start () == 0) {
428                 if (session && _session_is_new) {
429                         /* we need to retain initial visual
430                            settings for a new session
431                         */
432                         session->save_state ("");
433                 }
434         }
435 }
436
437 ARDOUR_UI::~ARDOUR_UI ()
438 {
439         save_ardour_state ();
440
441         delete keyboard;
442         delete editor;
443         delete mixer;
444         delete add_route_dialog;
445 }
446
447 void
448 ARDOUR_UI::pop_back_splash ()
449 {
450         if (Splash::instance()) {
451                 // Splash::instance()->pop_back();
452                 Splash::instance()->hide ();
453         }
454 }
455
456 gint
457 ARDOUR_UI::configure_timeout ()
458 {
459         if (last_configure_time == 0) {
460                 /* no configure events yet */
461                 return TRUE;
462         }
463
464         /* force a gap of 0.5 seconds since the last configure event
465          */
466
467         if (get_microseconds() - last_configure_time < 500000) {
468                 return TRUE;
469         } else {
470                 have_configure_timeout = false;
471                 save_ardour_state ();
472                 return FALSE;
473         }
474 }
475
476 gboolean
477 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
478 {
479         if (have_configure_timeout) {
480                 last_configure_time = get_microseconds();
481         } else {
482                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
483                 have_configure_timeout = true;
484         }
485
486         return FALSE;
487 }
488
489 void
490 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
491 {
492         const XMLProperty* prop;
493
494         if ((prop = node.property ("roll")) != 0) {
495                 roll_controllable->set_id (prop->value());
496         }
497         if ((prop = node.property ("stop")) != 0) {
498                 stop_controllable->set_id (prop->value());
499         }
500         if ((prop = node.property ("goto-start")) != 0) {
501                 goto_start_controllable->set_id (prop->value());
502         }
503         if ((prop = node.property ("goto-end")) != 0) {
504                 goto_end_controllable->set_id (prop->value());
505         }
506         if ((prop = node.property ("auto-loop")) != 0) {
507                 auto_loop_controllable->set_id (prop->value());
508         }
509         if ((prop = node.property ("play-selection")) != 0) {
510                 play_selection_controllable->set_id (prop->value());
511         }
512         if ((prop = node.property ("rec")) != 0) {
513                 rec_controllable->set_id (prop->value());
514         }
515         if ((prop = node.property ("shuttle")) != 0) {
516                 shuttle_controllable->set_id (prop->value());
517         }
518 }
519
520 XMLNode&
521 ARDOUR_UI::get_transport_controllable_state ()
522 {
523         XMLNode* node = new XMLNode(X_("TransportControllables"));
524         char buf[64];
525
526         roll_controllable->id().print (buf, sizeof (buf));
527         node->add_property (X_("roll"), buf);
528         stop_controllable->id().print (buf, sizeof (buf));
529         node->add_property (X_("stop"), buf);
530         goto_start_controllable->id().print (buf, sizeof (buf));
531         node->add_property (X_("goto_start"), buf);
532         goto_end_controllable->id().print (buf, sizeof (buf));
533         node->add_property (X_("goto_end"), buf);
534         auto_loop_controllable->id().print (buf, sizeof (buf));
535         node->add_property (X_("auto_loop"), buf);
536         play_selection_controllable->id().print (buf, sizeof (buf));
537         node->add_property (X_("play_selection"), buf);
538         rec_controllable->id().print (buf, sizeof (buf));
539         node->add_property (X_("rec"), buf);
540         shuttle_controllable->id().print (buf, sizeof (buf));
541         node->add_property (X_("shuttle"), buf);
542
543         return *node;
544 }
545
546 void
547 ARDOUR_UI::save_ardour_state ()
548 {
549         if (!keyboard || !mixer || !editor) {
550                 return;
551         }
552
553         /* XXX this is all a bit dubious. add_extra_xml() uses
554            a different lifetime model from add_instant_xml().
555         */
556
557         XMLNode* node = new XMLNode (keyboard->get_state());
558         Config->add_extra_xml (*node);
559         Config->add_extra_xml (get_transport_controllable_state());
560         if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
561                 Config->add_extra_xml (_startup->engine_control()->get_state());
562         }
563         Config->save_state();
564         ui_config->save_state ();
565
566         XMLNode enode(static_cast<Stateful*>(editor)->get_state());
567         XMLNode mnode(mixer->get_state());
568
569         if (session) {
570                 session->add_instant_xml (enode);
571                 session->add_instant_xml (mnode);
572         } else {
573                 Config->add_instant_xml (enode);
574                 Config->add_instant_xml (mnode);
575         }
576
577         Keyboard::save_keybindings ();
578 }
579
580 gint
581 ARDOUR_UI::autosave_session ()
582 {
583         if (g_main_depth() > 1) {
584                 /* inside a recursive main loop,
585                    give up because we may not be able to
586                    take a lock.
587                 */
588                 return 1;
589         }
590
591         if (!Config->get_periodic_safety_backups()) {
592                 return 1;
593         }
594
595         if (session) {
596                 session->maybe_write_autosave();
597         }
598
599         return 1;
600 }
601
602 void
603 ARDOUR_UI::update_autosave ()
604 {
605         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
606
607         if (session && session->dirty()) {
608                 if (_autosave_connection.connected()) {
609                         _autosave_connection.disconnect();
610                 }
611
612                 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
613                                 Config->get_periodic_safety_backup_interval() * 1000);
614
615         } else {
616                 if (_autosave_connection.connected()) {
617                         _autosave_connection.disconnect();
618                 }
619         }
620 }
621
622 void
623 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
624 {
625         string title;
626         if (we_set_params) {
627                 title = _("Ardour could not start JACK");
628         } else {
629                 title = _("Ardour could not connect to JACK.");
630         }
631
632         MessageDialog win (title,
633                            false,
634                            Gtk::MESSAGE_INFO,
635                            Gtk::BUTTONS_NONE);
636
637         if (we_set_params) {
638                 win.set_secondary_text(_("There are several possible reasons:\n\
639 \n\
640 1) You requested audio parameters that are not supported..\n\
641 2) JACK is running as another user.\n\
642 \n\
643 Please consider the possibilities, and perhaps try different parameters."));
644         } else {
645                 win.set_secondary_text(_("There are several possible reasons:\n\
646 \n\
647 1) JACK is not running.\n\
648 2) JACK is running as another user, perhaps root.\n\
649 3) There is already another client called \"ardour\".\n\
650 \n\
651 Please consider the possibilities, and perhaps (re)start JACK."));
652         }
653
654         if (toplevel) {
655                 win.set_transient_for (*toplevel);
656         }
657
658         if (we_set_params) {
659                 win.add_button (Stock::OK, RESPONSE_CLOSE);
660         } else {
661                 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
662         }
663
664         win.set_default_response (RESPONSE_CLOSE);
665
666         win.show_all ();
667         win.set_position (Gtk::WIN_POS_CENTER);
668         pop_back_splash ();
669
670         /* we just don't care about the result, but we want to block */
671
672         win.run ();
673 }
674
675 void
676 ARDOUR_UI::startup ()
677 {
678         XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
679
680         if (audio_setup && _startup && _startup->engine_control()) {
681                 _startup->engine_control()->set_state (*audio_setup);
682         }
683
684         if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
685                 exit (1);
686         }
687
688         use_config ();
689
690         goto_editor_window ();
691
692         BootMessage (_("Ardour is ready for use"));
693         show ();
694 }
695
696 void
697 ARDOUR_UI::no_memory_warning ()
698 {
699         XMLNode node (X_("no-memory-warning"));
700         Config->add_instant_xml (node);
701 }
702
703 void
704 ARDOUR_UI::check_memory_locking ()
705 {
706 #ifdef __APPLE__
707         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
708         return;
709 #else // !__APPLE__
710
711         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
712
713         if (engine->is_realtime() && memory_warning_node == 0) {
714
715                 struct rlimit limits;
716                 int64_t ram;
717                 long pages, page_size;
718
719                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
720                         ram = 0;
721                 } else {
722                         ram = (int64_t) pages * (int64_t) page_size;
723                 }
724
725                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
726                         return;
727                 }
728
729                 if (limits.rlim_cur != RLIM_INFINITY) {
730
731                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
732
733
734                                 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
735                                                      "This might cause Ardour to run out of memory before your system "
736                                                      "runs out of memory. \n\n"
737                                                      "You can view the memory limit with 'ulimit -l', "
738                                                      "and it is normally controlled by /etc/security/limits.conf"));
739
740                                 VBox* vbox = msg.get_vbox();
741                                 HBox hbox;
742                                 CheckButton cb (_("Do not show this window again"));
743
744                                 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
745
746                                 hbox.pack_start (cb, true, false);
747                                 vbox->pack_start (hbox);
748                                 cb.show();
749                                 vbox->show();
750                                 hbox.show ();
751
752                                 pop_back_splash ();
753
754                                 editor->ensure_float (msg);
755                                 msg.run ();
756                         }
757                 }
758         }
759 #endif // !__APPLE__
760 }
761
762
763 void
764 ARDOUR_UI::finish()
765 {
766         if (session) {
767
768                 if (session->transport_rolling()) {
769                         session->request_stop ();
770                         usleep (250000);
771                 }
772
773                 if (session->dirty()) {
774                         switch (ask_about_saving_session(_("quit"))) {
775                         case -1:
776                                 return;
777                                 break;
778                         case 1:
779                                 /* use the default name */
780                                 if (save_state_canfail ("")) {
781                                         /* failed - don't quit */
782                                         MessageDialog msg (*editor,
783                                                            _("\
784 Ardour was unable to save your session.\n\n\
785 If you still wish to quit, please use the\n\n\
786 \"Just quit\" option."));
787                                         pop_back_splash();
788                                         msg.run ();
789                                         return;
790                                 }
791                                 break;
792                         case 0:
793                                 break;
794                         }
795                 }
796
797                 second_connection.disconnect ();
798                 point_one_second_connection.disconnect ();
799                 point_oh_five_second_connection.disconnect ();
800                 point_zero_one_second_connection.disconnect();
801                 
802                 // session->set_deletion_in_progress ();
803                 session->remove_pending_capture_state ();
804                 delete session;
805                 session = 0;
806         }
807
808         ArdourDialog::close_all_dialogs ();
809         engine->stop (true);
810         save_ardour_state ();
811         quit ();
812 }
813
814 int
815 ARDOUR_UI::ask_about_saving_session (const string & what)
816 {
817         ArdourDialog window (_("ardour: save session?"));
818         Gtk::HBox dhbox;  // the hbox for the image and text
819         Gtk::Label  prompt_label;
820         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
821
822         string msg;
823
824         msg = string_compose(_("Don't %1"), what);
825         window.add_button (msg, RESPONSE_REJECT);
826         msg = string_compose(_("Just %1"), what);
827         window.add_button (msg, RESPONSE_APPLY);
828         msg = string_compose(_("Save and %1"), what);
829         window.add_button (msg, RESPONSE_ACCEPT);
830
831         window.set_default_response (RESPONSE_ACCEPT);
832
833         Gtk::Button noquit_button (msg);
834         noquit_button.set_name ("EditorGTKButton");
835
836         string prompt;
837         string type;
838
839         if (session->snap_name() == session->name()) {
840                 type = _("session");
841         } else {
842                 type = _("snapshot");
843         }
844         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?"),
845                          type, session->snap_name());
846
847         prompt_label.set_text (prompt);
848         prompt_label.set_name (X_("PrompterLabel"));
849         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
850
851         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
852         dhbox.set_homogeneous (false);
853         dhbox.pack_start (*dimage, false, false, 5);
854         dhbox.pack_start (prompt_label, true, false, 5);
855         window.get_vbox()->pack_start (dhbox);
856
857         window.set_name (_("Prompter"));
858         window.set_position (Gtk::WIN_POS_MOUSE);
859         window.set_modal (true);
860         window.set_resizable (false);
861
862         dhbox.show();
863         prompt_label.show();
864         dimage->show();
865         window.show();
866         window.set_keep_above (true);
867         window.present ();
868
869         ResponseType r = (ResponseType) window.run();
870
871         window.hide ();
872
873         switch (r) {
874         case RESPONSE_ACCEPT: // save and get out of here
875                 return 1;
876         case RESPONSE_APPLY:  // get out of here
877                 return 0;
878         default:
879                 break;
880         }
881
882         return -1;
883 }
884
885 gint
886 ARDOUR_UI::every_second ()
887 {
888         update_cpu_load ();
889         update_buffer_load ();
890         update_disk_space ();
891         return TRUE;
892 }
893
894 gint
895 ARDOUR_UI::every_point_one_seconds ()
896 {
897         update_speed_display ();
898         RapidScreenUpdate(); /* EMIT_SIGNAL */
899         return TRUE;
900 }
901
902 gint
903 ARDOUR_UI::every_point_zero_one_seconds ()
904 {
905         // august 2007: actual update frequency: 40Hz, not 100Hz
906
907         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
908         return TRUE;
909 }
910
911 void
912 ARDOUR_UI::update_sample_rate (nframes_t ignored)
913 {
914         char buf[32];
915
916         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
917
918         if (!engine->connected()) {
919
920                 snprintf (buf, sizeof (buf), _("disconnected"));
921
922         } else {
923
924                 nframes_t rate = engine->frame_rate();
925
926                 if (fmod (rate, 1000.0) != 0.0) {
927                         snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
928                                   (float) rate/1000.0f,
929                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
930                 } else {
931                         snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
932                                   rate/1000,
933                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
934                 }
935         }
936
937         sample_rate_label.set_text (buf);
938 }
939
940 void
941 ARDOUR_UI::update_cpu_load ()
942 {
943         char buf[32];
944         snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
945         cpu_load_label.set_text (buf);
946 }
947
948 void
949 ARDOUR_UI::update_buffer_load ()
950 {
951         char buf[64];
952         uint32_t c, p;
953
954         if (session) {
955                 c = session->capture_load ();
956                 p = session->playback_load ();
957
958                 push_buffer_stats (c, p);
959
960                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
961                           session->playback_load(), session->capture_load());
962                 buffer_load_label.set_text (buf);
963         } else {
964                 buffer_load_label.set_text ("");
965         }
966 }
967
968 void
969 ARDOUR_UI::count_recenabled_streams (Route& route)
970 {
971         Track* track = dynamic_cast<Track*>(&route);
972         if (track && track->diskstream()->record_enabled()) {
973                 rec_enabled_streams += track->n_inputs().n_total();
974         }
975 }
976
977 void
978 ARDOUR_UI::update_disk_space()
979 {
980         if (session == 0) {
981                 return;
982         }
983
984         nframes_t frames = session->available_capture_duration();
985         char buf[64];
986         nframes_t fr = session->frame_rate();
987
988         if (frames == max_frames) {
989                 strcpy (buf, _("Disk: 24hrs+"));
990         } else {
991                 rec_enabled_streams = 0;
992                 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
993
994                 if (rec_enabled_streams) {
995                         frames /= rec_enabled_streams;
996                 }
997
998                 int hrs;
999                 int mins;
1000                 int secs;
1001
1002                 hrs  = frames / (fr * 3600);
1003                 frames -= hrs * fr * 3600;
1004                 mins = frames / (fr * 60);
1005                 frames -= mins * fr * 60;
1006                 secs = frames / fr;
1007
1008                 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
1009         }
1010
1011         disk_space_label.set_text (buf);
1012
1013         // An attempt to make the disk space label flash red when space has run out.
1014
1015         if (frames < fr * 60 * 5) {
1016         /*      disk_space_box.style ("disk_space_label_empty"); */
1017         } else {
1018         /*      disk_space_box.style ("disk_space_label"); */
1019         }
1020
1021 }
1022
1023 gint
1024 ARDOUR_UI::update_wall_clock ()
1025 {
1026         time_t now;
1027         struct tm *tm_now;
1028         char buf[16];
1029
1030         time (&now);
1031         tm_now = localtime (&now);
1032
1033         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1034         wall_clock_label.set_text (buf);
1035
1036         return TRUE;
1037 }
1038
1039 gint
1040 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1041 {
1042         session_popup_menu->popup (0, 0);
1043         return TRUE;
1044 }
1045
1046 void
1047 ARDOUR_UI::redisplay_recent_sessions ()
1048 {
1049         std::vector<sys::path> session_directories;
1050         RecentSessionsSorter cmp;
1051
1052         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1053         recent_session_model->clear ();
1054
1055         ARDOUR::RecentSessions rs;
1056         ARDOUR::read_recent_sessions (rs);
1057
1058         if (rs.empty()) {
1059                 recent_session_display.set_model (recent_session_model);
1060                 return;
1061         }
1062         //
1063         // sort them alphabetically
1064         sort (rs.begin(), rs.end(), cmp);
1065
1066         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1067                 session_directories.push_back ((*i).second);
1068         }
1069
1070         for (vector<sys::path>::const_iterator i = session_directories.begin();
1071                         i != session_directories.end(); ++i)
1072         {
1073                 std::vector<sys::path> state_file_paths;
1074
1075                 // now get available states for this session
1076
1077                 get_state_files_in_directory (*i, state_file_paths);
1078
1079                 vector<string*>* states;
1080                 vector<const gchar*> item;
1081                 string fullpath = (*i).to_string();
1082
1083                 /* remove any trailing / */
1084
1085                 if (fullpath[fullpath.length()-1] == '/') {
1086                         fullpath = fullpath.substr (0, fullpath.length()-1);
1087                 }
1088
1089                 /* check whether session still exists */
1090                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1091                         /* session doesn't exist */
1092                         cerr << "skipping non-existent session " << fullpath << endl;
1093                         continue;
1094                 }
1095
1096                 /* now get available states for this session */
1097
1098                 if ((states = Session::possible_states (fullpath)) == 0) {
1099                         /* no state file? */
1100                         continue;
1101                 }
1102
1103                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1104
1105                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1106
1107                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1108                 row[recent_session_columns.fullpath] = fullpath;
1109
1110                 if (state_file_names.size() > 1) {
1111
1112                         // add the children
1113
1114                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1115                                         i2 != state_file_names.end(); ++i2)
1116                         {
1117
1118                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1119
1120                                 child_row[recent_session_columns.visible_name] = *i2;
1121                                 child_row[recent_session_columns.fullpath] = fullpath;
1122                         }
1123                 }
1124         }
1125
1126         recent_session_display.set_model (recent_session_model);
1127 }
1128
1129 void
1130 ARDOUR_UI::build_session_selector ()
1131 {
1132         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1133
1134         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1135
1136         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1137         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1138         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1139         recent_session_model = TreeStore::create (recent_session_columns);
1140         recent_session_display.set_model (recent_session_model);
1141         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1142         recent_session_display.set_headers_visible (false);
1143         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1144         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1145
1146         scroller->add (recent_session_display);
1147         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1148
1149         session_selector_window->set_name ("SessionSelectorWindow");
1150         session_selector_window->set_size_request (200, 400);
1151         session_selector_window->get_vbox()->pack_start (*scroller);
1152
1153         recent_session_display.show();
1154         scroller->show();
1155         //session_selector_window->get_vbox()->show();
1156 }
1157
1158 void
1159 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1160 {
1161         session_selector_window->response (RESPONSE_ACCEPT);
1162 }
1163
1164 void
1165 ARDOUR_UI::open_recent_session ()
1166 {
1167         bool can_return = (session != 0);
1168
1169         if (session_selector_window == 0) {
1170                 build_session_selector ();
1171         }
1172
1173         redisplay_recent_sessions ();
1174
1175         while (true) {
1176
1177                 session_selector_window->set_position (WIN_POS_MOUSE);
1178
1179                 ResponseType r = (ResponseType) session_selector_window->run ();
1180
1181                 switch (r) {
1182                 case RESPONSE_ACCEPT:
1183                         break;
1184                 default:
1185                         if (can_return) {
1186                                 session_selector_window->hide();
1187                                 return;
1188                         } else {
1189                                 exit (1);
1190                         }
1191                 }
1192
1193                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1194                         continue;
1195                 }
1196
1197                 session_selector_window->hide();
1198
1199                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1200
1201                 if (i == recent_session_model->children().end()) {
1202                         return;
1203                 }
1204
1205                 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1206                 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1207
1208                 _session_is_new = false;
1209
1210                 if (load_session (path, state) == 0) {
1211                         break;
1212                 }
1213
1214                 can_return = false;
1215         }
1216 }
1217
1218 bool
1219 ARDOUR_UI::check_audioengine ()
1220 {
1221         if (engine) {
1222                 if (!engine->connected()) {
1223                         MessageDialog msg (_("Ardour is not connected to JACK\n"
1224                                              "You cannot open or close sessions in this condition"));
1225                         pop_back_splash ();
1226                         msg.run ();
1227                         return false;
1228                 }
1229                 return true;
1230         } else {
1231                 return false;
1232         }
1233 }
1234
1235 void
1236 ARDOUR_UI::open_session ()
1237 {
1238         if (!check_audioengine()) {
1239                 return;
1240
1241         }
1242
1243         /* popup selector window */
1244
1245         if (open_session_selector == 0) {
1246
1247                 /* ardour sessions are folders */
1248
1249                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1250                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1251                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1252                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1253
1254                 FileFilter session_filter;
1255                 session_filter.add_pattern ("*.ardour");
1256                 session_filter.set_name (_("Ardour sessions"));
1257                 open_session_selector->add_filter (session_filter);
1258                 open_session_selector->set_filter (session_filter);
1259         }
1260
1261         int response = open_session_selector->run();
1262         open_session_selector->hide ();
1263
1264         switch (response) {
1265         case RESPONSE_ACCEPT:
1266                 break;
1267         default:
1268                 open_session_selector->hide();
1269                 return;
1270         }
1271
1272         open_session_selector->hide();
1273         string session_path = open_session_selector->get_filename();
1274         string path, name;
1275         bool isnew;
1276
1277         if (session_path.length() > 0) {
1278                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1279                         _session_is_new = isnew;
1280                         load_session (path, name);
1281                 }
1282         }
1283 }
1284
1285
1286 void
1287 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1288 {
1289         list<boost::shared_ptr<MidiTrack> > tracks;
1290
1291         if (session == 0) {
1292                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1293                 return;
1294         }
1295
1296         try {
1297                 if (disk) {
1298
1299                         tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1300
1301                         if (tracks.size() != how_many) {
1302                                 if (how_many == 1) {
1303                                         error << _("could not create a new midi track") << endmsg;
1304                                 } else {
1305                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1306                                 }
1307                         }
1308                 } /*else {
1309                         if ((route = session->new_midi_route ()) == 0) {
1310                                 error << _("could not create new midi bus") << endmsg;
1311                         }
1312                 }*/
1313         }
1314
1315         catch (...) {
1316                 MessageDialog msg (*editor,
1317                                    _("There are insufficient JACK ports available\n\
1318 to create a new track or bus.\n\
1319 You should save Ardour, exit and\n\
1320 restart JACK with more ports."));
1321                 msg.run ();
1322         }
1323 }
1324
1325
1326 void
1327 ARDOUR_UI::session_add_audio_route (bool track, bool aux, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1328 {
1329         list<boost::shared_ptr<AudioTrack> > tracks;
1330         RouteList routes;
1331
1332         if (session == 0) {
1333                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1334                 return;
1335         }
1336
1337         try {
1338                 if (track) {
1339                         tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1340
1341                         if (tracks.size() != how_many) {
1342                                 if (how_many == 1) {
1343                                         error << _("could not create a new audio track") << endmsg;
1344                                 } else {
1345                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1346                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1347                                 }
1348                         }
1349
1350                 } else {
1351
1352                         routes = session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1353
1354                         if (routes.size() != how_many) {
1355                                 if (how_many == 1) {
1356                                         error << _("could not create a new audio track") << endmsg;
1357                                 } else {
1358                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1359                                 }
1360                         }
1361                 }
1362
1363 #if CONTROLOUTS
1364                 if (need_control_room_outs) {
1365                         pan_t pans[2];
1366
1367                         pans[0] = 0.5;
1368                         pans[1] = 0.5;
1369
1370                         route->set_stereo_control_outs (control_lr_channels);
1371                         route->control_outs()->set_stereo_pan (pans, this);
1372                 }
1373 #endif /* CONTROLOUTS */
1374         }
1375
1376         catch (...) {
1377                 MessageDialog msg (*editor,
1378                                    _("There are insufficient JACK ports available\n\
1379 to create a new track or bus.\n\
1380 You should save Ardour, exit and\n\
1381 restart JACK with more ports."));
1382                 pop_back_splash ();
1383                 msg.run ();
1384         }
1385 }
1386
1387 void
1388 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1389 {
1390         nframes_t _preroll = 0;
1391
1392         if (session) {
1393                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1394                 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1395
1396                 if (new_position > _preroll) {
1397                         new_position -= _preroll;
1398                 } else {
1399                         new_position = 0;
1400                 }
1401
1402                 session->request_locate (new_position);
1403         }
1404 }
1405
1406 void
1407 ARDOUR_UI::transport_goto_start ()
1408 {
1409         if (session) {
1410                 session->goto_start();
1411
1412                 /* force displayed area in editor to start no matter
1413                    what "follow playhead" setting is.
1414                 */
1415
1416                 if (editor) {
1417                         editor->center_screen (session->current_start_frame ());
1418                 }
1419         }
1420 }
1421
1422 void
1423 ARDOUR_UI::transport_goto_zero ()
1424 {
1425         if (session) {
1426                 session->request_locate (0);
1427
1428
1429                 /* force displayed area in editor to start no matter
1430                    what "follow playhead" setting is.
1431                 */
1432
1433                 if (editor) {
1434                         editor->reset_x_origin (0);
1435                 }
1436         }
1437 }
1438
1439 void
1440 ARDOUR_UI::transport_goto_wallclock ()
1441 {
1442         if (session && editor) {
1443
1444                 time_t now;
1445                 struct tm tmnow;
1446                 nframes64_t frames;
1447
1448                 time (&now);
1449                 localtime_r (&now, &tmnow);
1450
1451                 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1452                 frames += tmnow.tm_min * (60 * session->frame_rate());
1453                 frames += tmnow.tm_sec * session->frame_rate();
1454
1455                 session->request_locate (frames);
1456
1457                 /* force displayed area in editor to start no matter
1458                    what "follow playhead" setting is.
1459                 */
1460
1461                 if (editor) {
1462                         editor->center_screen (frames);
1463                 }
1464         }
1465 }
1466
1467 void
1468 ARDOUR_UI::transport_goto_end ()
1469 {
1470         if (session) {
1471                 nframes_t const frame = session->current_end_frame();
1472                 session->request_locate (frame);
1473
1474                 /* force displayed area in editor to start no matter
1475                    what "follow playhead" setting is.
1476                 */
1477
1478                 if (editor) {
1479                         editor->center_screen (frame);
1480                 }
1481         }
1482 }
1483
1484 void
1485 ARDOUR_UI::transport_stop ()
1486 {
1487         if (!session) {
1488                 return;
1489         }
1490
1491         if (session->is_auditioning()) {
1492                 session->cancel_audition ();
1493                 return;
1494         }
1495
1496         session->request_stop ();
1497 }
1498
1499 void
1500 ARDOUR_UI::transport_stop_and_forget_capture ()
1501 {
1502         if (session) {
1503                 session->request_stop (true);
1504         }
1505 }
1506
1507 void
1508 ARDOUR_UI::remove_last_capture()
1509 {
1510         if (editor) {
1511                 editor->remove_last_capture();
1512         }
1513 }
1514
1515 void
1516 ARDOUR_UI::transport_record (bool roll)
1517 {
1518
1519         if (session) {
1520                 switch (session->record_status()) {
1521                 case Session::Disabled:
1522                         if (session->ntracks() == 0) {
1523                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1524                                 msg.run ();
1525                                 return;
1526                         }
1527                         session->maybe_enable_record ();
1528                         if (roll) {
1529                                 transport_roll ();
1530                         }
1531                         break;
1532                 case Session::Recording:
1533                         if (roll) {
1534                                 session->request_stop();
1535                         } else {
1536                                 session->disable_record (false, true);
1537                         }
1538                         break;
1539
1540                 case Session::Enabled:
1541                         session->disable_record (false, true);
1542                 }
1543         }
1544         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1545 }
1546
1547 void 
1548 ARDOUR_UI::transport_roll ()
1549 {
1550         if (!session) {
1551                 return;
1552         }
1553
1554         if (session->is_auditioning()) {
1555                 return;
1556         }
1557         
1558         if (session->config.get_external_sync()) {
1559                 switch (session->config.get_sync_source()) {
1560                 case JACK:
1561                         break;
1562                 default:
1563                         /* transport controlled by the master */
1564                         return;
1565                 }
1566         }
1567
1568         bool rolling = session->transport_rolling();
1569
1570         if (session->get_play_loop()) {
1571                 session->request_play_loop (false, true);
1572         } else if (session->get_play_range ()) {
1573                 session->request_play_range (false, true);
1574         } 
1575
1576         if (!rolling) {
1577                 session->request_transport_speed (1.0f);
1578         }
1579
1580         map_transport_state ();
1581 }
1582
1583 void
1584 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1585 {
1586         
1587         if (!session) {
1588                 return;
1589         }
1590
1591         if (session->is_auditioning()) {
1592                 session->cancel_audition ();
1593                 return;
1594         }
1595         
1596         if (session->config.get_external_sync()) {
1597                 switch (session->config.get_sync_source()) {
1598                 case JACK:
1599                         break;
1600                 default:
1601                         /* transport controlled by the master */
1602                         return;
1603                 }
1604         }
1605
1606         bool rolling = session->transport_rolling();
1607         bool affect_transport = true;
1608
1609         if (rolling && roll_out_of_bounded_mode) {
1610                 /* drop out of loop/range playback but leave transport rolling */
1611                 if (session->get_play_loop()) {
1612                         if (Config->get_seamless_loop()) {
1613                                 /* the disk buffers contain copies of the loop - we can't 
1614                                    just keep playing, so stop the transport. the user
1615                                    can restart as they wish.
1616                                 */
1617                                 affect_transport = true;
1618                         } else {
1619                                 /* disk buffers are normal, so we can keep playing */
1620                                 affect_transport = false;
1621                         }
1622                         session->request_play_loop (false, true);
1623                 } else if (session->get_play_range ()) {
1624                         affect_transport = false;
1625                         session->request_play_range (0, true);
1626                 } 
1627         } 
1628
1629         if (affect_transport) {
1630                 if (rolling) {
1631                         session->request_stop (with_abort, true);
1632                 } else {
1633                         session->request_transport_speed (1.0f);
1634                 }
1635         }
1636
1637         map_transport_state (); 
1638 }
1639
1640 void
1641 ARDOUR_UI::toggle_session_auto_loop ()
1642 {
1643         if (session) {
1644                 if (session->get_play_loop()) {
1645                         if (session->transport_rolling()) {
1646                                 Location * looploc = session->locations()->auto_loop_location();
1647                                 if (looploc) {
1648                                         session->request_locate (looploc->start(), true);
1649                                 }
1650                         } else {
1651                                 session->request_play_loop (false);
1652                         }
1653                 } else {
1654                         Location * looploc = session->locations()->auto_loop_location();
1655                         if (looploc) {
1656                                 session->request_play_loop (true);
1657                         }
1658                 }
1659         }
1660 }
1661
1662 void
1663 ARDOUR_UI::transport_play_selection ()
1664 {
1665         if (!session) {
1666                 return;
1667         }
1668
1669         editor->play_selection ();
1670 }
1671
1672 void
1673 ARDOUR_UI::transport_rewind (int option)
1674 {
1675         float current_transport_speed;
1676
1677         if (session) {
1678                 current_transport_speed = session->transport_speed();
1679
1680                 if (current_transport_speed >= 0.0f) {
1681                         switch (option) {
1682                         case 0:
1683                                 session->request_transport_speed (-1.0f);
1684                                 break;
1685                         case 1:
1686                                 session->request_transport_speed (-4.0f);
1687                                 break;
1688                         case -1:
1689                                 session->request_transport_speed (-0.5f);
1690                                 break;
1691                         }
1692                 } else {
1693                         /* speed up */
1694                         session->request_transport_speed (current_transport_speed * 1.5f);
1695                 }
1696         }
1697 }
1698
1699 void
1700 ARDOUR_UI::transport_forward (int option)
1701 {
1702         float current_transport_speed;
1703
1704         if (session) {
1705                 current_transport_speed = session->transport_speed();
1706
1707                 if (current_transport_speed <= 0.0f) {
1708                         switch (option) {
1709                         case 0:
1710                                 session->request_transport_speed (1.0f);
1711                                 break;
1712                         case 1:
1713                                 session->request_transport_speed (4.0f);
1714                                 break;
1715                         case -1:
1716                                 session->request_transport_speed (0.5f);
1717                                 break;
1718                         }
1719                 } else {
1720                         /* speed up */
1721                         session->request_transport_speed (current_transport_speed * 1.5f);
1722                 }
1723
1724         }
1725 }
1726
1727 void
1728 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1729 {
1730         if (session == 0) {
1731                 return;
1732         }
1733
1734         boost::shared_ptr<Route> r;
1735
1736         if ((r = session->route_by_remote_id (dstream)) != 0) {
1737
1738                 Track* t;
1739
1740                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1741                         t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1742                 }
1743         }
1744         if (session == 0) {
1745                 return;
1746         }
1747 }
1748
1749 void
1750 ARDOUR_UI::map_transport_state ()
1751 {
1752         ENSURE_GUI_THREAD(mem_fun (*this, &ARDOUR_UI::map_transport_state));
1753
1754         if (!session) {
1755                 auto_loop_button.set_visual_state (0);
1756                 play_selection_button.set_visual_state (0);
1757                 roll_button.set_visual_state (0);
1758                 stop_button.set_visual_state (1);
1759                 return;
1760         }
1761
1762         float sp = session->transport_speed();
1763
1764         if (sp == 1.0f) {
1765                 shuttle_fract = SHUTTLE_FRACT_SPEED1;  /* speed = 1.0, believe it or not */
1766                 shuttle_box.queue_draw ();
1767         } else if (sp == 0.0f) {
1768                 shuttle_fract = 0;
1769                 shuttle_box.queue_draw ();
1770                 update_disk_space ();
1771         }
1772
1773         if (sp != 0.0) {
1774
1775                 if (session->get_play_range()) {
1776
1777                         play_selection_button.set_visual_state (1);
1778                         roll_button.set_visual_state (0);
1779                         auto_loop_button.set_visual_state (0);
1780                         
1781                 } else if (session->get_play_loop ()) {
1782                         
1783                         auto_loop_button.set_visual_state (1);
1784                         play_selection_button.set_visual_state (0);
1785                         roll_button.set_visual_state (0);
1786
1787                 } else {
1788                         
1789                         roll_button.set_visual_state (1);
1790                         play_selection_button.set_visual_state (0);
1791                         auto_loop_button.set_visual_state (0);
1792                 }
1793
1794                 stop_button.set_visual_state (0);
1795
1796         } else {
1797
1798                 stop_button.set_visual_state (1);
1799                 roll_button.set_visual_state (0);
1800                 play_selection_button.set_visual_state (0);
1801                 auto_loop_button.set_visual_state (0);
1802         }
1803
1804 }
1805
1806 void
1807 ARDOUR_UI::engine_stopped ()
1808 {
1809         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1810         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1811         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1812 }
1813
1814 void
1815 ARDOUR_UI::engine_running ()
1816 {
1817         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1818         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1819         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1820
1821         Glib::RefPtr<Action> action;
1822         const char* action_name = 0;
1823
1824         switch (engine->frames_per_cycle()) {
1825         case 32:
1826                 action_name = X_("JACKLatency32");
1827                 break;
1828         case 64:
1829                 action_name = X_("JACKLatency64");
1830                 break;
1831         case 128:
1832                 action_name = X_("JACKLatency128");
1833                 break;
1834         case 512:
1835                 action_name = X_("JACKLatency512");
1836                 break;
1837         case 1024:
1838                 action_name = X_("JACKLatency1024");
1839                 break;
1840         case 2048:
1841                 action_name = X_("JACKLatency2048");
1842                 break;
1843         case 4096:
1844                 action_name = X_("JACKLatency4096");
1845                 break;
1846         case 8192:
1847                 action_name = X_("JACKLatency8192");
1848                 break;
1849         default:
1850                 /* XXX can we do anything useful ? */
1851                 break;
1852         }
1853
1854         if (action_name) {
1855
1856                 action = ActionManager::get_action (X_("JACK"), action_name);
1857
1858                 if (action) {
1859                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1860                         ract->set_active ();
1861                 }
1862         }
1863 }
1864
1865 void
1866 ARDOUR_UI::engine_halted ()
1867 {
1868         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1869
1870         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1871         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1872
1873         update_sample_rate (0);
1874
1875         MessageDialog msg (*editor,
1876                            _("\
1877 JACK has either been shutdown or it\n\
1878 disconnected Ardour because Ardour\n\
1879 was not fast enough. Try to restart\n\
1880 JACK, reconnect and save the session."));
1881         pop_back_splash ();
1882         msg.run ();
1883 }
1884
1885 int32_t
1886 ARDOUR_UI::do_engine_start ()
1887 {
1888         try {
1889                 engine->start();
1890         }
1891
1892         catch (...) {
1893                 engine->stop ();
1894                 error << _("Unable to start the session running")
1895                       << endmsg;
1896                 unload_session ();
1897                 return -2;
1898         }
1899
1900         return 0;
1901 }
1902
1903 void
1904 ARDOUR_UI::setup_theme ()
1905 {
1906         theme_manager->setup_theme();
1907 }
1908
1909 void
1910 ARDOUR_UI::update_clocks ()
1911 {
1912         if (!editor || !editor->dragging_playhead()) {
1913                 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1914         }
1915 }
1916
1917 void
1918 ARDOUR_UI::start_clocking ()
1919 {
1920         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1921 }
1922
1923 void
1924 ARDOUR_UI::stop_clocking ()
1925 {
1926         clock_signal_connection.disconnect ();
1927 }
1928
1929 void
1930 ARDOUR_UI::toggle_clocking ()
1931 {
1932 #if 0
1933         if (clock_button.get_active()) {
1934                 start_clocking ();
1935         } else {
1936                 stop_clocking ();
1937         }
1938 #endif
1939 }
1940
1941 gint
1942 ARDOUR_UI::_blink (void *arg)
1943
1944 {
1945         ((ARDOUR_UI *) arg)->blink ();
1946         return TRUE;
1947 }
1948
1949 void
1950 ARDOUR_UI::blink ()
1951 {
1952         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1953 }
1954
1955 void
1956 ARDOUR_UI::start_blinking ()
1957 {
1958         /* Start the blink signal. Everybody with a blinking widget
1959            uses Blink to drive the widget's state.
1960         */
1961
1962         if (blink_timeout_tag < 0) {
1963                 blink_on = false;
1964                 blink_timeout_tag = g_timeout_add (240, _blink, this);
1965         }
1966 }
1967
1968 void
1969 ARDOUR_UI::stop_blinking ()
1970 {
1971         if (blink_timeout_tag >= 0) {
1972                 g_source_remove (blink_timeout_tag);
1973                 blink_timeout_tag = -1;
1974         }
1975 }
1976
1977
1978 /** Ask the user for the name of a new shapshot and then take it.
1979  */
1980 void
1981 ARDOUR_UI::snapshot_session ()
1982 {
1983         ArdourPrompter prompter (true);
1984         string snapname;
1985         char timebuf[128];
1986         time_t n;
1987         struct tm local_time;
1988
1989         time (&n);
1990         localtime_r (&n, &local_time);
1991         strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1992
1993         prompter.set_name ("Prompter");
1994         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1995         prompter.set_title (_("Take Snapshot"));
1996         prompter.set_prompt (_("Name of New Snapshot"));
1997         prompter.set_initial_text (timebuf);
1998
1999         switch (prompter.run()) {
2000         case RESPONSE_ACCEPT:
2001         {
2002                 prompter.get_result (snapname);
2003
2004                 bool do_save = (snapname.length() != 0);
2005
2006                 vector<sys::path> p;
2007                 get_state_files_in_directory (session->session_directory().root_path(), p);
2008                 vector<string> n = get_file_names_no_extension (p);
2009                 if (find (n.begin(), n.end(), snapname) != n.end()) {
2010
2011                         ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
2012                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
2013                         confirm.get_vbox()->pack_start (m, true, true);
2014                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2015                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2016                         confirm.show_all ();
2017                         switch (confirm.run()) {
2018                         case RESPONSE_CANCEL:
2019                                 do_save = false;
2020                         }
2021                 }
2022
2023                 if (do_save) {
2024                         save_state (snapname);
2025                 }
2026                 break;
2027         }
2028
2029         default:
2030                 break;
2031         }
2032 }
2033
2034 void
2035 ARDOUR_UI::save_state (const string & name)
2036 {
2037         (void) save_state_canfail (name);
2038 }
2039
2040 int
2041 ARDOUR_UI::save_state_canfail (string name)
2042 {
2043         if (session) {
2044                 int ret;
2045
2046                 if (name.length() == 0) {
2047                         name = session->snap_name();
2048                 }
2049
2050                 if ((ret = session->save_state (name)) != 0) {
2051                         return ret;
2052                 }
2053         }
2054         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2055         return 0;
2056 }
2057
2058 void
2059 ARDOUR_UI::primary_clock_value_changed ()
2060 {
2061         if (session) {
2062                 session->request_locate (primary_clock.current_time ());
2063         }
2064 }
2065
2066 void
2067 ARDOUR_UI::big_clock_value_changed ()
2068 {
2069         if (session) {
2070                 session->request_locate (big_clock.current_time ());
2071         }
2072 }
2073
2074 void
2075 ARDOUR_UI::secondary_clock_value_changed ()
2076 {
2077         if (session) {
2078                 session->request_locate (secondary_clock.current_time ());
2079         }
2080 }
2081
2082 void
2083 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2084 {
2085         if (session == 0) {
2086                 return;
2087         }
2088
2089         Session::RecordState const r = session->record_status ();
2090         bool const h = session->have_rec_enabled_diskstream ();
2091
2092         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2093                 if (onoff) {
2094                         rec_button.set_visual_state (2);
2095                 } else {
2096                         rec_button.set_visual_state (0);
2097                 }
2098         } else if (r == Session::Recording && h) {
2099                 rec_button.set_visual_state (1);
2100         } else {
2101                 rec_button.set_visual_state (0);
2102         }
2103 }
2104
2105 void
2106 ARDOUR_UI::save_template ()
2107 {
2108         ArdourPrompter prompter (true);
2109         string name;
2110
2111         if (!check_audioengine()) {
2112                 return;
2113         }
2114
2115         prompter.set_name (X_("Prompter"));
2116         prompter.set_title (_("Save Mix Template"));
2117         prompter.set_prompt (_("Name for mix template:"));
2118         prompter.set_initial_text(session->name() + _("-template"));
2119         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2120
2121         switch (prompter.run()) {
2122         case RESPONSE_ACCEPT:
2123                 prompter.get_result (name);
2124
2125                 if (name.length()) {
2126                         session->save_template (name);
2127                 }
2128                 break;
2129
2130         default:
2131                 break;
2132         }
2133 }
2134
2135 void
2136 ARDOUR_UI::edit_metadata ()
2137 {
2138         SessionMetadataEditor dialog;
2139         dialog.set_session (session);
2140         editor->ensure_float (dialog);
2141         dialog.run ();
2142 }
2143
2144 void
2145 ARDOUR_UI::import_metadata ()
2146 {
2147         SessionMetadataImporter dialog;
2148         dialog.set_session (session);
2149         editor->ensure_float (dialog);
2150         dialog.run ();
2151 }
2152
2153 void
2154 ARDOUR_UI::fontconfig_dialog ()
2155 {
2156 #ifdef GTKOSX
2157         /* X11 users will always have fontconfig info around, but new GTK-OSX users
2158            may not and it can take a while to build it. Warn them.
2159         */
2160
2161         Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2162
2163         if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2164                 MessageDialog msg (*_startup,
2165                                    _("Welcome to Ardour.\n\n"
2166                                      "The program will take a bit longer to start up\n"
2167                                      "while the system fonts are checked.\n\n"
2168                                      "This will only be done once, and you will\n"
2169                                      "not see this message again\n"),
2170                                    true,
2171                                    Gtk::MESSAGE_INFO,
2172                                    Gtk::BUTTONS_OK);
2173                 pop_back_splash ();
2174                 msg.show_all ();
2175                 msg.present ();
2176                 msg.run ();
2177         }
2178 #endif
2179 }
2180
2181 void
2182 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2183 {
2184         existing_session = false;
2185
2186         if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2187                 session_path = cmdline_path;
2188                 existing_session = true;
2189         } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2190                 session_path = Glib::path_get_dirname (string (cmdline_path));
2191                 existing_session = true;
2192         } else {
2193                 /* it doesn't exist, assume the best */
2194                 session_path = Glib::path_get_dirname (string (cmdline_path));
2195         }
2196
2197         session_name = basename_nosuffix (string (cmdline_path));
2198 }
2199
2200 int
2201 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2202 {
2203         /* when this is called, the backend audio system must be running */
2204
2205         /* the main idea here is to deal with the fact that a cmdline argument for the session
2206            can be interpreted in different ways - it could be a directory or a file, and before
2207            we load, we need to know both the session directory and the snapshot (statefile) within it
2208            that we are supposed to use.
2209         */
2210
2211         if (session_name.length() == 0 || session_path.length() == 0) {
2212                 return false;
2213         }
2214
2215         if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2216
2217                 Glib::ustring predicted_session_file;
2218
2219                 predicted_session_file = session_path;
2220                 predicted_session_file += '/';
2221                 predicted_session_file += session_name;
2222                 predicted_session_file += ARDOUR::statefile_suffix;
2223
2224                 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2225                         existing_session = true;
2226                 }
2227
2228         } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2229
2230                 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2231                         /* existing .ardour file */
2232                         existing_session = true;
2233                 }
2234
2235         } else {
2236                 existing_session = false;
2237         }
2238
2239         /* lets just try to load it */
2240
2241         if (create_engine ()) {
2242                 backend_audio_error (false, _startup);
2243                 return -1;
2244         }
2245
2246         return load_session (session_path, session_name);
2247 }
2248
2249 bool
2250 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2251 {
2252         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2253
2254         MessageDialog msg (str,
2255                            false,
2256                            Gtk::MESSAGE_WARNING,
2257                            Gtk::BUTTONS_YES_NO,
2258                            true);
2259
2260
2261         msg.set_name (X_("OpenExistingDialog"));
2262         msg.set_title (_("Open Existing Session"));
2263         msg.set_wmclass (X_("existing_session"), "Ardour");
2264         msg.set_position (Gtk::WIN_POS_MOUSE);
2265         pop_back_splash ();
2266
2267         switch (msg.run()) {
2268         case RESPONSE_YES:
2269                 return true;
2270                 break;
2271         }
2272         return false;
2273 }
2274
2275 int
2276 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2277 {
2278
2279         uint32_t cchns;
2280         uint32_t mchns;
2281         AutoConnectOption iconnect;
2282         AutoConnectOption oconnect;
2283         uint32_t nphysin;
2284         uint32_t nphysout;
2285
2286         if (Profile->get_sae()) {
2287
2288                 cchns = 0;
2289                 mchns = 2;
2290                 iconnect = AutoConnectPhysical;
2291                 oconnect = AutoConnectMaster;
2292                 nphysin = 0; // use all available
2293                 nphysout = 0; // use all available
2294
2295         } else {
2296
2297                 /* get settings from advanced section of NSD */
2298
2299                 if (_startup->create_control_bus()) {
2300                         cchns = (uint32_t) _startup->control_channel_count();
2301                 } else {
2302                         cchns = 0;
2303                 }
2304
2305                 if (_startup->create_master_bus()) {
2306                         mchns = (uint32_t) _startup->master_channel_count();
2307                 } else {
2308                         mchns = 0;
2309                 }
2310
2311                 if (_startup->connect_inputs()) {
2312                         iconnect = AutoConnectPhysical;
2313                 } else {
2314                         iconnect = AutoConnectOption (0);
2315                 }
2316
2317                 /// @todo some minor tweaks.
2318
2319                 oconnect = AutoConnectOption (0);
2320
2321                 if (_startup->connect_outputs ()) {
2322                         if (_startup->connect_outs_to_master()) {
2323                                 oconnect = AutoConnectMaster;
2324                         } else if (_startup->connect_outs_to_physical()) {
2325                                 oconnect = AutoConnectPhysical;
2326                         }
2327                 }
2328
2329                 nphysin = (uint32_t) _startup->input_limit_count();
2330                 nphysout = (uint32_t) _startup->output_limit_count();
2331         }
2332
2333         if (build_session (session_path,
2334                            session_name,
2335                            cchns,
2336                            mchns,
2337                            iconnect,
2338                            oconnect,
2339                            nphysin,
2340                            nphysout,
2341                            engine->frame_rate() * 60 * 5)) {
2342
2343                 return -1;
2344         }
2345
2346         return 0;
2347 }
2348
2349 void
2350 ARDOUR_UI::idle_load (const Glib::ustring& path)
2351 {
2352         if (session) {
2353                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2354                         /* /path/to/foo => /path/to/foo, foo */
2355                         load_session (path, basename_nosuffix (path));
2356                 } else {
2357                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2358                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2359                 }
2360         } else {
2361
2362                 ARDOUR_COMMAND_LINE::session_name = path;
2363
2364                 /*
2365                  * new_session_dialog doens't exist in A3
2366                  * Try to remove all references to it to
2367                  * see if it will compile.  NOTE: this will
2368                  * likely cause a runtime issue is my somewhat
2369                  * uneducated guess.
2370                  */
2371
2372                 //if (new_session_dialog) {
2373
2374
2375                         /* make it break out of Dialog::run() and
2376                            start again.
2377                          */
2378
2379                         //new_session_dialog->response (1);
2380                 //}
2381         }
2382 }
2383
2384 void
2385 ARDOUR_UI::end_loading_messages ()
2386 {
2387         // hide_splash ();
2388 }
2389
2390 void
2391 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2392 {
2393         // show_splash ();
2394         // splash->message (msg);
2395         flush_pending ();
2396 }
2397
2398 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2399 int
2400 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2401 {
2402         Glib::ustring session_name;
2403         Glib::ustring session_path;
2404         Glib::ustring template_name;
2405         int ret = -1;
2406         bool likely_new = false;
2407
2408         while (ret != 0) {
2409
2410                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2411
2412                         /* if they named a specific statefile, use it, otherwise they are
2413                            just giving a session folder, and we want to use it as is
2414                            to find the session.
2415                         */
2416
2417                         if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2418                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2419                         } else {
2420                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2421                         }
2422
2423                         session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2424
2425                 } else {
2426
2427                         bool const apply = run_startup (should_be_new);
2428                         if (!apply) {
2429                                 if (quit_on_cancel) {
2430                                         exit (1);
2431                                 } else {
2432                                         return ret;
2433                                 }
2434                         }
2435
2436                         /* if we run the startup dialog again, offer more than just "new session" */
2437
2438                         should_be_new = false;
2439
2440                         session_name = _startup->session_name (likely_new);
2441
2442                         /* this shouldn't happen, but we catch it just in case it does */
2443
2444                         if (session_name.empty()) {
2445                                 break;
2446                         }
2447                         if (_startup->use_session_template()) {
2448                                 template_name = _startup->session_template_name();
2449                                 _session_is_new = true;
2450                         }
2451
2452                         if (session_name[0] == '/' ||
2453                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2454                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2455
2456                                 session_path = Glib::path_get_dirname (session_name);
2457                                 session_name = Glib::path_get_basename (session_name);
2458
2459                         } else {
2460
2461                                 session_path = _startup->session_folder();
2462                         }
2463                 }
2464
2465                 if (create_engine ()) {
2466                         break;
2467                 }
2468
2469                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2470
2471                         if (likely_new) {
2472
2473                                 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2474
2475                                 if (!ask_about_loading_existing_session (existing)) {
2476                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2477                                         continue;
2478                                 }
2479                         }
2480
2481                         _session_is_new = false;
2482
2483                 } else {
2484
2485                         if (!likely_new) {
2486                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2487                                 msg.run ();
2488                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2489                                 continue;
2490                         }
2491
2492                         _session_is_new = true;
2493                 }
2494
2495                 if (likely_new && template_name.empty()) {
2496
2497                         ret = build_session_from_nsd (session_path, session_name);
2498
2499                 } else {
2500
2501                         ret = load_session (session_path, session_name, template_name);
2502                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2503                                 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2504                                 exit (1);
2505                         }
2506                 }
2507         }
2508
2509         return ret;
2510 }
2511
2512 void
2513 ARDOUR_UI::close_session()
2514 {
2515         if (!check_audioengine()) {
2516                 return;
2517         }
2518
2519         unload_session (true);
2520
2521         ARDOUR_COMMAND_LINE::session_name = "";
2522         get_session_parameters (true, false);
2523 }
2524
2525 int
2526 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2527 {
2528         Session *new_session;
2529         int unload_status;
2530         int retval = -1;
2531
2532         session_loaded = false;
2533
2534         if (!check_audioengine()) {
2535                 return -1;
2536         }
2537
2538         unload_status = unload_session ();
2539
2540         if (unload_status < 0) {
2541                 goto out;
2542         } else if (unload_status > 0) {
2543                 retval = 0;
2544                 goto out;
2545         }
2546
2547         loading_message (_("Please wait while Ardour loads your session"));
2548
2549         try {
2550                 new_session = new Session (*engine, path, snap_name, mix_template);
2551         }
2552
2553         /* this one is special */
2554
2555         catch (AudioEngine::PortRegistrationFailure& err) {
2556
2557                 MessageDialog msg (err.what(),
2558                                    true,
2559                                    Gtk::MESSAGE_INFO,
2560                                    Gtk::BUTTONS_CLOSE);
2561
2562                 msg.set_title (_("Port Registration Error"));
2563                 msg.set_secondary_text (_("Click the Close button to try again."));
2564                 msg.set_position (Gtk::WIN_POS_CENTER);
2565                 pop_back_splash ();
2566                 msg.present ();
2567
2568                 int response = msg.run ();
2569
2570                 msg.hide ();
2571
2572                 switch (response) {
2573                 case RESPONSE_CANCEL:
2574                         exit (1);
2575                 default:
2576                         break;
2577                 }
2578                 goto out;
2579         }
2580
2581         catch (...) {
2582
2583                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2584                                    true,
2585                                    Gtk::MESSAGE_INFO,
2586                                    Gtk::BUTTONS_CLOSE);
2587
2588                 msg.set_title (_("Loading Error"));
2589                 msg.set_secondary_text (_("Click the Close button to try again."));
2590                 msg.set_position (Gtk::WIN_POS_CENTER);
2591                 pop_back_splash ();
2592                 msg.present ();
2593
2594                 int response = msg.run ();
2595
2596                 msg.hide ();
2597
2598                 switch (response) {
2599                 case RESPONSE_CANCEL:
2600                         exit (1);
2601                 default:
2602                         break;
2603                 }
2604                 goto out;
2605         }
2606
2607         connect_to_session (new_session);
2608
2609         session_loaded = true;
2610
2611         goto_editor_window ();
2612
2613         if (session) {
2614                 session->set_clean ();
2615         }
2616
2617         flush_pending ();
2618         retval = 0;
2619
2620   out:
2621         return retval;
2622 }
2623
2624 int
2625 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2626                           uint32_t control_channels,
2627                           uint32_t master_channels,
2628                           AutoConnectOption input_connect,
2629                           AutoConnectOption output_connect,
2630                           uint32_t nphysin,
2631                           uint32_t nphysout,
2632                           nframes_t initial_length)
2633 {
2634         Session *new_session;
2635         int x;
2636
2637         if (!check_audioengine()) {
2638                 return -1;
2639         }
2640
2641         session_loaded = false;
2642
2643         x = unload_session ();
2644
2645         if (x < 0) {
2646                 return -1;
2647         } else if (x > 0) {
2648                 return 0;
2649         }
2650
2651         _session_is_new = true;
2652
2653         try {
2654                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2655                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2656         }
2657
2658         catch (...) {
2659
2660                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2661                 pop_back_splash ();
2662                 msg.run ();
2663                 return -1;
2664         }
2665
2666         connect_to_session (new_session);
2667
2668         session_loaded = true;
2669
2670         new_session->save_state(new_session->name());
2671
2672         return 0;
2673 }
2674
2675 void
2676 ARDOUR_UI::show ()
2677 {
2678         if (editor) {
2679                 editor->show_window ();
2680
2681                 if (!shown_flag) {
2682                         editor->present ();
2683                 }
2684
2685                 shown_flag = true;
2686         }
2687 }
2688
2689 void
2690 ARDOUR_UI::show_about ()
2691 {
2692         if (about == 0) {
2693                 about = new About;
2694                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2695         }
2696
2697         about->show_all ();
2698 }
2699
2700 void
2701 ARDOUR_UI::hide_about ()
2702 {
2703         if (about) {
2704                 about->get_window()->set_cursor ();
2705                 about->hide ();
2706         }
2707 }
2708
2709 void
2710 ARDOUR_UI::about_signal_response (int /*response*/)
2711 {
2712         hide_about();
2713 }
2714
2715 void
2716 ARDOUR_UI::show_splash ()
2717 {
2718         if (splash == 0) {
2719                 try {
2720                         splash = new Splash;
2721                 } catch (...) {
2722                         return;
2723                 }
2724         }
2725
2726         splash->show ();
2727         splash->present ();
2728         splash->queue_draw ();
2729         splash->get_window()->process_updates (true);
2730         flush_pending ();
2731 }
2732
2733 void
2734 ARDOUR_UI::hide_splash ()
2735 {
2736         if (splash) {
2737                 splash->hide();
2738         }
2739 }
2740
2741 void
2742 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2743                                     const string& plural_msg, const string& singular_msg)
2744 {
2745         size_t removed;
2746
2747         removed = rep.paths.size();
2748
2749         if (removed == 0) {
2750                 MessageDialog msgd (*editor,
2751                                     _("No audio files were ready for cleanup"),
2752                                     true,
2753                                     Gtk::MESSAGE_INFO,
2754                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2755                 msgd.set_secondary_text (_("If this seems suprising, \n\
2756 check for any existing snapshots.\n\
2757 These may still include regions that\n\
2758 require some unused files to continue to exist."));
2759
2760                 msgd.run ();
2761                 return;
2762         }
2763
2764         ArdourDialog results (_("ardour: cleanup"), true, false);
2765
2766         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2767             CleanupResultsModelColumns() {
2768                     add (visible_name);
2769                     add (fullpath);
2770             }
2771             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2772             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2773         };
2774
2775
2776         CleanupResultsModelColumns results_columns;
2777         Glib::RefPtr<Gtk::ListStore> results_model;
2778         Gtk::TreeView results_display;
2779
2780         results_model = ListStore::create (results_columns);
2781         results_display.set_model (results_model);
2782         results_display.append_column (list_title, results_columns.visible_name);
2783
2784         results_display.set_name ("CleanupResultsList");
2785         results_display.set_headers_visible (true);
2786         results_display.set_headers_clickable (false);
2787         results_display.set_reorderable (false);
2788
2789         Gtk::ScrolledWindow list_scroller;
2790         Gtk::Label txt;
2791         Gtk::VBox dvbox;
2792         Gtk::HBox dhbox;  // the hbox for the image and text
2793         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2794         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2795
2796         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2797
2798         const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2799
2800
2801
2802
2803         /* subst:
2804            %1 - number of files removed
2805            %2 - location of "dead_sounds"
2806            %3 - size of files affected
2807            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2808         */
2809
2810         const char* bprefix;
2811
2812         if (rep.space < 1048576.0f) {
2813                 bprefix = X_("kilo");
2814         } else if (rep.space < 1048576.0f * 1000) {
2815                 bprefix = X_("mega");
2816         } else {
2817                 bprefix = X_("giga");
2818         }
2819
2820         if (removed > 1) {
2821                 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2822         } else {
2823                 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2824         }
2825
2826         dhbox.pack_start (*dimage, true, false, 5);
2827         dhbox.pack_start (txt, true, false, 5);
2828
2829         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2830                 TreeModel::Row row = *(results_model->append());
2831                 row[results_columns.visible_name] = *i;
2832                 row[results_columns.fullpath] = *i;
2833         }
2834
2835         list_scroller.add (results_display);
2836         list_scroller.set_size_request (-1, 150);
2837         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2838
2839         dvbox.pack_start (dhbox, true, false, 5);
2840         dvbox.pack_start (list_scroller, true, false, 5);
2841         ddhbox.pack_start (dvbox, true, false, 5);
2842
2843         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2844         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2845         results.set_default_response (RESPONSE_CLOSE);
2846         results.set_position (Gtk::WIN_POS_MOUSE);
2847
2848         results_display.show();
2849         list_scroller.show();
2850         txt.show();
2851         dvbox.show();
2852         dhbox.show();
2853         ddhbox.show();
2854         dimage->show();
2855
2856         //results.get_vbox()->show();
2857         results.set_resizable (false);
2858
2859         results.run ();
2860
2861 }
2862
2863 void
2864 ARDOUR_UI::cleanup ()
2865 {
2866         if (session == 0) {
2867                 /* shouldn't happen: menu item is insensitive */
2868                 return;
2869         }
2870
2871
2872         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2873                                 true,
2874                                 Gtk::MESSAGE_QUESTION,
2875                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2876
2877         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2878 ALL undo/redo information will be lost if you cleanup.\n\
2879 After cleanup, unused audio files will be moved to a \
2880 \"dead sounds\" location."));
2881
2882         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2883         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2884         checker.set_default_response (RESPONSE_CANCEL);
2885
2886         checker.set_name (_("CleanupDialog"));
2887         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2888         checker.set_position (Gtk::WIN_POS_MOUSE);
2889
2890         switch (checker.run()) {
2891         case RESPONSE_ACCEPT:
2892                 break;
2893         default:
2894                 return;
2895         }
2896
2897         ARDOUR::CleanupReport rep;
2898
2899         editor->prepare_for_cleanup ();
2900
2901         /* do not allow flush until a session is reloaded */
2902
2903         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2904         if (act) {
2905                 act->set_sensitive (false);
2906         }
2907
2908         if (session->cleanup_sources (rep)) {
2909                 editor->finish_cleanup ();
2910                 return;
2911         }
2912
2913         editor->finish_cleanup ();
2914
2915         checker.hide();
2916         display_cleanup_results (rep,
2917                                  _("cleaned files"),
2918                                  _("\
2919 The following %1 files were not in use and \n\
2920 have been moved to:\n\
2921 %2. \n\n\
2922 Flushing the wastebasket will \n\
2923 release an additional\n\
2924 %3 %4bytes of disk space.\n"),
2925                                  _("\
2926 The following file was not in use and \n        \
2927 has been moved to:\n                            \
2928 %2. \n\n\
2929 Flushing the wastebasket will \n\
2930 release an additional\n\
2931 %3 %4bytes of disk space.\n"
2932                                          ));
2933
2934 }
2935
2936 void
2937 ARDOUR_UI::flush_trash ()
2938 {
2939         if (session == 0) {
2940                 /* shouldn't happen: menu item is insensitive */
2941                 return;
2942         }
2943
2944         ARDOUR::CleanupReport rep;
2945
2946         if (session->cleanup_trash_sources (rep)) {
2947                 return;
2948         }
2949
2950         display_cleanup_results (rep,
2951                                  _("deleted file"),
2952                                  _("The following %1 files were deleted from\n\
2953 %2,\n\
2954 releasing %3 %4bytes of disk space"),
2955                                  _("The following file was deleted from\n\
2956 %2,\n\
2957 releasing %3 %4bytes of disk space"));
2958 }
2959
2960 void
2961 ARDOUR_UI::add_route (Gtk::Window* float_window)
2962 {
2963         int count;
2964
2965         if (!session) {
2966                 return;
2967         }
2968
2969         if (add_route_dialog == 0) {
2970                 add_route_dialog = new AddRouteDialog (*session);
2971                 if (float_window) {
2972                         add_route_dialog->set_transient_for (*float_window);
2973                 }
2974         }
2975
2976         if (add_route_dialog->is_visible()) {
2977                 /* we're already doing this */
2978                 return;
2979         }
2980
2981         ResponseType r = (ResponseType) add_route_dialog->run ();
2982
2983         add_route_dialog->hide();
2984
2985         switch (r) {
2986                 case RESPONSE_ACCEPT:
2987                         break;
2988                 default:
2989                         return;
2990                         break;
2991         }
2992
2993         if ((count = add_route_dialog->count()) <= 0) {
2994                 return;
2995         }
2996
2997         string template_path = add_route_dialog->track_template();
2998
2999         if (!template_path.empty()) {
3000                 session->new_route_from_template (count, template_path);
3001                 return;
3002         }
3003
3004         uint32_t input_chan = add_route_dialog->channels ();
3005         uint32_t output_chan;
3006         string name_template = add_route_dialog->name_template ();
3007         bool track = add_route_dialog->track ();
3008         bool aux = !track && add_route_dialog->aux();
3009         RouteGroup* route_group = add_route_dialog->route_group ();
3010
3011         AutoConnectOption oac = Config->get_output_auto_connect();
3012
3013         if (oac & AutoConnectMaster) {
3014                 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
3015         } else {
3016                 output_chan = input_chan;
3017         }
3018
3019         /* XXX do something with name template */
3020
3021         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3022                 if (track) {
3023                         session_add_midi_track (route_group, count);
3024                 } else  {
3025                         MessageDialog msg (*editor,
3026                                         _("Sorry, MIDI Busses are not supported at this time."));
3027                         msg.run ();
3028                         //session_add_midi_bus();
3029                 }
3030         } else {
3031                 if (track) {
3032                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3033                 } else {
3034                         session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3035                 }
3036         }
3037 }
3038
3039 XMLNode*
3040 ARDOUR_UI::mixer_settings () const
3041 {
3042         XMLNode* node = 0;
3043
3044         if (session) {
3045                 node = session->instant_xml(X_("Mixer"));
3046         } else {
3047                 node = Config->instant_xml(X_("Mixer"));
3048         }
3049
3050         if (!node) {
3051                 node = new XMLNode (X_("Mixer"));
3052         }
3053
3054         return node;
3055 }
3056
3057 XMLNode*
3058 ARDOUR_UI::editor_settings () const
3059 {
3060         XMLNode* node = 0;
3061
3062         if (session) {
3063                 node = session->instant_xml(X_("Editor"));
3064         } else {
3065                 node = Config->instant_xml(X_("Editor"));
3066         }
3067
3068         if (!node) {
3069                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3070                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3071                 }
3072         }
3073
3074         if (!node) {
3075                 node = new XMLNode (X_("Editor"));
3076         }
3077
3078         return node;
3079 }
3080
3081 XMLNode*
3082 ARDOUR_UI::keyboard_settings () const
3083 {
3084         XMLNode* node = 0;
3085
3086         node = Config->extra_xml(X_("Keyboard"));
3087
3088         if (!node) {
3089                 node = new XMLNode (X_("Keyboard"));
3090         }
3091         return node;
3092 }
3093
3094 void
3095 ARDOUR_UI::create_xrun_marker(nframes_t where)
3096 {
3097         editor->mouse_add_new_marker (where, false, true);
3098 }
3099
3100 void
3101 ARDOUR_UI::halt_on_xrun_message ()
3102 {
3103         MessageDialog msg (*editor,
3104                            _("Recording was stopped because your system could not keep up."));
3105         msg.run ();
3106 }
3107
3108 void
3109 ARDOUR_UI::xrun_handler(nframes_t where)
3110 {
3111         if (!session) {
3112                 return;
3113         }
3114
3115         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3116
3117         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3118                 create_xrun_marker(where);
3119         }
3120
3121         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3122                 halt_on_xrun_message ();
3123         }
3124 }
3125
3126 void
3127 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3128 {
3129         time_t now;
3130         time (&now);
3131
3132         while (disk_buffer_stats.size() > 60) {
3133                 disk_buffer_stats.pop_front ();
3134         }
3135
3136         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3137 }
3138
3139 void
3140 ARDOUR_UI::write_buffer_stats ()
3141 {
3142
3143         std::ofstream fout;
3144         struct tm tm;
3145         char buf[64];
3146         char path[PATH_MAX+1];  int fd;
3147
3148         strcpy (path, "ardourBufferingXXXXXX");
3149
3150         if ((fd = mkstemp (path )) < 0) {
3151                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3152                 return;
3153         }
3154         
3155         fout.open (path);
3156         close (fd);
3157
3158         if (!fout) {
3159                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3160                 return;
3161         }
3162
3163         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3164                 localtime_r (&(*i).when, &tm);
3165                 strftime (buf, sizeof (buf), "%T", &tm);
3166                 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3167         }
3168         
3169         disk_buffer_stats.clear ();
3170
3171         fout.close ();
3172
3173         cerr << "Ardour buffering statistics can be found in: " << path << endl;
3174 }
3175
3176 void
3177 ARDOUR_UI::disk_overrun_handler ()
3178 {
3179         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3180
3181         write_buffer_stats ();
3182
3183         if (!have_disk_speed_dialog_displayed) {
3184                 have_disk_speed_dialog_displayed = true;
3185                 MessageDialog* msg = new MessageDialog (*editor, _("\
3186 The disk system on your computer\n\
3187 was not able to keep up with Ardour.\n\
3188 \n\
3189 Specifically, it failed to write data to disk\n\
3190 quickly enough to keep up with recording.\n"));
3191                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3192                 msg->show ();
3193         }
3194 }
3195
3196 void
3197 ARDOUR_UI::disk_underrun_handler ()
3198 {
3199         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3200
3201         write_buffer_stats ();
3202
3203         if (!have_disk_speed_dialog_displayed) {
3204                 have_disk_speed_dialog_displayed = true;
3205                 MessageDialog* msg = new MessageDialog (*editor,
3206                                    _("The disk system on your computer\n\
3207 was not able to keep up with Ardour.\n\
3208 \n\
3209 Specifically, it failed to read data from disk\n\
3210 quickly enough to keep up with playback.\n"));
3211                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3212                 msg->show ();
3213         }
3214 }
3215
3216 void
3217 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3218 {
3219         have_disk_speed_dialog_displayed = false;
3220         delete msg;
3221 }
3222
3223 void
3224 ARDOUR_UI::session_dialog (std::string msg)
3225 {
3226         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3227
3228         MessageDialog* d;
3229
3230         if (editor) {
3231                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3232         } else {
3233                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3234         }
3235
3236         d->show_all ();
3237         d->run ();
3238         delete d;
3239 }
3240
3241 int
3242 ARDOUR_UI::pending_state_dialog ()
3243 {
3244         HBox* hbox = new HBox();
3245         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3246         ArdourDialog dialog (_("Crash Recovery"), true);
3247         Label  message (_("\
3248 This session appears to have been in\n\
3249 middle of recording when ardour or\n\
3250 the computer was shutdown.\n\
3251 \n\
3252 Ardour can recover any captured audio for\n\
3253 you, or it can ignore it. Please decide\n\
3254 what you would like to do.\n"));
3255         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3256         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3257         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3258         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3259         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3260         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3261         dialog.set_default_response (RESPONSE_ACCEPT);
3262         dialog.set_position (WIN_POS_CENTER);
3263         message.show();
3264         image->show();
3265         hbox->show();
3266
3267         switch (dialog.run ()) {
3268         case RESPONSE_ACCEPT:
3269                 return 1;
3270         default:
3271                 return 0;
3272         }
3273 }
3274
3275 int
3276 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3277 {
3278         HBox* hbox = new HBox();
3279         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3280         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3281         Label  message (string_compose (_("\
3282 This session was created with a sample rate of %1 Hz\n\
3283 \n\
3284 The audioengine is currently running at %2 Hz\n"), desired, actual));
3285
3286         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3287         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3288         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3289         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3290         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3291         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3292         dialog.set_default_response (RESPONSE_ACCEPT);
3293         dialog.set_position (WIN_POS_CENTER);
3294         message.show();
3295         image->show();
3296         hbox->show();
3297
3298         switch (dialog.run ()) {
3299         case RESPONSE_ACCEPT:
3300                 return 0;
3301         default:
3302                 return 1;
3303         }
3304 }
3305
3306
3307 void
3308 ARDOUR_UI::disconnect_from_jack ()
3309 {
3310         if (engine) {
3311                 if( engine->disconnect_from_jack ()) {
3312                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3313                         msg.run ();
3314                 }
3315
3316                 update_sample_rate (0);
3317         }
3318 }
3319
3320 void
3321 ARDOUR_UI::reconnect_to_jack ()
3322 {
3323         if (engine) {
3324                 if (engine->reconnect_to_jack ()) {
3325                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3326                         msg.run ();
3327                 }
3328
3329                 update_sample_rate (0);
3330         }
3331 }
3332
3333 void
3334 ARDOUR_UI::use_config ()
3335 {
3336
3337         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3338         if (node) {
3339                 set_transport_controllable_state (*node);
3340         }
3341 }
3342
3343 void
3344 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3345 {
3346         if (Config->get_primary_clock_delta_edit_cursor()) {
3347                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3348         } else {
3349                 primary_clock.set (pos, 0, true);
3350         }
3351
3352         if (Config->get_secondary_clock_delta_edit_cursor()) {
3353                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3354         } else {
3355                 secondary_clock.set (pos);
3356         }
3357
3358         if (big_clock_window) {
3359                 big_clock.set (pos);
3360         }
3361 }
3362
3363 void
3364 ARDOUR_UI::record_state_changed ()
3365 {
3366         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3367
3368         if (!session || !big_clock_window) {
3369                 /* why bother - the clock isn't visible */
3370                 return;
3371         }
3372
3373         Session::RecordState const r = session->record_status ();
3374         bool const h = session->have_rec_enabled_diskstream ();
3375
3376         if (r == Session::Recording && h)  {
3377                 big_clock.set_widget_name ("BigClockRecording");
3378         } else {
3379                 big_clock.set_widget_name ("BigClockNonRecording");
3380         }
3381 }
3382
3383 bool
3384 ARDOUR_UI::first_idle ()
3385 {
3386         if (session) {
3387                 session->allow_auto_play (true);
3388         }
3389
3390         if (editor) {
3391                 editor->first_idle();
3392         }
3393
3394         Keyboard::set_can_save_keybindings (true);
3395         return false;
3396 }
3397
3398 void
3399 ARDOUR_UI::store_clock_modes ()
3400 {
3401         XMLNode* node = new XMLNode(X_("ClockModes"));
3402
3403         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3404                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3405         }
3406
3407         session->add_extra_xml (*node);
3408         session->set_dirty ();
3409 }
3410
3411
3412
3413 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3414         : Controllable (name), ui (u), type(tp)
3415 {
3416
3417 }
3418
3419 void
3420 ARDOUR_UI::TransportControllable::set_value (float val)
3421 {
3422         if (type == ShuttleControl) {
3423                 double fract;
3424
3425                 if (val == 0.5f) {
3426                         fract = 0.0;
3427                 } else {
3428                         if (val < 0.5f) {
3429                                 fract = -((0.5f - val)/0.5f);
3430                         } else {
3431                                 fract = ((val - 0.5f)/0.5f);
3432                         }
3433                 }
3434
3435                 ui.set_shuttle_fract (fract);
3436                 return;
3437         }
3438
3439         if (val < 0.5f) {
3440                 /* do nothing: these are radio-style actions */
3441                 return;
3442         }
3443
3444         const char *action = 0;
3445
3446         switch (type) {
3447         case Roll:
3448                 action = X_("Roll");
3449                 break;
3450         case Stop:
3451                 action = X_("Stop");
3452                 break;
3453         case GotoStart:
3454                 action = X_("Goto Start");
3455                 break;
3456         case GotoEnd:
3457                 action = X_("Goto End");
3458                 break;
3459         case AutoLoop:
3460                 action = X_("Loop");
3461                 break;
3462         case PlaySelection:
3463                 action = X_("Play Selection");
3464                 break;
3465         case RecordEnable:
3466                 action = X_("Record");
3467                 break;
3468         default:
3469                 break;
3470         }
3471
3472         if (action == 0) {
3473                 return;
3474         }
3475
3476         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3477
3478         if (act) {
3479                 act->activate ();
3480         }
3481 }
3482
3483 float
3484 ARDOUR_UI::TransportControllable::get_value (void) const
3485 {
3486         float val = 0.0f;
3487
3488         switch (type) {
3489         case Roll:
3490                 break;
3491         case Stop:
3492                 break;
3493         case GotoStart:
3494                 break;
3495         case GotoEnd:
3496                 break;
3497         case AutoLoop:
3498                 break;
3499         case PlaySelection:
3500                 break;
3501         case RecordEnable:
3502                 break;
3503         case ShuttleControl:
3504                 break;
3505         default:
3506                 break;
3507         }
3508
3509         return val;
3510 }
3511
3512 void
3513 ARDOUR_UI::TransportControllable::set_id (const string& str)
3514 {
3515         _id = str;
3516 }
3517
3518 void
3519 ARDOUR_UI::setup_profile ()
3520 {
3521         if (gdk_screen_width() < 1200) {
3522                 Profile->set_small_screen ();
3523         }
3524
3525
3526         if (getenv ("ARDOUR_SAE")) {
3527                 Profile->set_sae ();
3528                 Profile->set_single_package ();
3529         }
3530 }
3531