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