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