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