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