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