merged with trunk revs 2605-2627
[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->get_preferred_edit_position()); /* 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         enable_screen_updates ();
2408         flush_pending ();
2409         retval = 0;
2410
2411   out:
2412         return retval;
2413 }
2414
2415 int
2416 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
2417                           uint32_t control_channels,
2418                           uint32_t master_channels, 
2419                           AutoConnectOption input_connect,
2420                           AutoConnectOption output_connect,
2421                           uint32_t nphysin,
2422                           uint32_t nphysout,
2423                           nframes_t initial_length)
2424 {
2425         Session *new_session;
2426         int x;
2427
2428         if (!check_audioengine()) {
2429                 return -1;
2430         }
2431
2432         session_loaded = false;
2433
2434         x = unload_session ();
2435
2436         if (x < 0) {
2437                 return -1;
2438         } else if (x > 0) {
2439                 return 0;
2440         }
2441         
2442         _session_is_new = true;
2443
2444         try {
2445                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2446                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2447         }
2448
2449         catch (...) {
2450
2451                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2452                 msg.run ();
2453                 return -1;
2454         }
2455
2456         connect_to_session (new_session);
2457
2458         session_loaded = true;
2459         return 0;
2460 }
2461
2462 void
2463 ARDOUR_UI::show ()
2464 {
2465         if (editor) {
2466                 editor->show_window ();
2467                 
2468                 if (!shown_flag) {
2469                         editor->present ();
2470                 }
2471
2472                 shown_flag = true;
2473         }
2474 }
2475
2476 void
2477 ARDOUR_UI::show_splash ()
2478 {
2479         if (about == 0) {
2480                 about = new About();
2481                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2482         }
2483         about->present();
2484         flush_pending ();
2485 }
2486
2487 void
2488 ARDOUR_UI::about_signal_response(int response)
2489 {
2490         hide_splash();
2491 }
2492
2493 void
2494 ARDOUR_UI::hide_splash ()
2495 {
2496         if (about) {
2497                 about->get_window()->set_cursor ();
2498                 about->hide();
2499         }
2500 }
2501
2502 void
2503 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2504 {
2505         size_t removed;
2506
2507         removed = rep.paths.size();
2508
2509         if (removed == 0) {
2510                 MessageDialog msgd (*editor,
2511                                     _("No audio files were ready for cleanup"), 
2512                                     true,
2513                                     Gtk::MESSAGE_INFO,
2514                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2515                 msgd.set_secondary_text (_("If this seems suprising, \n\
2516 check for any existing snapshots.\n\
2517 These may still include regions that\n\
2518 require some unused files to continue to exist."));
2519         
2520                 msgd.run ();
2521                 return;
2522         } 
2523
2524         ArdourDialog results (_("ardour: cleanup"), true, false);
2525         
2526         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2527             CleanupResultsModelColumns() { 
2528                     add (visible_name);
2529                     add (fullpath);
2530             }
2531             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2532             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2533         };
2534
2535         
2536         CleanupResultsModelColumns results_columns;
2537         Glib::RefPtr<Gtk::ListStore> results_model;
2538         Gtk::TreeView results_display;
2539         
2540         results_model = ListStore::create (results_columns);
2541         results_display.set_model (results_model);
2542         results_display.append_column (list_title, results_columns.visible_name);
2543
2544         results_display.set_name ("CleanupResultsList");
2545         results_display.set_headers_visible (true);
2546         results_display.set_headers_clickable (false);
2547         results_display.set_reorderable (false);
2548
2549         Gtk::ScrolledWindow list_scroller;
2550         Gtk::Label txt;
2551         Gtk::VBox dvbox;
2552         Gtk::HBox dhbox;  // the hbox for the image and text
2553         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2554         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2555
2556         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2557
2558         const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2559
2560         if (rep.space < 1048576.0f) {
2561                 if (removed > 1) {
2562                         txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2563                 } else {
2564                         txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2565                 }
2566         } else {
2567                 if (removed > 1) {
2568                         txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2569                 } else {
2570                         txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2571                 }
2572         }
2573
2574         dhbox.pack_start (*dimage, true, false, 5);
2575         dhbox.pack_start (txt, true, false, 5);
2576
2577         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2578                 TreeModel::Row row = *(results_model->append());
2579                 row[results_columns.visible_name] = *i;
2580                 row[results_columns.fullpath] = *i;
2581         }
2582         
2583         list_scroller.add (results_display);
2584         list_scroller.set_size_request (-1, 150);
2585         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2586
2587         dvbox.pack_start (dhbox, true, false, 5);
2588         dvbox.pack_start (list_scroller, true, false, 5);
2589         ddhbox.pack_start (dvbox, true, false, 5);
2590
2591         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2592         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2593         results.set_default_response (RESPONSE_CLOSE);
2594         results.set_position (Gtk::WIN_POS_MOUSE);
2595
2596         results_display.show();
2597         list_scroller.show();
2598         txt.show();
2599         dvbox.show();
2600         dhbox.show();
2601         ddhbox.show();
2602         dimage->show();
2603
2604         //results.get_vbox()->show();
2605         results.set_resizable (false);
2606
2607         results.run ();
2608
2609 }
2610
2611 void
2612 ARDOUR_UI::cleanup ()
2613 {
2614         if (session == 0) {
2615                 /* shouldn't happen: menu item is insensitive */
2616                 return;
2617         }
2618
2619
2620         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2621                                 true,
2622                                 Gtk::MESSAGE_QUESTION,
2623                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2624
2625         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2626 ALL undo/redo information will be lost if you cleanup.\n\
2627 After cleanup, unused audio files will be moved to a \
2628 \"dead sounds\" location."));
2629         
2630         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2631         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2632         checker.set_default_response (RESPONSE_CANCEL);
2633
2634         checker.set_name (_("CleanupDialog"));
2635         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2636         checker.set_position (Gtk::WIN_POS_MOUSE);
2637
2638         switch (checker.run()) {
2639         case RESPONSE_ACCEPT:
2640                 break;
2641         default:
2642                 return;
2643         }
2644
2645         Session::cleanup_report rep;
2646
2647         editor->prepare_for_cleanup ();
2648
2649         /* do not allow flush until a session is reloaded */
2650
2651         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2652         if (act) {
2653                 act->set_sensitive (false);
2654         }
2655
2656         if (session->cleanup_sources (rep)) {
2657                 return;
2658         }
2659
2660         checker.hide();
2661         display_cleanup_results (rep, 
2662                                  _("cleaned files"),
2663                                  _("\
2664 The following %1 %2 not in use and \n\
2665 have been moved to:\n\
2666 %3. \n\n\
2667 Flushing the wastebasket will \n\
2668 release an additional\n\
2669 %4 %5bytes of disk space.\n"
2670                                          ));
2671
2672
2673
2674 }
2675
2676 void
2677 ARDOUR_UI::flush_trash ()
2678 {
2679         if (session == 0) {
2680                 /* shouldn't happen: menu item is insensitive */
2681                 return;
2682         }
2683
2684         Session::cleanup_report rep;
2685
2686         if (session->cleanup_trash_sources (rep)) {
2687                 return;
2688         }
2689
2690         display_cleanup_results (rep, 
2691                                  _("deleted file"),
2692                                  _("The following %1 %2 deleted from\n\
2693 %3,\n\
2694 releasing %4 %5bytes of disk space"));
2695 }
2696
2697 void
2698 ARDOUR_UI::add_route (Gtk::Window* float_window)
2699 {
2700         int count;
2701
2702         if (!session) {
2703                 return;
2704         }
2705
2706         if (add_route_dialog == 0) {
2707                 add_route_dialog = new AddRouteDialog;
2708                 if (float_window) {
2709                         add_route_dialog->set_transient_for (*float_window);
2710                 }
2711         }
2712
2713         if (add_route_dialog->is_visible()) {
2714                 /* we're already doing this */
2715                 return;
2716         }
2717
2718         ResponseType r = (ResponseType) add_route_dialog->run ();
2719
2720         add_route_dialog->hide();
2721
2722         switch (r) {
2723                 case RESPONSE_ACCEPT:
2724                         break;
2725                 default:
2726                         return;
2727                         break;
2728         }
2729
2730         if ((count = add_route_dialog->count()) <= 0) {
2731                 return;
2732         }
2733
2734         uint32_t input_chan = add_route_dialog->channels ();
2735         uint32_t output_chan;
2736         string name_template = add_route_dialog->name_template ();
2737         bool track = add_route_dialog->track ();
2738
2739         AutoConnectOption oac = Config->get_output_auto_connect();
2740
2741         if (oac & AutoConnectMaster) {
2742                 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2743         } else {
2744                 output_chan = input_chan;
2745         }
2746
2747         /* XXX do something with name template */
2748
2749         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2750                 if (track) {
2751                         session_add_midi_track(count);
2752                 } else  {
2753                         MessageDialog msg (*editor,
2754                                         _("Sorry, MIDI Busses are not supported at this time."));
2755                         msg.run ();
2756                         //session_add_midi_bus();
2757                 }
2758         } else { 
2759                 if (track) {
2760                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2761                 } else {
2762                         session_add_audio_bus (input_chan, output_chan, count);
2763                 }
2764         }
2765 }
2766
2767 XMLNode*
2768 ARDOUR_UI::mixer_settings () const
2769 {
2770         XMLNode* node = 0;
2771
2772         if (session) {
2773                 node = session->instant_xml(X_("Mixer"));
2774         } else {
2775                 node = Config->instant_xml(X_("Mixer"));
2776         }
2777
2778         if (!node) {
2779                 node = new XMLNode (X_("Mixer"));
2780         }
2781
2782         return node;
2783 }
2784
2785 XMLNode*
2786 ARDOUR_UI::editor_settings () const
2787 {
2788         XMLNode* node = 0;
2789
2790         if (session) {
2791                 node = session->instant_xml(X_("Editor"));
2792         } else {
2793                 node = Config->instant_xml(X_("Editor"));
2794         }
2795
2796         if (!node) {
2797                 node = new XMLNode (X_("Editor"));
2798         }
2799         return node;
2800 }
2801
2802 XMLNode*
2803 ARDOUR_UI::keyboard_settings () const
2804 {
2805         XMLNode* node = 0;
2806
2807         node = Config->extra_xml(X_("Keyboard"));
2808         
2809         if (!node) {
2810                 node = new XMLNode (X_("Keyboard"));
2811         }
2812         return node;
2813 }
2814
2815 void
2816 ARDOUR_UI::halt_on_xrun_message ()
2817 {
2818         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2819
2820         MessageDialog msg (*editor,
2821                            _("Recording was stopped because your system could not keep up."));
2822         msg.run ();
2823 }
2824
2825 void
2826 ARDOUR_UI::disk_overrun_handler ()
2827 {
2828         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2829
2830         if (!have_disk_speed_dialog_displayed) {
2831                 have_disk_speed_dialog_displayed = true;
2832                 MessageDialog* msg = new MessageDialog (*editor, _("\
2833 The disk system on your computer\n\
2834 was not able to keep up with Ardour.\n\
2835 \n\
2836 Specifically, it failed to write data to disk\n\
2837 quickly enough to keep up with recording.\n"));
2838                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2839                 msg->show ();
2840         }
2841 }
2842
2843 void
2844 ARDOUR_UI::disk_underrun_handler ()
2845 {
2846         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2847
2848         if (!have_disk_speed_dialog_displayed) {
2849                 have_disk_speed_dialog_displayed = true;
2850                 MessageDialog* msg = new MessageDialog (*editor,
2851                                    _("The disk system on your computer\n\
2852 was not able to keep up with Ardour.\n\
2853 \n\
2854 Specifically, it failed to read data from disk\n\
2855 quickly enough to keep up with playback.\n"));
2856                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2857                 msg->show ();
2858         } 
2859 }
2860
2861 void
2862 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2863 {
2864         have_disk_speed_dialog_displayed = false;
2865         delete msg;
2866 }
2867
2868 int
2869 ARDOUR_UI::pending_state_dialog ()
2870 {
2871         HBox* hbox = new HBox();
2872         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2873         ArdourDialog dialog (_("Crash recovery"), true);
2874         Label  message (_("\
2875 This session appears to have been in\n\
2876 middle of recording when ardour or\n\
2877 the computer was shutdown.\n\
2878 \n\
2879 Ardour can recover any captured audio for\n\
2880 you, or it can ignore it. Please decide\n\
2881 what you would like to do.\n"));
2882
2883         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2884         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2885         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2886         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2887         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2888         dialog.set_default_response (RESPONSE_ACCEPT);
2889         dialog.set_position (WIN_POS_CENTER);
2890         message.show();
2891         image->show();
2892         hbox->show();
2893         //dialog.get_vbox()->show();
2894         
2895         switch (dialog.run ()) {
2896         case RESPONSE_ACCEPT:
2897                 return 1;
2898         default:
2899                 return 0;
2900         }
2901 }
2902         
2903 void
2904 ARDOUR_UI::disconnect_from_jack ()
2905 {
2906         if (engine) {
2907                 if( engine->disconnect_from_jack ()) {
2908                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2909                         msg.run ();
2910                 }
2911
2912                 update_sample_rate (0);
2913         }
2914 }
2915
2916 void
2917 ARDOUR_UI::reconnect_to_jack ()
2918 {
2919         if (engine) {
2920                 if (engine->reconnect_to_jack ()) {
2921                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2922                         msg.run ();
2923                 }
2924
2925                 update_sample_rate (0);
2926         }
2927 }
2928
2929 int
2930 ARDOUR_UI::cmdline_new_session (string path)
2931 {
2932         if (path[0] != '/') {
2933                 char buf[PATH_MAX+1];
2934                 string str;
2935
2936                 getcwd (buf, sizeof (buf));
2937                 str = buf;
2938                 str += '/';
2939                 str += path;
2940                 path = str;
2941         }
2942
2943         get_session_parameters (path, false, true);
2944
2945         _will_create_new_session_automatically = false; /* done it */
2946
2947         return FALSE; /* don't call it again */
2948 }
2949
2950 void
2951 ARDOUR_UI::use_config ()
2952 {
2953         Glib::RefPtr<Action> act;
2954
2955         switch (Config->get_native_file_data_format ()) {
2956         case FormatFloat:
2957                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2958                 break;
2959         case FormatInt24:
2960                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2961                 break;
2962         case FormatInt16:
2963                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2964                 break;
2965         }
2966
2967         if (act) {
2968                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2969                 ract->set_active ();
2970         }       
2971
2972         switch (Config->get_native_file_header_format ()) {
2973         case BWF:
2974                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2975                 break;
2976         case WAVE:
2977                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2978                 break;
2979         case WAVE64:
2980                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2981                 break;
2982         case iXML:
2983                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2984                 break;
2985         case RF64:
2986                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2987                 break;
2988         case CAF:
2989                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2990                 break;
2991         case AIFF:
2992                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2993                 break;
2994         }
2995
2996         if (act) {
2997                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2998                 ract->set_active ();
2999         }       
3000
3001         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3002         if (node) {
3003                 set_transport_controllable_state (*node);
3004         }
3005 }
3006
3007 void
3008 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3009 {
3010         if (Config->get_primary_clock_delta_edit_cursor()) {
3011                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3012         } else {
3013                 primary_clock.set (pos, 0, true);
3014         }
3015
3016         if (Config->get_secondary_clock_delta_edit_cursor()) {
3017                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3018         } else {
3019                 secondary_clock.set (pos);
3020         }
3021
3022         if (big_clock_window) {
3023                 big_clock.set (pos);
3024         }
3025 }
3026
3027 void
3028 ARDOUR_UI::record_state_changed ()
3029 {
3030         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3031
3032         if (!session || !big_clock_window) {
3033                 /* why bother - the clock isn't visible */
3034                 return;
3035         }
3036
3037         switch (session->record_status()) {
3038         case Session::Recording:
3039                 big_clock.set_widget_name ("BigClockRecording");
3040                 break;
3041         default:
3042                 big_clock.set_widget_name ("BigClockNonRecording");
3043                 break;
3044         }
3045 }
3046
3047 void
3048 ARDOUR_UI::set_keybindings_path (string path)
3049 {
3050         keybindings_path = path;
3051 }
3052
3053 void
3054 ARDOUR_UI::save_keybindings ()
3055 {
3056         if (can_save_keybindings) {
3057                 AccelMap::save (user_keybindings_path);
3058         } 
3059 }
3060
3061 bool
3062 ARDOUR_UI::first_idle ()
3063 {
3064         if (session) {
3065                 session->allow_auto_play (true);
3066         }
3067         can_save_keybindings = true;
3068         return false;
3069 }
3070
3071 void
3072 ARDOUR_UI::store_clock_modes ()
3073 {
3074         XMLNode* node = new XMLNode(X_("ClockModes"));
3075
3076         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3077                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3078         }
3079
3080         session->add_extra_xml (*node);
3081         session->set_dirty ();
3082 }
3083
3084
3085                 
3086 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3087         : Controllable (name), ui (u), type(tp)
3088 {
3089         
3090 }
3091
3092 void
3093 ARDOUR_UI::TransportControllable::set_value (float val)
3094 {
3095         if (type == ShuttleControl) {
3096                 double fract;
3097
3098                 if (val == 0.5f) {
3099                         fract = 0.0;
3100                 } else {
3101                         if (val < 0.5f) {
3102                                 fract = -((0.5f - val)/0.5f);
3103                         } else {
3104                                 fract = ((val - 0.5f)/0.5f);
3105                         }
3106                 }
3107                 
3108                 ui.set_shuttle_fract (fract);
3109                 return;
3110         }
3111
3112         if (val < 0.5f) {
3113                 /* do nothing: these are radio-style actions */
3114                 return;
3115         }
3116
3117         const char *action = 0;
3118
3119         switch (type) {
3120         case Roll:
3121                 action = X_("Roll");
3122                 break;
3123         case Stop:
3124                 action = X_("Stop");
3125                 break;
3126         case GotoStart:
3127                 action = X_("Goto Start");
3128                 break;
3129         case GotoEnd:
3130                 action = X_("Goto End");
3131                 break;
3132         case AutoLoop:
3133                 action = X_("Loop");
3134                 break;
3135         case PlaySelection:
3136                 action = X_("Play Selection");
3137                 break;
3138         case RecordEnable:
3139                 action = X_("Record");
3140                 break;
3141         default:
3142                 break;
3143         }
3144
3145         if (action == 0) {
3146                 return;
3147         }
3148
3149         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3150
3151         if (act) {
3152                 act->activate ();
3153         }
3154 }
3155
3156 float
3157 ARDOUR_UI::TransportControllable::get_value (void) const
3158 {
3159         float val = 0.0f;
3160         
3161         switch (type) {
3162         case Roll:
3163                 break;
3164         case Stop:
3165                 break;
3166         case GotoStart:
3167                 break;
3168         case GotoEnd:
3169                 break;
3170         case AutoLoop:
3171                 break;
3172         case PlaySelection:
3173                 break;
3174         case RecordEnable:
3175                 break;
3176         case ShuttleControl:
3177                 break;
3178         default:
3179                 break;
3180         }
3181
3182         return val;
3183 }
3184
3185 void
3186 ARDOUR_UI::TransportControllable::set_id (const string& str)
3187 {
3188         _id = str;
3189 }
3190
3191 void
3192 ARDOUR_UI::setup_profile ()
3193 {
3194         if (gdk_screen_width() < 1200) {
3195                 Profile->set_small_screen ();
3196         }
3197
3198
3199         if (getenv ("ARDOUR_SAE")) {
3200                 Profile->set_sae ();
3201                 Profile->set_single_package ();
3202         }
3203 }
3204
3205 void
3206 ARDOUR_UI::disable_all_plugins ()
3207 {
3208         if (!session) {
3209                 return;
3210         }
3211
3212         // session->begin_reversible_command (_("Disable all plugins"));
3213
3214         boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
3215
3216         for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
3217                 // XMLNode& before = (*i)->get_redirect_state ();
3218                 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
3219                 (*i)->disable_plugins ();
3220                 // XMLNode& after = (*i)->get_redirect_state ();
3221                 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
3222                                       
3223         }
3224
3225         // session->commit_reversible_command ();
3226 }
3227
3228 void
3229 ARDOUR_UI::ab_all_plugins ()
3230 {
3231         if (!session) {
3232                 return;
3233         }
3234
3235         boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
3236
3237         for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
3238                 (*i)->ab_plugins (ab_direction);
3239         }
3240         
3241         ab_direction = !ab_direction;
3242 }