Comments button now indicates when comments are present, more dialog work (ask about...
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2002 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     $Id$
19 */
20
21 #include <algorithm>
22 #include <cmath>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <cerrno>
27 #include <fstream>
28
29 #include <iostream>
30
31 #include <gtkmm/messagedialog.h>
32 #include <gtkmm/accelmap.h>
33
34 #include <pbd/error.h>
35 #include <pbd/compose.h>
36 #include <pbd/basename.h>
37 #include <pbd/pathscanner.h>
38 #include <pbd/failed_constructor.h>
39 #include <gtkmm2ext/gtk_ui.h>
40 #include <gtkmm2ext/utils.h>
41 #include <gtkmm2ext/click_box.h>
42 #include <gtkmm2ext/fastmeter.h>
43 #include <gtkmm2ext/stop_signal.h>
44 #include <gtkmm2ext/popup.h>
45
46 #include <midi++/port.h>
47 #include <midi++/mmc.h>
48
49 #include <ardour/ardour.h>
50 #include <ardour/port.h>
51 #include <ardour/audioengine.h>
52 #include <ardour/playlist.h>
53 #include <ardour/utils.h>
54 #include <ardour/diskstream.h>
55 #include <ardour/filesource.h>
56 #include <ardour/recent_sessions.h>
57 #include <ardour/session_diskstream.h>
58 #include <ardour/port.h>
59 #include <ardour/audio_track.h>
60
61 #include "actions.h"
62 #include "ardour_ui.h"
63 #include "public_editor.h"
64 #include "audio_clock.h"
65 #include "keyboard.h"
66 #include "mixer_ui.h"
67 #include "prompter.h"
68 #include "opts.h"
69 #include "keyboard_target.h"
70 #include "add_route_dialog.h"
71 #include "new_session_dialog.h"
72 #include "about.h"
73 #include "utils.h"
74 #include "gui_thread.h"
75 #include "color_manager.h"
76
77 #include "i18n.h"
78
79 using namespace ARDOUR;
80 using namespace Gtkmm2ext;
81 using namespace Gtk;
82 using namespace sigc;
83
84 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
85
86 sigc::signal<void,bool> ARDOUR_UI::Blink;
87 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
88 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
89 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
90
91 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
92
93         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
94           
95           primary_clock (X_("TransportClockDisplay"), true, false, true),
96           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
97           preroll_clock (X_("PreRollClock"), true, true),
98           postroll_clock (X_("PostRollClock"), true, true),
99
100           /* adjuster table */
101
102           adjuster_table (3, 3),
103
104           /* preroll stuff */
105
106           preroll_button (_("pre\nroll")),
107           postroll_button (_("post\nroll")),
108
109           /* big clock */
110
111           big_clock ("BigClockDisplay", true),
112
113           /* transport */
114
115           time_master_button (_("time\nmaster")),
116
117           shuttle_units_button (_("% ")),
118
119           punch_in_button (_("punch\nin")),
120           punch_out_button (_("punch\nout")),
121           auto_return_button (_("auto\nreturn")),
122           auto_play_button (_("auto\nplay")),
123           auto_input_button (_("auto\ninput")),
124           click_button (_("click")),
125           auditioning_alert_button (_("AUDITIONING")),
126           solo_alert_button (_("SOLO")),
127           shown_flag (false)
128
129 {
130         using namespace Gtk::Menu_Helpers;
131
132         Gtkmm2ext::init();
133         
134         about = 0;
135
136         if (theArdourUI == 0) {
137                 theArdourUI = this;
138         }
139
140         ActionManager::init ();
141
142         /* load colors */
143
144         color_manager = new ColorManager();
145
146         std::string color_file = ARDOUR::find_config_file("ardour.colors");
147         
148         color_manager->load (color_file);
149
150         m_new_session_dialog = 0;
151         m_new_session_dialog_ref = NewSessionDialogFactory::create();
152         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
153         editor = 0;
154         mixer = 0;
155         session = 0;
156         _session_is_new = false;
157         big_clock_window = 0;
158         session_selector_window = 0;
159         last_key_press_time = 0;
160         connection_editor = 0;
161         add_route_dialog = 0;
162         route_params = 0;
163         option_editor = 0;
164         location_ui = 0;
165         sfdb = 0;
166         open_session_selector = 0;
167         have_configure_timeout = false;
168         have_disk_overrun_displayed = false;
169         have_disk_underrun_displayed = false;
170         _will_create_new_session_automatically = false;
171         session_loaded = false;
172         last_speed_displayed = -1.0f;
173
174         last_configure_time.tv_sec = 0;
175         last_configure_time.tv_usec = 0;
176
177         shuttle_grabbed = false;
178         shuttle_fract = 0.0;
179         shuttle_max_speed = 8.0f;
180
181         set_shuttle_units (Percentage);
182         set_shuttle_behaviour (Sprung);
183
184         shuttle_style_menu = 0;
185         shuttle_unit_menu = 0;
186
187         gettimeofday (&last_peak_grab, 0);
188         gettimeofday (&last_shuttle_request, 0);
189
190         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
191         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
192         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
193         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
194
195         /* handle pending state with a dialog */
196
197         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
198
199         /* have to wait for AudioEngine and Configuration before proceeding */
200 }
201
202 void
203 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
204 {
205         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
206         
207         string msg = string_compose (_("\
208 You cannot record-enable\n\
209 track %1\n\
210 because it has no input connections.\n\
211 You would be wasting space recording silence."),
212                               ds->name());
213
214         MessageDialog message (*editor, msg);
215         message.run ();
216 }
217
218 void
219 ARDOUR_UI::set_engine (AudioEngine& e)
220 {
221         engine = &e;
222
223         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
224         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
225         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
226         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
227
228         _tooltips.enable();
229
230         keyboard = new Keyboard;
231
232         string meter_path;
233
234         meter_path = ARDOUR::find_data_file("v_meter_strip.xpm", "pixmaps");
235         if (meter_path.empty()) {
236                 error << _("no vertical meter strip image found") << endmsg;
237                 exit (1);
238         }
239         FastMeter::set_vertical_xpm (meter_path);
240
241         meter_path = ARDOUR::find_data_file("h_meter_strip.xpm", "pixmaps");
242         if (meter_path.empty()) {
243                 error << _("no horizontal meter strip image found") << endmsg;
244                 exit (1);
245         }
246         FastMeter::set_horizontal_xpm (meter_path);
247
248         if (setup_windows ()) {
249                 throw failed_constructor ();
250         }
251
252         if (GTK_ARDOUR::show_key_actions) {
253                 vector<string> names;
254                 vector<string> paths;
255                 vector<string> keys;
256                 vector<AccelKey> bindings;
257
258                 ActionManager::get_all_actions (names, paths, keys, bindings);
259
260                 vector<string>::iterator n;
261                 vector<string>::iterator k;
262                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
263                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
264                 }
265
266                 exit (0);
267         }
268
269         /* start with timecode, metering enabled
270         */
271         
272         blink_timeout_tag = -1;
273
274         /* the global configuration object is now valid */
275
276         use_config ();
277
278         /* this being a GUI and all, we want peakfiles */
279
280         FileSource::set_build_peakfiles (true);
281         FileSource::set_build_missing_peakfiles (true);
282
283         if (Source::start_peak_thread ()) {
284                 throw failed_constructor();
285         }
286
287         /* start the time-of-day-clock */
288         
289         update_wall_clock ();
290         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
291
292         update_disk_space ();
293         update_cpu_load ();
294         update_sample_rate (engine->frame_rate());
295
296         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
297         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
298 }
299
300 ARDOUR_UI::~ARDOUR_UI ()
301 {
302         save_ardour_state ();
303
304         if (keyboard) {
305                 delete keyboard;
306         }
307
308         if (editor) {
309                 delete editor;
310         }
311
312         if (mixer) {
313                 delete mixer;
314         }
315
316         if (add_route_dialog) {
317                 delete add_route_dialog;
318         }
319
320         Source::stop_peak_thread ();
321 }
322
323 gint
324 ARDOUR_UI::configure_timeout ()
325 {
326         struct timeval now;
327         struct timeval diff;
328
329         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
330                 /* no configure events yet */
331                 return TRUE;
332         }
333
334         gettimeofday (&now, 0);
335         timersub (&now, &last_configure_time, &diff);
336
337         /* force a gap of 0.5 seconds since the last configure event
338          */
339
340         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
341                 return TRUE;
342         } else {
343                 have_configure_timeout = false;
344                 save_ardour_state ();
345                 return FALSE;
346         }
347 }
348
349 gboolean
350 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
351 {
352         if (have_configure_timeout) {
353                 gettimeofday (&last_configure_time, 0);
354         } else {
355                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
356                 have_configure_timeout = true;
357         }
358                 
359         return FALSE;
360 }
361
362 void
363 ARDOUR_UI::save_ardour_state ()
364 {
365         if (!keyboard || !mixer || !editor) {
366                 return;
367         }
368         
369         /* XXX this is all a bit dubious. add_extra_xml() uses
370            a different lifetime model from add_instant_xml().
371         */
372
373         XMLNode* node = new XMLNode (keyboard->get_state());
374         Config->add_extra_xml (*node);
375         Config->save_state();
376
377         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
378         XMLNode& mnode (mixer->get_state());
379
380         if (session) {
381                 session->add_instant_xml(enode, session->path());
382                 session->add_instant_xml(mnode, session->path());
383         } else {
384                 Config->add_instant_xml(enode, get_user_ardour_path());
385                 Config->add_instant_xml(mnode, get_user_ardour_path());
386         }
387
388         /* keybindings */
389
390         AccelMap::save ("ardour.saved_bindings");
391 }
392
393 void
394 ARDOUR_UI::startup ()
395 {
396         /* Once the UI is up and running, start the audio engine. Doing
397            this before the UI is up and running can cause problems
398            when not running with SCHED_FIFO, because the amount of
399            CPU and disk work needed to get the UI started can interfere
400            with the scheduling of the audio thread.
401         */
402
403         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
404 }
405
406 void
407 ARDOUR_UI::finish()
408 {
409         if (session && session->dirty()) {
410                 switch (ask_about_saving_session(_("quit"))) {
411                 case -1:
412                         return;
413                         break;
414                 case 1:
415                         /* use the default name */
416                         if (save_state_canfail ("")) {
417                                 /* failed - don't quit */
418                                 MessageDialog msg (*editor, 
419                                                _("\
420 Ardour was unable to save your session.\n\n\
421 If you still wish to quit, please use the\n\n\
422 \"Just quit\" option."));
423                                 msg.run ();
424                                 return;
425                         }
426                         break;
427                 case 0:
428                         break;
429                 }
430         }
431
432         quit ();
433 }
434
435 int
436 ARDOUR_UI::ask_about_saving_session (const string & what)
437 {
438         ArdourDialog window (_("ardour: save session?"));
439         Gtk::HBox dhbox;  // the hbox for the image and text
440         Gtk::Label  prompt_label;
441         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
442
443         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
444
445         string msg;
446
447         msg = string_compose(_("Don't %1"), what);
448         window.add_button (msg, RESPONSE_REJECT);
449         msg = string_compose(_("Just %1"), what);
450         window.add_button (msg, RESPONSE_APPLY);
451         msg = string_compose(_("Save and %1"), what);
452         window.add_button (msg, RESPONSE_ACCEPT);
453
454         window.set_default_response (RESPONSE_ACCEPT);
455
456         Gtk::Button noquit_button (msg);
457         noquit_button.set_name ("EditorGTKButton");
458
459         string prompt;
460         string type;
461
462         if (session->snap_name() == session->name()) {
463                 type = _("session");
464         } else {
465                 type = _("snapshot");
466         }
467         prompt = string_compose(_("The %1\n\"%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?"), 
468                          type, session->snap_name());
469         
470         prompt_label.set_text (prompt);
471         prompt_label.set_name (X_("PrompterLabel"));
472         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
473         dhbox.pack_start (*dimage, true, false, 5);
474         dhbox.pack_start (prompt_label, true, false, 5);
475         window.get_vbox()->pack_start (dhbox);
476
477         window.set_name (_("Prompter"));
478         window.set_position (Gtk::WIN_POS_MOUSE);
479         window.set_modal (true);
480         window.set_resizable (false);
481         window.show_all ();
482
483         save_the_session = 0;
484
485         editor->ensure_float (window);
486
487         ResponseType r = (ResponseType) window.run();
488
489         window.hide ();
490
491         switch (r) {
492         case RESPONSE_ACCEPT: // save and get out of here
493                 return 1;
494         case RESPONSE_APPLY:  // get out of here
495                 return 0;
496         default:
497                 break;
498         }
499
500         return -1;
501 }
502         
503 gint
504 ARDOUR_UI::every_second ()
505 {
506         update_cpu_load ();
507         update_buffer_load ();
508         update_disk_space ();
509         return TRUE;
510 }
511
512 gint
513 ARDOUR_UI::every_point_one_seconds ()
514 {
515         update_speed_display ();
516         RapidScreenUpdate(); /* EMIT_SIGNAL */
517         return TRUE;
518 }
519
520 gint
521 ARDOUR_UI::every_point_zero_one_seconds ()
522 {
523         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
524         return TRUE;
525 }
526
527 void
528 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
529 {
530         char buf[32];
531
532         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
533
534         if (!engine->connected()) {
535
536                 snprintf (buf, sizeof (buf), _("disconnected"));
537
538         } else {
539
540                 jack_nframes_t rate = engine->frame_rate();
541                 
542                 if (fmod (rate, 1000.0) != 0.0) {
543                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
544                                   (float) rate/1000.0f,
545                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
546                 } else {
547                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
548                                   rate/1000,
549                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
550                 }
551         }
552
553         sample_rate_label.set_text (buf);
554 }
555
556 void
557 ARDOUR_UI::update_cpu_load ()
558 {
559         char buf[32];
560         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
561         cpu_load_label.set_text (buf);
562 }
563
564 void
565 ARDOUR_UI::update_buffer_load ()
566 {
567         char buf[64];
568
569         if (session) {
570                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
571                           session->playback_load(), session->capture_load());
572                 buffer_load_label.set_text (buf);
573         } else {
574                 buffer_load_label.set_text ("");
575         }
576 }
577
578 void
579 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
580 {
581         if (ds.record_enabled()) {
582                 rec_enabled_diskstreams++;
583         }
584 }
585
586 void
587 ARDOUR_UI::update_disk_space()
588 {
589         if (session == 0) {
590                 return;
591         }
592
593         jack_nframes_t frames = session->available_capture_duration();
594         char buf[64];
595
596         if (frames == max_frames) {
597                 strcpy (buf, _("space: 24hrs+"));
598         } else {
599                 int hrs;
600                 int mins;
601                 int secs;
602                 jack_nframes_t fr = session->frame_rate();
603                 
604                 if (session->actively_recording()){
605                         
606                         rec_enabled_diskstreams = 0;
607                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
608                         
609                         if (rec_enabled_diskstreams) {
610                                 frames /= rec_enabled_diskstreams;
611                         }
612                         
613                 } else {
614                         
615                         /* hmmm. shall we divide by the route count? or the diskstream count?
616                            or what? for now, do nothing ...
617                         */
618                         
619                 }
620                 
621                 hrs  = frames / (fr * 3600);
622                 frames -= hrs * fr * 3600;
623                 mins = frames / (fr * 60);
624                 frames -= mins * fr * 60;
625                 secs = frames / fr;
626                 
627                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
628         }
629
630         disk_space_label.set_text (buf);
631 }                 
632
633 gint
634 ARDOUR_UI::update_wall_clock ()
635 {
636         time_t now;
637         struct tm *tm_now;
638         char buf[16];
639
640         time (&now);
641         tm_now = localtime (&now);
642
643         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
644         wall_clock_label.set_text (buf);
645
646         return TRUE;
647 }
648 void
649 ARDOUR_UI::control_methods_adjusted ()
650
651 {
652         int which_method;
653
654         which_method = (int) online_control_button->adjustment.get_value();
655         switch (which_method) {
656         case 0:
657                 allow_mmc_and_local ();
658                 break;
659         case 1:
660                 allow_mmc_only ();
661                 break;
662         case 2:
663                 allow_local_only ();
664                 break;
665         default:
666                 fatal << _("programming error: impossible control method") << endmsg;
667         }
668 }
669         
670
671 void
672 ARDOUR_UI::mmc_device_id_adjusted ()
673
674 {
675 #if 0
676         if (mmc) {
677                 int dev_id = (int) mmc_id_button->adjustment.get_value();
678                 mmc->set_device_id (dev_id);
679         }
680 #endif
681 }
682
683 gint
684 ARDOUR_UI::session_menu (GdkEventButton *ev)
685 {
686         session_popup_menu->popup (0, 0);
687         return TRUE;
688 }
689
690 void
691 ARDOUR_UI::redisplay_recent_sessions ()
692 {
693         vector<string *> *sessions;
694         vector<string *>::iterator i;
695         RecentSessionsSorter cmp;
696         
697         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
698         recent_session_model->clear ();
699
700         RecentSessions rs;
701         ARDOUR::read_recent_sessions (rs);
702
703         if (rs.empty()) {
704                 recent_session_display.set_model (recent_session_model);
705                 return;
706         }
707
708         /* sort them alphabetically */
709         sort (rs.begin(), rs.end(), cmp);
710         sessions = new vector<string*>;
711
712         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
713                 sessions->push_back (new string ((*i).second));
714         }
715
716         for (i = sessions->begin(); i != sessions->end(); ++i) {
717
718                 vector<string*>* states;
719                 vector<const gchar*> item;
720                 string fullpath = *(*i);
721                 
722                 /* remove any trailing / */
723
724                 if (fullpath[fullpath.length()-1] == '/') {
725                         fullpath = fullpath.substr (0, fullpath.length()-1);
726                 }
727
728                 /* now get available states for this session */
729
730                 if ((states = Session::possible_states (fullpath)) == 0) {
731                         /* no state file? */
732                         continue;
733                 }
734
735                 TreeModel::Row row = *(recent_session_model->append());
736
737                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
738                 row[recent_session_columns.fullpath] = fullpath;
739
740                 if (states->size() > 1) {
741
742                         /* add the children */
743                         
744                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
745                                 
746                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
747
748                                 child_row[recent_session_columns.visible_name] = **i2;
749                                 child_row[recent_session_columns.fullpath] = fullpath;
750
751                                 delete *i2;
752                         }
753                 }
754
755                 delete states;
756         }
757
758         recent_session_display.set_model (recent_session_model);
759         delete sessions;
760 }
761
762 void
763 ARDOUR_UI::build_session_selector ()
764 {
765         session_selector_window = new ArdourDialog ("session selector");
766         
767         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
768         
769         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
770         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
771         session_selector_window->set_default_response (RESPONSE_ACCEPT);
772         recent_session_model = TreeStore::create (recent_session_columns);
773         recent_session_display.set_model (recent_session_model);
774         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
775         recent_session_display.set_headers_visible (false);
776         recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
777
778         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
779
780         scroller->add (recent_session_display);
781         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
782
783         session_selector_window->set_name ("SessionSelectorWindow");
784         session_selector_window->set_size_request (200, 400);
785         session_selector_window->get_vbox()->pack_start (*scroller);
786         session_selector_window->show_all_children();
787 }
788
789 void
790 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
791 {
792         session_selector_window->response (RESPONSE_ACCEPT);
793 }
794
795 void
796 ARDOUR_UI::open_recent_session ()
797 {
798         /* popup selector window */
799
800         if (session_selector_window == 0) {
801                 build_session_selector ();
802         }
803
804         redisplay_recent_sessions ();
805
806         ResponseType r = (ResponseType) session_selector_window->run ();
807
808         session_selector_window->hide();
809
810         switch (r) {
811         case RESPONSE_ACCEPT:
812                 break;
813         default:
814                 return;
815         }
816
817         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
818
819         if (i == recent_session_model->children().end()) {
820                 return;
821         }
822         
823         Glib::ustring path = (*i)[recent_session_columns.fullpath];
824         Glib::ustring state = (*i)[recent_session_columns.visible_name];
825
826         _session_is_new = false;
827
828         load_session (path, state);
829 }
830
831 bool
832 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
833 {
834         struct stat statbuf;
835
836         if (stat (info.filename.c_str(), &statbuf) != 0) {
837                 return false;
838         }
839
840         if (!S_ISDIR(statbuf.st_mode)) {
841                 return false;
842         }
843
844         string session_file = info.filename;
845         session_file += '/';
846         session_file += PBD::basename (info.filename);
847         session_file += ".ardour";
848         
849         if (stat (session_file.c_str(), &statbuf) != 0) {
850                 return false;
851         }
852
853         return S_ISREG (statbuf.st_mode);
854 }
855
856 void
857 ARDOUR_UI::open_session ()
858 {
859         /* popup selector window */
860
861         if (open_session_selector == 0) {
862
863                 /* ardour sessions are folders */
864
865                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
866                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
867                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
868
869                 FileFilter session_filter;
870                 session_filter.add_pattern ("*.ardour");
871                 session_filter.set_name (_("Ardour sessions"));
872                 open_session_selector->add_filter (session_filter);
873                 open_session_selector->set_filter (session_filter);
874         }
875
876         int response = open_session_selector->run();
877         open_session_selector->hide ();
878
879         switch (response) {
880         case RESPONSE_ACCEPT:
881                 break;
882         default:
883                 open_session_selector->hide();
884                 return;
885         }
886
887         open_session_selector->hide();
888         string session_path = open_session_selector->get_filename();
889         string path, name;
890         bool isnew;
891
892         if (session_path.length() > 0) {
893                 if (Session::find_session (session_path, path, name, isnew) == 0) {
894                         _session_is_new = isnew;
895                         load_session (path, name);
896                 }
897         }
898 }
899
900
901 void
902 ARDOUR_UI::session_add_midi_track ()
903 {
904         cerr << _("Patience is a virtue.\n");
905 }
906
907 void
908 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
909 {
910         Route* route;
911
912         if (session == 0) {
913                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
914                 return;
915         }
916
917         try { 
918                 if (disk) {
919                         if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
920                                 error << _("could not create new audio track") << endmsg;
921                         }
922                 } else {
923                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
924                                 error << _("could not create new audio bus") << endmsg;
925                         }
926                 }
927                 
928 #if CONTROLOUTS
929                 if (need_control_room_outs) {
930                         pan_t pans[2];
931                         
932                         pans[0] = 0.5;
933                         pans[1] = 0.5;
934                         
935                         route->set_stereo_control_outs (control_lr_channels);
936                         route->control_outs()->set_stereo_pan (pans, this);
937                 }
938 #endif /* CONTROLOUTS */
939         }
940
941         catch (...) {
942                 MessageDialog msg (*editor, 
943                                    _("There are insufficient JACK ports available\n\
944 to create a new track or bus.\n\
945 You should save Ardour, exit and\n\
946 restart JACK with more ports."));
947                 msg.run ();
948         }
949 }
950
951 void
952 ARDOUR_UI::diskstream_added (DiskStream* ds)
953 {
954 }
955
956 void
957 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
958 {
959         jack_nframes_t _preroll;
960
961         if (session) {
962                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
963
964                 if (new_position > _preroll) {
965                         new_position -= _preroll;
966                 } else {
967                         new_position = 0;
968                 }
969
970                 session->request_locate (new_position);
971         }
972 }
973
974 void
975 ARDOUR_UI::transport_goto_start ()
976 {
977         if (session) {
978                 session->goto_start();
979
980                 
981                 /* force displayed area in editor to start no matter
982                    what "follow playhead" setting is.
983                 */
984                 
985                 if (editor) {
986                         editor->reposition_x_origin (session->current_start_frame());
987                 }
988         }
989 }
990
991 void
992 ARDOUR_UI::transport_goto_zero ()
993 {
994         if (session) {
995                 session->request_locate (0);
996
997                 
998                 /* force displayed area in editor to start no matter
999                    what "follow playhead" setting is.
1000                 */
1001                 
1002                 if (editor) {
1003                         editor->reposition_x_origin (0);
1004                 }
1005         }
1006 }
1007
1008 void
1009 ARDOUR_UI::transport_goto_end ()
1010 {
1011         if (session) {
1012                 jack_nframes_t frame = session->current_end_frame();
1013                 session->request_locate (frame);
1014
1015                 /* force displayed area in editor to start no matter
1016                    what "follow playhead" setting is.
1017                 */
1018                 
1019                 if (editor) {
1020                         editor->reposition_x_origin (frame);
1021                 }
1022         }
1023 }
1024
1025 void
1026 ARDOUR_UI::transport_stop ()
1027 {
1028         if (!session) {
1029                 return;
1030         }
1031
1032         if (session->is_auditioning()) {
1033                 session->cancel_audition ();
1034                 return;
1035         }
1036         
1037         if (session->get_auto_loop()) {
1038                 session->request_auto_loop (false);
1039         }
1040         
1041         session->request_stop ();
1042 }
1043
1044 void
1045 ARDOUR_UI::transport_stop_and_forget_capture ()
1046 {
1047         if (session) {
1048                 session->request_stop (true);
1049         }
1050 }
1051
1052 void
1053 ARDOUR_UI::remove_last_capture()
1054 {
1055         if (editor) {
1056                 editor->remove_last_capture();
1057         }
1058 }
1059
1060 void
1061 ARDOUR_UI::transport_record ()
1062 {
1063         if (session) {
1064                 switch (session->record_status()) {
1065                 case Session::Disabled:
1066                         if (session->ntracks() == 0) {
1067                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1068                                 MessageDialog msg (*editor, txt);
1069                                 msg.run ();
1070                                 return;
1071                         }
1072                         session->maybe_enable_record ();
1073                         break;
1074                 case Session::Recording:
1075                 case Session::Enabled:
1076                         session->disable_record (true);
1077                 }
1078         }
1079 }
1080
1081 void
1082 ARDOUR_UI::transport_roll ()
1083 {
1084         bool rolling;
1085
1086         if (!session) {
1087                 return;
1088         }
1089
1090         rolling = session->transport_rolling ();
1091
1092         if (session->get_auto_loop()) {
1093                 session->request_auto_loop (false);
1094                 auto_loop_button.set_active (false);
1095                 roll_button.set_active (true);
1096         } else if (session->get_play_range ()) {
1097                 session->request_play_range (false);
1098                 play_selection_button.set_active (false);
1099         } else if (rolling) {
1100                 session->request_locate (session->last_transport_start(), true);
1101         }
1102
1103         session->request_transport_speed (1.0f);
1104 }
1105
1106 void
1107 ARDOUR_UI::transport_loop()
1108 {
1109         if (session) {
1110                 if (session->get_auto_loop()) {
1111                         if (session->transport_rolling()) {
1112                                 Location * looploc = session->locations()->auto_loop_location();
1113                                 if (looploc) {
1114                                         session->request_locate (looploc->start(), true);
1115                                 }
1116                         }
1117                 }
1118                 else {
1119                         session->request_auto_loop (true);
1120                 }
1121         }
1122 }
1123
1124 void
1125 ARDOUR_UI::transport_play_selection ()
1126 {
1127         if (!session) {
1128                 return;
1129         }
1130
1131         if (!session->get_play_range()) {
1132                 session->request_stop ();
1133         }
1134
1135         editor->play_selection ();
1136 }
1137
1138 void
1139 ARDOUR_UI::transport_rewind (int option)
1140 {
1141         float current_transport_speed;
1142  
1143         if (session) {
1144                 current_transport_speed = session->transport_speed();
1145                 
1146                 if (current_transport_speed >= 0.0f) {
1147                         switch (option) {
1148                         case 0:
1149                                 session->request_transport_speed (-1.0f);
1150                                 break;
1151                         case 1:
1152                                 session->request_transport_speed (-4.0f);
1153                                 break;
1154                         case -1:
1155                                 session->request_transport_speed (-0.5f);
1156                                 break;
1157                         }
1158                 } else {
1159                         /* speed up */
1160                         session->request_transport_speed (current_transport_speed * 1.5f);
1161                 }
1162         }
1163 }
1164
1165 void
1166 ARDOUR_UI::transport_forward (int option)
1167 {
1168         float current_transport_speed;
1169         
1170         if (session) {
1171                 current_transport_speed = session->transport_speed();
1172                 
1173                 if (current_transport_speed <= 0.0f) {
1174                         switch (option) {
1175                         case 0:
1176                                 session->request_transport_speed (1.0f);
1177                                 break;
1178                         case 1:
1179                                 session->request_transport_speed (4.0f);
1180                                 break;
1181                         case -1:
1182                                 session->request_transport_speed (0.5f);
1183                                 break;
1184                         }
1185                 } else {
1186                         /* speed up */
1187                         session->request_transport_speed (current_transport_speed * 1.5f);
1188                 }
1189         }
1190 }
1191
1192 void
1193 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1194 {
1195         if (session == 0) {
1196                 return;
1197         }
1198
1199         DiskStream *ds;
1200
1201         if ((ds = session->diskstream_by_id (dstream)) != 0) {
1202                 Port *port = ds->io()->input (0);
1203                 port->request_monitor_input (!port->monitoring_input());
1204         }
1205 }
1206
1207 void
1208 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1209 {
1210         if (session == 0) {
1211                 return;
1212         }
1213
1214         DiskStream *ds;
1215
1216         if ((ds = session->diskstream_by_id (dstream)) != 0) {
1217                 ds->set_record_enabled (!ds->record_enabled(), this);
1218         }
1219 }
1220
1221 void
1222 ARDOUR_UI::queue_transport_change ()
1223 {
1224         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1225 }
1226
1227 void
1228 ARDOUR_UI::map_transport_state ()
1229 {
1230         float sp = session->transport_speed();
1231
1232         if (sp == 1.0f) {
1233                 transport_rolling ();
1234         } else if (sp < 0.0f) {
1235                 transport_rewinding ();
1236         } else if (sp > 0.0f) {
1237                 transport_forwarding ();
1238         } else {
1239                 transport_stopped ();
1240         }
1241 }
1242
1243 void
1244 ARDOUR_UI::allow_local_only ()
1245 {
1246
1247 }
1248
1249 void
1250 ARDOUR_UI::allow_mmc_only ()
1251 {
1252
1253 }
1254
1255 void
1256 ARDOUR_UI::allow_mmc_and_local ()
1257 {
1258
1259 }
1260
1261 void
1262 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1263 {
1264         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1265                 (int) adj.get_value()].c_str());
1266 }
1267
1268 void
1269 ARDOUR_UI::engine_stopped ()
1270 {
1271         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1272         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1273         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1274 }
1275
1276
1277 void
1278 ARDOUR_UI::engine_running ()
1279 {
1280         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1281         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1282         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1283 }
1284
1285 void
1286 ARDOUR_UI::engine_halted ()
1287 {
1288         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1289
1290         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1291         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1292
1293         update_sample_rate (0);
1294
1295         MessageDialog msg (*editor, 
1296                            _("\
1297 JACK has either been shutdown or it\n\
1298 disconnected Ardour because Ardour\n\
1299 was not fast enough. You can save the\n\
1300 session and/or try to reconnect to JACK ."));
1301         msg.run ();
1302 }
1303
1304 int32_t
1305 ARDOUR_UI::do_engine_start ()
1306 {
1307         try { 
1308                 engine->start();
1309         }
1310
1311         catch (AudioEngine::PortRegistrationFailure& err) {
1312                 engine->stop ();
1313                 error << _("Unable to create all required ports")
1314                       << endmsg;
1315                 unload_session ();
1316                 return -1;
1317         }
1318
1319         catch (...) {
1320                 engine->stop ();
1321                 error << _("Unable to start the session running")
1322                       << endmsg;
1323                 unload_session ();
1324                 return -2;
1325         }
1326         
1327         return 0;
1328 }
1329
1330 gint
1331 ARDOUR_UI::start_engine ()
1332 {
1333         if (do_engine_start () == 0) {
1334                 if (session && _session_is_new) {
1335                         /* we need to retain initial visual 
1336                            settings for a new session 
1337                         */
1338                         session->save_state ("");
1339                 }
1340
1341                 /* there is too much going on, in too many threads, for us to 
1342                    end up with a clean session. So wait 1 second after loading,
1343                    and fix it up. its ugly, but until i come across a better
1344                    solution, its what we have.
1345                 */
1346
1347                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1348         }
1349
1350         return FALSE;
1351 }
1352
1353 void
1354 ARDOUR_UI::update_clocks ()
1355 {
1356          Clock (session->audible_frame()); /* EMIT_SIGNAL */
1357 }
1358
1359 void
1360 ARDOUR_UI::start_clocking ()
1361 {
1362         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1363 }
1364
1365 void
1366 ARDOUR_UI::stop_clocking ()
1367 {
1368         clock_signal_connection.disconnect ();
1369 }
1370         
1371 void
1372 ARDOUR_UI::toggle_clocking ()
1373 {
1374 #if 0
1375         if (clock_button.get_active()) {
1376                 start_clocking ();
1377         } else {
1378                 stop_clocking ();
1379         }
1380 #endif
1381 }
1382
1383 gint
1384 ARDOUR_UI::_blink (void *arg)
1385
1386 {
1387         ((ARDOUR_UI *) arg)->blink ();
1388         return TRUE;
1389 }
1390
1391 void
1392 ARDOUR_UI::blink ()
1393 {
1394          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1395 }
1396
1397 void
1398 ARDOUR_UI::start_blinking ()
1399 {
1400         /* Start the blink signal. Everybody with a blinking widget
1401            uses Blink to drive the widget's state.
1402         */
1403
1404         if (blink_timeout_tag < 0) {
1405                 blink_on = false;       
1406                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1407         }
1408 }
1409
1410 void
1411 ARDOUR_UI::stop_blinking ()
1412 {
1413         if (blink_timeout_tag >= 0) {
1414                 gtk_timeout_remove (blink_timeout_tag);
1415                 blink_timeout_tag = -1;
1416         }
1417 }
1418
1419
1420 void
1421 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1422 {
1423         using namespace Gtk;
1424         using namespace Menu_Helpers;
1425
1426         if (dstream.hidden()) {
1427                 return;
1428         }
1429
1430         MenuList& items = diskstream_menu->items();
1431         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1432 }
1433         
1434 void
1435 ARDOUR_UI::diskstream_selected (gint32 id)
1436 {
1437         selected_dstream = id;
1438         Main::quit ();
1439 }
1440
1441 gint32
1442 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1443 {
1444         using namespace Gtk;
1445         using namespace Menu_Helpers;
1446
1447         if (session == 0) {
1448                 return -1;
1449         }
1450
1451         diskstream_menu = new Menu();
1452         diskstream_menu->set_name ("ArdourContextMenu");
1453         using namespace Gtk;
1454         using namespace Menu_Helpers;
1455
1456         MenuList& items = diskstream_menu->items();
1457         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1458
1459         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1460
1461         if (ev) {
1462                 diskstream_menu->popup (ev->button, ev->time);
1463         } else {
1464                 diskstream_menu->popup (0, 0);
1465         }
1466
1467         selected_dstream = -1;
1468
1469         Main::run ();
1470
1471         delete diskstream_menu;
1472
1473         return selected_dstream;
1474 }
1475
1476 void
1477 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
1478                           string& buf,
1479                           IO& io,
1480                           bool in)
1481 {
1482         if (in) {
1483                 if (io.n_inputs() == 0) {
1484                         buf = _("none");
1485                         return;
1486                 }
1487                 
1488                 /* XXX we're not handling multiple ports yet. */
1489
1490                 const char **connections = io.input(0)->get_connections();
1491                 
1492                 if (connections == 0 || connections[0] == '\0') {
1493                         buf = _("off");
1494                 } else {
1495                         buf = connections[0];
1496                 }
1497
1498                 free (connections);
1499
1500         } else {
1501
1502                 if (io.n_outputs() == 0) {
1503                         buf = _("none");
1504                         return;
1505                 }
1506                 
1507                 /* XXX we're not handling multiple ports yet. */
1508
1509                 const char **connections = io.output(0)->get_connections();
1510                 
1511                 if (connections == 0 || connections[0] == '\0') {
1512                         buf = _("off");
1513                 } else {
1514                         buf = connections[0];
1515                 }
1516
1517                 free (connections);
1518         }
1519 }
1520
1521 void
1522 ARDOUR_UI::snapshot_session ()
1523 {
1524         ArdourPrompter prompter (true);
1525         string snapname;
1526         string now;
1527         time_t n;
1528
1529         time (&n);
1530         now = ctime (&n);
1531         now = now.substr (20, 4) + now.substr (3, 16) + " (" + now.substr (0, 3) + ")";
1532
1533         prompter.set_name ("Prompter");
1534         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1535         prompter.set_prompt (_("Name of New Snapshot"));
1536         prompter.set_initial_text (now);
1537         
1538         switch (prompter.run()) {
1539         case RESPONSE_ACCEPT:
1540                 prompter.get_result (snapname);
1541                 if (snapname.length()){
1542                         save_state (snapname);
1543                 }
1544                 break;
1545
1546         default:
1547                 break;
1548         }
1549 }
1550
1551 void
1552 ARDOUR_UI::save_state (const string & name)
1553 {
1554         (void) save_state_canfail (name);
1555 }
1556                 
1557 int
1558 ARDOUR_UI::save_state_canfail (string name)
1559 {
1560         if (session) {
1561                 int ret;
1562
1563                 if (name.length() == 0) {
1564                         name = session->snap_name();
1565                 }
1566
1567                 if ((ret = session->save_state (name)) != 0) {
1568                         return ret;
1569                 }
1570         }
1571         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1572         return 0;
1573 }
1574
1575 void
1576 ARDOUR_UI::restore_state (string name)
1577 {
1578         if (session) {
1579                 if (name.length() == 0) {
1580                         name = session->name();
1581                 }
1582                 session->restore_state (name);
1583         }
1584 }
1585
1586 void
1587 ARDOUR_UI::primary_clock_value_changed ()
1588 {
1589         if (session) {
1590                 session->request_locate (primary_clock.current_time ());
1591         }
1592 }
1593
1594 void
1595 ARDOUR_UI::secondary_clock_value_changed ()
1596 {
1597         if (session) {
1598                 session->request_locate (secondary_clock.current_time ());
1599         }
1600 }
1601
1602 void
1603 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1604 {
1605         if (session && dstream && dstream->record_enabled()) {
1606
1607                 Session::RecordState rs;
1608                 
1609                 rs = session->record_status ();
1610
1611                 switch (rs) {
1612                 case Session::Disabled:
1613                 case Session::Enabled:
1614                         if (w->get_state() != STATE_SELECTED) {
1615                                 w->set_state (STATE_SELECTED);
1616                         }
1617                         break;
1618
1619                 case Session::Recording:
1620                         if (w->get_state() != STATE_ACTIVE) {
1621                                 w->set_state (STATE_ACTIVE);
1622                         }
1623                         break;
1624                 }
1625
1626         } else {
1627                 if (w->get_state() != STATE_NORMAL) {
1628                         w->set_state (STATE_NORMAL);
1629                 }
1630         }
1631 }
1632
1633 void
1634 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1635 {
1636         if (session == 0) {
1637                 return;
1638         }
1639         
1640         switch (session->record_status()) {
1641         case Session::Enabled:
1642                 if (onoff) {
1643                         rec_button.set_state (1);
1644                 } else {
1645                         rec_button.set_state (0);
1646                 }
1647                 break;
1648
1649         case Session::Recording:
1650                 rec_button.set_state (2);
1651                 break;
1652
1653         default:
1654                 rec_button.set_state (0);
1655                 break;
1656         }
1657 }
1658
1659 gint
1660 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1661 {
1662         window->hide();
1663         Gtk::Main::quit ();
1664         return TRUE;
1665 }
1666
1667 void
1668 ARDOUR_UI::start_keyboard_prefix ()
1669 {
1670         keyboard->start_prefix();
1671 }
1672
1673 void
1674 ARDOUR_UI::save_template ()
1675
1676 {
1677         ArdourPrompter prompter (true);
1678         string name;
1679
1680         prompter.set_name (X_("Prompter"));
1681         prompter.set_prompt (_("Name for mix template:"));
1682         prompter.set_initial_text(session->name() + _("-template"));
1683         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1684         
1685         switch (prompter.run()) {
1686         case RESPONSE_ACCEPT:
1687                 prompter.get_result (name);
1688                 
1689                 if (name.length()) {
1690                         session->save_template (name);
1691                 }
1692                 break;
1693
1694         default:
1695                 break;
1696         }
1697 }
1698
1699 void
1700 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1701 {
1702         m_new_session_dialog->show_all();
1703         m_new_session_dialog->set_transient_for(*editor);
1704         m_new_session_dialog->set_name(predetermined_path);
1705
1706         int response = Gtk::RESPONSE_CANCEL;
1707
1708         do {
1709                 response = m_new_session_dialog->run ();
1710         
1711                 if(response == Gtk::RESPONSE_OK) {
1712
1713                         _session_is_new = true;
1714                         
1715                         std::string session_name = m_new_session_dialog->session_name();
1716                         std::string session_path = m_new_session_dialog->session_folder();
1717                         
1718                         /*
1719                           XXX This is needed because session constructor wants a 
1720                           non-existant path. hopefully this will be fixed at some point.
1721                         */
1722                         session_path = Glib::build_filename(session_path, session_name);
1723                         
1724                         std::string template_name = m_new_session_dialog->session_template_name();
1725                         
1726                         if (m_new_session_dialog->use_session_template()) {
1727                                 
1728                                 load_session (session_path, session_name, &template_name);
1729                                 
1730                         } else {
1731                                 
1732                                 uint32_t cchns;
1733                                 uint32_t mchns;
1734                                 Session::AutoConnectOption iconnect;
1735                                 Session::AutoConnectOption oconnect;
1736                                 
1737                                 if (m_new_session_dialog->create_control_bus()) {
1738                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1739                                 } else {
1740                                         cchns = 0;
1741                                 }
1742                                 
1743                                 if (m_new_session_dialog->create_master_bus()) {
1744                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1745                                 } else {
1746                                         mchns = 0;
1747                                 }
1748                                 
1749                                 if (m_new_session_dialog->connect_inputs()) {
1750                                         iconnect = Session::AutoConnectPhysical;
1751                                 } else {
1752                                         iconnect = Session::AutoConnectOption (0);
1753                                 }
1754                                 
1755                                 /// @todo some minor tweaks.
1756
1757                                 if (m_new_session_dialog->connect_outs_to_master()) {
1758                                         oconnect = Session::AutoConnectMaster;
1759                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1760                                         oconnect = Session::AutoConnectPhysical;
1761                                 } else {
1762                                         oconnect = Session::AutoConnectOption (0);
1763                                 } 
1764                                 
1765                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1766                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1767                                 
1768                                 build_session (session_path,
1769                                                session_name,
1770                                                cchns,
1771                                                mchns,
1772                                                iconnect,
1773                                                oconnect,
1774                                                nphysin,
1775                                                nphysout, 
1776                                                engine->frame_rate() * 60 * 5);
1777                         }               
1778                 }
1779
1780         } while(response == Gtk::RESPONSE_HELP);
1781         m_new_session_dialog->hide_all();
1782 }
1783
1784 int
1785 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1786 {
1787         Session *new_session;
1788         int x;
1789         session_loaded = false;
1790         x = unload_session ();
1791
1792         if (x < 0) {
1793                 return -1;
1794         } else if (x > 0) {
1795                 return 0;
1796         }
1797
1798         /* if it already exists, we must have write access */
1799
1800         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1801                 MessageDialog msg (*editor, _("\
1802 You do not have write access to this session.\n\
1803 This prevents the session from being loaded."));
1804                 msg.run ();
1805                 return -1;
1806         }
1807
1808         try {
1809                 new_session = new Session (*engine, path, snap_name, mix_template);
1810         }
1811
1812         catch (...) {
1813
1814                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1815                 return -1;
1816         }
1817
1818         connect_to_session (new_session);
1819
1820         //if (engine->running()) {
1821         //mixer->show_window();
1822         //}
1823         session_loaded = true;
1824         return 0;
1825 }
1826
1827 int
1828 ARDOUR_UI::make_session_clean ()
1829 {
1830         if (session) {
1831                 session->set_clean ();
1832         }
1833
1834         return FALSE;
1835 }
1836
1837 int
1838 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
1839                           uint32_t control_channels,
1840                           uint32_t master_channels, 
1841                           Session::AutoConnectOption input_connect,
1842                           Session::AutoConnectOption output_connect,
1843                           uint32_t nphysin,
1844                           uint32_t nphysout,
1845                           jack_nframes_t initial_length)
1846 {
1847         Session *new_session;
1848         int x;
1849
1850         session_loaded = false;
1851         x = unload_session ();
1852         if (x < 0) {
1853                 return -1;
1854         } else if (x > 0) {
1855                 return 0;
1856         }
1857         
1858         _session_is_new = true;
1859
1860         try {
1861                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1862                                            control_channels, master_channels, nphysin, nphysout, initial_length);
1863         }
1864
1865         catch (...) {
1866
1867                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1868                 return -1;
1869         }
1870
1871         connect_to_session (new_session);
1872
1873         //if (engine->running()) {
1874         //mixer->show_window();
1875         //}
1876         session_loaded = true;
1877         return 0;
1878 }
1879
1880 void
1881 ARDOUR_UI::show ()
1882 {
1883         if (editor) {
1884                 editor->show_window ();
1885                 shown_flag = true;
1886         }
1887
1888         if (session && mixer) {
1889                 // mixer->show_window ();
1890         }
1891         
1892         if (about) {
1893                 about->present ();
1894         }
1895 }
1896
1897 void
1898 ARDOUR_UI::show_splash ()
1899 {
1900         if (about == 0) {
1901                 about = new About();
1902         }
1903         about->present();
1904 }
1905
1906 void
1907 ARDOUR_UI::hide_splash ()
1908 {
1909         if (about) {
1910                 // about->hide();
1911         }
1912 }
1913
1914 void
1915 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1916 {
1917         size_t removed;
1918
1919         removed = rep.paths.size();
1920
1921         if (removed == 0) {
1922                 MessageDialog msgd (*editor,
1923                                     _("No audio files were ready for cleanup"), 
1924                                     true,
1925                                     Gtk::MESSAGE_INFO,
1926                                     (Gtk::ButtonsType)(Gtk::BUTTONS_CLOSE)  );
1927                 msgd.set_secondary_text (_("If this seems suprising, \n\
1928 check for any existing snapshots.\n\
1929 These may still include regions that\n\
1930 require some unused files to continue to exist."));
1931         
1932                 msgd.run ();
1933                 return;
1934         } 
1935
1936         ArdourDialog results (_("ardour: cleanup"), true, false);
1937         
1938         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1939             CleanupResultsModelColumns() { 
1940                     add (visible_name);
1941                     add (fullpath);
1942             }
1943             Gtk::TreeModelColumn<Glib::ustring> visible_name;
1944             Gtk::TreeModelColumn<Glib::ustring> fullpath;
1945         };
1946
1947         
1948         CleanupResultsModelColumns results_columns;
1949         Glib::RefPtr<Gtk::ListStore> results_model;
1950         Gtk::TreeView results_display;
1951         
1952         results_model = ListStore::create (results_columns);
1953         results_display.set_model (results_model);
1954         results_display.append_column (list_title, results_columns.visible_name);
1955
1956         results_display.set_name ("CleanupResultsList");
1957         results_display.set_headers_visible (true);
1958         results_display.set_headers_clickable (false);
1959         results_display.set_reorderable (false);
1960
1961         Gtk::ScrolledWindow list_scroller;
1962         Gtk::Label txt;
1963         Gtk::VBox dvbox;
1964         Gtk::HBox dhbox;  // the hbox for the image and text
1965         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
1966         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
1967
1968         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
1969
1970         if (rep.space < 1048576.0f) {
1971                 if (removed > 1) {
1972                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1973                 } else {
1974                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1975                 }
1976         } else {
1977                 if (removed > 1) {
1978                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1979                 } else {
1980                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1981                 }
1982         }
1983
1984         dhbox.pack_start (*dimage, true, false, 5);
1985         dhbox.pack_start (txt, true, false, 5);
1986
1987         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1988                 TreeModel::Row row = *(results_model->append());
1989                 row[results_columns.visible_name] = *i;
1990                 row[results_columns.fullpath] = *i;
1991         }
1992         
1993         list_scroller.add (results_display);
1994         list_scroller.set_size_request (-1, 150);
1995         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1996
1997         dvbox.pack_start (dhbox, true, false, 5);
1998         dvbox.pack_start (list_scroller, true, false, 5);
1999         ddhbox.pack_start (dvbox, true, false, 5);
2000
2001         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2002         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2003         results.set_default_response (RESPONSE_CLOSE);
2004         results.set_position (Gtk::WIN_POS_MOUSE);
2005         results.show_all_children ();
2006         results.set_resizable (false);
2007
2008         results.run ();
2009
2010 }
2011
2012 void
2013 ARDOUR_UI::cleanup ()
2014 {
2015         if (session == 0) {
2016                 /* shouldn't happen: menu item is insensitive */
2017                 return;
2018         }
2019
2020
2021         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2022                                 true,
2023                                 Gtk::MESSAGE_QUESTION,
2024                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2025
2026         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2027 ALL undo/redo information will be lost if you cleanup.\n\
2028 After cleanup, unused audio files will be moved to a \
2029 \"dead sounds\" location."));
2030         
2031         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2032         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2033         checker.set_default_response (RESPONSE_CANCEL);
2034
2035         checker.set_name (_("CleanupDialog"));
2036         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2037         checker.set_position (Gtk::WIN_POS_MOUSE);
2038
2039         switch (checker.run()) {
2040         case RESPONSE_ACCEPT:
2041                 break;
2042         default:
2043                 return;
2044         }
2045
2046         Session::cleanup_report rep;
2047
2048         editor->prepare_for_cleanup ();
2049
2050         if (session->cleanup_sources (rep)) {
2051                 return;
2052         }
2053         checker.hide();
2054         display_cleanup_results (rep, 
2055                                  _("cleaned files"),
2056                                  _("\
2057 The following %1 %2 not in use and \n\
2058 have been moved to:\n\
2059 %3. \n\n\
2060 Flushing the wastebasket will \n\
2061 release an additional\n\
2062 %4 %5bytes of disk space.\n"
2063                                          ));
2064 }
2065
2066 void
2067 ARDOUR_UI::flush_trash ()
2068 {
2069         if (session == 0) {
2070                 /* shouldn't happen: menu item is insensitive */
2071                 return;
2072         }
2073
2074         Session::cleanup_report rep;
2075
2076         if (session->cleanup_trash_sources (rep)) {
2077                 return;
2078         }
2079
2080         display_cleanup_results (rep, 
2081                                  _("deleted file"),
2082                                  _("The following %1 %2 deleted from\n\
2083 %3,\n\
2084 releasing %4 %5bytes of disk space"));
2085 }
2086
2087 void
2088 ARDOUR_UI::add_route ()
2089 {
2090         int count;
2091
2092         if (!session) {
2093                 return;
2094         }
2095
2096         if (add_route_dialog == 0) {
2097                 add_route_dialog = new AddRouteDialog;
2098                 editor->ensure_float (*add_route_dialog);
2099         }
2100
2101         if (add_route_dialog->is_visible()) {
2102                 /* we're already doing this */
2103                 return;
2104         }
2105
2106         ResponseType r = (ResponseType) add_route_dialog->run ();
2107         
2108         add_route_dialog->hide();
2109
2110         switch (r) {
2111         case RESPONSE_ACCEPT:
2112                 break;
2113         default:
2114                 return;
2115                 break;
2116         }
2117
2118         if ((count = add_route_dialog->count()) <= 0) {
2119                 return;
2120         }
2121
2122         uint32_t input_chan = add_route_dialog->channels ();
2123         uint32_t output_chan;
2124         string name_template = add_route_dialog->name_template ();
2125         bool track = add_route_dialog->track ();
2126
2127         Session::AutoConnectOption oac = session->get_output_auto_connect();
2128
2129         if (oac & Session::AutoConnectMaster) {
2130                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2131         } else {
2132                 output_chan = input_chan;
2133         }
2134
2135         /* XXX do something with name template */
2136
2137         while (count) {
2138                 if (track) {
2139                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2140                 } else {
2141                         session_add_audio_bus (input_chan, output_chan);
2142                 }
2143                 --count;
2144                 
2145                 while (Main::events_pending()) {
2146                         Main::iteration ();
2147                 }
2148         }
2149 }
2150
2151 XMLNode*
2152 ARDOUR_UI::mixer_settings () const
2153 {
2154         XMLNode* node = 0;
2155
2156         if (session) {
2157                 node = session->instant_xml(X_("Mixer"), session->path());
2158         } else {
2159                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2160         }
2161
2162         if (!node) {
2163                 node = new XMLNode (X_("Mixer"));
2164         }
2165
2166         return node;
2167 }
2168
2169 XMLNode*
2170 ARDOUR_UI::editor_settings () const
2171 {
2172         XMLNode* node = 0;
2173
2174         if (session) {
2175                 node = session->instant_xml(X_("Editor"), session->path());
2176         } else {
2177                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2178         }
2179
2180         if (!node) {
2181                 node = new XMLNode (X_("Editor"));
2182         }
2183         return node;
2184 }
2185
2186 XMLNode*
2187 ARDOUR_UI::keyboard_settings () const
2188 {
2189         XMLNode* node = 0;
2190
2191         node = Config->extra_xml(X_("Keyboard"));
2192         
2193         if (!node) {
2194                 node = new XMLNode (X_("Keyboard"));
2195         }
2196         return node;
2197 }
2198
2199 void
2200 ARDOUR_UI::halt_on_xrun_message ()
2201 {
2202         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2203
2204         MessageDialog msg (*editor,
2205                            _("Recording was stopped because your system could not keep up."));
2206         msg.run ();
2207 }
2208
2209 void 
2210 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2211 {
2212         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2213
2214         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2215                 delete *i;
2216         }
2217
2218         delete deletion_list;
2219 }
2220
2221 void
2222 ARDOUR_UI::disk_overrun_handler ()
2223 {
2224         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2225
2226         if (!have_disk_overrun_displayed) {
2227                 have_disk_overrun_displayed = true;
2228                 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2229 The disk system on your computer\n\
2230 was not able to keep up with Ardour.\n\
2231 \n\
2232 Specifically, it failed to write data to disk\n\
2233 quickly enough to keep up with recording.\n"));
2234                 msg.run ();
2235                 have_disk_overrun_displayed = false;
2236         }
2237 }
2238
2239 void
2240 ARDOUR_UI::disk_underrun_handler ()
2241 {
2242         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2243
2244         if (!have_disk_underrun_displayed) {
2245                 have_disk_underrun_displayed = true;
2246                 MessageDialog msg (*editor,
2247                         (_("The disk system on your computer\n\
2248 was not able to keep up with Ardour.\n\
2249 \n\
2250 Specifically, it failed to read data from disk\n\
2251 quickly enough to keep up with playback.\n")));
2252                 msg.run ();
2253                 have_disk_underrun_displayed = false;
2254         } 
2255 }
2256
2257 void
2258 ARDOUR_UI::disk_underrun_message_gone ()
2259 {
2260         have_disk_underrun_displayed = false;
2261 }
2262
2263 void
2264 ARDOUR_UI::disk_overrun_message_gone ()
2265 {
2266         have_disk_underrun_displayed = false;
2267 }
2268
2269 int
2270 ARDOUR_UI::pending_state_dialog ()
2271 {
2272         ArdourDialog dialog ("pending state dialog");
2273         Label  message (_("\
2274 This session appears to have been in\n\
2275 middle of recording when ardour or\n\
2276 the computer was shutdown.\n\
2277 \n\
2278 Ardour can recover any captured audio for\n\
2279 you, or it can ignore it. Please decide\n\
2280 what you would like to do.\n"));
2281
2282         dialog.get_vbox()->pack_start (message);
2283         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2284         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2285
2286         dialog.set_position (WIN_POS_CENTER);
2287         dialog.show_all ();
2288         
2289         switch (dialog.run ()) {
2290         case RESPONSE_ACCEPT:
2291                 return 1;
2292         default:
2293                 return 0;
2294         }
2295 }
2296         
2297 void
2298 ARDOUR_UI::disconnect_from_jack ()
2299 {
2300         if (engine) {
2301                 if( engine->disconnect_from_jack ()) {
2302                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2303                         msg.run ();
2304                 }
2305
2306                 update_sample_rate (0);
2307         }
2308 }
2309
2310 void
2311 ARDOUR_UI::reconnect_to_jack ()
2312 {
2313         if (engine) {
2314                 if (engine->reconnect_to_jack ()) {
2315                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2316                         msg.run ();
2317                 }
2318
2319                 update_sample_rate (0);
2320         }
2321 }
2322
2323 void
2324 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2325 {
2326         engine->request_buffer_size (nframes);
2327         update_sample_rate (0);
2328 }
2329
2330 int
2331 ARDOUR_UI::cmdline_new_session (string path)
2332 {
2333         if (path[0] != '/') {
2334                 char buf[PATH_MAX+1];
2335                 string str;
2336
2337                 getcwd (buf, sizeof (buf));
2338                 str = buf;
2339                 str += '/';
2340                 str += path;
2341                 path = str;
2342         }
2343
2344         new_session (false, path);
2345
2346         _will_create_new_session_automatically = false; /* done it */
2347         return FALSE; /* don't call it again */
2348 }
2349
2350 void
2351 ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
2352 {
2353         Glib::RefPtr<Action> act;
2354         
2355         switch (hf) {
2356         case BWF:
2357                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2358                 break;
2359         case WAVE:
2360                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2361                 break;
2362         case WAVE64:
2363                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2364                 break;
2365         case iXML:
2366                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2367                 break;
2368         case RF64:
2369                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2370                 break;
2371         }
2372
2373         if (act) {
2374                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2375                 if (ract && ract->get_active() && Config->get_native_file_header_format() != hf) {
2376                         Config->set_native_file_header_format (hf);
2377                         if (session) {
2378                                 session->reset_native_file_format ();
2379                         }
2380                 }
2381         }
2382 }
2383
2384 void
2385 ARDOUR_UI::set_native_file_data_format (SampleFormat sf)
2386 {
2387         Glib::RefPtr<Action> act;
2388         
2389         switch (sf) {
2390         case FormatFloat:
2391                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2392                 break;
2393         case FormatInt24:
2394                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2395                 break;
2396         }
2397
2398         if (act) {
2399                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2400
2401                 if (ract && ract->get_active() && Config->get_native_file_data_format() != sf) {
2402                         Config->set_native_file_data_format (sf);
2403                         if (session) {
2404                                 session->reset_native_file_format ();
2405                         }
2406                 }
2407         }
2408 }
2409
2410 void
2411 ARDOUR_UI::use_config ()
2412 {
2413         Glib::RefPtr<Action> act;
2414
2415         switch (Config->get_native_file_data_format ()) {
2416         case FormatFloat:
2417                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2418                 break;
2419         case FormatInt24:
2420                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2421                 break;
2422         }
2423
2424         if (act) {
2425                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2426                 ract->set_active ();
2427         }       
2428
2429         switch (Config->get_native_file_header_format ()) {
2430         case BWF:
2431                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2432                 break;
2433         case WAVE:
2434                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2435                 break;
2436         case WAVE64:
2437                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2438                 break;
2439         case iXML:
2440                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2441                 break;
2442         case RF64:
2443                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2444                 break;
2445         }
2446
2447         if (act) {
2448                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2449                 ract->set_active ();
2450         }       
2451 }