Tidy a couple of minor things up.
[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_("TransportClockDisplay"), true, true, false, true))
141         , secondary_clock (new AudioClock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true))
142
143           /* big clock */
144
145         , big_clock (new AudioClock (X_("bigclock"), false, "BigClockNonRecording", 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                 /// @todo some minor tweaks.
2515
2516                 bus_profile.output_ac = AutoConnectOption (0);
2517
2518                 if (_startup->connect_outputs ()) {
2519                         if (_startup->connect_outs_to_master()) {
2520                                 bus_profile.output_ac = AutoConnectMaster;
2521                         } else if (_startup->connect_outs_to_physical()) {
2522                                 bus_profile.output_ac = AutoConnectPhysical;
2523                         }
2524                 }
2525
2526                 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2527                 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2528         }
2529
2530         if (build_session (session_path, session_name, bus_profile)) {
2531                 return -1;
2532         }
2533
2534         return 0;
2535 }
2536
2537 void
2538 ARDOUR_UI::idle_load (const std::string& path)
2539 {
2540         if (_session) {
2541                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2542                         /* /path/to/foo => /path/to/foo, foo */
2543                         load_session (path, basename_nosuffix (path));
2544                 } else {
2545                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2546                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2547                 }
2548         } else {
2549
2550                 ARDOUR_COMMAND_LINE::session_name = path;
2551
2552                 /*
2553                  * new_session_dialog doens't exist in A3
2554                  * Try to remove all references to it to
2555                  * see if it will compile.  NOTE: this will
2556                  * likely cause a runtime issue is my somewhat
2557                  * uneducated guess.
2558                  */
2559
2560                 //if (new_session_dialog) {
2561
2562
2563                         /* make it break out of Dialog::run() and
2564                            start again.
2565                          */
2566
2567                         //new_session_dialog->response (1);
2568                 //}
2569         }
2570 }
2571
2572 void
2573 ARDOUR_UI::end_loading_messages ()
2574 {
2575         // hide_splash ();
2576 }
2577
2578 void
2579 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2580 {
2581         // show_splash ();
2582         // splash->message (msg);
2583         flush_pending ();
2584 }
2585
2586 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2587 int
2588 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2589 {
2590         string session_name;
2591         string session_path;
2592         string template_name;
2593         int ret = -1;
2594         bool likely_new = false;
2595
2596         if (!load_template.empty()) {
2597                 should_be_new = true;
2598                 template_name = load_template;
2599         }
2600
2601         while (ret != 0) {
2602
2603                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2604
2605                         /* if they named a specific statefile, use it, otherwise they are
2606                            just giving a session folder, and we want to use it as is
2607                            to find the session.
2608                         */
2609
2610                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2611
2612                         if (suffix != string::npos) {
2613                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2614                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2615                                 session_name = Glib::path_get_basename (session_name);
2616                         } else {
2617                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2618                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2619                         }
2620
2621                 } else {
2622
2623                         bool const apply = run_startup (should_be_new, load_template);
2624
2625                         if (!apply) {
2626                                 if (quit_on_cancel) {
2627                                         exit (1);
2628                                 } else {
2629                                         return ret;
2630                                 }
2631                         }
2632
2633                         /* if we run the startup dialog again, offer more than just "new session" */
2634
2635                         should_be_new = false;
2636
2637                         session_name = _startup->session_name (likely_new);
2638
2639                         string::size_type suffix = session_name.find (statefile_suffix);
2640
2641                         if (suffix != string::npos) {
2642                                 session_name = session_name.substr (0, suffix);
2643                         }
2644
2645                         /* this shouldn't happen, but we catch it just in case it does */
2646
2647                         if (session_name.empty()) {
2648                                 continue;
2649                         }
2650
2651                         if (_startup->use_session_template()) {
2652                                 template_name = _startup->session_template_name();
2653                                 _session_is_new = true;
2654                         }
2655
2656                         if (session_name[0] == G_DIR_SEPARATOR ||
2657                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
2658                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)) {
2659
2660                                 /* absolute path or cwd-relative path specified for session name: infer session folder
2661                                    from what was given.
2662                                 */
2663
2664                                 session_path = Glib::path_get_dirname (session_name);
2665                                 session_name = Glib::path_get_basename (session_name);
2666
2667                         } else {
2668
2669                                 session_path = _startup->session_folder();
2670
2671                                 if (session_name.find ('/') != string::npos) {
2672                                         MessageDialog msg (*_startup,
2673                                                            _("To ensure compatibility with various systems\n"
2674                                                              "session names may not contain a '/' character"));
2675                                         msg.run ();
2676                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2677                                         continue;
2678                                 }
2679
2680                                 if (session_name.find ('\\') != string::npos) {
2681                                         MessageDialog msg (*_startup,
2682                                                            _("To ensure compatibility with various systems\n"
2683                                                              "session names may not contain a '\\' character"));
2684                                         msg.run ();
2685                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2686                                         continue;
2687                                 }
2688                         }
2689                 }
2690
2691                 if (create_engine ()) {
2692                         break;
2693                 }
2694
2695                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2696
2697                         if (likely_new) {
2698
2699                                 std::string existing = Glib::build_filename (session_path, session_name);
2700
2701                                 if (!ask_about_loading_existing_session (existing)) {
2702                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2703                                         continue;
2704                                 }
2705                         }
2706
2707                         _session_is_new = false;
2708
2709                 } else {
2710
2711                         if (!likely_new) {
2712                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2713                                 msg.run ();
2714                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2715                                 continue;
2716                         }
2717
2718                         if (session_name.find ('/') != std::string::npos) {
2719                                 MessageDialog msg (*_startup,
2720                                                    _("To ensure compatibility with various systems\n"
2721                                                      "session names may not contain a '/' character"));
2722                                 msg.run ();
2723                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2724                                 continue;
2725                         }
2726
2727                         if (session_name.find ('\\') != std::string::npos) {
2728                                 MessageDialog msg (*_startup,
2729                                                    _("To ensure compatibility with various systems\n"
2730                                                      "session names may not contain a '\\' character"));
2731                                 msg.run ();
2732                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2733                                 continue;
2734                         }
2735
2736                         _session_is_new = true;
2737                 }
2738
2739                 if (likely_new && template_name.empty()) {
2740
2741                         ret = build_session_from_nsd (session_path, session_name);
2742
2743                 } else {
2744
2745                         ret = load_session (session_path, session_name, template_name);
2746
2747                         if (ret == -2) {
2748                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
2749                                 exit (1);
2750                         }
2751
2752                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2753                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2754                                 exit (1);
2755                         }
2756                 }
2757         }
2758
2759         return ret;
2760 }
2761
2762 void
2763 ARDOUR_UI::close_session()
2764 {
2765         if (!check_audioengine()) {
2766                 return;
2767         }
2768
2769         if (unload_session (true)) {
2770                 return;
2771         }
2772
2773         ARDOUR_COMMAND_LINE::session_name = "";
2774
2775         if (get_session_parameters (true, false)) {
2776                 exit (1);
2777         }
2778
2779         goto_editor_window ();
2780 }
2781
2782 /** @param snap_name Snapshot name (without .ardour suffix).
2783  *  @return -2 if the load failed because we are not connected to the AudioEngine.
2784  */
2785 int
2786 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
2787 {
2788         Session *new_session;
2789         int unload_status;
2790         int retval = -1;
2791
2792         session_loaded = false;
2793
2794         if (!check_audioengine()) {
2795                 return -2;
2796         }
2797
2798         unload_status = unload_session ();
2799
2800         if (unload_status < 0) {
2801                 goto out;
2802         } else if (unload_status > 0) {
2803                 retval = 0;
2804                 goto out;
2805         }
2806
2807         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
2808
2809         try {
2810                 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2811         }
2812
2813         /* this one is special */
2814
2815         catch (AudioEngine::PortRegistrationFailure& err) {
2816
2817                 MessageDialog msg (err.what(),
2818                                    true,
2819                                    Gtk::MESSAGE_INFO,
2820                                    Gtk::BUTTONS_CLOSE);
2821
2822                 msg.set_title (_("Port Registration Error"));
2823                 msg.set_secondary_text (_("Click the Close button to try again."));
2824                 msg.set_position (Gtk::WIN_POS_CENTER);
2825                 pop_back_splash ();
2826                 msg.present ();
2827
2828                 int response = msg.run ();
2829
2830                 msg.hide ();
2831
2832                 switch (response) {
2833                 case RESPONSE_CANCEL:
2834                         exit (1);
2835                 default:
2836                         break;
2837                 }
2838                 goto out;
2839         }
2840
2841         catch (...) {
2842
2843                 MessageDialog msg (string_compose(
2844                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
2845                                            path, snap_name),
2846                                    true,
2847                                    Gtk::MESSAGE_INFO,
2848                                    BUTTONS_OK);
2849
2850                 msg.set_title (_("Loading Error"));
2851                 msg.set_secondary_text (_("Click the Refresh button to try again."));
2852                 msg.add_button (Stock::REFRESH, 1);
2853                 msg.set_position (Gtk::WIN_POS_CENTER);
2854                 pop_back_splash ();
2855                 msg.present ();
2856
2857                 int response = msg.run ();
2858
2859                 switch (response) {
2860                 case 1:
2861                         break;
2862                 default:
2863                         exit (1);
2864                 }
2865
2866                 msg.hide ();
2867
2868                 goto out;
2869         }
2870
2871         {
2872                 list<string> const u = new_session->unknown_processors ();
2873                 if (!u.empty()) {
2874                         MissingPluginDialog d (_session, u);
2875                         d.run ();
2876                 }
2877         }
2878
2879         /* Now the session been created, add the transport controls */
2880         new_session->add_controllable(roll_controllable);
2881         new_session->add_controllable(stop_controllable);
2882         new_session->add_controllable(goto_start_controllable);
2883         new_session->add_controllable(goto_end_controllable);
2884         new_session->add_controllable(auto_loop_controllable);
2885         new_session->add_controllable(play_selection_controllable);
2886         new_session->add_controllable(rec_controllable);
2887
2888         set_session (new_session);
2889
2890         session_loaded = true;
2891
2892         goto_editor_window ();
2893
2894         if (_session) {
2895                 _session->set_clean ();
2896         }
2897
2898         flush_pending ();
2899         retval = 0;
2900
2901   out:
2902         return retval;
2903 }
2904
2905 int
2906 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
2907 {
2908         Session *new_session;
2909         int x;
2910
2911         if (!check_audioengine()) {
2912                 return -1;
2913         }
2914
2915         session_loaded = false;
2916
2917         x = unload_session ();
2918
2919         if (x < 0) {
2920                 return -1;
2921         } else if (x > 0) {
2922                 return 0;
2923         }
2924
2925         _session_is_new = true;
2926
2927         try {
2928                 new_session = new Session (*engine, path, snap_name, &bus_profile);
2929         }
2930
2931         catch (...) {
2932
2933                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2934                 pop_back_splash ();
2935                 msg.run ();
2936                 return -1;
2937         }
2938
2939         /* Give the new session the default GUI state, if such things exist */
2940
2941         XMLNode* n;
2942         n = Config->instant_xml (X_("Editor"));
2943         if (n) {
2944                 new_session->add_instant_xml (*n, false);
2945         }
2946         n = Config->instant_xml (X_("Mixer"));
2947         if (n) {
2948                 new_session->add_instant_xml (*n, false);
2949         }
2950
2951         /* Put the playhead at 0 and scroll fully left */
2952         n = new_session->instant_xml (X_("Editor"));
2953         if (n) {
2954                 n->add_property (X_("playhead"), X_("0"));
2955                 n->add_property (X_("left-frame"), X_("0"));
2956         }
2957
2958         set_session (new_session);
2959
2960         session_loaded = true;
2961
2962         new_session->save_state(new_session->name());
2963
2964         return 0;
2965 }
2966
2967 void
2968 ARDOUR_UI::launch_chat ()
2969 {
2970 #ifdef __APPLE__
2971         open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2972 #else
2973         open_uri("http://webchat.freenode.net/?channels=ardour");
2974 #endif
2975 }
2976
2977 void
2978 ARDOUR_UI::show_about ()
2979 {
2980         if (about == 0) {
2981                 about = new About;
2982                 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2983         }
2984
2985         about->set_transient_for(*editor);
2986         about->show_all ();
2987 }
2988
2989 void
2990 ARDOUR_UI::launch_manual ()
2991 {
2992         PBD::open_uri("http://ardour.org/flossmanual");
2993 }
2994
2995 void
2996 ARDOUR_UI::launch_reference ()
2997 {
2998         PBD::open_uri("http://ardour.org/refmanual");
2999 }
3000
3001 void
3002 ARDOUR_UI::hide_about ()
3003 {
3004         if (about) {
3005                 about->get_window()->set_cursor ();
3006                 about->hide ();
3007         }
3008 }
3009
3010 void
3011 ARDOUR_UI::about_signal_response (int /*response*/)
3012 {
3013         hide_about();
3014 }
3015
3016 void
3017 ARDOUR_UI::show_splash ()
3018 {
3019         if (splash == 0) {
3020                 try {
3021                         splash = new Splash;
3022                 } catch (...) {
3023                         return;
3024                 }
3025         }
3026
3027         splash->show ();
3028         splash->present ();
3029         splash->queue_draw ();
3030         splash->get_window()->process_updates (true);
3031         flush_pending ();
3032 }
3033
3034 void
3035 ARDOUR_UI::hide_splash ()
3036 {
3037         if (splash) {
3038                 splash->hide();
3039         }
3040 }
3041
3042 void
3043 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
3044                                     const string& plural_msg, const string& singular_msg)
3045 {
3046         size_t removed;
3047
3048         removed = rep.paths.size();
3049
3050         if (removed == 0) {
3051                 MessageDialog msgd (*editor,
3052                                     _("No files were ready for clean-up"),
3053                                     true,
3054                                     Gtk::MESSAGE_INFO,
3055                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
3056                 msgd.set_title (_("Clean-up"));
3057                 msgd.set_secondary_text (_("If this seems suprising, \n\
3058 check for any existing snapshots.\n\
3059 These may still include regions that\n\
3060 require some unused files to continue to exist."));
3061
3062                 msgd.run ();
3063                 return;
3064         }
3065
3066         ArdourDialog results (_("Clean-up"), true, false);
3067
3068         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3069             CleanupResultsModelColumns() {
3070                     add (visible_name);
3071                     add (fullpath);
3072             }
3073             Gtk::TreeModelColumn<std::string> visible_name;
3074             Gtk::TreeModelColumn<std::string> fullpath;
3075         };
3076
3077
3078         CleanupResultsModelColumns results_columns;
3079         Glib::RefPtr<Gtk::ListStore> results_model;
3080         Gtk::TreeView results_display;
3081
3082         results_model = ListStore::create (results_columns);
3083         results_display.set_model (results_model);
3084         results_display.append_column (list_title, results_columns.visible_name);
3085
3086         results_display.set_name ("CleanupResultsList");
3087         results_display.set_headers_visible (true);
3088         results_display.set_headers_clickable (false);
3089         results_display.set_reorderable (false);
3090
3091         Gtk::ScrolledWindow list_scroller;
3092         Gtk::Label txt;
3093         Gtk::VBox dvbox;
3094         Gtk::HBox dhbox;  // the hbox for the image and text
3095         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3096         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3097
3098         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3099
3100         const string dead_directory = _session->session_directory().dead_path().to_string();
3101
3102         /* subst:
3103            %1 - number of files removed
3104            %2 - location of "dead"
3105            %3 - size of files affected
3106            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3107         */
3108
3109         const char* bprefix;
3110         double space_adjusted = 0;
3111
3112         if (rep.space < 1000) {
3113                 bprefix = X_("");
3114                 space_adjusted = rep.space;
3115         } else if (rep.space < 1000000) {
3116                 bprefix = X_("kilo");
3117                 space_adjusted = truncf((float)rep.space / 1000.0);
3118         } else if (rep.space < 1000000 * 1000) {
3119                 bprefix = X_("mega");
3120                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000.0));
3121         } else {
3122                 bprefix = X_("giga");
3123                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000 * 1000.0));
3124         }
3125
3126         if (removed > 1) {
3127                 txt.set_text (string_compose (plural_msg, removed, dead_directory, space_adjusted, bprefix));
3128         } else {
3129                 txt.set_text (string_compose (singular_msg, removed, dead_directory, space_adjusted, bprefix));
3130         }
3131
3132         dhbox.pack_start (*dimage, true, false, 5);
3133         dhbox.pack_start (txt, true, false, 5);
3134
3135         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3136                 TreeModel::Row row = *(results_model->append());
3137                 row[results_columns.visible_name] = *i;
3138                 row[results_columns.fullpath] = *i;
3139         }
3140
3141         list_scroller.add (results_display);
3142         list_scroller.set_size_request (-1, 150);
3143         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3144
3145         dvbox.pack_start (dhbox, true, false, 5);
3146         dvbox.pack_start (list_scroller, true, false, 5);
3147         ddhbox.pack_start (dvbox, true, false, 5);
3148
3149         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3150         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3151         results.set_default_response (RESPONSE_CLOSE);
3152         results.set_position (Gtk::WIN_POS_MOUSE);
3153
3154         results_display.show();
3155         list_scroller.show();
3156         txt.show();
3157         dvbox.show();
3158         dhbox.show();
3159         ddhbox.show();
3160         dimage->show();
3161
3162         //results.get_vbox()->show();
3163         results.set_resizable (false);
3164
3165         results.run ();
3166
3167 }
3168
3169 void
3170 ARDOUR_UI::cleanup ()
3171 {
3172         if (_session == 0) {
3173                 /* shouldn't happen: menu item is insensitive */
3174                 return;
3175         }
3176
3177
3178         MessageDialog checker (_("Are you sure you want to clean-up?"),
3179                                 true,
3180                                 Gtk::MESSAGE_QUESTION,
3181                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
3182
3183         checker.set_title (_("Clean-up"));
3184
3185         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3186 ALL undo/redo information will be lost if you clean-up.\n\
3187 Clean-up will move all unused files to a \"dead\" location."));
3188
3189         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3190         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3191         checker.set_default_response (RESPONSE_CANCEL);
3192
3193         checker.set_name (_("CleanupDialog"));
3194         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3195         checker.set_position (Gtk::WIN_POS_MOUSE);
3196
3197         switch (checker.run()) {
3198         case RESPONSE_ACCEPT:
3199                 break;
3200         default:
3201                 return;
3202         }
3203
3204         ARDOUR::CleanupReport rep;
3205
3206         editor->prepare_for_cleanup ();
3207
3208         /* do not allow flush until a session is reloaded */
3209
3210         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3211         if (act) {
3212                 act->set_sensitive (false);
3213         }
3214
3215         if (_session->cleanup_sources (rep)) {
3216                 editor->finish_cleanup ();
3217                 return;
3218         }
3219
3220         editor->finish_cleanup ();
3221
3222         checker.hide();
3223         display_cleanup_results (rep,
3224                                  _("Cleaned Files"),
3225                                  _("\
3226 The following %1 files were not in use and \n\
3227 have been moved to:\n\n\
3228 %2\n\n\
3229 After a restart of Ardour,\n\n\
3230 Session -> Clean-up -> Flush Wastebasket\n\n\
3231 will release an additional\n\
3232 %3 %4bytes of disk space.\n"),
3233                                  _("\
3234 The following file was not in use and \n\
3235 has been moved to:\n                            \
3236 %2\n\n\
3237 After a restart of Ardour,\n\n\
3238 Session -> Clean-up -> Flush Wastebasket\n\n\
3239 will release an additional\n\
3240 %3 %4bytes of disk space.\n"
3241                                          ));
3242
3243 }
3244
3245 void
3246 ARDOUR_UI::flush_trash ()
3247 {
3248         if (_session == 0) {
3249                 /* shouldn't happen: menu item is insensitive */
3250                 return;
3251         }
3252
3253         ARDOUR::CleanupReport rep;
3254
3255         if (_session->cleanup_trash_sources (rep)) {
3256                 return;
3257         }
3258
3259         display_cleanup_results (rep,
3260                                  _("deleted file"),
3261                                  _("The following %1 files were deleted from\n\
3262 %2,\n\
3263 releasing %3 %4bytes of disk space"),
3264                                  _("The following file was deleted from\n\
3265 %2,\n\
3266 releasing %3 %4bytes of disk space"));
3267 }
3268
3269 void
3270 ARDOUR_UI::add_route (Gtk::Window* float_window)
3271 {
3272         int count;
3273
3274         if (!_session) {
3275                 return;
3276         }
3277
3278         if (add_route_dialog == 0) {
3279                 add_route_dialog = new AddRouteDialog (_session);
3280                 if (float_window) {
3281                         add_route_dialog->set_transient_for (*float_window);
3282                 }
3283         }
3284
3285         if (add_route_dialog->is_visible()) {
3286                 /* we're already doing this */
3287                 return;
3288         }
3289
3290         ResponseType r = (ResponseType) add_route_dialog->run ();
3291
3292         add_route_dialog->hide();
3293
3294         switch (r) {
3295                 case RESPONSE_ACCEPT:
3296                         break;
3297                 default:
3298                         return;
3299                         break;
3300         }
3301
3302         if ((count = add_route_dialog->count()) <= 0) {
3303                 return;
3304         }
3305
3306         string template_path = add_route_dialog->track_template();
3307
3308         if (!template_path.empty()) {
3309                 _session->new_route_from_template (count, template_path);
3310                 return;
3311         }
3312
3313         uint32_t input_chan = add_route_dialog->channels ();
3314         uint32_t output_chan;
3315         string name_template = add_route_dialog->name_template ();
3316         bool track = add_route_dialog->track ();
3317         RouteGroup* route_group = add_route_dialog->route_group ();
3318
3319         AutoConnectOption oac = Config->get_output_auto_connect();
3320
3321         if (oac & AutoConnectMaster) {
3322                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3323         } else {
3324                 output_chan = input_chan;
3325         }
3326
3327         /* XXX do something with name template */
3328
3329         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3330                 if (track) {
3331                         session_add_midi_track (route_group, count, name_template);
3332                 } else  {
3333                         MessageDialog msg (*editor,
3334                                         _("Sorry, MIDI Busses are not supported at this time."));
3335                         msg.run ();
3336                         //session_add_midi_bus();
3337                 }
3338         } else {
3339                 if (track) {
3340                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count, name_template);
3341                 } else {
3342                         session_add_audio_bus (input_chan, output_chan, route_group, count, name_template);
3343                 }
3344         }
3345 }
3346
3347 XMLNode*
3348 ARDOUR_UI::mixer_settings () const
3349 {
3350         XMLNode* node = 0;
3351
3352         if (_session) {
3353                 node = _session->instant_xml(X_("Mixer"));
3354         } else {
3355                 node = Config->instant_xml(X_("Mixer"));
3356         }
3357
3358         if (!node) {
3359                 node = new XMLNode (X_("Mixer"));
3360         }
3361
3362         return node;
3363 }
3364
3365 XMLNode*
3366 ARDOUR_UI::editor_settings () const
3367 {
3368         XMLNode* node = 0;
3369
3370         if (_session) {
3371                 node = _session->instant_xml(X_("Editor"));
3372         } else {
3373                 node = Config->instant_xml(X_("Editor"));
3374         }
3375
3376         if (!node) {
3377                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3378                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3379                 }
3380         }
3381
3382         if (!node) {
3383                 node = new XMLNode (X_("Editor"));
3384         }
3385
3386         return node;
3387 }
3388
3389 XMLNode*
3390 ARDOUR_UI::keyboard_settings () const
3391 {
3392         XMLNode* node = 0;
3393
3394         node = Config->extra_xml(X_("Keyboard"));
3395
3396         if (!node) {
3397                 node = new XMLNode (X_("Keyboard"));
3398         }
3399
3400         return node;
3401 }
3402
3403 void
3404 ARDOUR_UI::create_xrun_marker (framepos_t where)
3405 {
3406         editor->mouse_add_new_marker (where, false, true);
3407 }
3408
3409 void
3410 ARDOUR_UI::halt_on_xrun_message ()
3411 {
3412         MessageDialog msg (*editor,
3413                            _("Recording was stopped because your system could not keep up."));
3414         msg.run ();
3415 }
3416
3417 void
3418 ARDOUR_UI::xrun_handler (framepos_t where)
3419 {
3420         if (!_session) {
3421                 return;
3422         }
3423
3424         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3425
3426         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3427                 create_xrun_marker(where);
3428         }
3429
3430         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3431                 halt_on_xrun_message ();
3432         }
3433 }
3434
3435 void
3436 ARDOUR_UI::disk_overrun_handler ()
3437 {
3438         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3439
3440         if (!have_disk_speed_dialog_displayed) {
3441                 have_disk_speed_dialog_displayed = true;
3442                 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
3443 The disk system on your computer\n\
3444 was not able to keep up with %1.\n\
3445 \n\
3446 Specifically, it failed to write data to disk\n\
3447 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
3448                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3449                 msg->show ();
3450         }
3451 }
3452
3453 void
3454 ARDOUR_UI::disk_underrun_handler ()
3455 {
3456         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3457
3458         if (!have_disk_speed_dialog_displayed) {
3459                 have_disk_speed_dialog_displayed = true;
3460                 MessageDialog* msg = new MessageDialog (
3461                         *editor, string_compose (_("The disk system on your computer\n\
3462 was not able to keep up with %1.\n\
3463 \n\
3464 Specifically, it failed to read data from disk\n\
3465 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
3466                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3467                 msg->show ();
3468         }
3469 }
3470
3471 void
3472 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3473 {
3474         have_disk_speed_dialog_displayed = false;
3475         delete msg;
3476 }
3477
3478 void
3479 ARDOUR_UI::session_dialog (std::string msg)
3480 {
3481         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3482
3483         MessageDialog* d;
3484
3485         if (editor) {
3486                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3487         } else {
3488                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3489         }
3490
3491         d->show_all ();
3492         d->run ();
3493         delete d;
3494 }
3495
3496 int
3497 ARDOUR_UI::pending_state_dialog ()
3498 {
3499         HBox* hbox = new HBox();
3500         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3501         ArdourDialog dialog (_("Crash Recovery"), true);
3502         Label  message (_("\
3503 This session appears to have been in\n\
3504 middle of recording when ardour or\n\
3505 the computer was shutdown.\n\
3506 \n\
3507 Ardour can recover any captured audio for\n\
3508 you, or it can ignore it. Please decide\n\
3509 what you would like to do.\n"));
3510         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3511         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3512         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3513         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3514         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3515         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3516         dialog.set_default_response (RESPONSE_ACCEPT);
3517         dialog.set_position (WIN_POS_CENTER);
3518         message.show();
3519         image->show();
3520         hbox->show();
3521
3522         switch (dialog.run ()) {
3523         case RESPONSE_ACCEPT:
3524                 return 1;
3525         default:
3526                 return 0;
3527         }
3528 }
3529
3530 int
3531 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
3532 {
3533         HBox* hbox = new HBox();
3534         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3535         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3536         Label  message (string_compose (_("\
3537 This session was created with a sample rate of %1 Hz\n\
3538 \n\
3539 The audioengine is currently running at %2 Hz\n"), desired, actual));
3540
3541         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3542         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3543         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3544         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3545         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3546         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3547         dialog.set_default_response (RESPONSE_ACCEPT);
3548         dialog.set_position (WIN_POS_CENTER);
3549         message.show();
3550         image->show();
3551         hbox->show();
3552
3553         switch (dialog.run ()) {
3554         case RESPONSE_ACCEPT:
3555                 return 0;
3556         default:
3557                 return 1;
3558         }
3559 }
3560
3561
3562 void
3563 ARDOUR_UI::disconnect_from_jack ()
3564 {
3565         if (engine) {
3566                 if( engine->disconnect_from_jack ()) {
3567                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3568                         msg.run ();
3569                 }
3570
3571                 update_sample_rate (0);
3572         }
3573 }
3574
3575 void
3576 ARDOUR_UI::reconnect_to_jack ()
3577 {
3578         if (engine) {
3579                 if (engine->reconnect_to_jack ()) {
3580                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3581                         msg.run ();
3582                 }
3583
3584                 update_sample_rate (0);
3585         }
3586 }
3587
3588 void
3589 ARDOUR_UI::use_config ()
3590 {
3591         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3592         if (node) {
3593                 set_transport_controllable_state (*node);
3594         }
3595 }
3596
3597 void
3598 ARDOUR_UI::update_transport_clocks (framepos_t pos)
3599 {
3600         if (Config->get_primary_clock_delta_edit_cursor()) {
3601                 primary_clock->set (pos, false, editor->get_preferred_edit_position(), 1);
3602         } else {
3603                 primary_clock->set (pos, 0, true);
3604         }
3605
3606         if (Config->get_secondary_clock_delta_edit_cursor()) {
3607                 secondary_clock->set (pos, false, editor->get_preferred_edit_position(), 2);
3608         } else {
3609                 secondary_clock->set (pos);
3610         }
3611
3612         if (big_clock_window->get()) {
3613                 big_clock->set (pos);
3614         }
3615 }
3616
3617
3618 void
3619 ARDOUR_UI::step_edit_status_change (bool yn)
3620 {
3621         // XXX should really store pre-step edit status of things
3622         // we make insensitive
3623
3624         if (yn) {
3625                 rec_button.set_active_state (Mid);
3626                 rec_button.set_sensitive (false);
3627         } else {
3628                 rec_button.unset_active_state ();;
3629                 rec_button.set_sensitive (true);
3630         }
3631 }
3632
3633 void
3634 ARDOUR_UI::record_state_changed ()
3635 {
3636         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3637
3638         if (!_session || !big_clock_window->get()) {
3639                 /* why bother - the clock isn't visible */
3640                 return;
3641         }
3642
3643         Session::RecordState const r = _session->record_status ();
3644         bool const h = _session->have_rec_enabled_track ();
3645
3646         if (r == Session::Recording && h)  {
3647                 big_clock->set_widget_name ("BigClockRecording");
3648         } else {
3649                 big_clock->set_widget_name ("BigClockNonRecording");
3650         }
3651 }
3652
3653 bool
3654 ARDOUR_UI::first_idle ()
3655 {
3656         if (_session) {
3657                 _session->allow_auto_play (true);
3658         }
3659
3660         if (editor) {
3661                 editor->first_idle();
3662         }
3663
3664         Keyboard::set_can_save_keybindings (true);
3665         return false;
3666 }
3667
3668 void
3669 ARDOUR_UI::store_clock_modes ()
3670 {
3671         XMLNode* node = new XMLNode(X_("ClockModes"));
3672
3673         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3674                 XMLNode* child = new XMLNode (X_("Clock"));
3675                 
3676                 child->add_property (X_("name"), (*x)->name());
3677                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
3678                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
3679
3680                 node->add_child_nocopy (*child);
3681         }
3682
3683         _session->add_extra_xml (*node);
3684         _session->set_dirty ();
3685 }
3686
3687 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3688         : Controllable (name), ui (u), type(tp)
3689 {
3690
3691 }
3692
3693 void
3694 ARDOUR_UI::TransportControllable::set_value (double val)
3695 {
3696         if (val < 0.5) {
3697                 /* do nothing: these are radio-style actions */
3698                 return;
3699         }
3700
3701         const char *action = 0;
3702
3703         switch (type) {
3704         case Roll:
3705                 action = X_("Roll");
3706                 break;
3707         case Stop:
3708                 action = X_("Stop");
3709                 break;
3710         case GotoStart:
3711                 action = X_("Goto Start");
3712                 break;
3713         case GotoEnd:
3714                 action = X_("Goto End");
3715                 break;
3716         case AutoLoop:
3717                 action = X_("Loop");
3718                 break;
3719         case PlaySelection:
3720                 action = X_("Play Selection");
3721                 break;
3722         case RecordEnable:
3723                 action = X_("Record");
3724                 break;
3725         default:
3726                 break;
3727         }
3728
3729         if (action == 0) {
3730                 return;
3731         }
3732
3733         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3734
3735         if (act) {
3736                 act->activate ();
3737         }
3738 }
3739
3740 double
3741 ARDOUR_UI::TransportControllable::get_value (void) const
3742 {
3743         float val = 0.0;
3744
3745         switch (type) {
3746         case Roll:
3747                 break;
3748         case Stop:
3749                 break;
3750         case GotoStart:
3751                 break;
3752         case GotoEnd:
3753                 break;
3754         case AutoLoop:
3755                 break;
3756         case PlaySelection:
3757                 break;
3758         case RecordEnable:
3759                 break;
3760         default:
3761                 break;
3762         }
3763
3764         return val;
3765 }
3766
3767 void
3768 ARDOUR_UI::setup_profile ()
3769 {
3770         if (gdk_screen_width() < 1200) {
3771                 Profile->set_small_screen ();
3772         }
3773
3774
3775         if (getenv ("ARDOUR_SAE")) {
3776                 Profile->set_sae ();
3777                 Profile->set_single_package ();
3778         }
3779 }
3780
3781 void
3782 ARDOUR_UI::toggle_translations ()
3783 {
3784         using namespace Glib;
3785
3786         RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3787         if (act) {
3788                 RefPtr<ToggleAction> ract = RefPtr<ToggleAction>::cast_dynamic (act);
3789                 if (ract) {
3790
3791                         string i18n_killer = ARDOUR::translation_kill_path();
3792
3793                         bool already_enabled = !ARDOUR::translations_are_disabled ();
3794
3795                         if (ract->get_active ()) {
3796 /* we don't care about errors */
3797                                 int fd = ::open (i18n_killer.c_str(), O_RDONLY|O_CREAT, 0644);
3798                                 close (fd);
3799                         } else {
3800 /* we don't care about errors */
3801                                 unlink (i18n_killer.c_str());
3802                         }
3803
3804                         if (already_enabled != ract->get_active()) {
3805                                 MessageDialog win (already_enabled ? _("Translations disabled") : _("Translations enabled"),
3806                                                    false,
3807                                                    Gtk::MESSAGE_WARNING,
3808                                                    Gtk::BUTTONS_OK);
3809                                 win.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME));
3810                                 win.set_position (Gtk::WIN_POS_CENTER);
3811                                 win.present ();
3812                                 win.run ();
3813                         }
3814                 }
3815         }
3816 }
3817
3818 /** Add a window proxy to our list, so that its state will be saved.
3819  *  This call also causes the window to be created and opened if its
3820  *  state was saved as `visible'.
3821  */
3822 void
3823 ARDOUR_UI::add_window_proxy (WindowProxyBase* p)
3824 {
3825         _window_proxies.push_back (p);
3826         p->maybe_show ();
3827 }
3828
3829 /** Remove a window proxy from our list.  Must be called if a WindowProxy
3830  *  is deleted, to prevent hanging pointers.
3831  */
3832 void
3833 ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
3834 {
3835         _window_proxies.remove (p);
3836 }
3837
3838 int
3839 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
3840 {
3841         MissingFileDialog dialog (s, str, type);
3842
3843         dialog.show ();
3844         dialog.present ();
3845
3846         int result = dialog.run ();
3847         dialog.hide ();
3848
3849         switch (result) {
3850         case RESPONSE_OK:
3851                 break;
3852         default:
3853                 return 1; // quit entire session load
3854         }
3855
3856         result = dialog.get_action ();
3857
3858         return result;
3859 }
3860
3861 int
3862 ARDOUR_UI::ambiguous_file (std::string file, std::string /*path*/, std::vector<std::string> hits)
3863 {
3864         AmbiguousFileDialog dialog (file, hits);
3865
3866         dialog.show ();
3867         dialog.present ();
3868
3869         dialog.run ();
3870         return dialog.get_which ();
3871 }
3872
3873 /** Allocate our thread-local buffers */
3874 void
3875 ARDOUR_UI::get_process_buffers ()
3876 {
3877         _process_thread->get_buffers ();
3878 }
3879
3880 /** Drop our thread-local buffers */
3881 void
3882 ARDOUR_UI::drop_process_buffers ()
3883 {
3884         _process_thread->drop_buffers ();
3885 }
3886
3887 void
3888 ARDOUR_UI::feedback_detected ()
3889 {
3890         _feedback_exists = true;
3891 }
3892
3893 void
3894 ARDOUR_UI::successful_graph_sort ()
3895 {
3896         _feedback_exists = false;
3897 }
3898
3899 void
3900 ARDOUR_UI::midi_panic ()
3901 {
3902         if (_session) {
3903                 _session->midi_panic();
3904         }
3905 }