do not attempt to use scroll view for AU plugin GUIs (fixes crash-on-delete of Cocoa...
[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         if (unload_session (true)) {
2412                 return;
2413         }
2414         
2415         get_session_parameters (true, false);
2416 }
2417
2418 int
2419 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2420 {
2421         Session *new_session;
2422         int unload_status;
2423         int retval = -1;
2424
2425         session_loaded = false;
2426
2427         if (!check_audioengine()) {
2428                 return -1;
2429         }
2430
2431         unload_status = unload_session ();
2432
2433         if (unload_status < 0) {
2434                 goto out;
2435         } else if (unload_status > 0) {
2436                 retval = 0;
2437                 goto out;
2438         }
2439
2440         /* if it already exists, we must have write access */
2441
2442         if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2443                 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2444                                               "This prevents the session from being loaded."));
2445                 pop_back_splash ();
2446                 msg.run ();
2447                 goto out;
2448         }
2449
2450         loading_message (_("Please wait while Ardour loads your session"));
2451
2452         try {
2453                 new_session = new Session (*engine, path, snap_name, mix_template);
2454         }
2455
2456         /* this one is special */
2457
2458         catch (AudioEngine::PortRegistrationFailure& err) {
2459
2460                 MessageDialog msg (err.what(),
2461                                    true,
2462                                    Gtk::MESSAGE_INFO,
2463                                    Gtk::BUTTONS_CLOSE);
2464                 
2465                 msg.set_title (_("Port Registration Error"));
2466                 msg.set_secondary_text (_("Click the Close button to try again."));
2467                 msg.set_position (Gtk::WIN_POS_CENTER);
2468                 pop_back_splash ();
2469                 msg.present ();
2470
2471                 int response = msg.run ();
2472
2473                 msg.hide ();
2474
2475                 switch (response) {
2476                 case RESPONSE_CANCEL:
2477                         exit (1);
2478                 default:
2479                         break;
2480                 }
2481                 goto out;
2482         }
2483
2484         catch (...) {
2485
2486                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2487                                    true,
2488                                    Gtk::MESSAGE_INFO,
2489                                    Gtk::BUTTONS_CLOSE);
2490                 
2491                 msg.set_title (_("Loading Error"));
2492                 msg.set_secondary_text (_("Click the Close button to try again."));
2493                 msg.set_position (Gtk::WIN_POS_CENTER);
2494                 pop_back_splash ();
2495                 msg.present ();
2496
2497                 int response = msg.run ();
2498
2499                 msg.hide ();
2500
2501                 switch (response) {
2502                 case RESPONSE_CANCEL:
2503                         exit (1);
2504                 default:
2505                         break;
2506                 }
2507                 goto out;
2508         }
2509
2510         connect_to_session (new_session);
2511
2512         Config->set_current_owner (ConfigVariableBase::Interface);
2513
2514         session_loaded = true;
2515         
2516         goto_editor_window ();
2517
2518         if (session) {
2519                 session->set_clean ();
2520         }
2521
2522         flush_pending ();
2523         retval = 0;
2524
2525   out:
2526         return retval;
2527 }
2528
2529 int
2530 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, 
2531                           uint32_t control_channels,
2532                           uint32_t master_channels, 
2533                           AutoConnectOption input_connect,
2534                           AutoConnectOption output_connect,
2535                           uint32_t nphysin,
2536                           uint32_t nphysout,
2537                           nframes_t initial_length)
2538 {
2539         Session *new_session;
2540         int x;
2541
2542         if (!check_audioengine()) {
2543                 return -1;
2544         }
2545
2546         session_loaded = false;
2547
2548         x = unload_session ();
2549
2550         if (x < 0) {
2551                 return -1;
2552         } else if (x > 0) {
2553                 return 0;
2554         }
2555         
2556         _session_is_new = true;
2557
2558         try {
2559                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2560                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2561         }
2562
2563         catch (...) {
2564
2565                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2566                 pop_back_splash ();
2567                 msg.run ();
2568                 return -1;
2569         }
2570
2571         connect_to_session (new_session);
2572
2573         session_loaded = true;
2574
2575         new_session->save_state(new_session->name());
2576
2577         return 0;
2578 }
2579
2580 void
2581 ARDOUR_UI::show ()
2582 {
2583         if (editor) {
2584                 editor->show_window ();
2585                 
2586                 if (!shown_flag) {
2587                         editor->present ();
2588                 }
2589
2590                 shown_flag = true;
2591         }
2592 }
2593
2594 void
2595 ARDOUR_UI::show_about ()
2596 {
2597         if (about == 0) {
2598                 about = new About;
2599                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2600         }
2601
2602         about->show_all ();
2603 }
2604
2605 void
2606 ARDOUR_UI::launch_chat ()
2607 {
2608 #ifdef __APPLE__
2609         NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2610 #else
2611         NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2612 #endif
2613 }
2614
2615 void
2616 ARDOUR_UI::hide_about ()
2617 {
2618         if (about) {
2619                 about->get_window()->set_cursor ();
2620                 about->hide ();
2621         }
2622 }
2623
2624 void
2625 ARDOUR_UI::about_signal_response(int response)
2626 {
2627         hide_about();
2628 }
2629
2630 void
2631 ARDOUR_UI::show_splash ()
2632 {
2633         if (splash == 0) {
2634                 try {
2635                         splash = new Splash;
2636                 } catch (...) {
2637                         return;
2638                 }
2639         }
2640
2641         splash->show ();
2642         splash->present ();
2643         splash->queue_draw ();
2644         splash->get_window()->process_updates (true);
2645         flush_pending ();
2646 }
2647
2648 void
2649 ARDOUR_UI::hide_splash ()
2650 {
2651         if (splash) {
2652                 splash->hide();
2653         }
2654 }
2655
2656 void
2657 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2658 {
2659         size_t removed;
2660
2661         removed = rep.paths.size();
2662
2663         if (removed == 0) {
2664                 MessageDialog msgd (*editor,
2665                                     _("No audio files were ready for cleanup"), 
2666                                     true,
2667                                     Gtk::MESSAGE_INFO,
2668                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2669                 msgd.set_secondary_text (_("If this seems suprising, \n\
2670 check for any existing snapshots.\n\
2671 These may still include regions that\n\
2672 require some unused files to continue to exist."));
2673         
2674                 msgd.run ();
2675                 return;
2676         } 
2677
2678         ArdourDialog results (_("ardour: cleanup"), true, false);
2679         
2680         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2681             CleanupResultsModelColumns() { 
2682                     add (visible_name);
2683                     add (fullpath);
2684             }
2685             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2686             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2687         };
2688
2689         
2690         CleanupResultsModelColumns results_columns;
2691         Glib::RefPtr<Gtk::ListStore> results_model;
2692         Gtk::TreeView results_display;
2693         
2694         results_model = ListStore::create (results_columns);
2695         results_display.set_model (results_model);
2696         results_display.append_column (list_title, results_columns.visible_name);
2697
2698         results_display.set_name ("CleanupResultsList");
2699         results_display.set_headers_visible (true);
2700         results_display.set_headers_clickable (false);
2701         results_display.set_reorderable (false);
2702
2703         Gtk::ScrolledWindow list_scroller;
2704         Gtk::Label txt;
2705         Gtk::VBox dvbox;
2706         Gtk::HBox dhbox;  // the hbox for the image and text
2707         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2708         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2709
2710         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2711
2712         if (rep.space < 1048576.0f) {
2713                 if (removed > 1) {
2714                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2715                 } else {
2716                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2717                 }
2718         } else {
2719                 if (removed > 1) {
2720                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2721                 } else {
2722                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2723                 }
2724         }
2725
2726         dhbox.pack_start (*dimage, true, false, 5);
2727         dhbox.pack_start (txt, true, false, 5);
2728
2729         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2730                 TreeModel::Row row = *(results_model->append());
2731                 row[results_columns.visible_name] = *i;
2732                 row[results_columns.fullpath] = *i;
2733         }
2734         
2735         list_scroller.add (results_display);
2736         list_scroller.set_size_request (-1, 150);
2737         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2738
2739         dvbox.pack_start (dhbox, true, false, 5);
2740         dvbox.pack_start (list_scroller, true, false, 5);
2741         ddhbox.pack_start (dvbox, true, false, 5);
2742
2743         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2744         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2745         results.set_default_response (RESPONSE_CLOSE);
2746         results.set_position (Gtk::WIN_POS_MOUSE);
2747         results.show_all_children ();
2748         results.set_resizable (false);
2749
2750         results.run ();
2751
2752 }
2753
2754 void
2755 ARDOUR_UI::cleanup ()
2756 {
2757         if (session == 0) {
2758                 /* shouldn't happen: menu item is insensitive */
2759                 return;
2760         }
2761
2762
2763         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2764                                 true,
2765                                 Gtk::MESSAGE_QUESTION,
2766                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2767
2768         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2769 ALL undo/redo information will be lost if you cleanup.\n\
2770 After cleanup, unused audio files will be moved to a \
2771 \"dead sounds\" location."));
2772         
2773         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2774         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2775         checker.set_default_response (RESPONSE_CANCEL);
2776
2777         checker.set_name (_("CleanupDialog"));
2778         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2779         checker.set_position (Gtk::WIN_POS_MOUSE);
2780
2781         switch (checker.run()) {
2782         case RESPONSE_ACCEPT:
2783                 break;
2784         default:
2785                 return;
2786         }
2787
2788         Session::cleanup_report rep;
2789
2790         editor->prepare_for_cleanup ();
2791
2792         /* do not allow flush until a session is reloaded */
2793
2794         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2795         if (act) {
2796                 act->set_sensitive (false);
2797         }
2798
2799         if (session->cleanup_sources (rep)) {
2800                 editor->finish_cleanup ();
2801                 return;
2802         }
2803         
2804         editor->finish_cleanup ();
2805
2806         checker.hide();
2807         display_cleanup_results (rep, 
2808                                  _("cleaned files"),
2809                                  _("\
2810 The following %1 %2 not in use and \n\
2811 have been moved to:\n\
2812 %3. \n\n\
2813 Flushing the wastebasket will \n\
2814 release an additional\n\
2815 %4 %5bytes of disk space.\n"
2816                                          ));
2817
2818 }
2819
2820 void
2821 ARDOUR_UI::flush_trash ()
2822 {
2823         if (session == 0) {
2824                 /* shouldn't happen: menu item is insensitive */
2825                 return;
2826         }
2827
2828         Session::cleanup_report rep;
2829
2830         if (session->cleanup_trash_sources (rep)) {
2831                 return;
2832         }
2833
2834         display_cleanup_results (rep, 
2835                                  _("deleted file"),
2836                                  _("The following %1 %2 deleted from\n\
2837 %3,\n\
2838 releasing %4 %5bytes of disk space"));
2839 }
2840
2841 void
2842 ARDOUR_UI::add_route (Gtk::Window* float_window)
2843 {
2844         int count;
2845
2846         if (!session) {
2847                 return;
2848         }
2849
2850         if (add_route_dialog == 0) {
2851                 add_route_dialog = new AddRouteDialog;
2852                 if (float_window) {
2853                         add_route_dialog->set_transient_for (*float_window);
2854                 }
2855         }
2856
2857         if (add_route_dialog->is_visible()) {
2858                 /* we're already doing this */
2859                 return;
2860         }
2861
2862         ResponseType r = (ResponseType) add_route_dialog->run ();
2863         
2864         add_route_dialog->hide();
2865
2866         switch (r) {
2867         case RESPONSE_ACCEPT:
2868                 break;
2869         default:
2870                 return;
2871                 break;
2872         }
2873
2874         if ((count = add_route_dialog->count()) <= 0) {
2875                 return;
2876         }
2877
2878         string template_path = add_route_dialog->track_template();
2879
2880         if (!template_path.empty()) {
2881           session->new_route_from_template (count, template_path);
2882           return;
2883         }
2884         
2885         uint32_t input_chan = add_route_dialog->channels ();
2886         uint32_t output_chan;
2887         string name_template = add_route_dialog->name_template ();
2888         bool track = add_route_dialog->track ();
2889
2890         AutoConnectOption oac = Config->get_output_auto_connect();
2891
2892         if (oac & AutoConnectMaster) {
2893                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2894         } else {
2895                 output_chan = input_chan;
2896         }
2897
2898         /* XXX do something with name template */
2899
2900         if (track) {
2901                 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2902         } else {
2903                 session_add_audio_bus (input_chan, output_chan, count);
2904         }
2905 }
2906
2907 XMLNode*
2908 ARDOUR_UI::mixer_settings () const
2909 {
2910         XMLNode* node = 0;
2911
2912         if (session) {
2913                 node = session->instant_xml(X_("Mixer"), session->path());
2914         } else {
2915                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2916         }
2917
2918         if (!node) {
2919                 node = new XMLNode (X_("Mixer"));
2920         }
2921
2922         return node;
2923 }
2924
2925 XMLNode*
2926 ARDOUR_UI::editor_settings () const
2927 {
2928         XMLNode* node = 0;
2929
2930         if (session) {
2931                 node = session->instant_xml(X_("Editor"), session->path());
2932         } else {
2933                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2934         }
2935         
2936         if (!node) {
2937                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2938                         node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2939                 }
2940         }
2941
2942         if (!node) {
2943                 node = new XMLNode (X_("Editor"));
2944         }
2945         return node;
2946 }
2947
2948 XMLNode*
2949 ARDOUR_UI::keyboard_settings () const
2950 {
2951         XMLNode* node = 0;
2952
2953         node = Config->extra_xml(X_("Keyboard"));
2954         
2955         if (!node) {
2956                 node = new XMLNode (X_("Keyboard"));
2957         }
2958         return node;
2959 }
2960
2961 void
2962 ARDOUR_UI::create_xrun_marker(nframes_t where)
2963 {
2964         editor->mouse_add_new_marker (where, false, true);
2965 }
2966
2967 void
2968 ARDOUR_UI::halt_on_xrun_message ()
2969 {
2970         MessageDialog msg (*editor,
2971                            _("Recording was stopped because your system could not keep up."));
2972         msg.run ();
2973 }
2974
2975 void
2976 ARDOUR_UI::xrun_handler(nframes_t where)
2977 {
2978         if (!session) {
2979                 return;
2980         }
2981
2982         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2983
2984         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2985                 create_xrun_marker(where);
2986         }
2987
2988         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2989                 halt_on_xrun_message ();
2990         }
2991 }
2992
2993 bool
2994 ARDOUR_UI::preset_file_exists_handler ()
2995 {
2996         /* if driven from another thread, say "do not overwrite" and show the user nothing.
2997          */
2998
2999         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {        \
3000                 return false;
3001         }
3002         
3003         HBox* hbox = new HBox();
3004         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3005         Gtk::Dialog dialog (_("Preset Exists"), true, false);
3006         Label  message (_("\
3007 A preset with this name already exists for this plugin.\n\
3008 \n\
3009 What you would like to do?\n"));
3010         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3011         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3012         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3013         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3014         dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3015         dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3016         dialog.set_default_response (RESPONSE_ACCEPT);
3017         dialog.set_position (WIN_POS_MOUSE);
3018         dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3019
3020         message.show();
3021         image->show();
3022         hbox->show();
3023
3024         switch (dialog.run ()) {
3025         case RESPONSE_ACCEPT:
3026                 return true;
3027         default:
3028                 return false;
3029         }
3030 }
3031
3032 void
3033 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3034 {
3035         time_t now;
3036         time (&now);
3037
3038         while (disk_buffer_stats.size() > 60) {
3039                 disk_buffer_stats.pop_front ();
3040         }
3041
3042         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3043 }
3044
3045 void
3046 ARDOUR_UI::write_buffer_stats ()
3047 {
3048         std::ofstream fout;
3049         struct tm tm;
3050         char buf[64];
3051         char* path;
3052
3053         if ((path = tempnam (0, "ardourBuffering")) == 0) {
3054                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3055                 return;
3056         }
3057
3058         fout.open (path);
3059
3060         if (!fout) {
3061                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3062                 return;
3063         }
3064
3065         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3066                 localtime_r (&(*i).when, &tm);
3067                 strftime (buf, sizeof (buf), "%T", &tm);
3068                 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3069         }
3070         
3071         disk_buffer_stats.clear ();
3072
3073         fout.close ();
3074
3075         cerr << "Ardour buffering statistics can be found in: " << path << endl;
3076         free (path);
3077 }
3078
3079 void
3080 ARDOUR_UI::disk_overrun_handler ()
3081 {
3082
3083         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3084
3085         write_buffer_stats ();
3086
3087         if (!have_disk_speed_dialog_displayed) {
3088                 have_disk_speed_dialog_displayed = true;
3089                 MessageDialog* msg = new MessageDialog (*editor, _("\
3090 The disk system on your computer\n\
3091 was not able to keep up with Ardour.\n\
3092 \n\
3093 Specifically, it failed to write data to disk\n\
3094 quickly enough to keep up with recording.\n"));
3095                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3096                 msg->show_all ();
3097         }
3098 }
3099
3100 void
3101 ARDOUR_UI::disk_underrun_handler ()
3102 {
3103
3104         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3105
3106         write_buffer_stats ();
3107
3108         if (!have_disk_speed_dialog_displayed) {
3109                 have_disk_speed_dialog_displayed = true;
3110                 MessageDialog* msg = new MessageDialog (*editor,
3111                                    _("The disk system on your computer\n\
3112 was not able to keep up with Ardour.\n\
3113 \n\
3114 Specifically, it failed to read data from disk\n\
3115 quickly enough to keep up with playback.\n"));
3116                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3117                 msg->show_all ();
3118         } 
3119 }
3120
3121 void
3122 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3123 {
3124         have_disk_speed_dialog_displayed = false;
3125         delete msg;
3126 }
3127
3128 void
3129 ARDOUR_UI::session_dialog (std::string msg)
3130 {
3131         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3132         
3133         MessageDialog* d;
3134
3135         if (editor) {
3136                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3137         } else {
3138                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3139         }
3140
3141         d->show_all ();
3142         d->run ();
3143         delete d;
3144 }       
3145
3146 int
3147 ARDOUR_UI::pending_state_dialog ()
3148 {
3149         HBox* hbox = new HBox();
3150         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3151         ArdourDialog dialog (_("Crash Recovery"), true);
3152         Label  message (_("\
3153 This session appears to have been in\n\
3154 middle of recording when ardour or\n\
3155 the computer was shutdown.\n\
3156 \n\
3157 Ardour can recover any captured audio for\n\
3158 you, or it can ignore it. Please decide\n\
3159 what you would like to do.\n"));
3160         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3161         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3162         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3163         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3164         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3165         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3166         dialog.set_default_response (RESPONSE_ACCEPT);
3167         dialog.set_position (WIN_POS_CENTER);
3168         message.show();
3169         image->show();
3170         hbox->show();
3171
3172         pop_back_splash ();
3173
3174         switch (dialog.run ()) {
3175         case RESPONSE_ACCEPT:
3176                 return 1;
3177         default:
3178                 return 0;
3179         }
3180 }
3181
3182 int
3183 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3184 {
3185         HBox* hbox = new HBox();
3186         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3187         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3188         Label  message (string_compose (_("\
3189 This session was created with a sample rate of %1 Hz\n\
3190 \n\
3191 The audioengine is currently running at %2 Hz\n"), desired, actual));
3192
3193         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3194         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3195         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3196         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3197         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3198         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3199         dialog.set_default_response (RESPONSE_ACCEPT);
3200         dialog.set_position (WIN_POS_CENTER);
3201         message.show();
3202         image->show();
3203         hbox->show();
3204
3205         switch (dialog.run ()) {
3206         case RESPONSE_ACCEPT:
3207                 return 0;
3208         default:
3209                 return 1;
3210         }
3211 }
3212
3213         
3214 void
3215 ARDOUR_UI::disconnect_from_jack ()
3216 {
3217         if (engine) {
3218                 if( engine->disconnect_from_jack ()) {
3219                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3220                         msg.run ();
3221                 }
3222
3223                 update_sample_rate (0);
3224         }
3225 }
3226
3227 void
3228 ARDOUR_UI::reconnect_to_jack ()
3229 {
3230         if (engine) {
3231                 if (engine->reconnect_to_jack ()) {
3232                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3233                         msg.run ();
3234                 }
3235
3236                 update_sample_rate (0);
3237         }
3238 }
3239
3240 void
3241 ARDOUR_UI::use_config ()
3242 {
3243         Glib::RefPtr<Action> act;
3244
3245         switch (Config->get_native_file_data_format ()) {
3246         case FormatFloat:
3247                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3248                 break;
3249         case FormatInt24:
3250                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3251                 break;
3252         case FormatInt16:
3253                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3254                 break;
3255         }
3256
3257         if (act) {
3258                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3259                 ract->set_active ();
3260         }       
3261
3262         switch (Config->get_native_file_header_format ()) {
3263         case BWF:
3264                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3265                 break;
3266         case WAVE:
3267                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3268                 break;
3269         case WAVE64:
3270                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3271                 break;
3272         case iXML:
3273                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3274                 break;
3275         case RF64:
3276                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3277                 break;
3278         case CAF:
3279                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3280                 break;
3281         case AIFF:
3282                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3283                 break;
3284         }
3285
3286         if (act) {
3287                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3288                 ract->set_active ();
3289         }       
3290
3291         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3292         if (node) {
3293                 set_transport_controllable_state (*node);
3294         }
3295 }
3296
3297 void
3298 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3299 {
3300         if (Config->get_primary_clock_delta_edit_cursor()) {
3301                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3302         } else {
3303                 primary_clock.set (pos, 0, true);
3304         }
3305
3306         if (Config->get_secondary_clock_delta_edit_cursor()) {
3307                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3308         } else {
3309                 secondary_clock.set (pos);
3310         }
3311
3312         if (big_clock_window) {
3313                 big_clock.set (pos);
3314         }
3315 }
3316
3317 void
3318 ARDOUR_UI::record_state_changed ()
3319 {
3320         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3321
3322         if (!session || !big_clock_window) {
3323                 /* why bother - the clock isn't visible */
3324                 return;
3325         }
3326
3327         switch (session->record_status()) {
3328         case Session::Recording:
3329                 big_clock.set_widget_name ("BigClockRecording");
3330                 break;
3331         default:
3332                 big_clock.set_widget_name ("BigClockNonRecording");
3333                 break;
3334         }
3335 }
3336
3337 bool
3338 ARDOUR_UI::first_idle ()
3339 {
3340         if (session) {
3341                 session->allow_auto_play (true);
3342         }
3343
3344         if (editor) {
3345                 editor->first_idle();
3346         }
3347
3348         Keyboard::set_can_save_keybindings (true);
3349         return false;
3350 }
3351
3352 void
3353 ARDOUR_UI::store_clock_modes ()
3354 {
3355         XMLNode* node = new XMLNode(X_("ClockModes"));
3356
3357         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3358                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3359         }
3360
3361         session->add_extra_xml (*node);
3362         session->set_dirty ();
3363 }
3364
3365
3366                 
3367 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3368         : Controllable (name), ui (u), type(tp)
3369 {
3370         
3371 }
3372
3373 void
3374 ARDOUR_UI::TransportControllable::set_value (float val)
3375 {
3376         if (type == ShuttleControl) {
3377                 double fract;
3378
3379                 if (val == 0.5f) {
3380                         fract = 0.0;
3381                 } else {
3382                         if (val < 0.5f) {
3383                                 fract = -((0.5f - val)/0.5f);
3384                         } else {
3385                                 fract = ((val - 0.5f)/0.5f);
3386                         }
3387                 }
3388                 
3389                 ui.set_shuttle_fract (fract);
3390                 return;
3391         }
3392
3393         if (val < 0.5f) {
3394                 /* do nothing: these are radio-style actions */
3395                 return;
3396         }
3397
3398         const char *action = 0;
3399
3400         switch (type) {
3401         case Roll:
3402                 action = X_("Roll");
3403                 break;
3404         case Stop:
3405                 action = X_("Stop");
3406                 break;
3407         case GotoStart:
3408                 action = X_("Goto Start");
3409                 break;
3410         case GotoEnd:
3411                 action = X_("Goto End");
3412                 break;
3413         case AutoLoop:
3414                 action = X_("Loop");
3415                 break;
3416         case PlaySelection:
3417                 action = X_("Play Selection");
3418                 break;
3419         case RecordEnable:
3420                 action = X_("Record");
3421                 break;
3422         default:
3423                 break;
3424         }
3425
3426         if (action == 0) {
3427                 return;
3428         }
3429
3430         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3431
3432         if (act) {
3433                 act->activate ();
3434         }
3435 }
3436
3437 float
3438 ARDOUR_UI::TransportControllable::get_value (void) const
3439 {
3440         float val = 0.0f;
3441         
3442         switch (type) {
3443         case Roll:
3444                 break;
3445         case Stop:
3446                 break;
3447         case GotoStart:
3448                 break;
3449         case GotoEnd:
3450                 break;
3451         case AutoLoop:
3452                 break;
3453         case PlaySelection:
3454                 break;
3455         case RecordEnable:
3456                 break;
3457         case ShuttleControl:
3458                 break;
3459         default:
3460                 break;
3461         }
3462
3463         return val;
3464 }
3465
3466 void
3467 ARDOUR_UI::TransportControllable::set_id (const string& str)
3468 {
3469         _id = str;
3470 }
3471
3472 void
3473 ARDOUR_UI::setup_profile ()
3474 {
3475         if (gdk_screen_width() < 1200) {
3476                 Profile->set_small_screen ();
3477         }
3478
3479         if (getenv ("ARDOUR_SAE")) {
3480                 Profile->set_sae ();
3481                 Profile->set_single_package ();
3482         }
3483 }
3484