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