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