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