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