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