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