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