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