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