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