correct check for presence of / or \ in a session name
[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   again:
1855         switch (prompter.run()) {
1856         case RESPONSE_ACCEPT:
1857                 prompter.get_result (snapname);
1858                 if (snapname.length()){
1859                         if (snapname.find ('/') != string::npos) {
1860                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
1861                                                      "snapshot names may not contain a '/' character"));
1862                                 msg.run ();
1863                                 goto again;
1864                         }
1865                         if (snapname.find ('\\') != string::npos) {
1866                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
1867                                                      "snapshot names may not contain a '\\' character"));
1868                                 msg.run ();
1869                                 goto again;
1870                         }
1871                         save_state (snapname);
1872                 }
1873                 break;
1874
1875         default:
1876                 break;
1877         }
1878 }
1879
1880 void
1881 ARDOUR_UI::save_state (const string & name)
1882 {
1883         (void) save_state_canfail (name);
1884 }
1885                 
1886 int
1887 ARDOUR_UI::save_state_canfail (string name)
1888 {
1889         if (session) {
1890                 int ret;
1891
1892                 if (name.length() == 0) {
1893                         name = session->snap_name();
1894                 }
1895
1896                 if ((ret = session->save_state (name)) != 0) {
1897                         return ret;
1898                 }
1899         }
1900         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1901         return 0;
1902 }
1903
1904 void
1905 ARDOUR_UI::primary_clock_value_changed ()
1906 {
1907         if (session) {
1908                 session->request_locate (primary_clock.current_time ());
1909         }
1910 }
1911
1912 void
1913 ARDOUR_UI::big_clock_value_changed ()
1914 {
1915         if (session) {
1916                 session->request_locate (big_clock.current_time ());
1917         }
1918 }
1919
1920 void
1921 ARDOUR_UI::secondary_clock_value_changed ()
1922 {
1923         if (session) {
1924                 session->request_locate (secondary_clock.current_time ());
1925         }
1926 }
1927
1928 void
1929 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1930 {
1931         if (session == 0) {
1932                 return;
1933         }
1934         
1935         switch (session->record_status()) {
1936         case Session::Enabled:
1937                 if (onoff) {
1938                         rec_button.set_visual_state (2);
1939                 } else {
1940                         rec_button.set_visual_state (0);
1941                 }
1942                 break;
1943
1944         case Session::Recording:
1945                 rec_button.set_visual_state (1);
1946                 break;
1947
1948         default:
1949                 rec_button.set_visual_state (0);
1950                 break;
1951         }
1952 }
1953
1954 void
1955 ARDOUR_UI::save_template ()
1956
1957 {
1958         ArdourPrompter prompter (true);
1959         string name;
1960
1961         if (!check_audioengine()) {
1962                 return;
1963         }
1964
1965         prompter.set_name (X_("Prompter"));
1966         prompter.set_prompt (_("Name for mix template:"));
1967         prompter.set_initial_text(session->name() + _("-template"));
1968         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1969
1970         switch (prompter.run()) {
1971         case RESPONSE_ACCEPT:
1972                 prompter.get_result (name);
1973                 
1974                 if (name.length()) {
1975                         session->save_template (name);
1976                 }
1977                 break;
1978
1979         default:
1980                 break;
1981         }
1982 }
1983
1984 void
1985 ARDOUR_UI::fontconfig_dialog ()
1986 {
1987 #ifdef GTKOSX
1988         /* X11 users will always have fontconfig info around, but new GTK-OSX users 
1989            may not and it can take a while to build it. Warn them.
1990         */
1991         
1992         Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1993         
1994         if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1995                 MessageDialog msg (*new_session_dialog,
1996                                    _("Welcome to Ardour.\n\n"
1997                                      "The program will take a bit longer to start up\n"
1998                                      "while the system fonts are checked.\n\n"
1999                                      "This will only be done once, and you will\n"
2000                                      "not see this message again\n"),
2001                                    true,
2002                                    Gtk::MESSAGE_INFO,
2003                                    Gtk::BUTTONS_OK);
2004                 pop_back_splash ();
2005                 msg.show_all ();
2006                 msg.present ();
2007                 msg.run ();
2008         }
2009 #endif
2010 }
2011
2012 void
2013 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2014 {
2015         existing_session = false;
2016
2017         if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2018                 session_path = cmdline_path;
2019                 existing_session = true;
2020         } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2021                 session_path = Glib::path_get_dirname (string (cmdline_path));
2022                 existing_session = true;
2023         } else {
2024                 /* it doesn't exist, assume the best */
2025                 session_path = Glib::path_get_dirname (string (cmdline_path));
2026         }
2027         
2028         session_name = basename_nosuffix (string (cmdline_path));
2029 }
2030
2031 int
2032 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2033 {
2034         /* when this is called, the backend audio system must be running */
2035
2036         /* the main idea here is to deal with the fact that a cmdline argument for the session
2037            can be interpreted in different ways - it could be a directory or a file, and before
2038            we load, we need to know both the session directory and the snapshot (statefile) within it
2039            that we are supposed to use.
2040         */
2041
2042         if (session_name.length() == 0 || session_path.length() == 0) {
2043                 return false;
2044         }
2045         
2046         if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2047
2048                 Glib::ustring predicted_session_file;
2049                 
2050                 predicted_session_file = session_path;
2051                 predicted_session_file += '/';
2052                 predicted_session_file += session_name;
2053                 predicted_session_file += Session::statefile_suffix();
2054                 
2055                 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2056                         existing_session = true;
2057                 }
2058                 
2059         } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2060                 
2061                 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2062                         /* existing .ardour file */
2063                         existing_session = true;
2064                 }
2065
2066         } else {
2067                 existing_session = false;
2068         }
2069         
2070         /* lets just try to load it */
2071         
2072         if (create_engine ()) {
2073                 backend_audio_error (false, new_session_dialog);
2074                 return -1;
2075         }
2076         
2077         return load_session (session_path, session_name);
2078 }
2079
2080 bool
2081 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2082 {
2083         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2084         
2085         MessageDialog msg (str,
2086                            false,
2087                            Gtk::MESSAGE_WARNING,
2088                            Gtk::BUTTONS_YES_NO,
2089                            true);
2090         
2091         
2092         msg.set_name (X_("CleanupDialog"));
2093         msg.set_wmclass (X_("existing_session"), "Ardour");
2094         msg.set_position (Gtk::WIN_POS_MOUSE);
2095         pop_back_splash ();
2096
2097         switch (msg.run()) {
2098         case RESPONSE_YES:
2099                 return true;
2100                 break;
2101         }
2102         return false;
2103 }
2104
2105 int
2106 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2107 {
2108         
2109         uint32_t cchns;
2110         uint32_t mchns;
2111         AutoConnectOption iconnect;
2112         AutoConnectOption oconnect;
2113         uint32_t nphysin;
2114         uint32_t nphysout;
2115         
2116         if (Profile->get_sae()) {
2117                 
2118                 cchns = 0;
2119                 mchns = 2;
2120                 iconnect = AutoConnectPhysical;
2121                 oconnect = AutoConnectMaster;
2122                 nphysin = 0; // use all available
2123                 nphysout = 0; // use all available
2124                 
2125         } else {
2126                 
2127                 /* get settings from advanced section of NSD */
2128                 
2129                 if (new_session_dialog->create_control_bus()) {
2130                         cchns = (uint32_t) new_session_dialog->control_channel_count();
2131                 } else {
2132                         cchns = 0;
2133                 }
2134                 
2135                 if (new_session_dialog->create_master_bus()) {
2136                         mchns = (uint32_t) new_session_dialog->master_channel_count();
2137                 } else {
2138                         mchns = 0;
2139                 }
2140                 
2141                 if (new_session_dialog->connect_inputs()) {
2142                         iconnect = AutoConnectPhysical;
2143                 } else {
2144                         iconnect = AutoConnectOption (0);
2145                 }
2146                 
2147                 /// @todo some minor tweaks.
2148                 
2149                 if (new_session_dialog->connect_outs_to_master()) {
2150                         oconnect = AutoConnectMaster;
2151                 } else if (new_session_dialog->connect_outs_to_physical()) {
2152                         oconnect = AutoConnectPhysical;
2153                 } else {
2154                         oconnect = AutoConnectOption (0);
2155                 } 
2156                 
2157                 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2158                 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2159         }
2160         
2161         if (build_session (session_path,
2162                            session_name,
2163                            cchns,
2164                            mchns,
2165                            iconnect,
2166                            oconnect,
2167                            nphysin,
2168                            nphysout, 
2169                            engine->frame_rate() * 60 * 5)) {
2170                 
2171                 return -1;
2172         }
2173
2174         return 0;
2175 }
2176
2177 void
2178 ARDOUR_UI::end_loading_messages ()
2179 {
2180         // hide_splash ();
2181 }
2182
2183 void
2184 ARDOUR_UI::loading_message (const std::string& msg)
2185 {
2186         show_splash ();
2187         splash->message (msg);
2188         flush_pending ();
2189 }
2190
2191 void
2192 ARDOUR_UI::idle_load (const Glib::ustring& path)
2193 {
2194         if (session) {
2195                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2196                         /* /path/to/foo => /path/to/foo, foo */
2197                         load_session (path, basename_nosuffix (path));
2198                 } else {
2199                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2200                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2201                 }
2202         } else {
2203
2204                 ARDOUR_COMMAND_LINE::session_name = path;
2205
2206                 if (new_session_dialog) {
2207
2208
2209                         /* make it break out of Dialog::run() and
2210                            start again.
2211                          */
2212
2213                         new_session_dialog->response (1);
2214                 }
2215         }
2216 }
2217
2218 bool
2219 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2220 {
2221         bool existing_session = false;
2222         Glib::ustring session_name;
2223         Glib::ustring session_path;
2224         Glib::ustring template_name;
2225         int response;
2226         
2227   begin:
2228         response = Gtk::RESPONSE_NONE;
2229
2230         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2231
2232                 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2233
2234                 /* don't ever reuse this */
2235
2236                 ARDOUR_COMMAND_LINE::session_name = string();
2237
2238                 if (existing_session && backend_audio_is_running) {
2239
2240                         /* just load the thing already */
2241
2242                         if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2243                                 return true;
2244                         }
2245                 }
2246
2247                 /* make the NSD use whatever information we have */
2248
2249                 new_session_dialog->set_session_name (session_name);
2250                 new_session_dialog->set_session_folder (session_path);
2251         }
2252
2253         /* loading failed, or we need the NSD for something */
2254
2255         new_session_dialog->set_modal (false);
2256         new_session_dialog->set_position (WIN_POS_CENTER);
2257         new_session_dialog->set_current_page (0);
2258         new_session_dialog->set_existing_session (existing_session);
2259         new_session_dialog->reset_recent();
2260
2261         do {
2262                 new_session_dialog->set_have_engine (backend_audio_is_running);
2263                 new_session_dialog->present ();
2264                 response = new_session_dialog->run ();
2265                 
2266                 _session_is_new = false;
2267                 
2268                 /* handle possible negative responses */
2269
2270                 switch (response) {
2271                 case 1:
2272                         /* sent by idle_load, meaning restart the whole process again */
2273                         new_session_dialog->hide();
2274                         new_session_dialog->reset();
2275                         goto begin;
2276                         break;
2277
2278                 case Gtk::RESPONSE_CANCEL:
2279                 case Gtk::RESPONSE_DELETE_EVENT:
2280                         if (!session) {
2281                                 if (engine && engine->running()) {
2282                                         engine->stop (true);
2283                                 }
2284                                 quit();
2285                         }
2286                         new_session_dialog->hide ();
2287                         return false;
2288                         
2289                 case Gtk::RESPONSE_NONE:
2290                         /* "Clear" was pressed */
2291                         goto try_again;
2292                 }
2293
2294                 fontconfig_dialog();
2295
2296                 if (!backend_audio_is_running) {
2297                         int ret = new_session_dialog->engine_control.setup_engine ();
2298                         if (ret < 0) {
2299                                 return false;
2300                         } else if (ret > 0) {
2301                                 response = Gtk::RESPONSE_REJECT;
2302                                 goto try_again;
2303                         }
2304                 }
2305                 
2306                 if (create_engine ()) {
2307
2308                         backend_audio_error (!backend_audio_is_running, new_session_dialog);
2309                         flush_pending ();
2310
2311                         new_session_dialog->set_existing_session (false);
2312                         new_session_dialog->set_current_page (2);
2313
2314                         response = Gtk::RESPONSE_NONE;
2315                         goto try_again;
2316                 }
2317
2318                 backend_audio_is_running = true;                
2319                         
2320                 if (response == Gtk::RESPONSE_OK) {
2321
2322                         session_name = new_session_dialog->session_name();
2323                         
2324                         if (session_name.empty()) {
2325                                 response = Gtk::RESPONSE_NONE;
2326                                 goto try_again;
2327                         } 
2328
2329                         /* if the user mistakenly typed path information into the session filename entry,
2330                            convert what they typed into a path & a name
2331                         */
2332                         
2333                         if (session_name[0] == '/' || 
2334                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2335                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2336
2337                                 session_path = Glib::path_get_dirname (session_name);
2338                                 session_name = Glib::path_get_basename (session_name);
2339                                 
2340                         } else {
2341                                 
2342                                 session_path = new_session_dialog->session_folder();
2343                         }
2344
2345                         template_name = Glib::ustring();                        
2346                         switch (new_session_dialog->which_page()) {
2347
2348                         case NewSessionDialog::OpenPage: 
2349                         case NewSessionDialog::EnginePage:
2350                                 goto loadit;
2351                                 break;
2352
2353                         case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2354                                 
2355                                 should_be_new = true;
2356
2357                                 if (session_name.find ('/') != Glib::ustring::npos) {
2358                                         MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2359                                                          "session names may not contain a '/' character"));
2360                                         msg.run ();
2361                                         response = RESPONSE_NONE;
2362                                         goto try_again;
2363                                 }
2364
2365                                 if (session_name.find ('\\') != Glib::ustring::npos) {
2366                                         MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2367                                                          "session names may not contain a '\\' character"));
2368                                         msg.run ();
2369                                         response = RESPONSE_NONE;
2370                                         goto try_again;
2371                                 }
2372
2373                                 //XXX This is needed because session constructor wants a 
2374                                 //non-existant path. hopefully this will be fixed at some point.
2375
2376                                 session_path = Glib::build_filename (session_path, session_name);
2377
2378                                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2379
2380                                         if (ask_about_loading_existing_session (session_path)) {
2381                                                 goto loadit;
2382                                         } else {
2383                                                 response = RESPONSE_NONE;
2384                                                 goto try_again;
2385                                         } 
2386                                 }
2387
2388                                 _session_is_new = true;
2389                                                 
2390                                 if (new_session_dialog->use_session_template()) {
2391
2392                                         template_name = new_session_dialog->session_template_name();
2393                                         goto loadit;
2394                           
2395                                 } else {
2396                                         if (build_session_from_nsd (session_path, session_name)) {
2397                                                 response = RESPONSE_NONE;
2398                                                 goto try_again;
2399                                         }
2400                                         goto done;
2401                                 }
2402                                 break;
2403                                 
2404                         default:
2405                                 break;
2406                         }
2407                         
2408                   loadit:
2409                         new_session_dialog->hide ();
2410
2411                         if (load_session (session_path, session_name, template_name)) {
2412                                 /* force a retry */
2413                                 response = Gtk::RESPONSE_NONE;
2414                         }
2415
2416                   try_again:
2417                         if (response == Gtk::RESPONSE_NONE) {
2418                                 new_session_dialog->set_existing_session (false);
2419                                 new_session_dialog->reset ();
2420                         }
2421                 }
2422
2423         } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2424
2425   done:
2426         show();
2427         new_session_dialog->hide();
2428         new_session_dialog->reset();
2429         goto_editor_window ();
2430         return true;
2431 }       
2432
2433 void
2434 ARDOUR_UI::close_session ()
2435 {
2436         if (!check_audioengine()) {
2437                 return;
2438         }
2439
2440         if (unload_session (true)) {
2441                 return;
2442         }
2443         
2444         get_session_parameters (true, false);
2445 }
2446
2447 int
2448 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2449 {
2450         Session *new_session;
2451         int unload_status;
2452         int retval = -1;
2453
2454         session_loaded = false;
2455
2456         if (!check_audioengine()) {
2457                 return -1;
2458         }
2459
2460         unload_status = unload_session ();
2461
2462         if (unload_status < 0) {
2463                 goto out;
2464         } else if (unload_status > 0) {
2465                 retval = 0;
2466                 goto out;
2467         }
2468
2469         /* if it already exists, we must have write access */
2470
2471         if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2472                 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2473                                               "This prevents the session from being loaded."));
2474                 pop_back_splash ();
2475                 msg.run ();
2476                 goto out;
2477         }
2478
2479         loading_message (_("Please wait while Ardour loads your session"));
2480
2481         try {
2482                 new_session = new Session (*engine, path, snap_name, mix_template);
2483         }
2484
2485         /* this one is special */
2486
2487         catch (AudioEngine::PortRegistrationFailure& err) {
2488
2489                 MessageDialog msg (err.what(),
2490                                    true,
2491                                    Gtk::MESSAGE_INFO,
2492                                    Gtk::BUTTONS_CLOSE);
2493                 
2494                 msg.set_title (_("Port Registration Error"));
2495                 msg.set_secondary_text (_("Click the Close button to try again."));
2496                 msg.set_position (Gtk::WIN_POS_CENTER);
2497                 pop_back_splash ();
2498                 msg.present ();
2499
2500                 int response = msg.run ();
2501
2502                 msg.hide ();
2503
2504                 switch (response) {
2505                 case RESPONSE_CANCEL:
2506                         exit (1);
2507                 default:
2508                         break;
2509                 }
2510                 goto out;
2511         }
2512
2513         catch (...) {
2514
2515                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2516                                    true,
2517                                    Gtk::MESSAGE_INFO,
2518                                    Gtk::BUTTONS_CLOSE);
2519                 
2520                 msg.set_title (_("Loading Error"));
2521                 msg.set_secondary_text (_("Click the Close button to try again."));
2522                 msg.set_position (Gtk::WIN_POS_CENTER);
2523                 pop_back_splash ();
2524                 msg.present ();
2525
2526                 int response = msg.run ();
2527
2528                 msg.hide ();
2529
2530                 switch (response) {
2531                 case RESPONSE_CANCEL:
2532                         exit (1);
2533                 default:
2534                         break;
2535                 }
2536                 goto out;
2537         }
2538
2539         connect_to_session (new_session);
2540
2541         Config->set_current_owner (ConfigVariableBase::Interface);
2542
2543         session_loaded = true;
2544         
2545         goto_editor_window ();
2546
2547         if (session) {
2548                 session->set_clean ();
2549         }
2550
2551         flush_pending ();
2552         retval = 0;
2553
2554   out:
2555         return retval;
2556 }
2557
2558 int
2559 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, 
2560                           uint32_t control_channels,
2561                           uint32_t master_channels, 
2562                           AutoConnectOption input_connect,
2563                           AutoConnectOption output_connect,
2564                           uint32_t nphysin,
2565                           uint32_t nphysout,
2566                           nframes_t initial_length)
2567 {
2568         Session *new_session;
2569         int x;
2570
2571         if (!check_audioengine()) {
2572                 return -1;
2573         }
2574
2575         session_loaded = false;
2576
2577         x = unload_session ();
2578
2579         if (x < 0) {
2580                 return -1;
2581         } else if (x > 0) {
2582                 return 0;
2583         }
2584         
2585         _session_is_new = true;
2586
2587         try {
2588                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2589                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2590         }
2591
2592         catch (...) {
2593
2594                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2595                 pop_back_splash ();
2596                 msg.run ();
2597                 return -1;
2598         }
2599
2600         connect_to_session (new_session);
2601
2602         session_loaded = true;
2603
2604         new_session->save_state(new_session->name());
2605
2606         return 0;
2607 }
2608
2609 void
2610 ARDOUR_UI::show ()
2611 {
2612         if (editor) {
2613                 editor->show_window ();
2614                 
2615                 if (!shown_flag) {
2616                         editor->present ();
2617                 }
2618
2619                 shown_flag = true;
2620         }
2621 }
2622
2623 void
2624 ARDOUR_UI::show_about ()
2625 {
2626         if (about == 0) {
2627                 about = new About;
2628                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2629         }
2630
2631         about->show_all ();
2632 }
2633
2634 void
2635 ARDOUR_UI::launch_chat ()
2636 {
2637 #ifdef __APPLE__
2638         NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2639 #else
2640         NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2641 #endif
2642 }
2643
2644 void
2645 ARDOUR_UI::hide_about ()
2646 {
2647         if (about) {
2648                 about->get_window()->set_cursor ();
2649                 about->hide ();
2650         }
2651 }
2652
2653 void
2654 ARDOUR_UI::about_signal_response(int response)
2655 {
2656         hide_about();
2657 }
2658
2659 void
2660 ARDOUR_UI::show_splash ()
2661 {
2662         if (splash == 0) {
2663                 try {
2664                         splash = new Splash;
2665                 } catch (...) {
2666                         return;
2667                 }
2668         }
2669
2670         splash->show ();
2671         splash->present ();
2672         splash->queue_draw ();
2673         splash->get_window()->process_updates (true);
2674         flush_pending ();
2675 }
2676
2677 void
2678 ARDOUR_UI::hide_splash ()
2679 {
2680         if (splash) {
2681                 splash->hide();
2682         }
2683 }
2684
2685 void
2686 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2687 {
2688         size_t removed;
2689
2690         removed = rep.paths.size();
2691
2692         if (removed == 0) {
2693                 MessageDialog msgd (*editor,
2694                                     _("No audio files were ready for cleanup"), 
2695                                     true,
2696                                     Gtk::MESSAGE_INFO,
2697                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2698                 msgd.set_secondary_text (_("If this seems suprising, \n\
2699 check for any existing snapshots.\n\
2700 These may still include regions that\n\
2701 require some unused files to continue to exist."));
2702         
2703                 msgd.run ();
2704                 return;
2705         } 
2706
2707         ArdourDialog results (_("ardour: cleanup"), true, false);
2708         
2709         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2710             CleanupResultsModelColumns() { 
2711                     add (visible_name);
2712                     add (fullpath);
2713             }
2714             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2715             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2716         };
2717
2718         
2719         CleanupResultsModelColumns results_columns;
2720         Glib::RefPtr<Gtk::ListStore> results_model;
2721         Gtk::TreeView results_display;
2722         
2723         results_model = ListStore::create (results_columns);
2724         results_display.set_model (results_model);
2725         results_display.append_column (list_title, results_columns.visible_name);
2726
2727         results_display.set_name ("CleanupResultsList");
2728         results_display.set_headers_visible (true);
2729         results_display.set_headers_clickable (false);
2730         results_display.set_reorderable (false);
2731
2732         Gtk::ScrolledWindow list_scroller;
2733         Gtk::Label txt;
2734         Gtk::VBox dvbox;
2735         Gtk::HBox dhbox;  // the hbox for the image and text
2736         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2737         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2738
2739         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2740
2741         if (rep.space < 1048576.0f) {
2742                 if (removed > 1) {
2743                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2744                 } else {
2745                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2746                 }
2747         } else {
2748                 if (removed > 1) {
2749                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2750                 } else {
2751                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2752                 }
2753         }
2754
2755         dhbox.pack_start (*dimage, true, false, 5);
2756         dhbox.pack_start (txt, true, false, 5);
2757
2758         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2759                 TreeModel::Row row = *(results_model->append());
2760                 row[results_columns.visible_name] = *i;
2761                 row[results_columns.fullpath] = *i;
2762         }
2763         
2764         list_scroller.add (results_display);
2765         list_scroller.set_size_request (-1, 150);
2766         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2767
2768         dvbox.pack_start (dhbox, true, false, 5);
2769         dvbox.pack_start (list_scroller, true, false, 5);
2770         ddhbox.pack_start (dvbox, true, false, 5);
2771
2772         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2773         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2774         results.set_default_response (RESPONSE_CLOSE);
2775         results.set_position (Gtk::WIN_POS_MOUSE);
2776         results.show_all_children ();
2777         results.set_resizable (false);
2778
2779         results.run ();
2780
2781 }
2782
2783 void
2784 ARDOUR_UI::cleanup ()
2785 {
2786         if (session == 0) {
2787                 /* shouldn't happen: menu item is insensitive */
2788                 return;
2789         }
2790
2791
2792         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2793                                 true,
2794                                 Gtk::MESSAGE_QUESTION,
2795                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2796
2797         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2798 ALL undo/redo information will be lost if you cleanup.\n\
2799 After cleanup, unused audio files will be moved to a \
2800 \"dead sounds\" location."));
2801         
2802         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2803         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2804         checker.set_default_response (RESPONSE_CANCEL);
2805
2806         checker.set_name (_("CleanupDialog"));
2807         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2808         checker.set_position (Gtk::WIN_POS_MOUSE);
2809
2810         switch (checker.run()) {
2811         case RESPONSE_ACCEPT:
2812                 break;
2813         default:
2814                 return;
2815         }
2816
2817         Session::cleanup_report rep;
2818
2819         editor->prepare_for_cleanup ();
2820
2821         /* do not allow flush until a session is reloaded */
2822
2823         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2824         if (act) {
2825                 act->set_sensitive (false);
2826         }
2827
2828         if (session->cleanup_sources (rep)) {
2829                 editor->finish_cleanup ();
2830                 return;
2831         }
2832         
2833         editor->finish_cleanup ();
2834
2835         checker.hide();
2836         display_cleanup_results (rep, 
2837                                  _("cleaned files"),
2838                                  _("\
2839 The following %1 %2 not in use and \n\
2840 have been moved to:\n\
2841 %3. \n\n\
2842 Flushing the wastebasket will \n\
2843 release an additional\n\
2844 %4 %5bytes of disk space.\n"
2845                                          ));
2846
2847 }
2848
2849 void
2850 ARDOUR_UI::flush_trash ()
2851 {
2852         if (session == 0) {
2853                 /* shouldn't happen: menu item is insensitive */
2854                 return;
2855         }
2856
2857         Session::cleanup_report rep;
2858
2859         if (session->cleanup_trash_sources (rep)) {
2860                 return;
2861         }
2862
2863         display_cleanup_results (rep, 
2864                                  _("deleted file"),
2865                                  _("The following %1 %2 deleted from\n\
2866 %3,\n\
2867 releasing %4 %5bytes of disk space"));
2868 }
2869
2870 void
2871 ARDOUR_UI::add_route (Gtk::Window* float_window)
2872 {
2873         int count;
2874
2875         if (!session) {
2876                 return;
2877         }
2878
2879         if (add_route_dialog == 0) {
2880                 add_route_dialog = new AddRouteDialog;
2881                 if (float_window) {
2882                         add_route_dialog->set_transient_for (*float_window);
2883                 }
2884         }
2885
2886         if (add_route_dialog->is_visible()) {
2887                 /* we're already doing this */
2888                 return;
2889         }
2890
2891         ResponseType r = (ResponseType) add_route_dialog->run ();
2892         
2893         add_route_dialog->hide();
2894
2895         switch (r) {
2896         case RESPONSE_ACCEPT:
2897                 break;
2898         default:
2899                 return;
2900                 break;
2901         }
2902
2903         if ((count = add_route_dialog->count()) <= 0) {
2904                 return;
2905         }
2906
2907         string template_path = add_route_dialog->track_template();
2908
2909         if (!template_path.empty()) {
2910           session->new_route_from_template (count, template_path);
2911           return;
2912         }
2913         
2914         uint32_t input_chan = add_route_dialog->channels ();
2915         uint32_t output_chan;
2916         string name_template = add_route_dialog->name_template ();
2917         bool track = add_route_dialog->track ();
2918
2919         AutoConnectOption oac = Config->get_output_auto_connect();
2920
2921         if (oac & AutoConnectMaster) {
2922                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2923         } else {
2924                 output_chan = input_chan;
2925         }
2926
2927         /* XXX do something with name template */
2928
2929         if (track) {
2930                 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2931         } else {
2932                 session_add_audio_bus (input_chan, output_chan, count);
2933         }
2934 }
2935
2936 XMLNode*
2937 ARDOUR_UI::mixer_settings () const
2938 {
2939         XMLNode* node = 0;
2940
2941         if (session) {
2942                 node = session->instant_xml(X_("Mixer"), session->path());
2943         } else {
2944                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2945         }
2946
2947         if (!node) {
2948                 node = new XMLNode (X_("Mixer"));
2949         }
2950
2951         return node;
2952 }
2953
2954 XMLNode*
2955 ARDOUR_UI::editor_settings () const
2956 {
2957         XMLNode* node = 0;
2958
2959         if (session) {
2960                 node = session->instant_xml(X_("Editor"), session->path());
2961         } else {
2962                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2963         }
2964         
2965         if (!node) {
2966                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2967                         node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2968                 }
2969         }
2970
2971         if (!node) {
2972                 node = new XMLNode (X_("Editor"));
2973         }
2974         return node;
2975 }
2976
2977 XMLNode*
2978 ARDOUR_UI::keyboard_settings () const
2979 {
2980         XMLNode* node = 0;
2981
2982         node = Config->extra_xml(X_("Keyboard"));
2983         
2984         if (!node) {
2985                 node = new XMLNode (X_("Keyboard"));
2986         }
2987         return node;
2988 }
2989
2990 void
2991 ARDOUR_UI::create_xrun_marker(nframes_t where)
2992 {
2993         editor->mouse_add_new_marker (where, false, true);
2994 }
2995
2996 void
2997 ARDOUR_UI::halt_on_xrun_message ()
2998 {
2999         MessageDialog msg (*editor,
3000                            _("Recording was stopped because your system could not keep up."));
3001         msg.run ();
3002 }
3003
3004 void
3005 ARDOUR_UI::xrun_handler(nframes_t where)
3006 {
3007         if (!session) {
3008                 return;
3009         }
3010
3011         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3012
3013         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3014                 create_xrun_marker(where);
3015         }
3016
3017         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3018                 halt_on_xrun_message ();
3019         }
3020 }
3021
3022 bool
3023 ARDOUR_UI::preset_file_exists_handler ()
3024 {
3025         /* if driven from another thread, say "do not overwrite" and show the user nothing.
3026          */
3027
3028         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {        \
3029                 return false;
3030         }
3031         
3032         HBox* hbox = new HBox();
3033         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3034         Gtk::Dialog dialog (_("Preset Exists"), true, false);
3035         Label  message (_("\
3036 A preset with this name already exists for this plugin.\n\
3037 \n\
3038 What you would like to do?\n"));
3039         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3040         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3041         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3042         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3043         dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3044         dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3045         dialog.set_default_response (RESPONSE_ACCEPT);
3046         dialog.set_position (WIN_POS_MOUSE);
3047         dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3048
3049         message.show();
3050         image->show();
3051         hbox->show();
3052
3053         switch (dialog.run ()) {
3054         case RESPONSE_ACCEPT:
3055                 return true;
3056         default:
3057                 return false;
3058         }
3059 }
3060
3061 void
3062 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3063 {
3064         time_t now;
3065         time (&now);
3066
3067         while (disk_buffer_stats.size() > 60) {
3068                 disk_buffer_stats.pop_front ();
3069         }
3070
3071         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3072 }
3073
3074 void
3075 ARDOUR_UI::write_buffer_stats ()
3076 {
3077         std::ofstream fout;
3078         struct tm tm;
3079         char buf[64];
3080         char* path;
3081
3082         if ((path = tempnam (0, "ardourBuffering")) == 0) {
3083                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3084                 return;
3085         }
3086
3087         fout.open (path);
3088
3089         if (!fout) {
3090                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3091                 return;
3092         }
3093
3094         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3095                 localtime_r (&(*i).when, &tm);
3096                 strftime (buf, sizeof (buf), "%T", &tm);
3097                 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3098         }
3099         
3100         disk_buffer_stats.clear ();
3101
3102         fout.close ();
3103
3104         cerr << "Ardour buffering statistics can be found in: " << path << endl;
3105         free (path);
3106 }
3107
3108 void
3109 ARDOUR_UI::disk_overrun_handler ()
3110 {
3111
3112         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3113
3114         write_buffer_stats ();
3115
3116         if (!have_disk_speed_dialog_displayed) {
3117                 have_disk_speed_dialog_displayed = true;
3118                 MessageDialog* msg = new MessageDialog (*editor, _("\
3119 The disk system on your computer\n\
3120 was not able to keep up with Ardour.\n\
3121 \n\
3122 Specifically, it failed to write data to disk\n\
3123 quickly enough to keep up with recording.\n"));
3124                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3125                 msg->show_all ();
3126         }
3127 }
3128
3129 void
3130 ARDOUR_UI::disk_underrun_handler ()
3131 {
3132
3133         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3134
3135         write_buffer_stats ();
3136
3137         if (!have_disk_speed_dialog_displayed) {
3138                 have_disk_speed_dialog_displayed = true;
3139                 MessageDialog* msg = new MessageDialog (*editor,
3140                                    _("The disk system on your computer\n\
3141 was not able to keep up with Ardour.\n\
3142 \n\
3143 Specifically, it failed to read data from disk\n\
3144 quickly enough to keep up with playback.\n"));
3145                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3146                 msg->show_all ();
3147         } 
3148 }
3149
3150 void
3151 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3152 {
3153         have_disk_speed_dialog_displayed = false;
3154         delete msg;
3155 }
3156
3157 void
3158 ARDOUR_UI::session_dialog (std::string msg)
3159 {
3160         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3161         
3162         MessageDialog* d;
3163
3164         if (editor) {
3165                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3166         } else {
3167                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3168         }
3169
3170         d->show_all ();
3171         d->run ();
3172         delete d;
3173 }       
3174
3175 int
3176 ARDOUR_UI::pending_state_dialog ()
3177 {
3178         HBox* hbox = new HBox();
3179         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3180         ArdourDialog dialog (_("Crash Recovery"), true);
3181         Label  message (_("\
3182 This session appears to have been in\n\
3183 middle of recording when ardour or\n\
3184 the computer was shutdown.\n\
3185 \n\
3186 Ardour can recover any captured audio for\n\
3187 you, or it can ignore it. Please decide\n\
3188 what you would like to do.\n"));
3189         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3190         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3191         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3192         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3193         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3194         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3195         dialog.set_default_response (RESPONSE_ACCEPT);
3196         dialog.set_position (WIN_POS_CENTER);
3197         message.show();
3198         image->show();
3199         hbox->show();
3200
3201         pop_back_splash ();
3202
3203         switch (dialog.run ()) {
3204         case RESPONSE_ACCEPT:
3205                 return 1;
3206         default:
3207                 return 0;
3208         }
3209 }
3210
3211 int
3212 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3213 {
3214         HBox* hbox = new HBox();
3215         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3216         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3217         Label  message (string_compose (_("\
3218 This session was created with a sample rate of %1 Hz\n\
3219 \n\
3220 The audioengine is currently running at %2 Hz\n"), desired, actual));
3221
3222         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3223         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3224         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3225         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3226         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3227         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3228         dialog.set_default_response (RESPONSE_ACCEPT);
3229         dialog.set_position (WIN_POS_CENTER);
3230         message.show();
3231         image->show();
3232         hbox->show();
3233
3234         switch (dialog.run ()) {
3235         case RESPONSE_ACCEPT:
3236                 return 0;
3237         default:
3238                 return 1;
3239         }
3240 }
3241
3242         
3243 void
3244 ARDOUR_UI::disconnect_from_jack ()
3245 {
3246         if (engine) {
3247                 if( engine->disconnect_from_jack ()) {
3248                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3249                         msg.run ();
3250                 }
3251
3252                 update_sample_rate (0);
3253         }
3254 }
3255
3256 void
3257 ARDOUR_UI::reconnect_to_jack ()
3258 {
3259         if (engine) {
3260                 if (engine->reconnect_to_jack ()) {
3261                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3262                         msg.run ();
3263                 }
3264
3265                 update_sample_rate (0);
3266         }
3267 }
3268
3269 void
3270 ARDOUR_UI::use_config ()
3271 {
3272         Glib::RefPtr<Action> act;
3273
3274         switch (Config->get_native_file_data_format ()) {
3275         case FormatFloat:
3276                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3277                 break;
3278         case FormatInt24:
3279                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3280                 break;
3281         case FormatInt16:
3282                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
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         switch (Config->get_native_file_header_format ()) {
3292         case BWF:
3293                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3294                 break;
3295         case WAVE:
3296                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3297                 break;
3298         case WAVE64:
3299                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3300                 break;
3301         case iXML:
3302                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3303                 break;
3304         case RF64:
3305                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3306                 break;
3307         case CAF:
3308                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3309                 break;
3310         case AIFF:
3311                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3312                 break;
3313         }
3314
3315         if (act) {
3316                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3317                 ract->set_active ();
3318         }       
3319
3320         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3321         if (node) {
3322                 set_transport_controllable_state (*node);
3323         }
3324 }
3325
3326 void
3327 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3328 {
3329         if (Config->get_primary_clock_delta_edit_cursor()) {
3330                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3331         } else {
3332                 primary_clock.set (pos, 0, true);
3333         }
3334
3335         if (Config->get_secondary_clock_delta_edit_cursor()) {
3336                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3337         } else {
3338                 secondary_clock.set (pos);
3339         }
3340
3341         if (big_clock_window) {
3342                 big_clock.set (pos);
3343         }
3344 }
3345
3346 void
3347 ARDOUR_UI::record_state_changed ()
3348 {
3349         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3350
3351         if (!session || !big_clock_window) {
3352                 /* why bother - the clock isn't visible */
3353                 return;
3354         }
3355
3356         switch (session->record_status()) {
3357         case Session::Recording:
3358                 big_clock.set_widget_name ("BigClockRecording");
3359                 break;
3360         default:
3361                 big_clock.set_widget_name ("BigClockNonRecording");
3362                 break;
3363         }
3364 }
3365
3366 bool
3367 ARDOUR_UI::first_idle ()
3368 {
3369         if (session) {
3370                 session->allow_auto_play (true);
3371         }
3372
3373         if (editor) {
3374                 editor->first_idle();
3375         }
3376
3377         Keyboard::set_can_save_keybindings (true);
3378         return false;
3379 }
3380
3381 void
3382 ARDOUR_UI::store_clock_modes ()
3383 {
3384         XMLNode* node = new XMLNode(X_("ClockModes"));
3385
3386         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3387                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3388         }
3389
3390         session->add_extra_xml (*node);
3391         session->set_dirty ();
3392 }
3393
3394
3395                 
3396 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3397         : Controllable (name), ui (u), type(tp)
3398 {
3399         
3400 }
3401
3402 void
3403 ARDOUR_UI::TransportControllable::set_value (float val)
3404 {
3405         if (type == ShuttleControl) {
3406                 double fract;
3407
3408                 if (val == 0.5f) {
3409                         fract = 0.0;
3410                 } else {
3411                         if (val < 0.5f) {
3412                                 fract = -((0.5f - val)/0.5f);
3413                         } else {
3414                                 fract = ((val - 0.5f)/0.5f);
3415                         }
3416                 }
3417                 
3418                 ui.set_shuttle_fract (fract);
3419                 return;
3420         }
3421
3422         if (val < 0.5f) {
3423                 /* do nothing: these are radio-style actions */
3424                 return;
3425         }
3426
3427         const char *action = 0;
3428
3429         switch (type) {
3430         case Roll:
3431                 action = X_("Roll");
3432                 break;
3433         case Stop:
3434                 action = X_("Stop");
3435                 break;
3436         case GotoStart:
3437                 action = X_("Goto Start");
3438                 break;
3439         case GotoEnd:
3440                 action = X_("Goto End");
3441                 break;
3442         case AutoLoop:
3443                 action = X_("Loop");
3444                 break;
3445         case PlaySelection:
3446                 action = X_("Play Selection");
3447                 break;
3448         case RecordEnable:
3449                 action = X_("Record");
3450                 break;
3451         default:
3452                 break;
3453         }
3454
3455         if (action == 0) {
3456                 return;
3457         }
3458
3459         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3460
3461         if (act) {
3462                 act->activate ();
3463         }
3464 }
3465
3466 float
3467 ARDOUR_UI::TransportControllable::get_value (void) const
3468 {
3469         float val = 0.0f;
3470         
3471         switch (type) {
3472         case Roll:
3473                 break;
3474         case Stop:
3475                 break;
3476         case GotoStart:
3477                 break;
3478         case GotoEnd:
3479                 break;
3480         case AutoLoop:
3481                 break;
3482         case PlaySelection:
3483                 break;
3484         case RecordEnable:
3485                 break;
3486         case ShuttleControl:
3487                 break;
3488         default:
3489                 break;
3490         }
3491
3492         return val;
3493 }
3494
3495 void
3496 ARDOUR_UI::TransportControllable::set_id (const string& str)
3497 {
3498         _id = str;
3499 }
3500
3501 void
3502 ARDOUR_UI::setup_profile ()
3503 {
3504         if (gdk_screen_width() < 1200) {
3505                 Profile->set_small_screen ();
3506         }
3507
3508         if (getenv ("ARDOUR_SAE")) {
3509                 Profile->set_sae ();
3510                 Profile->set_single_package ();
3511         }
3512 }
3513