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