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