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