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