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