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