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