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