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