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