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