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