patch from lucus for wastebasket content size message
[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, 
2687                                     const string& plural_msg, const string& singular_msg)
2688 {
2689         size_t removed;
2690
2691         removed = rep.paths.size();
2692
2693         if (removed == 0) {
2694                 MessageDialog msgd (*editor,
2695                                     _("No audio files were ready for cleanup"), 
2696                                     true,
2697                                     Gtk::MESSAGE_INFO,
2698                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2699                 msgd.set_secondary_text (_("If this seems suprising, \n\
2700 check for any existing snapshots.\n\
2701 These may still include regions that\n\
2702 require some unused files to continue to exist."));
2703         
2704                 msgd.run ();
2705                 return;
2706         } 
2707
2708         ArdourDialog results (_("ardour: cleanup"), true, false);
2709         
2710         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2711             CleanupResultsModelColumns() { 
2712                     add (visible_name);
2713                     add (fullpath);
2714             }
2715             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2716             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2717         };
2718
2719         
2720         CleanupResultsModelColumns results_columns;
2721         Glib::RefPtr<Gtk::ListStore> results_model;
2722         Gtk::TreeView results_display;
2723         
2724         results_model = ListStore::create (results_columns);
2725         results_display.set_model (results_model);
2726         results_display.append_column (list_title, results_columns.visible_name);
2727
2728         results_display.set_name ("CleanupResultsList");
2729         results_display.set_headers_visible (true);
2730         results_display.set_headers_clickable (false);
2731         results_display.set_reorderable (false);
2732
2733         Gtk::ScrolledWindow list_scroller;
2734         Gtk::Label txt;
2735         Gtk::VBox dvbox;
2736         Gtk::HBox dhbox;  // the hbox for the image and text
2737         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2738         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2739
2740         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2741
2742
2743         /* subst:
2744            %1 - number of files removed
2745            %2 - location of "dead_sounds"
2746            %3 - size of files affected
2747            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2748         */
2749
2750         const char* bprefix;
2751         float space_adjusted;
2752
2753         if (rep.space < 1000000.0f) {
2754                 bprefix = X_("kilo");
2755                 space_adjusted = truncf((float)rep.space / 1000.0f);
2756         } else if (rep.space < (1000000.0f * 1000)) {
2757                 bprefix = X_("mega");
2758                 space_adjusted = truncf((float)rep.space / (1000000.0f));
2759         } else {
2760                 bprefix = X_("giga");
2761                 space_adjusted = truncf((float)rep.space / (1000000.0f * 1000));
2762         }
2763
2764         if (removed > 1) {
2765                 txt.set_text (string_compose (plural_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2766         } else {
2767                 txt.set_text (string_compose (singular_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2768         }
2769
2770         dhbox.pack_start (*dimage, true, false, 5);
2771         dhbox.pack_start (txt, true, false, 5);
2772
2773         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2774                 TreeModel::Row row = *(results_model->append());
2775                 row[results_columns.visible_name] = *i;
2776                 row[results_columns.fullpath] = *i;
2777         }
2778         
2779         list_scroller.add (results_display);
2780         list_scroller.set_size_request (-1, 150);
2781         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2782
2783         dvbox.pack_start (dhbox, true, false, 5);
2784         dvbox.pack_start (list_scroller, true, false, 5);
2785         ddhbox.pack_start (dvbox, true, false, 5);
2786
2787         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2788         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2789         results.set_default_response (RESPONSE_CLOSE);
2790         results.set_position (Gtk::WIN_POS_MOUSE);
2791         results.show_all_children ();
2792         results.set_resizable (false);
2793
2794         results.run ();
2795
2796 }
2797
2798 void
2799 ARDOUR_UI::cleanup ()
2800 {
2801         if (session == 0) {
2802                 /* shouldn't happen: menu item is insensitive */
2803                 return;
2804         }
2805
2806
2807         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2808                                 true,
2809                                 Gtk::MESSAGE_QUESTION,
2810                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2811
2812         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2813 ALL undo/redo information will be lost if you cleanup.\n\
2814 After cleanup, unused audio files will be moved to a \
2815 \"dead sounds\" location."));
2816         
2817         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2818         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2819         checker.set_default_response (RESPONSE_CANCEL);
2820
2821         checker.set_name (_("CleanupDialog"));
2822         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2823         checker.set_position (Gtk::WIN_POS_MOUSE);
2824
2825         switch (checker.run()) {
2826         case RESPONSE_ACCEPT:
2827                 break;
2828         default:
2829                 return;
2830         }
2831
2832         Session::cleanup_report rep;
2833
2834         editor->prepare_for_cleanup ();
2835
2836         /* do not allow flush until a session is reloaded */
2837
2838         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2839         if (act) {
2840                 act->set_sensitive (false);
2841         }
2842
2843         if (session->cleanup_sources (rep)) {
2844                 editor->finish_cleanup ();
2845                 return;
2846         }
2847         
2848         editor->finish_cleanup ();
2849
2850         checker.hide();
2851         display_cleanup_results (rep, 
2852                                  _("cleaned files"),
2853                                  _("\
2854 The following %1 files were not in use and \n\
2855 have been moved to:\n\
2856 %2. \n\n\
2857 Flushing the wastebasket will \n\
2858 release an additional\n\
2859 %3 %4bytes of disk space.\n"),
2860                                  _("\
2861 The following file was not in use and \n        \
2862 has been moved to:\n                            \
2863 %2. \n\n\
2864 Flushing the wastebasket will \n\
2865 release an additional\n\
2866 %3 %4bytes of disk space.\n"
2867                                          ));
2868
2869 }
2870
2871 void
2872 ARDOUR_UI::flush_trash ()
2873 {
2874         if (session == 0) {
2875                 /* shouldn't happen: menu item is insensitive */
2876                 return;
2877         }
2878
2879         Session::cleanup_report rep;
2880
2881         if (session->cleanup_trash_sources (rep)) {
2882                 return;
2883         }
2884
2885         display_cleanup_results (rep, 
2886                                  _("deleted file"),
2887                                  _("The following %1 files were deleted from\n\
2888 %2,\n\
2889 releasing %3 %4bytes of disk space"),
2890                                  _("The following file was deleted from\n\
2891 %2,\n\
2892 releasing %3 %4bytes of disk space"));
2893 }
2894
2895 void
2896 ARDOUR_UI::add_route (Gtk::Window* float_window)
2897 {
2898         int count;
2899
2900         if (!session) {
2901                 return;
2902         }
2903
2904         if (add_route_dialog == 0) {
2905                 add_route_dialog = new AddRouteDialog;
2906                 if (float_window) {
2907                         add_route_dialog->set_transient_for (*float_window);
2908                 }
2909         }
2910
2911         if (add_route_dialog->is_visible()) {
2912                 /* we're already doing this */
2913                 return;
2914         }
2915
2916         ResponseType r = (ResponseType) add_route_dialog->run ();
2917         
2918         add_route_dialog->hide();
2919
2920         switch (r) {
2921         case RESPONSE_ACCEPT:
2922                 break;
2923         default:
2924                 return;
2925                 break;
2926         }
2927
2928         if ((count = add_route_dialog->count()) <= 0) {
2929                 return;
2930         }
2931
2932         string template_path = add_route_dialog->track_template();
2933
2934         if (!template_path.empty()) {
2935           session->new_route_from_template (count, template_path);
2936           return;
2937         }
2938         
2939         uint32_t input_chan = add_route_dialog->channels ();
2940         uint32_t output_chan;
2941         string name_template = add_route_dialog->name_template ();
2942         bool track = add_route_dialog->track ();
2943
2944         AutoConnectOption oac = Config->get_output_auto_connect();
2945
2946         if (oac & AutoConnectMaster) {
2947                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2948         } else {
2949                 output_chan = input_chan;
2950         }
2951
2952         /* XXX do something with name template */
2953
2954         if (track) {
2955                 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2956         } else {
2957                 session_add_audio_bus (input_chan, output_chan, count);
2958         }
2959 }
2960
2961 XMLNode*
2962 ARDOUR_UI::mixer_settings () const
2963 {
2964         XMLNode* node = 0;
2965
2966         if (session) {
2967                 node = session->instant_xml(X_("Mixer"), session->path());
2968         } else {
2969                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2970         }
2971
2972         if (!node) {
2973                 node = new XMLNode (X_("Mixer"));
2974         }
2975
2976         return node;
2977 }
2978
2979 XMLNode*
2980 ARDOUR_UI::editor_settings () const
2981 {
2982         XMLNode* node = 0;
2983
2984         if (session) {
2985                 node = session->instant_xml(X_("Editor"), session->path());
2986         } else {
2987                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2988         }
2989         
2990         if (!node) {
2991                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2992                         node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2993                 }
2994         }
2995
2996         if (!node) {
2997                 node = new XMLNode (X_("Editor"));
2998         }
2999         return node;
3000 }
3001
3002 XMLNode*
3003 ARDOUR_UI::keyboard_settings () const
3004 {
3005         XMLNode* node = 0;
3006
3007         node = Config->extra_xml(X_("Keyboard"));
3008         
3009         if (!node) {
3010                 node = new XMLNode (X_("Keyboard"));
3011         }
3012         return node;
3013 }
3014
3015 void
3016 ARDOUR_UI::create_xrun_marker(nframes_t where)
3017 {
3018         editor->mouse_add_new_marker (where, false, true);
3019 }
3020
3021 void
3022 ARDOUR_UI::halt_on_xrun_message ()
3023 {
3024         MessageDialog msg (*editor,
3025                            _("Recording was stopped because your system could not keep up."));
3026         msg.run ();
3027 }
3028
3029 void
3030 ARDOUR_UI::xrun_handler(nframes_t where)
3031 {
3032         if (!session) {
3033                 return;
3034         }
3035
3036         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3037
3038         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3039                 create_xrun_marker(where);
3040         }
3041
3042         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3043                 halt_on_xrun_message ();
3044         }
3045 }
3046
3047 bool
3048 ARDOUR_UI::preset_file_exists_handler ()
3049 {
3050         /* if driven from another thread, say "do not overwrite" and show the user nothing.
3051          */
3052
3053         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {        \
3054                 return false;
3055         }
3056         
3057         HBox* hbox = new HBox();
3058         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3059         Gtk::Dialog dialog (_("Preset Exists"), true, false);
3060         Label  message (_("\
3061 A preset with this name already exists for this plugin.\n\
3062 \n\
3063 What you would like to do?\n"));
3064         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3065         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3066         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3067         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3068         dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3069         dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3070         dialog.set_default_response (RESPONSE_ACCEPT);
3071         dialog.set_position (WIN_POS_MOUSE);
3072         dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3073
3074         message.show();
3075         image->show();
3076         hbox->show();
3077
3078         switch (dialog.run ()) {
3079         case RESPONSE_ACCEPT:
3080                 return true;
3081         default:
3082                 return false;
3083         }
3084 }
3085
3086 void
3087 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3088 {
3089         time_t now;
3090         time (&now);
3091
3092         while (disk_buffer_stats.size() > 60) {
3093                 disk_buffer_stats.pop_front ();
3094         }
3095
3096         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3097 }
3098
3099 void
3100 ARDOUR_UI::write_buffer_stats ()
3101 {
3102         std::ofstream fout;
3103         struct tm tm;
3104         char buf[64];
3105         char* path;
3106
3107         if ((path = tempnam (0, "ardourBuffering")) == 0) {
3108                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3109                 return;
3110         }
3111
3112         fout.open (path);
3113
3114         if (!fout) {
3115                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3116                 return;
3117         }
3118
3119         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3120                 localtime_r (&(*i).when, &tm);
3121                 strftime (buf, sizeof (buf), "%T", &tm);
3122                 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3123         }
3124         
3125         disk_buffer_stats.clear ();
3126
3127         fout.close ();
3128
3129         cerr << "Ardour buffering statistics can be found in: " << path << endl;
3130         free (path);
3131 }
3132
3133 void
3134 ARDOUR_UI::disk_overrun_handler ()
3135 {
3136
3137         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3138
3139         write_buffer_stats ();
3140
3141         if (!have_disk_speed_dialog_displayed) {
3142                 have_disk_speed_dialog_displayed = true;
3143                 MessageDialog* msg = new MessageDialog (*editor, _("\
3144 The disk system on your computer\n\
3145 was not able to keep up with Ardour.\n\
3146 \n\
3147 Specifically, it failed to write data to disk\n\
3148 quickly enough to keep up with recording.\n"));
3149                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3150                 msg->show_all ();
3151         }
3152 }
3153
3154 void
3155 ARDOUR_UI::disk_underrun_handler ()
3156 {
3157
3158         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3159
3160         write_buffer_stats ();
3161
3162         if (!have_disk_speed_dialog_displayed) {
3163                 have_disk_speed_dialog_displayed = true;
3164                 MessageDialog* msg = new MessageDialog (*editor,
3165                                    _("The disk system on your computer\n\
3166 was not able to keep up with Ardour.\n\
3167 \n\
3168 Specifically, it failed to read data from disk\n\
3169 quickly enough to keep up with playback.\n"));
3170                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3171                 msg->show_all ();
3172         } 
3173 }
3174
3175 void
3176 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3177 {
3178         have_disk_speed_dialog_displayed = false;
3179         delete msg;
3180 }
3181
3182 void
3183 ARDOUR_UI::session_dialog (std::string msg)
3184 {
3185         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3186         
3187         MessageDialog* d;
3188
3189         if (editor) {
3190                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3191         } else {
3192                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3193         }
3194
3195         d->show_all ();
3196         d->run ();
3197         delete d;
3198 }       
3199
3200 int
3201 ARDOUR_UI::pending_state_dialog ()
3202 {
3203         HBox* hbox = new HBox();
3204         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3205         ArdourDialog dialog (_("Crash Recovery"), true);
3206         Label  message (_("\
3207 This session appears to have been in\n\
3208 middle of recording when ardour or\n\
3209 the computer was shutdown.\n\
3210 \n\
3211 Ardour can recover any captured audio for\n\
3212 you, or it can ignore it. Please decide\n\
3213 what you would like to do.\n"));
3214         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3215         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3216         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3217         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3218         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3219         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3220         dialog.set_default_response (RESPONSE_ACCEPT);
3221         dialog.set_position (WIN_POS_CENTER);
3222         message.show();
3223         image->show();
3224         hbox->show();
3225
3226         pop_back_splash ();
3227
3228         switch (dialog.run ()) {
3229         case RESPONSE_ACCEPT:
3230                 return 1;
3231         default:
3232                 return 0;
3233         }
3234 }
3235
3236 int
3237 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3238 {
3239         HBox* hbox = new HBox();
3240         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3241         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3242         Label  message (string_compose (_("\
3243 This session was created with a sample rate of %1 Hz\n\
3244 \n\
3245 The audioengine is currently running at %2 Hz\n"), desired, actual));
3246
3247         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3248         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3249         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3250         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3251         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3252         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3253         dialog.set_default_response (RESPONSE_ACCEPT);
3254         dialog.set_position (WIN_POS_CENTER);
3255         message.show();
3256         image->show();
3257         hbox->show();
3258
3259         switch (dialog.run ()) {
3260         case RESPONSE_ACCEPT:
3261                 return 0;
3262         default:
3263                 return 1;
3264         }
3265 }
3266
3267         
3268 void
3269 ARDOUR_UI::disconnect_from_jack ()
3270 {
3271         if (engine) {
3272                 if( engine->disconnect_from_jack ()) {
3273                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3274                         msg.run ();
3275                 }
3276
3277                 update_sample_rate (0);
3278         }
3279 }
3280
3281 void
3282 ARDOUR_UI::reconnect_to_jack ()
3283 {
3284         if (engine) {
3285                 if (engine->reconnect_to_jack ()) {
3286                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3287                         msg.run ();
3288                 }
3289
3290                 update_sample_rate (0);
3291         }
3292 }
3293
3294 void
3295 ARDOUR_UI::use_config ()
3296 {
3297         Glib::RefPtr<Action> act;
3298
3299         switch (Config->get_native_file_data_format ()) {
3300         case FormatFloat:
3301                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3302                 break;
3303         case FormatInt24:
3304                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3305                 break;
3306         case FormatInt16:
3307                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3308                 break;
3309         }
3310
3311         if (act) {
3312                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3313                 ract->set_active ();
3314         }       
3315
3316         switch (Config->get_native_file_header_format ()) {
3317         case BWF:
3318                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3319                 break;
3320         case WAVE:
3321                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3322                 break;
3323         case WAVE64:
3324                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3325                 break;
3326         case iXML:
3327                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3328                 break;
3329         case RF64:
3330                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3331                 break;
3332         case CAF:
3333                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3334                 break;
3335         case AIFF:
3336                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3337                 break;
3338         }
3339
3340         if (act) {
3341                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3342                 ract->set_active ();
3343         }       
3344
3345         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3346         if (node) {
3347                 set_transport_controllable_state (*node);
3348         }
3349 }
3350
3351 void
3352 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3353 {
3354         if (Config->get_primary_clock_delta_edit_cursor()) {
3355                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3356         } else {
3357                 primary_clock.set (pos, 0, true);
3358         }
3359
3360         if (Config->get_secondary_clock_delta_edit_cursor()) {
3361                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3362         } else {
3363                 secondary_clock.set (pos);
3364         }
3365
3366         if (big_clock_window) {
3367                 big_clock.set (pos);
3368         }
3369 }
3370
3371 void
3372 ARDOUR_UI::record_state_changed ()
3373 {
3374         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3375
3376         if (!session || !big_clock_window) {
3377                 /* why bother - the clock isn't visible */
3378                 return;
3379         }
3380
3381         switch (session->record_status()) {
3382         case Session::Recording:
3383                 big_clock.set_widget_name ("BigClockRecording");
3384                 break;
3385         default:
3386                 big_clock.set_widget_name ("BigClockNonRecording");
3387                 break;
3388         }
3389 }
3390
3391 bool
3392 ARDOUR_UI::first_idle ()
3393 {
3394         if (session) {
3395                 session->allow_auto_play (true);
3396         }
3397
3398         if (editor) {
3399                 editor->first_idle();
3400         }
3401
3402         Keyboard::set_can_save_keybindings (true);
3403         return false;
3404 }
3405
3406 void
3407 ARDOUR_UI::store_clock_modes ()
3408 {
3409         XMLNode* node = new XMLNode(X_("ClockModes"));
3410
3411         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3412                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3413         }
3414
3415         session->add_extra_xml (*node);
3416         session->set_dirty ();
3417 }
3418
3419
3420                 
3421 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3422         : Controllable (name), ui (u), type(tp)
3423 {
3424         
3425 }
3426
3427 void
3428 ARDOUR_UI::TransportControllable::set_value (float val)
3429 {
3430         if (type == ShuttleControl) {
3431                 double fract;
3432
3433                 if (val == 0.5f) {
3434                         fract = 0.0;
3435                 } else {
3436                         if (val < 0.5f) {
3437                                 fract = -((0.5f - val)/0.5f);
3438                         } else {
3439                                 fract = ((val - 0.5f)/0.5f);
3440                         }
3441                 }
3442                 
3443                 ui.set_shuttle_fract (fract);
3444                 return;
3445         }
3446
3447         if (val < 0.5f) {
3448                 /* do nothing: these are radio-style actions */
3449                 return;
3450         }
3451
3452         const char *action = 0;
3453
3454         switch (type) {
3455         case Roll:
3456                 action = X_("Roll");
3457                 break;
3458         case Stop:
3459                 action = X_("Stop");
3460                 break;
3461         case GotoStart:
3462                 action = X_("Goto Start");
3463                 break;
3464         case GotoEnd:
3465                 action = X_("Goto End");
3466                 break;
3467         case AutoLoop:
3468                 action = X_("Loop");
3469                 break;
3470         case PlaySelection:
3471                 action = X_("Play Selection");
3472                 break;
3473         case RecordEnable:
3474                 action = X_("Record");
3475                 break;
3476         default:
3477                 break;
3478         }
3479
3480         if (action == 0) {
3481                 return;
3482         }
3483
3484         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3485
3486         if (act) {
3487                 act->activate ();
3488         }
3489 }
3490
3491 float
3492 ARDOUR_UI::TransportControllable::get_value (void) const
3493 {
3494         float val = 0.0f;
3495         
3496         switch (type) {
3497         case Roll:
3498                 break;
3499         case Stop:
3500                 break;
3501         case GotoStart:
3502                 break;
3503         case GotoEnd:
3504                 break;
3505         case AutoLoop:
3506                 break;
3507         case PlaySelection:
3508                 break;
3509         case RecordEnable:
3510                 break;
3511         case ShuttleControl:
3512                 break;
3513         default:
3514                 break;
3515         }
3516
3517         return val;
3518 }
3519
3520 void
3521 ARDOUR_UI::TransportControllable::set_id (const string& str)
3522 {
3523         _id = str;
3524 }
3525
3526 void
3527 ARDOUR_UI::setup_profile ()
3528 {
3529         if (gdk_screen_width() < 1200) {
3530                 Profile->set_small_screen ();
3531         }
3532
3533         if (getenv ("ARDOUR_SAE")) {
3534                 Profile->set_sae ();
3535                 Profile->set_single_package ();
3536         }
3537 }
3538