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