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