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