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