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