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