use hovering/show click for transport buttons, and remove fixed-size size requests...
[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 (_("Auto Return"))
157         , auto_play_button (_("Auto Play"))
158         , auto_input_button (_("Auto Input"))
159           // , click_button (_("Click"))
160         , time_master_button (_("time\nmaster"))
161
162         , auditioning_alert_button (_("AUDITION"))
163         , solo_alert_button (_("SOLO"))
164
165         , error_log_button (_("Errors"))
166
167         , _status_bar_visibility (X_("status-bar"))
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
240         roll_button.set_tweaks (ArdourButton::ShowHover);
241         stop_button.set_tweaks (ArdourButton::ShowHover);
242         auto_loop_button.set_tweaks (ArdourButton::ShowHover);
243         play_selection_button.set_tweaks (ArdourButton::ShowHover);
244         rec_button.set_tweaks (ArdourButton::ShowHover);
245         join_play_range_button.set_tweaks (ArdourButton::ShowHover);
246
247         goto_start_button.set_tweaks (ArdourButton::Tweaks(ArdourButton::ShowClick|ArdourButton::ShowHover));
248         goto_end_button.set_tweaks (ArdourButton::Tweaks(ArdourButton::ShowClick|ArdourButton::ShowHover));
249         
250         last_configure_time= 0;
251         last_peak_grab = 0;
252
253         ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
254         ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
255
256         /* handle dialog requests */
257
258         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
259
260         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
261
262         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
263
264         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
265
266         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
267
268         /* handle requests to quit (coming from JACK session) */
269
270         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::finish, 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                 frames -= hrs * fr * 3600;
1142                 mins = frames / (fr * 60);
1143                 frames -= mins * fr * 60;
1144                 secs = frames / fr;
1145
1146                 bool const low = (hrs == 0 && mins <= 30);
1147
1148                 snprintf (
1149                         buf, sizeof(buf),
1150                         _("Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"),
1151                         low ? X_("red") : X_("green"),
1152                         hrs, mins, secs
1153                         );
1154         }
1155
1156         disk_space_label.set_markup (buf);
1157
1158         // An attempt to make the disk space label flash red when space has run out.
1159
1160         if (frames < fr * 60 * 5) {
1161         /*      disk_space_box.style ("disk_space_label_empty"); */
1162         } else {
1163         /*      disk_space_box.style ("disk_space_label"); */
1164         }
1165
1166 }
1167
1168 gint
1169 ARDOUR_UI::update_wall_clock ()
1170 {
1171         time_t now;
1172         struct tm *tm_now;
1173         char buf[16];
1174
1175         time (&now);
1176         tm_now = localtime (&now);
1177
1178         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1179         wall_clock_label.set_text (buf);
1180
1181         return TRUE;
1182 }
1183
1184 gint
1185 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1186 {
1187         session_popup_menu->popup (0, 0);
1188         return TRUE;
1189 }
1190
1191 void
1192 ARDOUR_UI::redisplay_recent_sessions ()
1193 {
1194         std::vector<sys::path> session_directories;
1195         RecentSessionsSorter cmp;
1196
1197         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1198         recent_session_model->clear ();
1199
1200         ARDOUR::RecentSessions rs;
1201         ARDOUR::read_recent_sessions (rs);
1202
1203         if (rs.empty()) {
1204                 recent_session_display.set_model (recent_session_model);
1205                 return;
1206         }
1207         //
1208         // sort them alphabetically
1209         sort (rs.begin(), rs.end(), cmp);
1210
1211         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1212                 session_directories.push_back ((*i).second);
1213         }
1214
1215         for (vector<sys::path>::const_iterator i = session_directories.begin();
1216                         i != session_directories.end(); ++i)
1217         {
1218                 std::vector<sys::path> state_file_paths;
1219
1220                 // now get available states for this session
1221
1222                 get_state_files_in_directory (*i, state_file_paths);
1223
1224                 vector<string*>* states;
1225                 vector<const gchar*> item;
1226                 string fullpath = (*i).to_string();
1227
1228                 /* remove any trailing / */
1229
1230                 if (fullpath[fullpath.length()-1] == '/') {
1231                         fullpath = fullpath.substr (0, fullpath.length()-1);
1232                 }
1233
1234                 /* check whether session still exists */
1235                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1236                         /* session doesn't exist */
1237                         cerr << "skipping non-existent session " << fullpath << endl;
1238                         continue;
1239                 }
1240
1241                 /* now get available states for this session */
1242
1243                 if ((states = Session::possible_states (fullpath)) == 0) {
1244                         /* no state file? */
1245                         continue;
1246                 }
1247
1248                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1249
1250                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1251
1252                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1253                 row[recent_session_columns.fullpath] = fullpath;
1254
1255                 if (state_file_names.size() > 1) {
1256
1257                         // add the children
1258
1259                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1260                                         i2 != state_file_names.end(); ++i2)
1261                         {
1262
1263                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1264
1265                                 child_row[recent_session_columns.visible_name] = *i2;
1266                                 child_row[recent_session_columns.fullpath] = fullpath;
1267                         }
1268                 }
1269         }
1270
1271         recent_session_display.set_model (recent_session_model);
1272 }
1273
1274 void
1275 ARDOUR_UI::build_session_selector ()
1276 {
1277         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1278
1279         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1280
1281         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1282         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1283         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1284         recent_session_model = TreeStore::create (recent_session_columns);
1285         recent_session_display.set_model (recent_session_model);
1286         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1287         recent_session_display.set_headers_visible (false);
1288         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1289         recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1290
1291         scroller->add (recent_session_display);
1292         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1293
1294         session_selector_window->set_name ("SessionSelectorWindow");
1295         session_selector_window->set_size_request (200, 400);
1296         session_selector_window->get_vbox()->pack_start (*scroller);
1297
1298         recent_session_display.show();
1299         scroller->show();
1300         //session_selector_window->get_vbox()->show();
1301 }
1302
1303 void
1304 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1305 {
1306         session_selector_window->response (RESPONSE_ACCEPT);
1307 }
1308
1309 void
1310 ARDOUR_UI::open_recent_session ()
1311 {
1312         bool can_return = (_session != 0);
1313
1314         if (session_selector_window == 0) {
1315                 build_session_selector ();
1316         }
1317
1318         redisplay_recent_sessions ();
1319
1320         while (true) {
1321
1322                 session_selector_window->set_position (WIN_POS_MOUSE);
1323
1324                 ResponseType r = (ResponseType) session_selector_window->run ();
1325
1326                 switch (r) {
1327                 case RESPONSE_ACCEPT:
1328                         break;
1329                 default:
1330                         if (can_return) {
1331                                 session_selector_window->hide();
1332                                 return;
1333                         } else {
1334                                 exit (1);
1335                         }
1336                 }
1337
1338                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1339                         continue;
1340                 }
1341
1342                 session_selector_window->hide();
1343
1344                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1345
1346                 if (i == recent_session_model->children().end()) {
1347                         return;
1348                 }
1349
1350                 std::string path = (*i)[recent_session_columns.fullpath];
1351                 std::string state = (*i)[recent_session_columns.visible_name];
1352
1353                 _session_is_new = false;
1354
1355                 if (load_session (path, state) == 0) {
1356                         break;
1357                 }
1358
1359                 can_return = false;
1360         }
1361 }
1362
1363 bool
1364 ARDOUR_UI::check_audioengine ()
1365 {
1366         if (engine) {
1367                 if (!engine->connected()) {
1368                         MessageDialog msg (string_compose (
1369                                                    _("%1 is not connected to JACK\n"
1370                                                      "You cannot open or close sessions in this condition"),
1371                                                    PROGRAM_NAME));
1372                         pop_back_splash ();
1373                         msg.run ();
1374                         return false;
1375                 }
1376                 return true;
1377         } else {
1378                 return false;
1379         }
1380 }
1381
1382 void
1383 ARDOUR_UI::open_session ()
1384 {
1385         if (!check_audioengine()) {
1386                 return;
1387
1388         }
1389
1390         /* popup selector window */
1391
1392         if (open_session_selector == 0) {
1393
1394                 /* ardour sessions are folders */
1395
1396                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1397                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1398                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1399                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1400
1401                 FileFilter session_filter;
1402                 session_filter.add_pattern ("*.ardour");
1403                 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1404                 open_session_selector->add_filter (session_filter);
1405                 open_session_selector->set_filter (session_filter);
1406         }
1407
1408         int response = open_session_selector->run();
1409         open_session_selector->hide ();
1410
1411         switch (response) {
1412         case RESPONSE_ACCEPT:
1413                 break;
1414         default:
1415                 open_session_selector->hide();
1416                 return;
1417         }
1418
1419         open_session_selector->hide();
1420         string session_path = open_session_selector->get_filename();
1421         string path, name;
1422         bool isnew;
1423
1424         if (session_path.length() > 0) {
1425                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1426                         _session_is_new = isnew;
1427                         load_session (path, name);
1428                 }
1429         }
1430 }
1431
1432
1433 void
1434 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, string const & name_template)
1435 {
1436         list<boost::shared_ptr<MidiTrack> > tracks;
1437
1438         if (_session == 0) {
1439                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1440                 return;
1441         }
1442
1443         try {
1444                 if (disk) {
1445
1446                         tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many, name_template);
1447
1448                         if (tracks.size() != how_many) {
1449                                 if (how_many == 1) {
1450                                         error << _("could not create a new midi track") << endmsg;
1451                                 } else {
1452                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1453                                 }
1454                         }
1455                 } /*else {
1456                         if ((route = _session->new_midi_route ()) == 0) {
1457                                 error << _("could not create new midi bus") << endmsg;
1458                         }
1459                 }*/
1460         }
1461
1462         catch (...) {
1463                 MessageDialog msg (*editor,
1464                                    string_compose (_("There are insufficient JACK ports available\n\
1465 to create a new track or bus.\n\
1466 You should save %1, exit and\n\
1467 restart JACK with more ports."), PROGRAM_NAME));
1468                 msg.run ();
1469         }
1470 }
1471
1472
1473 void
1474 ARDOUR_UI::session_add_audio_route (
1475         bool track,
1476         int32_t input_channels,
1477         int32_t output_channels,
1478         ARDOUR::TrackMode mode,
1479         RouteGroup* route_group,
1480         uint32_t how_many,
1481         string const & name_template
1482         )
1483 {
1484         list<boost::shared_ptr<AudioTrack> > tracks;
1485         RouteList routes;
1486
1487         if (_session == 0) {
1488                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1489                 return;
1490         }
1491
1492         try {
1493                 if (track) {
1494                         tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1495
1496                         if (tracks.size() != how_many) {
1497                                 if (how_many == 1) {
1498                                         error << _("could not create a new audio track") << endmsg;
1499                                 } else {
1500                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1501                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1502                                 }
1503                         }
1504
1505                 } else {
1506
1507                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1508
1509                         if (routes.size() != how_many) {
1510                                 if (how_many == 1) {
1511                                         error << _("could not create a new audio bus") << endmsg;
1512                                 } else {
1513                                         error << string_compose (_("could not create %1 new audio busses"), how_many) << endmsg;
1514                                 }
1515                         }
1516                 }
1517         }
1518
1519         catch (...) {
1520                 MessageDialog msg (*editor,
1521                                    string_compose (_("There are insufficient JACK ports available\n\
1522 to create a new track or bus.\n\
1523 You should save %1, exit and\n\
1524 restart JACK with more ports."), PROGRAM_NAME));
1525                 pop_back_splash ();
1526                 msg.run ();
1527         }
1528 }
1529
1530 void
1531 ARDOUR_UI::do_transport_locate (framepos_t new_position, bool with_roll)
1532 {
1533         framecnt_t _preroll = 0;
1534
1535         if (_session) {
1536                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1537                 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1538
1539                 if (new_position > _preroll) {
1540                         new_position -= _preroll;
1541                 } else {
1542                         new_position = 0;
1543                 }
1544
1545                 _session->request_locate (new_position, with_roll);
1546         }
1547 }
1548
1549 void
1550 ARDOUR_UI::transport_goto_start ()
1551 {
1552         if (_session) {
1553                 _session->goto_start();
1554
1555                 /* force displayed area in editor to start no matter
1556                    what "follow playhead" setting is.
1557                 */
1558
1559                 if (editor) {
1560                         editor->center_screen (_session->current_start_frame ());
1561                 }
1562         }
1563 }
1564
1565 void
1566 ARDOUR_UI::transport_goto_zero ()
1567 {
1568         if (_session) {
1569                 _session->request_locate (0);
1570
1571                 /* force displayed area in editor to start no matter
1572                    what "follow playhead" setting is.
1573                 */
1574
1575                 if (editor) {
1576                         editor->reset_x_origin (0);
1577                 }
1578         }
1579 }
1580
1581 void
1582 ARDOUR_UI::transport_goto_wallclock ()
1583 {
1584         if (_session && editor) {
1585
1586                 time_t now;
1587                 struct tm tmnow;
1588                 framepos_t frames;
1589
1590                 time (&now);
1591                 localtime_r (&now, &tmnow);
1592
1593                 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1594                 frames += tmnow.tm_min * (60 * _session->frame_rate());
1595                 frames += tmnow.tm_sec * _session->frame_rate();
1596
1597                 _session->request_locate (frames, _session->transport_rolling ());
1598
1599                 /* force displayed area in editor to start no matter
1600                    what "follow playhead" setting is.
1601                 */
1602
1603                 if (editor) {
1604                         editor->center_screen (frames);
1605                 }
1606         }
1607 }
1608
1609 void
1610 ARDOUR_UI::transport_goto_end ()
1611 {
1612         if (_session) {
1613                 framepos_t const frame = _session->current_end_frame();
1614                 _session->request_locate (frame);
1615
1616                 /* force displayed area in editor to start no matter
1617                    what "follow playhead" setting is.
1618                 */
1619
1620                 if (editor) {
1621                         editor->center_screen (frame);
1622                 }
1623         }
1624 }
1625
1626 void
1627 ARDOUR_UI::transport_stop ()
1628 {
1629         if (!_session) {
1630                 return;
1631         }
1632
1633         if (_session->is_auditioning()) {
1634                 _session->cancel_audition ();
1635                 return;
1636         }
1637
1638         _session->request_stop (false, true);
1639 }
1640
1641 void
1642 ARDOUR_UI::transport_stop_and_forget_capture ()
1643 {
1644         if (_session) {
1645                 _session->request_stop (true, true);
1646         }
1647 }
1648
1649 void
1650 ARDOUR_UI::remove_last_capture()
1651 {
1652         if (editor) {
1653                 editor->remove_last_capture();
1654         }
1655 }
1656
1657 void
1658 ARDOUR_UI::transport_record (bool roll)
1659 {
1660
1661         if (_session) {
1662                 switch (_session->record_status()) {
1663                 case Session::Disabled:
1664                         if (_session->ntracks() == 0) {
1665                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1666                                 msg.run ();
1667                                 return;
1668                         }
1669                         _session->maybe_enable_record ();
1670                         if (roll) {
1671                                 transport_roll ();
1672                         }
1673                         break;
1674                 case Session::Recording:
1675                         if (roll) {
1676                                 _session->request_stop();
1677                         } else {
1678                                 _session->disable_record (false, true);
1679                         }
1680                         break;
1681
1682                 case Session::Enabled:
1683                         _session->disable_record (false, true);
1684                 }
1685         }
1686         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1687 }
1688
1689 void
1690 ARDOUR_UI::transport_roll ()
1691 {
1692         if (!_session) {
1693                 return;
1694         }
1695
1696         if (_session->is_auditioning()) {
1697                 return;
1698         }
1699
1700 #if 0
1701         if (_session->config.get_external_sync()) {
1702                 switch (_session->config.get_sync_source()) {
1703                 case JACK:
1704                         break;
1705                 default:
1706                         /* transport controlled by the master */
1707                         return;
1708                 }
1709         }
1710 #endif
1711
1712         bool rolling = _session->transport_rolling();
1713
1714         if (_session->get_play_loop()) {
1715                 /* XXX it is not possible to just leave seamless loop and keep
1716                    playing at present (nov 4th 2009)
1717                 */
1718                 if (!Config->get_seamless_loop()) {
1719                         _session->request_play_loop (false, true);
1720                 }
1721         } else if (_session->get_play_range () && !join_play_range_button.active_state()) {
1722                 /* stop playing a range if we currently are */
1723                 _session->request_play_range (0, true);
1724         }
1725
1726         if (join_play_range_button.active_state()) {
1727                 _session->request_play_range (&editor->get_selection().time, true);
1728         }
1729
1730         if (!rolling) {
1731                 _session->request_transport_speed (1.0f);
1732         }
1733 }
1734
1735 void
1736 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1737 {
1738
1739         if (!_session) {
1740                 return;
1741         }
1742
1743         if (_session->is_auditioning()) {
1744                 _session->cancel_audition ();
1745                 return;
1746         }
1747
1748         if (_session->config.get_external_sync()) {
1749                 switch (_session->config.get_sync_source()) {
1750                 case JACK:
1751                         break;
1752                 default:
1753                         /* transport controlled by the master */
1754                         return;
1755                 }
1756         }
1757
1758         bool rolling = _session->transport_rolling();
1759         bool affect_transport = true;
1760
1761         if (rolling && roll_out_of_bounded_mode) {
1762                 /* drop out of loop/range playback but leave transport rolling */
1763                 if (_session->get_play_loop()) {
1764                         if (Config->get_seamless_loop()) {
1765                                 /* the disk buffers contain copies of the loop - we can't
1766                                    just keep playing, so stop the transport. the user
1767                                    can restart as they wish.
1768                                 */
1769                                 affect_transport = true;
1770                         } else {
1771                                 /* disk buffers are normal, so we can keep playing */
1772                                 affect_transport = false;
1773                         }
1774                         _session->request_play_loop (false, true);
1775                 } else if (_session->get_play_range ()) {
1776                         affect_transport = false;
1777                         _session->request_play_range (0, true);
1778                 }
1779         }
1780
1781         if (affect_transport) {
1782                 if (rolling) {
1783                         _session->request_stop (with_abort, true);
1784                 } else {
1785                         if (join_play_range_button.active_state()) {
1786                                 _session->request_play_range (&editor->get_selection().time, true);
1787                         }
1788
1789                         _session->request_transport_speed (1.0f);
1790                 }
1791         }
1792 }
1793
1794 void
1795 ARDOUR_UI::toggle_session_auto_loop ()
1796 {
1797         if (!_session) {
1798                 return;
1799         }
1800
1801         if (_session->get_play_loop()) {
1802
1803                 if (_session->transport_rolling()) {
1804
1805                         Location * looploc = _session->locations()->auto_loop_location();
1806
1807                         if (looploc) {
1808                                 _session->request_locate (looploc->start(), true);
1809                                 _session->request_play_loop (false);
1810                         }
1811
1812                 } else {
1813                         _session->request_play_loop (false);
1814                 }
1815         } else {
1816
1817           Location * looploc = _session->locations()->auto_loop_location();
1818
1819                 if (looploc) {
1820                         _session->request_play_loop (true);
1821                 }
1822         }
1823 }
1824
1825 void
1826 ARDOUR_UI::transport_play_selection ()
1827 {
1828         if (!_session) {
1829                 return;
1830         }
1831
1832         editor->play_selection ();
1833 }
1834
1835 void
1836 ARDOUR_UI::transport_rewind (int option)
1837 {
1838         float current_transport_speed;
1839
1840         if (_session) {
1841                 current_transport_speed = _session->transport_speed();
1842
1843                 if (current_transport_speed >= 0.0f) {
1844                         switch (option) {
1845                         case 0:
1846                                 _session->request_transport_speed (-1.0f);
1847                                 break;
1848                         case 1:
1849                                 _session->request_transport_speed (-4.0f);
1850                                 break;
1851                         case -1:
1852                                 _session->request_transport_speed (-0.5f);
1853                                 break;
1854                         }
1855                 } else {
1856                         /* speed up */
1857                         _session->request_transport_speed (current_transport_speed * 1.5f);
1858                 }
1859         }
1860 }
1861
1862 void
1863 ARDOUR_UI::transport_forward (int option)
1864 {
1865         float current_transport_speed;
1866
1867         if (_session) {
1868                 current_transport_speed = _session->transport_speed();
1869
1870                 if (current_transport_speed <= 0.0f) {
1871                         switch (option) {
1872                         case 0:
1873                                 _session->request_transport_speed (1.0f);
1874                                 break;
1875                         case 1:
1876                                 _session->request_transport_speed (4.0f);
1877                                 break;
1878                         case -1:
1879                                 _session->request_transport_speed (0.5f);
1880                                 break;
1881                         }
1882                 } else {
1883                         /* speed up */
1884                         _session->request_transport_speed (current_transport_speed * 1.5f);
1885                 }
1886
1887         }
1888 }
1889
1890 void
1891 ARDOUR_UI::toggle_record_enable (uint32_t rid)
1892 {
1893         if (_session == 0) {
1894                 return;
1895         }
1896
1897         boost::shared_ptr<Route> r;
1898
1899         if ((r = _session->route_by_remote_id (rid)) != 0) {
1900
1901                 Track* t;
1902
1903                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1904                         t->set_record_enabled (!t->record_enabled(), this);
1905                 }
1906         }
1907         if (_session == 0) {
1908                 return;
1909         }
1910 }
1911
1912 void
1913 ARDOUR_UI::map_transport_state ()
1914 {
1915         if (!_session) {
1916                 auto_loop_button.unset_active_state ();
1917                 play_selection_button.unset_active_state ();
1918                 roll_button.unset_active_state ();
1919                 stop_button.set_active_state (Gtkmm2ext::Active);
1920                 return;
1921         }
1922
1923         shuttle_box->map_transport_state ();
1924
1925         float sp = _session->transport_speed();
1926
1927         if (sp != 0.0f) {
1928
1929                 /* we're rolling */
1930
1931                 if (_session->get_play_range()) {
1932
1933                         play_selection_button.set_active_state (Gtkmm2ext::Active);
1934                         roll_button.unset_active_state ();
1935                         auto_loop_button.unset_active_state ();
1936
1937                 } else if (_session->get_play_loop ()) {
1938
1939                         auto_loop_button.set_active_state (Gtkmm2ext::Active);
1940                         play_selection_button.unset_active_state ();
1941                         roll_button.unset_active_state ();
1942
1943                 } else {
1944
1945                         roll_button.set_active_state (Gtkmm2ext::Active);
1946                         play_selection_button.unset_active_state ();
1947                         auto_loop_button.unset_active_state ();
1948                 }
1949
1950                 if (join_play_range_button.active_state()) {
1951                         /* light up both roll and play-selection if they are joined */
1952                         roll_button.set_active_state (Gtkmm2ext::Active);
1953                         play_selection_button.set_active_state (Gtkmm2ext::Active);
1954                 }
1955
1956                 stop_button.unset_active_state ();
1957
1958         } else {
1959
1960                 stop_button.set_active_state (Gtkmm2ext::Active);
1961                 roll_button.unset_active_state ();
1962                 play_selection_button.unset_active_state ();
1963                 auto_loop_button.unset_active_state ();
1964                 update_disk_space ();
1965         }
1966 }
1967
1968 void
1969 ARDOUR_UI::engine_stopped ()
1970 {
1971         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1972         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1973         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1974 }
1975
1976 void
1977 ARDOUR_UI::engine_running ()
1978 {
1979         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1980         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1981         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1982
1983         Glib::RefPtr<Action> action;
1984         const char* action_name = 0;
1985
1986         switch (engine->frames_per_cycle()) {
1987         case 32:
1988                 action_name = X_("JACKLatency32");
1989                 break;
1990         case 64:
1991                 action_name = X_("JACKLatency64");
1992                 break;
1993         case 128:
1994                 action_name = X_("JACKLatency128");
1995                 break;
1996         case 512:
1997                 action_name = X_("JACKLatency512");
1998                 break;
1999         case 1024:
2000                 action_name = X_("JACKLatency1024");
2001                 break;
2002         case 2048:
2003                 action_name = X_("JACKLatency2048");
2004                 break;
2005         case 4096:
2006                 action_name = X_("JACKLatency4096");
2007                 break;
2008         case 8192:
2009                 action_name = X_("JACKLatency8192");
2010                 break;
2011         default:
2012                 /* XXX can we do anything useful ? */
2013                 break;
2014         }
2015
2016         if (action_name) {
2017
2018                 action = ActionManager::get_action (X_("JACK"), action_name);
2019
2020                 if (action) {
2021                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
2022                         ract->set_active ();
2023                 }
2024         }
2025 }
2026
2027 void
2028 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
2029 {
2030         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
2031                 /* we can't rely on the original string continuing to exist when we are called
2032                    again in the GUI thread, so make a copy and note that we need to
2033                    free it later.
2034                 */
2035                 char *copy = strdup (reason);
2036                 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
2037                 return;
2038         }
2039
2040         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2041         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2042
2043         update_sample_rate (0);
2044
2045         string msgstr;
2046
2047         /* if the reason is a non-empty string, it means that the backend was shutdown
2048            rather than just Ardour.
2049         */
2050
2051         if (strlen (reason)) {
2052                 msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
2053         } else {
2054                 msgstr = string_compose (_("\
2055 JACK has either been shutdown or it\n\
2056 disconnected %1 because %1\n\
2057 was not fast enough. Try to restart\n\
2058 JACK, reconnect and save the session."), PROGRAM_NAME);
2059         }
2060
2061         MessageDialog msg (*editor, msgstr);
2062         pop_back_splash ();
2063         msg.run ();
2064
2065         if (free_reason) {
2066                 free ((char*) reason);
2067         }
2068 }
2069
2070 int32_t
2071 ARDOUR_UI::do_engine_start ()
2072 {
2073         try {
2074                 engine->start();
2075         }
2076
2077         catch (...) {
2078                 engine->stop ();
2079                 error << _("Unable to start the session running")
2080                       << endmsg;
2081                 unload_session ();
2082                 return -2;
2083         }
2084
2085         return 0;
2086 }
2087
2088 void
2089 ARDOUR_UI::setup_theme ()
2090 {
2091         theme_manager->setup_theme();
2092 }
2093
2094 void
2095 ARDOUR_UI::update_clocks ()
2096 {
2097         if (!editor || !editor->dragging_playhead()) {
2098                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
2099         }
2100 }
2101
2102 void
2103 ARDOUR_UI::start_clocking ()
2104 {
2105         clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2106 }
2107
2108 void
2109 ARDOUR_UI::stop_clocking ()
2110 {
2111         clock_signal_connection.disconnect ();
2112 }
2113
2114 void
2115 ARDOUR_UI::toggle_clocking ()
2116 {
2117 #if 0
2118         if (clock_button.get_active()) {
2119                 start_clocking ();
2120         } else {
2121                 stop_clocking ();
2122         }
2123 #endif
2124 }
2125
2126 gint
2127 ARDOUR_UI::_blink (void *arg)
2128
2129 {
2130         ((ARDOUR_UI *) arg)->blink ();
2131         return TRUE;
2132 }
2133
2134 void
2135 ARDOUR_UI::blink ()
2136 {
2137         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2138 }
2139
2140 void
2141 ARDOUR_UI::start_blinking ()
2142 {
2143         /* Start the blink signal. Everybody with a blinking widget
2144            uses Blink to drive the widget's state.
2145         */
2146
2147         if (blink_timeout_tag < 0) {
2148                 blink_on = false;
2149                 blink_timeout_tag = g_timeout_add (240, _blink, this);
2150         }
2151 }
2152
2153 void
2154 ARDOUR_UI::stop_blinking ()
2155 {
2156         if (blink_timeout_tag >= 0) {
2157                 g_source_remove (blink_timeout_tag);
2158                 blink_timeout_tag = -1;
2159         }
2160 }
2161
2162
2163 /** Ask the user for the name of a new shapshot and then take it.
2164  */
2165
2166 void
2167 ARDOUR_UI::snapshot_session (bool switch_to_it)
2168 {
2169         ArdourPrompter prompter (true);
2170         string snapname;
2171
2172         prompter.set_name ("Prompter");
2173         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2174         prompter.set_title (_("Take Snapshot"));
2175         prompter.set_prompt (_("Name of new snapshot"));
2176
2177         if (!switch_to_it) {
2178                 char timebuf[128];
2179                 time_t n;
2180                 struct tm local_time;
2181
2182                 time (&n);
2183                 localtime_r (&n, &local_time);
2184                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2185                 prompter.set_initial_text (timebuf);
2186         }
2187
2188   again:
2189         switch (prompter.run()) {
2190         case RESPONSE_ACCEPT:
2191         {
2192                 prompter.get_result (snapname);
2193
2194                 bool do_save = (snapname.length() != 0);
2195
2196                 if (do_save) {
2197                         if (snapname.find ('/') != string::npos) {
2198                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2199                                                      "snapshot names may not contain a '/' character"));
2200                                 msg.run ();
2201                                 goto again;
2202                         }
2203                         if (snapname.find ('\\') != string::npos) {
2204                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2205                                                      "snapshot names may not contain a '\\' character"));
2206                                 msg.run ();
2207                                 goto again;
2208                         }
2209                         if (snapname.find (':') != string::npos) {
2210                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2211                                                      "snapshot names may not contain a ':' character"));
2212                                 msg.run ();
2213                                 goto again;
2214                         }
2215                 }
2216
2217                 vector<sys::path> p;
2218                 get_state_files_in_directory (_session->session_directory().root_path(), p);
2219                 vector<string> n = get_file_names_no_extension (p);
2220                 if (find (n.begin(), n.end(), snapname) != n.end()) {
2221
2222                         ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
2223                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
2224                         confirm.get_vbox()->pack_start (m, true, true);
2225                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2226                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2227                         confirm.show_all ();
2228                         switch (confirm.run()) {
2229                         case RESPONSE_CANCEL:
2230                                 do_save = false;
2231                         }
2232                 }
2233
2234                 if (do_save) {
2235                         save_state (snapname, switch_to_it);
2236                 }
2237                 break;
2238         }
2239
2240         default:
2241                 break;
2242         }
2243 }
2244
2245 /** Ask the user for the name of a new shapshot and then take it.
2246  */
2247
2248 void
2249 ARDOUR_UI::rename_session ()
2250 {
2251         if (!_session) {
2252                 return;
2253         }
2254
2255         ArdourPrompter prompter (true);
2256         string name;
2257
2258         prompter.set_name ("Prompter");
2259         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2260         prompter.set_title (_("Rename Session"));
2261         prompter.set_prompt (_("New session name"));
2262
2263   again:
2264         switch (prompter.run()) {
2265         case RESPONSE_ACCEPT:
2266         {
2267                 prompter.get_result (name);
2268
2269                 bool do_rename = (name.length() != 0);
2270
2271                 if (do_rename) {
2272                         if (name.find ('/') != string::npos) {
2273                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2274                                                      "session names may not contain a '/' character"));
2275                                 msg.run ();
2276                                 goto again;
2277                         }
2278                         if (name.find ('\\') != string::npos) {
2279                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2280                                                      "session names may not contain a '\\' character"));
2281                                 msg.run ();
2282                                 goto again;
2283                         }
2284
2285                         switch (_session->rename (name)) {
2286                         case -1: {
2287                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2288                                 msg.set_position (WIN_POS_MOUSE);
2289                                 msg.run ();
2290                                 goto again;
2291                                 break;
2292                         }
2293                         case 0:
2294                                 break;
2295                         default: {
2296                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2297                                 msg.set_position (WIN_POS_MOUSE);
2298                                 msg.run ();
2299                                 break;
2300                         }
2301                         }
2302                 }
2303                 
2304                 break;
2305         }
2306
2307         default:
2308                 break;
2309         }
2310 }
2311
2312 void
2313 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2314 {
2315         XMLNode* node = new XMLNode (X_("UI"));
2316
2317         for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) {
2318                 if (!(*i)->rc_configured()) {
2319                         node->add_child_nocopy (*((*i)->get_state ()));
2320                 }
2321         }
2322
2323         node->add_child_nocopy (gui_object_state->get_state());
2324
2325         _session->add_extra_xml (*node);
2326
2327         save_state_canfail (name, switch_to_it);
2328 }
2329
2330 int
2331 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2332 {
2333         if (_session) {
2334                 int ret;
2335
2336                 if (name.length() == 0) {
2337                         name = _session->snap_name();
2338                 }
2339
2340                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2341                         return ret;
2342                 }
2343         }
2344
2345         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2346         return 0;
2347 }
2348
2349 void
2350 ARDOUR_UI::primary_clock_value_changed ()
2351 {
2352         if (_session) {
2353                 _session->request_locate (primary_clock->current_time ());
2354         }
2355 }
2356
2357 void
2358 ARDOUR_UI::big_clock_value_changed ()
2359 {
2360         if (_session) {
2361                 _session->request_locate (big_clock->current_time ());
2362         }
2363 }
2364
2365 void
2366 ARDOUR_UI::secondary_clock_value_changed ()
2367 {
2368         if (_session) {
2369                 _session->request_locate (secondary_clock->current_time ());
2370         }
2371 }
2372
2373 void
2374 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2375 {
2376         if (_session == 0) {
2377                 return;
2378         }
2379
2380         if (_session->step_editing()) {
2381                 return;
2382         }
2383
2384         Session::RecordState const r = _session->record_status ();
2385         bool const h = _session->have_rec_enabled_track ();
2386
2387         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2388                 if (onoff) {
2389                         rec_button.set_active_state (Active);
2390                 } else {
2391                         rec_button.set_active_state (Mid);
2392                 }
2393         } else if (r == Session::Recording && h) {
2394                 rec_button.set_active_state (Mid);
2395         } else {
2396                 rec_button.unset_active_state ();
2397         }
2398 }
2399
2400 void
2401 ARDOUR_UI::save_template ()
2402 {
2403         ArdourPrompter prompter (true);
2404         string name;
2405
2406         if (!check_audioengine()) {
2407                 return;
2408         }
2409
2410         prompter.set_name (X_("Prompter"));
2411         prompter.set_title (_("Save Template"));
2412         prompter.set_prompt (_("Name for template:"));
2413         prompter.set_initial_text(_session->name() + _("-template"));
2414         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2415
2416         switch (prompter.run()) {
2417         case RESPONSE_ACCEPT:
2418                 prompter.get_result (name);
2419
2420                 if (name.length()) {
2421                         _session->save_template (name);
2422                 }
2423                 break;
2424
2425         default:
2426                 break;
2427         }
2428 }
2429
2430 void
2431 ARDOUR_UI::edit_metadata ()
2432 {
2433         SessionMetadataEditor dialog;
2434         dialog.set_session (_session);
2435         editor->ensure_float (dialog);
2436         dialog.run ();
2437 }
2438
2439 void
2440 ARDOUR_UI::import_metadata ()
2441 {
2442         SessionMetadataImporter dialog;
2443         dialog.set_session (_session);
2444         editor->ensure_float (dialog);
2445         dialog.run ();
2446 }
2447
2448 bool
2449 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2450 {
2451         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2452
2453         MessageDialog msg (str,
2454                            false,
2455                            Gtk::MESSAGE_WARNING,
2456                            Gtk::BUTTONS_YES_NO,
2457                            true);
2458
2459
2460         msg.set_name (X_("OpenExistingDialog"));
2461         msg.set_title (_("Open Existing Session"));
2462         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2463         msg.set_position (Gtk::WIN_POS_MOUSE);
2464         pop_back_splash ();
2465
2466         switch (msg.run()) {
2467         case RESPONSE_YES:
2468                 return true;
2469                 break;
2470         }
2471         return false;
2472 }
2473
2474 int
2475 ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::string& session_name)
2476 {
2477         BusProfile bus_profile;
2478
2479         if (Profile->get_sae()) {
2480
2481                 bus_profile.master_out_channels = 2;
2482                 bus_profile.input_ac = AutoConnectPhysical;
2483                 bus_profile.output_ac = AutoConnectMaster;
2484                 bus_profile.requested_physical_in = 0; // use all available
2485                 bus_profile.requested_physical_out = 0; // use all available
2486
2487         } else {
2488
2489                 /* get settings from advanced section of NSD */
2490
2491                 if (_startup->create_master_bus()) {
2492                         bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
2493                 } else {
2494                         bus_profile.master_out_channels = 0;
2495                 }
2496
2497                 if (_startup->connect_inputs()) {
2498                         bus_profile.input_ac = AutoConnectPhysical;
2499                 } else {
2500                         bus_profile.input_ac = AutoConnectOption (0);
2501                 }
2502
2503                 /// @todo some minor tweaks.
2504
2505                 bus_profile.output_ac = AutoConnectOption (0);
2506
2507                 if (_startup->connect_outputs ()) {
2508                         if (_startup->connect_outs_to_master()) {
2509                                 bus_profile.output_ac = AutoConnectMaster;
2510                         } else if (_startup->connect_outs_to_physical()) {
2511                                 bus_profile.output_ac = AutoConnectPhysical;
2512                         }
2513                 }
2514
2515                 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2516                 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2517         }
2518
2519         if (build_session (session_path, session_name, bus_profile)) {
2520                 return -1;
2521         }
2522
2523         return 0;
2524 }
2525
2526 void
2527 ARDOUR_UI::idle_load (const std::string& path)
2528 {
2529         if (_session) {
2530                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2531                         /* /path/to/foo => /path/to/foo, foo */
2532                         load_session (path, basename_nosuffix (path));
2533                 } else {
2534                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2535                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2536                 }
2537         } else {
2538
2539                 ARDOUR_COMMAND_LINE::session_name = path;
2540
2541                 /*
2542                  * new_session_dialog doens't exist in A3
2543                  * Try to remove all references to it to
2544                  * see if it will compile.  NOTE: this will
2545                  * likely cause a runtime issue is my somewhat
2546                  * uneducated guess.
2547                  */
2548
2549                 //if (new_session_dialog) {
2550
2551
2552                         /* make it break out of Dialog::run() and
2553                            start again.
2554                          */
2555
2556                         //new_session_dialog->response (1);
2557                 //}
2558         }
2559 }
2560
2561 void
2562 ARDOUR_UI::end_loading_messages ()
2563 {
2564         // hide_splash ();
2565 }
2566
2567 void
2568 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2569 {
2570         // show_splash ();
2571         // splash->message (msg);
2572         flush_pending ();
2573 }
2574
2575 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2576 int
2577 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2578 {
2579         string session_name;
2580         string session_path;
2581         string template_name;
2582         int ret = -1;
2583         bool likely_new = false;
2584
2585         if (!load_template.empty()) {
2586                 should_be_new = true;
2587                 template_name = load_template;
2588         }
2589
2590         while (ret != 0) {
2591
2592                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2593
2594                         /* if they named a specific statefile, use it, otherwise they are
2595                            just giving a session folder, and we want to use it as is
2596                            to find the session.
2597                         */
2598
2599                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2600
2601                         if (suffix != string::npos) {
2602                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2603                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2604                                 session_name = Glib::path_get_basename (session_name);
2605                         } else {
2606                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2607                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2608                         }
2609
2610                 } else {
2611
2612                         bool const apply = run_startup (should_be_new, load_template);
2613
2614                         if (!apply) {
2615                                 if (quit_on_cancel) {
2616                                         exit (1);
2617                                 } else {
2618                                         return ret;
2619                                 }
2620                         }
2621
2622                         /* if we run the startup dialog again, offer more than just "new session" */
2623
2624                         should_be_new = false;
2625
2626                         session_name = _startup->session_name (likely_new);
2627
2628                         string::size_type suffix = session_name.find (statefile_suffix);
2629
2630                         if (suffix != string::npos) {
2631                                 session_name = session_name.substr (0, suffix);
2632                         }
2633
2634                         /* this shouldn't happen, but we catch it just in case it does */
2635
2636                         if (session_name.empty()) {
2637                                 continue;
2638                         }
2639
2640                         if (_startup->use_session_template()) {
2641                                 template_name = _startup->session_template_name();
2642                                 _session_is_new = true;
2643                         }
2644
2645                         if (session_name[0] == G_DIR_SEPARATOR ||
2646                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
2647                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)) {
2648
2649                                 /* absolute path or cwd-relative path specified for session name: infer session folder
2650                                    from what was given.
2651                                 */
2652
2653                                 session_path = Glib::path_get_dirname (session_name);
2654                                 session_name = Glib::path_get_basename (session_name);
2655
2656                         } else {
2657
2658                                 session_path = _startup->session_folder();
2659
2660                                 if (session_name.find ('/') != string::npos) {
2661                                         MessageDialog msg (*_startup,
2662                                                            _("To ensure compatibility with various systems\n"
2663                                                              "session names may not contain a '/' character"));
2664                                         msg.run ();
2665                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2666                                         continue;
2667                                 }
2668
2669                                 if (session_name.find ('\\') != string::npos) {
2670                                         MessageDialog msg (*_startup,
2671                                                            _("To ensure compatibility with various systems\n"
2672                                                              "session names may not contain a '\\' character"));
2673                                         msg.run ();
2674                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2675                                         continue;
2676                                 }
2677                         }
2678                 }
2679
2680                 if (create_engine ()) {
2681                         break;
2682                 }
2683
2684                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2685
2686                         if (likely_new) {
2687
2688                                 std::string existing = Glib::build_filename (session_path, session_name);
2689
2690                                 if (!ask_about_loading_existing_session (existing)) {
2691                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2692                                         continue;
2693                                 }
2694                         }
2695
2696                         _session_is_new = false;
2697
2698                 } else {
2699
2700                         if (!likely_new) {
2701                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2702                                 msg.run ();
2703                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2704                                 continue;
2705                         }
2706
2707                         if (session_name.find ('/') != std::string::npos) {
2708                                 MessageDialog msg (*_startup,
2709                                                    _("To ensure compatibility with various systems\n"
2710                                                      "session names may not contain a '/' character"));
2711                                 msg.run ();
2712                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2713                                 continue;
2714                         }
2715
2716                         if (session_name.find ('\\') != std::string::npos) {
2717                                 MessageDialog msg (*_startup,
2718                                                    _("To ensure compatibility with various systems\n"
2719                                                      "session names may not contain a '\\' character"));
2720                                 msg.run ();
2721                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2722                                 continue;
2723                         }
2724
2725                         _session_is_new = true;
2726                 }
2727
2728                 if (likely_new && template_name.empty()) {
2729
2730                         ret = build_session_from_nsd (session_path, session_name);
2731
2732                 } else {
2733
2734                         ret = load_session (session_path, session_name, template_name);
2735
2736                         if (ret == -2) {
2737                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
2738                                 exit (1);
2739                         }
2740
2741                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2742                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2743                                 exit (1);
2744                         }
2745                 }
2746         }
2747
2748         return ret;
2749 }
2750
2751 void
2752 ARDOUR_UI::close_session()
2753 {
2754         if (!check_audioengine()) {
2755                 return;
2756         }
2757
2758         if (unload_session (true)) {
2759                 return;
2760         }
2761
2762         ARDOUR_COMMAND_LINE::session_name = "";
2763
2764         if (get_session_parameters (true, false)) {
2765                 exit (1);
2766         }
2767
2768         goto_editor_window ();
2769 }
2770
2771 /** @param snap_name Snapshot name (without .ardour suffix).
2772  *  @return -2 if the load failed because we are not connected to the AudioEngine.
2773  */
2774 int
2775 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
2776 {
2777         Session *new_session;
2778         int unload_status;
2779         int retval = -1;
2780
2781         session_loaded = false;
2782
2783         if (!check_audioengine()) {
2784                 return -2;
2785         }
2786
2787         unload_status = unload_session ();
2788
2789         if (unload_status < 0) {
2790                 goto out;
2791         } else if (unload_status > 0) {
2792                 retval = 0;
2793                 goto out;
2794         }
2795
2796         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
2797
2798         try {
2799                 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2800         }
2801
2802         /* this one is special */
2803
2804         catch (AudioEngine::PortRegistrationFailure& err) {
2805
2806                 MessageDialog msg (err.what(),
2807                                    true,
2808                                    Gtk::MESSAGE_INFO,
2809                                    Gtk::BUTTONS_CLOSE);
2810
2811                 msg.set_title (_("Port Registration Error"));
2812                 msg.set_secondary_text (_("Click the Close button to try again."));
2813                 msg.set_position (Gtk::WIN_POS_CENTER);
2814                 pop_back_splash ();
2815                 msg.present ();
2816
2817                 int response = msg.run ();
2818
2819                 msg.hide ();
2820
2821                 switch (response) {
2822                 case RESPONSE_CANCEL:
2823                         exit (1);
2824                 default:
2825                         break;
2826                 }
2827                 goto out;
2828         }
2829
2830         catch (...) {
2831
2832                 MessageDialog msg (string_compose(
2833                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
2834                                            path, snap_name),
2835                                    true,
2836                                    Gtk::MESSAGE_INFO,
2837                                    BUTTONS_OK);
2838
2839                 msg.set_title (_("Loading Error"));
2840                 msg.set_secondary_text (_("Click the Refresh button to try again."));
2841                 msg.add_button (Stock::REFRESH, 1);
2842                 msg.set_position (Gtk::WIN_POS_CENTER);
2843                 pop_back_splash ();
2844                 msg.present ();
2845
2846                 int response = msg.run ();
2847
2848                 switch (response) {
2849                 case 1:
2850                         break;
2851                 default:
2852                         exit (1);
2853                 }
2854
2855                 msg.hide ();
2856
2857                 goto out;
2858         }
2859
2860         {
2861                 list<string> const u = new_session->unknown_processors ();
2862                 if (!u.empty()) {
2863                         MissingPluginDialog d (_session, u);
2864                         d.run ();
2865                 }
2866         }
2867
2868         /* Now the session been created, add the transport controls */
2869         new_session->add_controllable(roll_controllable);
2870         new_session->add_controllable(stop_controllable);
2871         new_session->add_controllable(goto_start_controllable);
2872         new_session->add_controllable(goto_end_controllable);
2873         new_session->add_controllable(auto_loop_controllable);
2874         new_session->add_controllable(play_selection_controllable);
2875         new_session->add_controllable(rec_controllable);
2876
2877         set_session (new_session);
2878
2879         session_loaded = true;
2880
2881         goto_editor_window ();
2882
2883         if (_session) {
2884                 _session->set_clean ();
2885         }
2886
2887         flush_pending ();
2888         retval = 0;
2889
2890   out:
2891         return retval;
2892 }
2893
2894 int
2895 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
2896 {
2897         Session *new_session;
2898         int x;
2899
2900         if (!check_audioengine()) {
2901                 return -1;
2902         }
2903
2904         session_loaded = false;
2905
2906         x = unload_session ();
2907
2908         if (x < 0) {
2909                 return -1;
2910         } else if (x > 0) {
2911                 return 0;
2912         }
2913
2914         _session_is_new = true;
2915
2916         try {
2917                 new_session = new Session (*engine, path, snap_name, &bus_profile);
2918         }
2919
2920         catch (...) {
2921
2922                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2923                 pop_back_splash ();
2924                 msg.run ();
2925                 return -1;
2926         }
2927
2928         /* Give the new session the default GUI state, if such things exist */
2929
2930         XMLNode* n;
2931         n = Config->instant_xml (X_("Editor"));
2932         if (n) {
2933                 new_session->add_instant_xml (*n, false);
2934         }
2935         n = Config->instant_xml (X_("Mixer"));
2936         if (n) {
2937                 new_session->add_instant_xml (*n, false);
2938         }
2939
2940         /* Put the playhead at 0 and scroll fully left */
2941         n = new_session->instant_xml (X_("Editor"));
2942         if (n) {
2943                 n->add_property (X_("playhead"), X_("0"));
2944                 n->add_property (X_("left-frame"), X_("0"));
2945         }
2946
2947         set_session (new_session);
2948
2949         session_loaded = true;
2950
2951         new_session->save_state(new_session->name());
2952
2953         return 0;
2954 }
2955
2956 void
2957 ARDOUR_UI::launch_chat ()
2958 {
2959 #ifdef __APPLE__
2960         open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2961 #else
2962         open_uri("http://webchat.freenode.net/?channels=ardour");
2963 #endif
2964 }
2965
2966 void
2967 ARDOUR_UI::show_about ()
2968 {
2969         if (about == 0) {
2970                 about = new About;
2971                 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2972         }
2973
2974         about->set_transient_for(*editor);
2975         about->show_all ();
2976 }
2977
2978 void
2979 ARDOUR_UI::launch_manual ()
2980 {
2981         PBD::open_uri("http://ardour.org/flossmanual");
2982 }
2983
2984 void
2985 ARDOUR_UI::launch_reference ()
2986 {
2987         PBD::open_uri("http://ardour.org/refmanual");
2988 }
2989
2990 void
2991 ARDOUR_UI::hide_about ()
2992 {
2993         if (about) {
2994                 about->get_window()->set_cursor ();
2995                 about->hide ();
2996         }
2997 }
2998
2999 void
3000 ARDOUR_UI::about_signal_response (int /*response*/)
3001 {
3002         hide_about();
3003 }
3004
3005 void
3006 ARDOUR_UI::show_splash ()
3007 {
3008         if (splash == 0) {
3009                 try {
3010                         splash = new Splash;
3011                 } catch (...) {
3012                         return;
3013                 }
3014         }
3015
3016         splash->show ();
3017         splash->present ();
3018         splash->queue_draw ();
3019         splash->get_window()->process_updates (true);
3020         flush_pending ();
3021 }
3022
3023 void
3024 ARDOUR_UI::hide_splash ()
3025 {
3026         if (splash) {
3027                 splash->hide();
3028         }
3029 }
3030
3031 void
3032 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
3033                                     const string& plural_msg, const string& singular_msg)
3034 {
3035         size_t removed;
3036
3037         removed = rep.paths.size();
3038
3039         if (removed == 0) {
3040                 MessageDialog msgd (*editor,
3041                                     _("No files were ready for clean-up"),
3042                                     true,
3043                                     Gtk::MESSAGE_INFO,
3044                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
3045                 msgd.set_title (_("Clean-up"));
3046                 msgd.set_secondary_text (_("If this seems suprising, \n\
3047 check for any existing snapshots.\n\
3048 These may still include regions that\n\
3049 require some unused files to continue to exist."));
3050
3051                 msgd.run ();
3052                 return;
3053         }
3054
3055         ArdourDialog results (_("Clean-up"), true, false);
3056
3057         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3058             CleanupResultsModelColumns() {
3059                     add (visible_name);
3060                     add (fullpath);
3061             }
3062             Gtk::TreeModelColumn<std::string> visible_name;
3063             Gtk::TreeModelColumn<std::string> fullpath;
3064         };
3065
3066
3067         CleanupResultsModelColumns results_columns;
3068         Glib::RefPtr<Gtk::ListStore> results_model;
3069         Gtk::TreeView results_display;
3070
3071         results_model = ListStore::create (results_columns);
3072         results_display.set_model (results_model);
3073         results_display.append_column (list_title, results_columns.visible_name);
3074
3075         results_display.set_name ("CleanupResultsList");
3076         results_display.set_headers_visible (true);
3077         results_display.set_headers_clickable (false);
3078         results_display.set_reorderable (false);
3079
3080         Gtk::ScrolledWindow list_scroller;
3081         Gtk::Label txt;
3082         Gtk::VBox dvbox;
3083         Gtk::HBox dhbox;  // the hbox for the image and text
3084         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3085         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3086
3087         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3088
3089         const string dead_directory = _session->session_directory().dead_path().to_string();
3090
3091         /* subst:
3092            %1 - number of files removed
3093            %2 - location of "dead"
3094            %3 - size of files affected
3095            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3096         */
3097
3098         const char* bprefix;
3099         double space_adjusted = 0;
3100
3101         if (rep.space < 1000) {
3102                 bprefix = X_("");
3103                 space_adjusted = rep.space;
3104         } else if (rep.space < 1000000) {
3105                 bprefix = X_("kilo");
3106                 space_adjusted = truncf((float)rep.space / 1000.0);
3107         } else if (rep.space < 1000000 * 1000) {
3108                 bprefix = X_("mega");
3109                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000.0));
3110         } else {
3111                 bprefix = X_("giga");
3112                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000 * 1000.0));
3113         }
3114
3115         if (removed > 1) {
3116                 txt.set_text (string_compose (plural_msg, removed, dead_directory, space_adjusted, bprefix));
3117         } else {
3118                 txt.set_text (string_compose (singular_msg, removed, dead_directory, space_adjusted, bprefix));
3119         }
3120
3121         dhbox.pack_start (*dimage, true, false, 5);
3122         dhbox.pack_start (txt, true, false, 5);
3123
3124         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3125                 TreeModel::Row row = *(results_model->append());
3126                 row[results_columns.visible_name] = *i;
3127                 row[results_columns.fullpath] = *i;
3128         }
3129
3130         list_scroller.add (results_display);
3131         list_scroller.set_size_request (-1, 150);
3132         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3133
3134         dvbox.pack_start (dhbox, true, false, 5);
3135         dvbox.pack_start (list_scroller, true, false, 5);
3136         ddhbox.pack_start (dvbox, true, false, 5);
3137
3138         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3139         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3140         results.set_default_response (RESPONSE_CLOSE);
3141         results.set_position (Gtk::WIN_POS_MOUSE);
3142
3143         results_display.show();
3144         list_scroller.show();
3145         txt.show();
3146         dvbox.show();
3147         dhbox.show();
3148         ddhbox.show();
3149         dimage->show();
3150
3151         //results.get_vbox()->show();
3152         results.set_resizable (false);
3153
3154         results.run ();
3155
3156 }
3157
3158 void
3159 ARDOUR_UI::cleanup ()
3160 {
3161         if (_session == 0) {
3162                 /* shouldn't happen: menu item is insensitive */
3163                 return;
3164         }
3165
3166
3167         MessageDialog checker (_("Are you sure you want to clean-up?"),
3168                                 true,
3169                                 Gtk::MESSAGE_QUESTION,
3170                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
3171
3172         checker.set_title (_("Clean-up"));
3173
3174         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3175 ALL undo/redo information will be lost if you clean-up.\n\
3176 Clean-up will move all unused files to a \"dead\" location."));
3177
3178         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3179         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3180         checker.set_default_response (RESPONSE_CANCEL);
3181
3182         checker.set_name (_("CleanupDialog"));
3183         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3184         checker.set_position (Gtk::WIN_POS_MOUSE);
3185
3186         switch (checker.run()) {
3187         case RESPONSE_ACCEPT:
3188                 break;
3189         default:
3190                 return;
3191         }
3192
3193         ARDOUR::CleanupReport rep;
3194
3195         editor->prepare_for_cleanup ();
3196
3197         /* do not allow flush until a session is reloaded */
3198
3199         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3200         if (act) {
3201                 act->set_sensitive (false);
3202         }
3203
3204         if (_session->cleanup_sources (rep)) {
3205                 editor->finish_cleanup ();
3206                 return;
3207         }
3208
3209         editor->finish_cleanup ();
3210
3211         checker.hide();
3212         display_cleanup_results (rep,
3213                                  _("Cleaned Files"),
3214                                  _("\
3215 The following %1 files were not in use and \n\
3216 have been moved to:\n\n\
3217 %2\n\n\
3218 After a restart of Ardour,\n\n\
3219 Session -> Clean-up -> Flush Wastebasket\n\n\
3220 will release an additional\n\
3221 %3 %4bytes of disk space.\n"),
3222                                  _("\
3223 The following file was not in use and \n\
3224 has been moved to:\n                            \
3225 %2\n\n\
3226 After a restart of Ardour,\n\n\
3227 Session -> Clean-up -> Flush Wastebasket\n\n\
3228 will release an additional\n\
3229 %3 %4bytes of disk space.\n"
3230                                          ));
3231
3232 }
3233
3234 void
3235 ARDOUR_UI::flush_trash ()
3236 {
3237         if (_session == 0) {
3238                 /* shouldn't happen: menu item is insensitive */
3239                 return;
3240         }
3241
3242         ARDOUR::CleanupReport rep;
3243
3244         if (_session->cleanup_trash_sources (rep)) {
3245                 return;
3246         }
3247
3248         display_cleanup_results (rep,
3249                                  _("deleted file"),
3250                                  _("The following %1 files were deleted from\n\
3251 %2,\n\
3252 releasing %3 %4bytes of disk space"),
3253                                  _("The following file was deleted from\n\
3254 %2,\n\
3255 releasing %3 %4bytes of disk space"));
3256 }
3257
3258 void
3259 ARDOUR_UI::add_route (Gtk::Window* float_window)
3260 {
3261         int count;
3262
3263         if (!_session) {
3264                 return;
3265         }
3266
3267         if (add_route_dialog == 0) {
3268                 add_route_dialog = new AddRouteDialog (_session);
3269                 if (float_window) {
3270                         add_route_dialog->set_transient_for (*float_window);
3271                 }
3272         }
3273
3274         if (add_route_dialog->is_visible()) {
3275                 /* we're already doing this */
3276                 return;
3277         }
3278
3279         ResponseType r = (ResponseType) add_route_dialog->run ();
3280
3281         add_route_dialog->hide();
3282
3283         switch (r) {
3284                 case RESPONSE_ACCEPT:
3285                         break;
3286                 default:
3287                         return;
3288                         break;
3289         }
3290
3291         if ((count = add_route_dialog->count()) <= 0) {
3292                 return;
3293         }
3294
3295         string template_path = add_route_dialog->track_template();
3296
3297         if (!template_path.empty()) {
3298                 _session->new_route_from_template (count, template_path);
3299                 return;
3300         }
3301
3302         uint32_t input_chan = add_route_dialog->channels ();
3303         uint32_t output_chan;
3304         string name_template = add_route_dialog->name_template ();
3305         bool track = add_route_dialog->track ();
3306         RouteGroup* route_group = add_route_dialog->route_group ();
3307
3308         AutoConnectOption oac = Config->get_output_auto_connect();
3309
3310         if (oac & AutoConnectMaster) {
3311                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3312         } else {
3313                 output_chan = input_chan;
3314         }
3315
3316         /* XXX do something with name template */
3317
3318         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3319                 if (track) {
3320                         session_add_midi_track (route_group, count, name_template);
3321                 } else  {
3322                         MessageDialog msg (*editor,
3323                                         _("Sorry, MIDI Busses are not supported at this time."));
3324                         msg.run ();
3325                         //session_add_midi_bus();
3326                 }
3327         } else {
3328                 if (track) {
3329                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count, name_template);
3330                 } else {
3331                         session_add_audio_bus (input_chan, output_chan, route_group, count, name_template);
3332                 }
3333         }
3334 }
3335
3336 XMLNode*
3337 ARDOUR_UI::mixer_settings () const
3338 {
3339         XMLNode* node = 0;
3340
3341         if (_session) {
3342                 node = _session->instant_xml(X_("Mixer"));
3343         } else {
3344                 node = Config->instant_xml(X_("Mixer"));
3345         }
3346
3347         if (!node) {
3348                 node = new XMLNode (X_("Mixer"));
3349         }
3350
3351         return node;
3352 }
3353
3354 XMLNode*
3355 ARDOUR_UI::editor_settings () const
3356 {
3357         XMLNode* node = 0;
3358
3359         if (_session) {
3360                 node = _session->instant_xml(X_("Editor"));
3361         } else {
3362                 node = Config->instant_xml(X_("Editor"));
3363         }
3364
3365         if (!node) {
3366                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3367                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3368                 }
3369         }
3370
3371         if (!node) {
3372                 node = new XMLNode (X_("Editor"));
3373         }
3374
3375         return node;
3376 }
3377
3378 XMLNode*
3379 ARDOUR_UI::keyboard_settings () const
3380 {
3381         XMLNode* node = 0;
3382
3383         node = Config->extra_xml(X_("Keyboard"));
3384
3385         if (!node) {
3386                 node = new XMLNode (X_("Keyboard"));
3387         }
3388
3389         return node;
3390 }
3391
3392 void
3393 ARDOUR_UI::create_xrun_marker (framepos_t where)
3394 {
3395         editor->mouse_add_new_marker (where, false, true);
3396 }
3397
3398 void
3399 ARDOUR_UI::halt_on_xrun_message ()
3400 {
3401         MessageDialog msg (*editor,
3402                            _("Recording was stopped because your system could not keep up."));
3403         msg.run ();
3404 }
3405
3406 void
3407 ARDOUR_UI::xrun_handler (framepos_t where)
3408 {
3409         if (!_session) {
3410                 return;
3411         }
3412
3413         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3414
3415         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3416                 create_xrun_marker(where);
3417         }
3418
3419         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3420                 halt_on_xrun_message ();
3421         }
3422 }
3423
3424 void
3425 ARDOUR_UI::disk_overrun_handler ()
3426 {
3427         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3428
3429         if (!have_disk_speed_dialog_displayed) {
3430                 have_disk_speed_dialog_displayed = true;
3431                 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
3432 The disk system on your computer\n\
3433 was not able to keep up with %1.\n\
3434 \n\
3435 Specifically, it failed to write data to disk\n\
3436 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
3437                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3438                 msg->show ();
3439         }
3440 }
3441
3442 void
3443 ARDOUR_UI::disk_underrun_handler ()
3444 {
3445         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3446
3447         if (!have_disk_speed_dialog_displayed) {
3448                 have_disk_speed_dialog_displayed = true;
3449                 MessageDialog* msg = new MessageDialog (
3450                         *editor, string_compose (_("The disk system on your computer\n\
3451 was not able to keep up with %1.\n\
3452 \n\
3453 Specifically, it failed to read data from disk\n\
3454 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
3455                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3456                 msg->show ();
3457         }
3458 }
3459
3460 void
3461 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3462 {
3463         have_disk_speed_dialog_displayed = false;
3464         delete msg;
3465 }
3466
3467 void
3468 ARDOUR_UI::session_dialog (std::string msg)
3469 {
3470         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3471
3472         MessageDialog* d;
3473
3474         if (editor) {
3475                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3476         } else {
3477                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3478         }
3479
3480         d->show_all ();
3481         d->run ();
3482         delete d;
3483 }
3484
3485 int
3486 ARDOUR_UI::pending_state_dialog ()
3487 {
3488         HBox* hbox = new HBox();
3489         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3490         ArdourDialog dialog (_("Crash Recovery"), true);
3491         Label  message (_("\
3492 This session appears to have been in\n\
3493 middle of recording when ardour or\n\
3494 the computer was shutdown.\n\
3495 \n\
3496 Ardour can recover any captured audio for\n\
3497 you, or it can ignore it. Please decide\n\
3498 what you would like to do.\n"));
3499         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3500         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3501         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3502         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3503         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3504         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3505         dialog.set_default_response (RESPONSE_ACCEPT);
3506         dialog.set_position (WIN_POS_CENTER);
3507         message.show();
3508         image->show();
3509         hbox->show();
3510
3511         switch (dialog.run ()) {
3512         case RESPONSE_ACCEPT:
3513                 return 1;
3514         default:
3515                 return 0;
3516         }
3517 }
3518
3519 int
3520 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
3521 {
3522         HBox* hbox = new HBox();
3523         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3524         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3525         Label  message (string_compose (_("\
3526 This session was created with a sample rate of %1 Hz\n\
3527 \n\
3528 The audioengine is currently running at %2 Hz\n"), desired, actual));
3529
3530         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3531         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3532         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3533         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3534         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3535         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3536         dialog.set_default_response (RESPONSE_ACCEPT);
3537         dialog.set_position (WIN_POS_CENTER);
3538         message.show();
3539         image->show();
3540         hbox->show();
3541
3542         switch (dialog.run ()) {
3543         case RESPONSE_ACCEPT:
3544                 return 0;
3545         default:
3546                 return 1;
3547         }
3548 }
3549
3550
3551 void
3552 ARDOUR_UI::disconnect_from_jack ()
3553 {
3554         if (engine) {
3555                 if( engine->disconnect_from_jack ()) {
3556                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3557                         msg.run ();
3558                 }
3559
3560                 update_sample_rate (0);
3561         }
3562 }
3563
3564 void
3565 ARDOUR_UI::reconnect_to_jack ()
3566 {
3567         if (engine) {
3568                 if (engine->reconnect_to_jack ()) {
3569                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3570                         msg.run ();
3571                 }
3572
3573                 update_sample_rate (0);
3574         }
3575 }
3576
3577 void
3578 ARDOUR_UI::use_config ()
3579 {
3580         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3581         if (node) {
3582                 set_transport_controllable_state (*node);
3583         }
3584 }
3585
3586 void
3587 ARDOUR_UI::update_transport_clocks (framepos_t pos)
3588 {
3589         if (Config->get_primary_clock_delta_edit_cursor()) {
3590                 primary_clock->set (pos, false, editor->get_preferred_edit_position(), 1);
3591         } else {
3592                 primary_clock->set (pos, 0, true);
3593         }
3594
3595         if (Config->get_secondary_clock_delta_edit_cursor()) {
3596                 secondary_clock->set (pos, false, editor->get_preferred_edit_position(), 2);
3597         } else {
3598                 secondary_clock->set (pos);
3599         }
3600
3601         if (big_clock_window->get()) {
3602                 big_clock->set (pos);
3603         }
3604 }
3605
3606
3607 void
3608 ARDOUR_UI::step_edit_status_change (bool yn)
3609 {
3610         // XXX should really store pre-step edit status of things
3611         // we make insensitive
3612
3613         if (yn) {
3614                 rec_button.set_active_state (Mid);
3615                 rec_button.set_sensitive (false);
3616         } else {
3617                 rec_button.unset_active_state ();;
3618                 rec_button.set_sensitive (true);
3619         }
3620 }
3621
3622 void
3623 ARDOUR_UI::record_state_changed ()
3624 {
3625         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3626
3627         if (!_session || !big_clock_window->get()) {
3628                 /* why bother - the clock isn't visible */
3629                 return;
3630         }
3631
3632         Session::RecordState const r = _session->record_status ();
3633         bool const h = _session->have_rec_enabled_track ();
3634
3635         if (r == Session::Recording && h)  {
3636                 big_clock->set_widget_name ("BigClockRecording");
3637         } else {
3638                 big_clock->set_widget_name ("BigClockNonRecording");
3639         }
3640 }
3641
3642 bool
3643 ARDOUR_UI::first_idle ()
3644 {
3645         if (_session) {
3646                 _session->allow_auto_play (true);
3647         }
3648
3649         if (editor) {
3650                 editor->first_idle();
3651         }
3652
3653         Keyboard::set_can_save_keybindings (true);
3654         return false;
3655 }
3656
3657 void
3658 ARDOUR_UI::store_clock_modes ()
3659 {
3660         XMLNode* node = new XMLNode(X_("ClockModes"));
3661
3662         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3663                 XMLNode* child = new XMLNode (X_("Clock"));
3664                 
3665                 child->add_property (X_("name"), (*x)->name());
3666                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
3667                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
3668
3669                 node->add_child_nocopy (*child);
3670         }
3671
3672         _session->add_extra_xml (*node);
3673         _session->set_dirty ();
3674 }
3675
3676 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3677         : Controllable (name), ui (u), type(tp)
3678 {
3679
3680 }
3681
3682 void
3683 ARDOUR_UI::TransportControllable::set_value (double val)
3684 {
3685         if (val < 0.5) {
3686                 /* do nothing: these are radio-style actions */
3687                 return;
3688         }
3689
3690         const char *action = 0;
3691
3692         switch (type) {
3693         case Roll:
3694                 action = X_("Roll");
3695                 break;
3696         case Stop:
3697                 action = X_("Stop");
3698                 break;
3699         case GotoStart:
3700                 action = X_("Goto Start");
3701                 break;
3702         case GotoEnd:
3703                 action = X_("Goto End");
3704                 break;
3705         case AutoLoop:
3706                 action = X_("Loop");
3707                 break;
3708         case PlaySelection:
3709                 action = X_("Play Selection");
3710                 break;
3711         case RecordEnable:
3712                 action = X_("Record");
3713                 break;
3714         default:
3715                 break;
3716         }
3717
3718         if (action == 0) {
3719                 return;
3720         }
3721
3722         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3723
3724         if (act) {
3725                 act->activate ();
3726         }
3727 }
3728
3729 double
3730 ARDOUR_UI::TransportControllable::get_value (void) const
3731 {
3732         float val = 0.0;
3733
3734         switch (type) {
3735         case Roll:
3736                 break;
3737         case Stop:
3738                 break;
3739         case GotoStart:
3740                 break;
3741         case GotoEnd:
3742                 break;
3743         case AutoLoop:
3744                 break;
3745         case PlaySelection:
3746                 break;
3747         case RecordEnable:
3748                 break;
3749         default:
3750                 break;
3751         }
3752
3753         return val;
3754 }
3755
3756 void
3757 ARDOUR_UI::setup_profile ()
3758 {
3759         if (gdk_screen_width() < 1200) {
3760                 Profile->set_small_screen ();
3761         }
3762
3763
3764         if (getenv ("ARDOUR_SAE")) {
3765                 Profile->set_sae ();
3766                 Profile->set_single_package ();
3767         }
3768 }
3769
3770 void
3771 ARDOUR_UI::toggle_translations ()
3772 {
3773         using namespace Glib;
3774
3775         RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3776         if (act) {
3777                 RefPtr<ToggleAction> ract = RefPtr<ToggleAction>::cast_dynamic (act);
3778                 if (ract) {
3779
3780                         string i18n_killer = ARDOUR::translation_kill_path();
3781
3782                         bool already_enabled = !ARDOUR::translations_are_disabled ();
3783
3784                         if (ract->get_active ()) {
3785 /* we don't care about errors */
3786                                 int fd = ::open (i18n_killer.c_str(), O_RDONLY|O_CREAT, 0644);
3787                                 close (fd);
3788                         } else {
3789 /* we don't care about errors */
3790                                 unlink (i18n_killer.c_str());
3791                         }
3792
3793                         if (already_enabled != ract->get_active()) {
3794                                 MessageDialog win (already_enabled ? _("Translations disabled") : _("Translations enabled"),
3795                                                    false,
3796                                                    Gtk::MESSAGE_WARNING,
3797                                                    Gtk::BUTTONS_OK);
3798                                 win.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME));
3799                                 win.set_position (Gtk::WIN_POS_CENTER);
3800                                 win.present ();
3801                                 win.run ();
3802                         }
3803                 }
3804         }
3805 }
3806
3807 /** Add a window proxy to our list, so that its state will be saved.
3808  *  This call also causes the window to be created and opened if its
3809  *  state was saved as `visible'.
3810  */
3811 void
3812 ARDOUR_UI::add_window_proxy (WindowProxyBase* p)
3813 {
3814         _window_proxies.push_back (p);
3815         p->maybe_show ();
3816 }
3817
3818 /** Remove a window proxy from our list.  Must be called if a WindowProxy
3819  *  is deleted, to prevent hanging pointers.
3820  */
3821 void
3822 ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
3823 {
3824         _window_proxies.remove (p);
3825 }
3826
3827 int
3828 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
3829 {
3830         MissingFileDialog dialog (s, str, type);
3831
3832         dialog.show ();
3833         dialog.present ();
3834
3835         int result = dialog.run ();
3836         dialog.hide ();
3837
3838         switch (result) {
3839         case RESPONSE_OK:
3840                 break;
3841         default:
3842                 return 1; // quit entire session load
3843         }
3844
3845         result = dialog.get_action ();
3846
3847         return result;
3848 }
3849
3850 int
3851 ARDOUR_UI::ambiguous_file (std::string file, std::string /*path*/, std::vector<std::string> hits)
3852 {
3853         AmbiguousFileDialog dialog (file, hits);
3854
3855         dialog.show ();
3856         dialog.present ();
3857
3858         dialog.run ();
3859         return dialog.get_which ();
3860 }
3861
3862 /** Allocate our thread-local buffers */
3863 void
3864 ARDOUR_UI::get_process_buffers ()
3865 {
3866         _process_thread->get_buffers ();
3867 }
3868
3869 /** Drop our thread-local buffers */
3870 void
3871 ARDOUR_UI::drop_process_buffers ()
3872 {
3873         _process_thread->drop_buffers ();
3874 }