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