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