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