bcaf4d0cc6ebfff2610985a6bb5dabab1652c56c
[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
75 #include "i18n.h"
76
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Gtk;
80 using namespace sigc;
81
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
83
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
88
89 /* XPM */
90 static const gchar *h_meter_strip_xpm[] = {
91 "186 5 187 2",
92 "       c None",
93 ".      c #2BFE00",
94 "+      c #2DFE00",
95 "@      c #2FFE01",
96 "#      c #32FE01",
97 "$      c #34FE02",
98 "%      c #36FE02",
99 "&      c #38FE03",
100 "*      c #3BFE03",
101 "=      c #3DFD04",
102 "-      c #3FFD04",
103 ";      c #41FD05",
104 ">      c #44FD05",
105 ",      c #46FD06",
106 "'      c #48FD06",
107 ")      c #4AFD07",
108 "!      c #4DFD07",
109 "~      c #4FFD08",
110 "{      c #51FC08",
111 "]      c #53FC09",
112 "^      c #56FC09",
113 "/      c #58FC09",
114 "(      c #5AFC0A",
115 "_      c #5CFC0A",
116 ":      c #5FFC0B",
117 "<      c #61FC0B",
118 "[      c #63FB0C",
119 "}      c #65FB0C",
120 "|      c #68FB0D",
121 "1      c #6AFB0D",
122 "2      c #6CFB0E",
123 "3      c #6EFB0E",
124 "4      c #71FB0F",
125 "5      c #73FB0F",
126 "6      c #75FB10",
127 "7      c #77FA10",
128 "8      c #7AFA11",
129 "9      c #7CFA11",
130 "0      c #7EFA12",
131 "a      c #80FA12",
132 "b      c #83FA12",
133 "c      c #85FA13",
134 "d      c #87FA13",
135 "e      c #89FA14",
136 "f      c #8CF914",
137 "g      c #8EF915",
138 "h      c #90F915",
139 "i      c #92F916",
140 "j      c #95F916",
141 "k      c #97F917",
142 "l      c #99F917",
143 "m      c #9BF918",
144 "n      c #9EF818",
145 "o      c #A0F819",
146 "p      c #A2F819",
147 "q      c #A4F81A",
148 "r      c #A7F81A",
149 "s      c #A9F81A",
150 "t      c #ABF81B",
151 "u      c #ADF81B",
152 "v      c #B0F81C",
153 "w      c #B2F71C",
154 "x      c #B4F71D",
155 "y      c #B6F71D",
156 "z      c #B9F71E",
157 "A      c #BBF71E",
158 "B      c #BDF71F",
159 "C      c #BFF71F",
160 "D      c #C2F720",
161 "E      c #C4F720",
162 "F      c #C6F621",
163 "G      c #C8F621",
164 "H      c #CBF622",
165 "I      c #CDF622",
166 "J      c #CFF623",
167 "K      c #D1F623",
168 "L      c #D4F624",
169 "M      c #D6F624",
170 "N      c #D8F524",
171 "O      c #DAF525",
172 "P      c #DDF525",
173 "Q      c #DFF526",
174 "R      c #E1F526",
175 "S      c #E3F527",
176 "T      c #E6F527",
177 "U      c #E8F528",
178 "V      c #EAF528",
179 "W      c #ECF429",
180 "X      c #EFF429",
181 "Y      c #F1F42A",
182 "Z      c #F3F42A",
183 "`      c #F5F42B",
184 " .     c #F8F42B",
185 "..     c #FAF42C",
186 "+.     c #FCF42C",
187 "@.     c #FFF42D",
188 "#.     c #FFF22C",
189 "$.     c #FFF12B",
190 "%.     c #FFF02A",
191 "&.     c #FFEF2A",
192 "*.     c #FFEE29",
193 "=.     c #FFED28",
194 "-.     c #FFEC28",
195 ";.     c #FFEB27",
196 ">.     c #FFE926",
197 ",.     c #FFE826",
198 "'.     c #FFE725",
199 ").     c #FFE624",
200 "!.     c #FFE524",
201 "~.     c #FFE423",
202 "{.     c #FFE322",
203 "].     c #FFE222",
204 "^.     c #FFE021",
205 "/.     c #FFDF20",
206 "(.     c #FFDE20",
207 "_.     c #FFDD1F",
208 ":.     c #FFDC1E",
209 "<.     c #FFDB1E",
210 "[.     c #FFDA1D",
211 "}.     c #FFD91C",
212 "|.     c #FFD71B",
213 "1.     c #FFD61B",
214 "2.     c #FFD51A",
215 "3.     c #FFD419",
216 "4.     c #FFD319",
217 "5.     c #FFD218",
218 "6.     c #FFD117",
219 "7.     c #FFD017",
220 "8.     c #FFCF16",
221 "9.     c #FFCD15",
222 "0.     c #FFCC15",
223 "a.     c #FFCB14",
224 "b.     c #FFCA13",
225 "c.     c #FFC913",
226 "d.     c #FFC812",
227 "e.     c #FFC711",
228 "f.     c #FFC611",
229 "g.     c #FFC410",
230 "h.     c #FFC30F",
231 "i.     c #FFC20F",
232 "j.     c #FFC10E",
233 "k.     c #FFC00D",
234 "l.     c #FFBF0C",
235 "m.     c #FFBE0C",
236 "n.     c #FFBD0B",
237 "o.     c #FFBB0A",
238 "p.     c #FFBA0A",
239 "q.     c #FFB909",
240 "r.     c #FFB808",
241 "s.     c #FFB708",
242 "t.     c #FFB607",
243 "u.     c #FFB506",
244 "v.     c #FFB406",
245 "w.     c #FFB205",
246 "x.     c #FFB104",
247 "y.     c #FFB004",
248 "z.     c #FFAF03",
249 "A.     c #FFAE02",
250 "B.     c #FFAD02",
251 "C.     c #FFAC01",
252 "D.     c #FFAB00",
253 "E.     c #FFA900",
254 "F.     c #F11F00",
255 "G.     c #F21E00",
256 "H.     c #F21C00",
257 "I.     c #F31B00",
258 "J.     c #F31A00",
259 "K.     c #F41800",
260 "L.     c #F41700",
261 "M.     c #F51600",
262 "N.     c #F61400",
263 "O.     c #F61300",
264 "P.     c #F71100",
265 "Q.     c #F71000",
266 "R.     c #F80F00",
267 "S.     c #F90D00",
268 "T.     c #F90C00",
269 "U.     c #FA0B00",
270 "V.     c #FA0900",
271 "W.     c #FB0800",
272 "X.     c #FC0600",
273 "Y.     c #FC0500",
274 "Z.     c #FD0400",
275 "`.     c #FD0200",
276 " +     c #FE0100",
277 ".+     c #FE0000",
278 "++     c #FF0000",
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
284
285 /* XPM */
286 static const gchar * v_meter_strip_xpm[] = {
287 "5 250 230 2",
288 "       c None",
289 ".      c #FE0000",
290 "+      c #FF0000",
291 "@      c #FE0100",
292 "#      c #FD0200",
293 "$      c #FD0300",
294 "%      c #FD0400",
295 "&      c #FC0500",
296 "*      c #FC0600",
297 "=      c #FC0700",
298 "-      c #FB0800",
299 ";      c #FA0900",
300 ">      c #FA0A00",
301 ",      c #FA0B00",
302 "'      c #F90C00",
303 ")      c #F90D00",
304 "!      c #F80E00",
305 "~      c #F80F00",
306 "{      c #F71000",
307 "]      c #F71100",
308 "^      c #F61200",
309 "/      c #F61300",
310 "(      c #F61400",
311 "_      c #F51600",
312 ":      c #F41700",
313 "<      c #F41800",
314 "[      c #F31A00",
315 "}      c #F31B00",
316 "|      c #F21C00",
317 "1      c #F21E00",
318 "2      c #F11F00",
319 "3      c #F54A00",
320 "4      c #FFA900",
321 "5      c #FFAB00",
322 "6      c #FFAC01",
323 "7      c #FFAD02",
324 "8      c #FFAE02",
325 "9      c #FFAF03",
326 "0      c #FFB004",
327 "a      c #FFB104",
328 "b      c #FFB205",
329 "c      c #FFB406",
330 "d      c #FFB506",
331 "e      c #FFB607",
332 "f      c #FFB708",
333 "g      c #FFB808",
334 "h      c #FFB909",
335 "i      c #FFBA0A",
336 "j      c #FFBB0A",
337 "k      c #FFBC0A",
338 "l      c #FFBD0B",
339 "m      c #FFBE0C",
340 "n      c #FFBF0C",
341 "o      c #FFC00D",
342 "p      c #FFC10E",
343 "q      c #FFC20F",
344 "r      c #FFC30F",
345 "s      c #FFC410",
346 "t      c #FFC511",
347 "u      c #FFC611",
348 "v      c #FFC711",
349 "w      c #FFC812",
350 "x      c #FFC913",
351 "y      c #FFCA13",
352 "z      c #FFCB14",
353 "A      c #FFCC15",
354 "B      c #FFCD15",
355 "C      c #FFCF16",
356 "D      c #FFD017",
357 "E      c #FFD117",
358 "F      c #FFD218",
359 "G      c #FFD319",
360 "H      c #FFD419",
361 "I      c #FFD51A",
362 "J      c #FFD61B",
363 "K      c #FFD71B",
364 "L      c #FFD81C",
365 "M      c #FFD91C",
366 "N      c #FFDA1D",
367 "O      c #FFDB1E",
368 "P      c #FFDC1E",
369 "Q      c #FFDD1F",
370 "R      c #FFDE20",
371 "S      c #FFDF20",
372 "T      c #FFE021",
373 "U      c #FFE222",
374 "V      c #FFE322",
375 "W      c #FFE423",
376 "X      c #FFE524",
377 "Y      c #FFE624",
378 "Z      c #FFE725",
379 "`      c #FFE826",
380 " .     c #FFE926",
381 "..     c #FFEA26",
382 "+.     c #FFEB27",
383 "@.     c #FFEC28",
384 "#.     c #FFED28",
385 "$.     c #FFEE29",
386 "%.     c #FFEF2A",
387 "&.     c #FFF02A",
388 "*.     c #FFF12B",
389 "=.     c #FFF22C",
390 "-.     c #FFF32D",
391 ";.     c #FFF42D",
392 ">.     c #FDF42C",
393 ",.     c #FBF42C",
394 "'.     c #FAF42C",
395 ").     c #F8F42B",
396 "!.     c #F6F42B",
397 "~.     c #F4F42B",
398 "{.     c #F3F42A",
399 "].     c #F1F42A",
400 "^.     c #F0F429",
401 "/.     c #EEF429",
402 "(.     c #ECF429",
403 "_.     c #EAF528",
404 ":.     c #E9F528",
405 "<.     c #E7F528",
406 "[.     c #E5F527",
407 "}.     c #E3F527",
408 "|.     c #E2F526",
409 "1.     c #E0F526",
410 "2.     c #DFF526",
411 "3.     c #DDF525",
412 "4.     c #DBF525",
413 "5.     c #D9F525",
414 "6.     c #D8F524",
415 "7.     c #D6F624",
416 "8.     c #D5F624",
417 "9.     c #D3F624",
418 "0.     c #D1F623",
419 "a.     c #CFF623",
420 "b.     c #CEF622",
421 "c.     c #CCF622",
422 "d.     c #CBF622",
423 "e.     c #C9F621",
424 "f.     c #C7F621",
425 "g.     c #C5F621",
426 "h.     c #C4F720",
427 "i.     c #C2F720",
428 "j.     c #C0F71F",
429 "k.     c #BEF71F",
430 "l.     c #BDF71F",
431 "m.     c #BBF71E",
432 "n.     c #BAF71E",
433 "o.     c #B8F71E",
434 "p.     c #B6F71D",
435 "q.     c #B5F71D",
436 "r.     c #B3F71D",
437 "s.     c #B2F71C",
438 "t.     c #B0F81C",
439 "u.     c #AEF81B",
440 "v.     c #ACF81B",
441 "w.     c #ABF81B",
442 "x.     c #A9F81A",
443 "y.     c #A8F81A",
444 "z.     c #A6F81A",
445 "A.     c #A4F81A",
446 "B.     c #A2F819",
447 "C.     c #A1F819",
448 "D.     c #9FF819",
449 "E.     c #9EF818",
450 "F.     c #9BF918",
451 "G.     c #9AF917",
452 "H.     c #98F917",
453 "I.     c #97F917",
454 "J.     c #95F916",
455 "K.     c #93F916",
456 "L.     c #91F916",
457 "M.     c #90F915",
458 "N.     c #8EF915",
459 "O.     c #8DF914",
460 "P.     c #8BF914",
461 "Q.     c #89FA14",
462 "R.     c #87FA13",
463 "S.     c #86FA13",
464 "T.     c #84FA13",
465 "U.     c #83FA12",
466 "V.     c #81FA12",
467 "W.     c #7FFA12",
468 "X.     c #7DFA12",
469 "Y.     c #7CFA11",
470 "Z.     c #7AFA11",
471 "`.     c #78FA10",
472 " +     c #76FA10",
473 ".+     c #75FB10",
474 "++     c #73FB0F",
475 "@+     c #72FB0F",
476 "#+     c #70FB0F",
477 "$+     c #6EFB0E",
478 "%+     c #6DFB0E",
479 "&+     c #6BFB0E",
480 "*+     c #6AFB0D",
481 "=+     c #68FB0D",
482 "-+     c #66FB0C",
483 ";+     c #64FB0C",
484 ">+     c #63FB0C",
485 ",+     c #61FC0B",
486 "'+     c #60FC0B",
487 ")+     c #5EFC0B",
488 "!+     c #5CFC0A",
489 "~+     c #5AFC0A",
490 "{+     c #59FC09",
491 "]+     c #57FC09",
492 "^+     c #56FC09",
493 "/+     c #53FC09",
494 "(+     c #52FC08",
495 "_+     c #50FC08",
496 ":+     c #4FFD08",
497 "<+     c #4DFD07",
498 "[+     c #4BFD07",
499 "}+     c #49FD07",
500 "|+     c #48FD06",
501 "1+     c #46FD06",
502 "2+     c #45FD05",
503 "3+     c #43FD05",
504 "4+     c #41FD05",
505 "5+     c #3FFD04",
506 "6+     c #3EFD04",
507 "7+     c #3CFD04",
508 "8+     c #3BFE03",
509 "9+     c #39FE03",
510 "0+     c #37FE02",
511 "a+     c #35FE02",
512 "b+     c #34FE02",
513 "c+     c #32FE01",
514 "d+     c #30FE01",
515 "e+     c #2EFE01",
516 "f+     c #2DFE00",
517 "g+     c #2BFE00",
518 ". . + + + ",
519 ". . + + + ",
520 "@ @ @ @ @ ",
521 "# # # # # ",
522 "$ $ $ $ $ ",
523 "% % % % % ",
524 "& & & & & ",
525 "* * * * * ",
526 "= = = = = ",
527 "- - - - - ",
528 "; ; ; ; ; ",
529 "> > > > > ",
530 ", , , , , ",
531 "' ' ' ' ' ",
532 ") ) ) ) ) ",
533 "! ! ! ! ! ",
534 "~ ~ ~ ~ ~ ",
535 "{ { { { { ",
536 "] ] ] ] ] ",
537 "^ ^ ^ ^ ^ ",
538 "/ / / / / ",
539 "( ( ( ( ( ",
540 "_ _ _ _ _ ",
541 ": : : : : ",
542 ": : : : : ",
543 "< < < < < ",
544 "[ [ [ [ [ ",
545 "} } } } } ",
546 "} } } } } ",
547 "| | | | | ",
548 "1 1 1 1 1 ",
549 "2 2 2 2 2 ",
550 "3 3 3 3 3 ",
551 "4 4 4 4 4 ",
552 "5 5 5 5 5 ",
553 "6 6 6 6 6 ",
554 "6 6 6 6 6 ",
555 "7 7 7 7 7 ",
556 "8 8 8 8 8 ",
557 "9 9 9 9 9 ",
558 "9 9 9 9 9 ",
559 "0 0 0 0 0 ",
560 "a a a a a ",
561 "a a a a a ",
562 "b b b b b ",
563 "c c c c c ",
564 "d d d d d ",
565 "d d d d d ",
566 "e e e e e ",
567 "f f f f f ",
568 "g g g g g ",
569 "g g g g g ",
570 "h h h h h ",
571 "i i i i i ",
572 "j j j j j ",
573 "k k k k k ",
574 "l l l l l ",
575 "m m m m m ",
576 "n n n n n ",
577 "n n n n n ",
578 "o o o o o ",
579 "p p p p p ",
580 "q q q q q ",
581 "q q q q q ",
582 "r r r r r ",
583 "s s s s s ",
584 "t t t t t ",
585 "u u u u u ",
586 "v v v v v ",
587 "w w w w w ",
588 "x x x x x ",
589 "x x x x x ",
590 "y y y y y ",
591 "z z z z z ",
592 "A A A A A ",
593 "A A A A A ",
594 "B B B B B ",
595 "C C C C C ",
596 "D D D D D ",
597 "D D D D D ",
598 "E E E E E ",
599 "F F F F F ",
600 "G G G G G ",
601 "G G G G G ",
602 "H H H H H ",
603 "I I I I I ",
604 "I I I I I ",
605 "J J J J J ",
606 "K K K K K ",
607 "L L L L L ",
608 "M M M M M ",
609 "N N N N N ",
610 "O O O O O ",
611 "P P P P P ",
612 "P P P P P ",
613 "Q Q Q Q Q ",
614 "R R R R R ",
615 "S S S S S ",
616 "S S S S S ",
617 "T T T T T ",
618 "U U U U U ",
619 "V V V V V ",
620 "V V V V V ",
621 "W W W W W ",
622 "X X X X X ",
623 "Y Y Y Y Y ",
624 "Y Y Y Y Y ",
625 "Z Z Z Z Z ",
626 "` ` ` ` ` ",
627 " . . . . .",
628 "..........",
629 "+.+.+.+.+.",
630 "@.@.@.@.@.",
631 "#.#.#.#.#.",
632 "#.#.#.#.#.",
633 "$.$.$.$.$.",
634 "%.%.%.%.%.",
635 "&.&.&.&.&.",
636 "&.&.&.&.&.",
637 "*.*.*.*.*.",
638 "=.=.=.=.=.",
639 "-.-.-.-.-.",
640 ";.;.;.;.;.",
641 ";.;.;.;.;.",
642 ">.>.>.>.>.",
643 ",.,.,.,.,.",
644 "'.'.'.'.'.",
645 ").).).).).",
646 "!.!.!.!.!.",
647 "~.~.~.~.~.",
648 "{.{.{.{.{.",
649 "].].].].].",
650 "^.^.^.^.^.",
651 "/././././.",
652 "(.(.(.(.(.",
653 "_._._._._.",
654 ":.:.:.:.:.",
655 "<.<.<.<.<.",
656 "[.[.[.[.[.",
657 "}.}.}.}.}.",
658 "|.|.|.|.|.",
659 "1.1.1.1.1.",
660 "2.2.2.2.2.",
661 "3.3.3.3.3.",
662 "4.4.4.4.4.",
663 "5.5.5.5.5.",
664 "6.6.6.6.6.",
665 "7.7.7.7.7.",
666 "8.8.8.8.8.",
667 "9.9.9.9.9.",
668 "0.0.0.0.0.",
669 "a.a.a.a.a.",
670 "b.b.b.b.b.",
671 "c.c.c.c.c.",
672 "d.d.d.d.d.",
673 "e.e.e.e.e.",
674 "f.f.f.f.f.",
675 "g.g.g.g.g.",
676 "h.h.h.h.h.",
677 "i.i.i.i.i.",
678 "j.j.j.j.j.",
679 "k.k.k.k.k.",
680 "l.l.l.l.l.",
681 "m.m.m.m.m.",
682 "n.n.n.n.n.",
683 "o.o.o.o.o.",
684 "p.p.p.p.p.",
685 "q.q.q.q.q.",
686 "r.r.r.r.r.",
687 "s.s.s.s.s.",
688 "t.t.t.t.t.",
689 "u.u.u.u.u.",
690 "v.v.v.v.v.",
691 "w.w.w.w.w.",
692 "x.x.x.x.x.",
693 "y.y.y.y.y.",
694 "z.z.z.z.z.",
695 "A.A.A.A.A.",
696 "B.B.B.B.B.",
697 "C.C.C.C.C.",
698 "D.D.D.D.D.",
699 "E.E.E.E.E.",
700 "F.F.F.F.F.",
701 "G.G.G.G.G.",
702 "H.H.H.H.H.",
703 "I.I.I.I.I.",
704 "J.J.J.J.J.",
705 "K.K.K.K.K.",
706 "L.L.L.L.L.",
707 "M.M.M.M.M.",
708 "N.N.N.N.N.",
709 "O.O.O.O.O.",
710 "P.P.P.P.P.",
711 "Q.Q.Q.Q.Q.",
712 "R.R.R.R.R.",
713 "S.S.S.S.S.",
714 "T.T.T.T.T.",
715 "U.U.U.U.U.",
716 "V.V.V.V.V.",
717 "W.W.W.W.W.",
718 "X.X.X.X.X.",
719 "Y.Y.Y.Y.Y.",
720 "Z.Z.Z.Z.Z.",
721 "`.`.`.`.`.",
722 " + + + + +",
723 ".+.+.+.+.+",
724 "++++++++++",
725 "@+@+@+@+@+",
726 "#+#+#+#+#+",
727 "$+$+$+$+$+",
728 "%+%+%+%+%+",
729 "&+&+&+&+&+",
730 "*+*+*+*+*+",
731 "=+=+=+=+=+",
732 "-+-+-+-+-+",
733 ";+;+;+;+;+",
734 ">+>+>+>+>+",
735 ",+,+,+,+,+",
736 "'+'+'+'+'+",
737 ")+)+)+)+)+",
738 "!+!+!+!+!+",
739 "~+~+~+~+~+",
740 "{+{+{+{+{+",
741 "]+]+]+]+]+",
742 "^+^+^+^+^+",
743 "/+/+/+/+/+",
744 "(+(+(+(+(+",
745 "_+_+_+_+_+",
746 ":+:+:+:+:+",
747 "<+<+<+<+<+",
748 "[+[+[+[+[+",
749 "}+}+}+}+}+",
750 "|+|+|+|+|+",
751 "1+1+1+1+1+",
752 "2+2+2+2+2+",
753 "3+3+3+3+3+",
754 "4+4+4+4+4+",
755 "5+5+5+5+5+",
756 "6+6+6+6+6+",
757 "7+7+7+7+7+",
758 "8+8+8+8+8+",
759 "9+9+9+9+9+",
760 "0+0+0+0+0+",
761 "a+a+a+a+a+",
762 "b+b+b+b+b+",
763 "c+c+c+c+c+",
764 "d+d+d+d+d+",
765 "e+e+e+e+e+",
766 "f+f+f+f+f+",
767 "g+g+g+g+g+"};
768
769 static const char* channel_setup_names[] = {
770         "mono",
771         "stereo",
772         "3 channels",
773         "4 channels",
774         "5 channels",
775         "8 channels",
776         "manual setup",
777         0
778 };
779
780 vector<string> channel_combo_strings;
781
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
783
784         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
785           
786           primary_clock (X_("TransportClockDisplay"), true, false, true),
787           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788           preroll_clock (X_("PreRollClock"), true, true),
789           postroll_clock (X_("PostRollClock"), true, true),
790
791           /* adjuster table */
792
793           adjuster_table (3, 3),
794
795           /* preroll stuff */
796
797           preroll_button (_("pre\nroll")),
798           postroll_button (_("post\nroll")),
799
800           /* big clock */
801
802           big_clock ("BigClockDisplay", true),
803
804           /* transport */
805
806           shuttle_units_button (_("% ")),
807           shuttle_style_button (_("spring")),
808           
809           punch_in_button (_("punch\nin")),
810           punch_out_button (_("punch\nout")),
811           auto_return_button (_("auto\nreturn")),
812           auto_play_button (_("auto\nplay")),
813           auto_input_button (_("auto\ninput")),
814           click_button (_("click")),
815           follow_button (_("follow\nPH")),
816           auditioning_alert_button (_("AUDITIONING")),
817           solo_alert_button (_("SOLO")),
818           shown_flag (false)
819
820 {
821         using namespace Gtk::Menu_Helpers;
822
823         Gtkmm2ext::init();
824
825         /* actually, its already loaded, but ... */
826
827         cerr << "Loading UI configuration file " << rcfile << endl;
828
829         about = 0;
830
831         if (theArdourUI == 0) {
832                 theArdourUI = this;
833         }
834
835         // allow run-time rebinding of accels
836
837         Settings::get_default()->property_gtk_can_change_accels() = true;
838
839         ActionManager::init ();
840         
841         m_new_session_dialog = 0;
842         m_new_session_dialog_ref = NewSessionDialogFactory::create();
843         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
844         editor = 0;
845         mixer = 0;
846         session = 0;
847         _session_is_new = false;
848         big_clock_window = 0;
849         session_selector_window = 0;
850         last_key_press_time = 0;
851         connection_editor = 0;
852         add_route_dialog = 0;
853         route_params = 0;
854         option_editor = 0;
855         location_ui = 0;
856         open_session_selector = 0;
857         have_configure_timeout = false;
858         have_disk_overrun_displayed = false;
859         have_disk_underrun_displayed = false;
860         _will_create_new_session_automatically = false;
861         session_loaded = false;
862
863
864         last_configure_time.tv_sec = 0;
865         last_configure_time.tv_usec = 0;
866
867         shuttle_grabbed = false;
868         shuttle_fract = 0.0;
869
870         set_shuttle_units (Percentage);
871         set_shuttle_behaviour (Sprung);
872
873         shuttle_style_menu = 0;
874         shuttle_unit_menu = 0;
875
876         gettimeofday (&last_peak_grab, 0);
877         gettimeofday (&last_shuttle_request, 0);
878
879         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
883
884         /* handle pending state with a dialog */
885
886         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
887
888         channel_combo_strings = internationalize (channel_setup_names);
889         
890         /* have to wait for AudioEngine and Configuration before proceeding */
891 }
892
893 void
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
895 {
896         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
897         
898         string msg = string_compose (_("\
899 You cannot record-enable\n\
900 track %1\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
903                               ds->name());
904
905         ArdourMessage message (editor, X_("cannotrecord"), msg);
906 }
907
908 void
909 ARDOUR_UI::set_engine (AudioEngine& e)
910 {
911         engine = &e;
912
913         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
917
918         _tooltips.enable();
919
920         keyboard = new Keyboard;
921         install_keybindings ();
922
923         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
925
926         if (setup_windows ()) {
927                 throw failed_constructor ();
928         }
929
930         if (GTK_ARDOUR::show_key_actions) {
931                 // GTK2FIX
932                 // show_all_actions ();
933                 exit (0);
934         }
935
936         /* start with timecode, metering enabled
937         */
938         
939         blink_timeout_tag = -1;
940
941         /* this being a GUI and all, we want peakfiles */
942
943         FileSource::set_build_peakfiles (true);
944         FileSource::set_build_missing_peakfiles (true);
945
946         if (Source::start_peak_thread ()) {
947                 throw failed_constructor();
948         }
949
950         /* start the time-of-day-clock */
951         
952         update_wall_clock ();
953         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
954
955         update_disk_space ();
956         update_cpu_load ();
957         update_sample_rate (engine->frame_rate());
958
959         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
960         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
961 }
962
963 ARDOUR_UI::~ARDOUR_UI ()
964 {
965         save_ardour_state ();
966
967         if (keyboard) {
968                 delete keyboard;
969         }
970
971         if (editor) {
972                 delete editor;
973         }
974
975         if (mixer) {
976                 delete mixer;
977         }
978
979         if (add_route_dialog) {
980                 delete add_route_dialog;
981         }
982
983         Source::stop_peak_thread ();
984 }
985
986 gint
987 ARDOUR_UI::configure_timeout ()
988 {
989         struct timeval now;
990         struct timeval diff;
991
992         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
993                 /* no configure events yet */
994                 return TRUE;
995         }
996
997         gettimeofday (&now, 0);
998         timersub (&now, &last_configure_time, &diff);
999
1000         /* force a gap of 0.5 seconds since the last configure event
1001          */
1002
1003         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1004                 return TRUE;
1005         } else {
1006                 have_configure_timeout = false;
1007                 save_ardour_state ();
1008                 return FALSE;
1009         }
1010 }
1011
1012 gboolean
1013 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1014 {
1015         if (have_configure_timeout) {
1016                 gettimeofday (&last_configure_time, 0);
1017         } else {
1018                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1019                 have_configure_timeout = true;
1020         }
1021                 
1022         return FALSE;
1023 }
1024
1025 void
1026 ARDOUR_UI::save_ardour_state ()
1027 {
1028         if (!keyboard || !mixer || !editor) {
1029                 return;
1030         }
1031         
1032         /* XXX this is all a bit dubious. add_extra_xml() uses
1033            a different lifetime model from add_instant_xml().
1034         */
1035
1036         XMLNode* node = new XMLNode (keyboard->get_state());
1037         Config->add_extra_xml (*node);
1038         Config->save_state();
1039
1040         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1041         XMLNode& mnode (mixer->get_state());
1042
1043         if (session) {
1044                 session->add_instant_xml(enode, session->path());
1045                 session->add_instant_xml(mnode, session->path());
1046         } else {
1047                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1048                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1049         }
1050 }
1051
1052 void
1053 ARDOUR_UI::startup ()
1054 {
1055         /* Once the UI is up and running, start the audio engine. Doing
1056            this before the UI is up and running can cause problems
1057            when not running with SCHED_FIFO, because the amount of
1058            CPU and disk work needed to get the UI started can interfere
1059            with the scheduling of the audio thread.
1060         */
1061
1062         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1063 }
1064
1065 void
1066 ARDOUR_UI::finish()
1067 {
1068         if (session && session->dirty()) {
1069                 switch (ask_about_saving_session(_("quit"))) {
1070                 case -1:
1071                         return;
1072                         break;
1073                 case 1:
1074                         /* use the default name */
1075                         if (save_state_canfail ("")) {
1076                                 /* failed - don't quit */
1077                                 ArdourMessage (editor, X_("badsave dialog"),
1078                                                _("\
1079 Ardour was unable to save your session.\n\n\
1080 If you still wish to quit, please use the\n\n\
1081 \"Just quit\" option."));
1082                                 return;
1083                         }
1084                         break;
1085                 case 0:
1086                         break;
1087                 }
1088         }
1089
1090         quit();
1091 }
1092
1093 int
1094 ARDOUR_UI::ask_about_saving_session (string what)
1095 {
1096         ArdourDialog window (_("ardour: save session?"));
1097         Gtk::Label  prompt_label;
1098         string msg;
1099
1100         msg = string_compose(_("Save and %1"), what);
1101         window.add_button (msg, RESPONSE_ACCEPT);
1102         msg = string_compose(_("Just %1"), what);
1103         window.add_button (msg, RESPONSE_REJECT);
1104         msg = string_compose(_("Don't %1"), what);
1105         window.add_button (msg, RESPONSE_REJECT);
1106
1107         Gtk::Button noquit_button (msg);
1108         noquit_button.set_name ("EditorGTKButton");
1109
1110         string prompt;
1111         string type;
1112
1113         if (session->snap_name() == session->name()) {
1114                 type = _("session");
1115         } else {
1116                 type = _("snapshot");
1117         }
1118         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?"), 
1119                          type, session->snap_name());
1120         
1121         prompt_label.set_text (prompt);
1122         prompt_label.set_alignment (0.5, 0.5);
1123         prompt_label.set_name (X_("PrompterLabel"));
1124         
1125         window.get_vbox()->pack_start (prompt_label);
1126
1127         window.set_name (_("Prompter"));
1128         window.set_position (Gtk::WIN_POS_MOUSE);
1129         window.set_modal (true);
1130         window.show_all ();
1131
1132         save_the_session = 0;
1133
1134         editor->ensure_float (window);
1135
1136         ResponseType r = (ResponseType) window.run();
1137
1138         window.hide ();
1139
1140         switch (r) {
1141         case RESPONSE_ACCEPT:
1142                 return 0;
1143         default:
1144                 break;
1145         }
1146
1147         return -1;
1148 }
1149         
1150 gint
1151 ARDOUR_UI::every_second ()
1152 {
1153         update_cpu_load ();
1154         update_buffer_load ();
1155         update_disk_space ();
1156         // update_disk_rate ();
1157         return TRUE;
1158 }
1159
1160 gint
1161 ARDOUR_UI::every_point_one_seconds ()
1162 {
1163         struct timeval now;
1164         struct timeval diff;
1165         
1166         /* do not attempt to grab peak power more than once per cycle.
1167          */
1168
1169         gettimeofday (&now, 0);
1170         timersub (&now, &last_peak_grab, &diff);
1171
1172         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1173                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1174                 last_peak_grab = now;
1175         } 
1176
1177         update_speed_display ();
1178         RapidScreenUpdate(); /* EMIT_SIGNAL */
1179         return TRUE;
1180 }
1181
1182 gint
1183 ARDOUR_UI::every_point_zero_one_seconds ()
1184 {
1185         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1186         return TRUE;
1187 }
1188
1189 void
1190 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1191 {
1192         char buf[32];
1193
1194         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1195
1196         if (!engine->connected()) {
1197
1198                 snprintf (buf, sizeof (buf), _("disconnected"));
1199
1200         } else {
1201
1202                 jack_nframes_t rate = engine->frame_rate();
1203                 
1204                 if (fmod (rate, 1000.0) != 0.0) {
1205                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1206                                   (float) rate/1000.0f,
1207                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1208                 } else {
1209                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1210                                   rate/1000,
1211                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1212                 }
1213         }
1214
1215         sample_rate_label.set_text (buf);
1216 }
1217
1218 void
1219 ARDOUR_UI::update_cpu_load ()
1220 {
1221         char buf[32];
1222         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1223         cpu_load_label.set_text (buf);
1224 }
1225
1226 void
1227 ARDOUR_UI::update_disk_rate ()
1228 {
1229         char buf[64];
1230
1231         if (session) {
1232                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1233                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1234                 disk_rate_label.set_text (buf);
1235         } else {
1236                 disk_rate_label.set_text ("");
1237         }
1238 }
1239
1240 void
1241 ARDOUR_UI::update_buffer_load ()
1242 {
1243         char buf[64];
1244
1245         if (session) {
1246                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1247                           session->playback_load(), session->capture_load());
1248                 buffer_load_label.set_text (buf);
1249         } else {
1250                 buffer_load_label.set_text ("");
1251         }
1252 }
1253
1254 void
1255 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1256 {
1257         if (ds.record_enabled()) {
1258                 rec_enabled_diskstreams++;
1259         }
1260 }
1261
1262 void
1263 ARDOUR_UI::update_disk_space()
1264 {
1265         if (session == 0) {
1266                 return;
1267         }
1268
1269         jack_nframes_t frames = session->available_capture_duration();
1270         char buf[64];
1271
1272         if (frames == max_frames) {
1273                 strcpy (buf, _("space: 24hrs+"));
1274         } else {
1275                 int hrs;
1276                 int mins;
1277                 int secs;
1278                 jack_nframes_t fr = session->frame_rate();
1279                 
1280                 if (session->actively_recording()){
1281                         
1282                         rec_enabled_diskstreams = 0;
1283                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1284                         
1285                         if (rec_enabled_diskstreams) {
1286                                 frames /= rec_enabled_diskstreams;
1287                         }
1288                         
1289                 } else {
1290                         
1291                         /* hmmm. shall we divide by the route count? or the diskstream count?
1292                            or what? for now, do nothing ...
1293                         */
1294                         
1295                 }
1296                 
1297                 hrs  = frames / (fr * 3600);
1298                 frames -= hrs * fr * 3600;
1299                 mins = frames / (fr * 60);
1300                 frames -= mins * fr * 60;
1301                 secs = frames / fr;
1302                 
1303                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1304         }
1305
1306         disk_space_label.set_text (buf);
1307 }                 
1308
1309 gint
1310 ARDOUR_UI::update_wall_clock ()
1311 {
1312         time_t now;
1313         struct tm *tm_now;
1314         char buf[16];
1315
1316         time (&now);
1317         tm_now = localtime (&now);
1318
1319         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1320         wall_clock_label.set_text (buf);
1321
1322         return TRUE;
1323 }
1324
1325 void
1326 ARDOUR_UI::toggle_recording_plugins ()
1327 {
1328         /* XXX use toggle_some_session_state */
1329
1330         if (session == 0) {
1331                 return;
1332         }
1333
1334         session->set_recording_plugins (!session->get_recording_plugins());
1335 }
1336         
1337 void
1338 ARDOUR_UI::toggle_auto_play ()
1339
1340 {
1341         toggle_some_session_state (auto_play_button,
1342                                    &Session::get_auto_play,
1343                                    &Session::set_auto_play);
1344 }
1345
1346 void
1347 ARDOUR_UI::toggle_auto_return ()
1348
1349 {
1350         toggle_some_session_state (auto_return_button,
1351                                    &Session::get_auto_return,
1352                                    &Session::set_auto_return);
1353 }
1354
1355 void
1356 ARDOUR_UI::toggle_click ()
1357 {
1358         toggle_some_session_state (click_button,
1359                                    &Session::get_clicking,
1360                                    &Session::set_clicking);
1361 }
1362
1363 void
1364 ARDOUR_UI::follow_changed ()
1365 {
1366         bool x;
1367
1368         if (!editor) {
1369                 return;
1370         }
1371
1372         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1373                 follow_button.set_active (x);
1374         }
1375 }
1376
1377 void
1378 ARDOUR_UI::toggle_follow ()
1379 {
1380         bool x;
1381
1382         if (!editor) {
1383                 return;
1384         }
1385
1386         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1387                 editor->set_follow_playhead (x);
1388         }
1389 }
1390
1391 void
1392 ARDOUR_UI::toggle_session_auto_loop ()
1393 {
1394         if (session) {
1395                 if (session->get_auto_loop()) {
1396                         if (session->transport_rolling()) {
1397                                 transport_roll();
1398                         }
1399                         else {
1400                                 session->request_auto_loop (false);
1401                         }
1402                 }
1403                 else {
1404                         session->request_auto_loop (true);
1405                 }
1406         }
1407 }
1408
1409 void
1410 ARDOUR_UI::toggle_session_punch_in ()
1411 {
1412         if (session) {
1413                 session->set_punch_in (!session->get_punch_in());
1414         }
1415 }
1416
1417 void
1418 ARDOUR_UI::toggle_punch_out ()
1419 {
1420         toggle_some_session_state (punch_out_button,
1421                                    &Session::get_punch_out,
1422                                    &Session::set_punch_out);
1423 }
1424
1425 void
1426 ARDOUR_UI::toggle_punch_in ()
1427 {
1428         toggle_some_session_state (punch_in_button,
1429                                    &Session::get_punch_in,
1430                                    &Session::set_punch_in);
1431 }
1432
1433 void
1434 ARDOUR_UI::map_button_state ()
1435
1436 {
1437         map_some_session_state (auto_return_button,
1438                                 &Session::get_auto_return);
1439         map_some_session_state (auto_play_button,
1440                                 &Session::get_auto_play);
1441         map_some_session_state (auto_input_button,
1442                                 &Session::get_auto_input);
1443         map_some_session_state (punch_in_button,
1444                                 &Session::get_punch_in);
1445         map_some_session_state (punch_out_button,
1446                                 &Session::get_punch_out);
1447         map_some_session_state (click_button,
1448                                 &Session::get_clicking);
1449 }
1450
1451 void
1452 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1453 {
1454         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1455 }
1456
1457 void
1458 ARDOUR_UI::map_control_change (Session::ControlType t)
1459 {
1460         switch (t) {
1461         case Session::AutoPlay:
1462                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1463                 break;
1464
1465         case Session::AutoLoop:
1466                 break;
1467
1468         case Session::AutoReturn:
1469                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1470                 break;
1471
1472         case Session::AutoInput:
1473                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1474                 break;
1475
1476         case Session::PunchOut:
1477                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1478                 break;
1479
1480         case Session::PunchIn:
1481                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1482                 break;
1483
1484         case Session::Clicking:
1485                 map_some_session_state (click_button, &Session::get_clicking);
1486                 break;
1487
1488         case Session::SlaveType:
1489 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1490                 break;
1491
1492         case Session::SendMTC:
1493 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1494                 break;
1495
1496         case Session::SendMMC:
1497 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1498                 break;
1499
1500         case Session::MMCControl:       
1501 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1502                 break;
1503
1504         case Session::MidiFeedback:       
1505 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1506                 break;
1507         case Session::MidiControl:       
1508 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1509                 break;
1510                 
1511         case Session::Live:
1512                 break;
1513
1514         case Session::RecordingPlugins:
1515                 break;
1516
1517         case Session::CrossFadesActive:
1518                 break;
1519                 
1520         case Session::EditingMode:
1521                 break;
1522
1523         case Session::PlayRange:
1524                 break;
1525
1526         case Session::AlignChoice:
1527                 /* don't care, this is handled by the options editor */
1528                 break;
1529         case Session::SeamlessLoop:
1530                 /* don't care, this is handled by the options editor */
1531                 break;
1532                
1533         }
1534 }
1535
1536 void
1537 ARDOUR_UI::control_methods_adjusted ()
1538
1539 {
1540         int which_method;
1541
1542         which_method = (int) online_control_button->adjustment.get_value();
1543         switch (which_method) {
1544         case 0:
1545                 allow_mmc_and_local ();
1546                 break;
1547         case 1:
1548                 allow_mmc_only ();
1549                 break;
1550         case 2:
1551                 allow_local_only ();
1552                 break;
1553         default:
1554                 fatal << _("programming error: impossible control method") << endmsg;
1555         }
1556 }
1557         
1558
1559 void
1560 ARDOUR_UI::mmc_device_id_adjusted ()
1561
1562 {
1563 #if 0
1564         if (mmc) {
1565                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1566                 mmc->set_device_id (dev_id);
1567         }
1568 #endif
1569 }
1570
1571 void
1572 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1573                                    bool (Session::*get)() const)
1574         
1575 {
1576         bool x;
1577
1578         if (session == 0) {
1579                 return;
1580         }
1581         
1582         if (button.get_active() != (x = (session->*get)())) {
1583                 button.set_active (x);
1584         }
1585 }
1586
1587 void
1588 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1589                                       bool (Session::*get)() const,
1590                                       void (Session::*set)(bool))
1591
1592 {
1593         bool button_state;
1594         bool session_state;
1595
1596         if (session == 0) {
1597                 return;
1598         }
1599
1600         button_state = button.get_active ();
1601         session_state = (session->*get)();
1602
1603         if (button_state != session_state) {
1604                 (session->*set) (button_state);
1605 #if 0
1606         
1607                 /* check that it worked, and reverse
1608                    the button state if it didn't
1609                 */
1610
1611                 if ((session->*get)() != button_state) {
1612                         button->set_active (!button_state);
1613                 }
1614 #endif
1615
1616         }
1617 }       
1618
1619 gint
1620 ARDOUR_UI::session_menu (GdkEventButton *ev)
1621 {
1622         session_popup_menu->popup (0, 0);
1623         return TRUE;
1624 }
1625
1626 void
1627 ARDOUR_UI::redisplay_recent_sessions ()
1628 {
1629         vector<string *> *sessions;
1630         vector<string *>::iterator i;
1631         RecentSessionsSorter cmp;
1632         
1633         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1634         recent_session_model->clear ();
1635
1636         RecentSessions rs;
1637         ARDOUR::read_recent_sessions (rs);
1638
1639         if (rs.empty()) {
1640                 recent_session_display.set_model (recent_session_model);
1641                 return;
1642         }
1643
1644         /* sort them alphabetically */
1645         sort (rs.begin(), rs.end(), cmp);
1646         sessions = new vector<string*>;
1647
1648         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1649                 sessions->push_back (new string ((*i).second));
1650         }
1651
1652         for (i = sessions->begin(); i != sessions->end(); ++i) {
1653
1654                 vector<string*>* states;
1655                 vector<const gchar*> item;
1656                 string fullpath = *(*i);
1657                 
1658                 /* remove any trailing / */
1659
1660                 if (fullpath[fullpath.length()-1] == '/') {
1661                         fullpath = fullpath.substr (0, fullpath.length()-1);
1662                 }
1663
1664                 /* now get available states for this session */
1665
1666                 if ((states = Session::possible_states (fullpath)) == 0) {
1667                         /* no state file? */
1668                         continue;
1669                 }
1670
1671                 TreeModel::Row row = *(recent_session_model->append());
1672
1673                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1674                 row[recent_session_columns.fullpath] = fullpath;
1675
1676                 if (states->size() > 1) {
1677
1678                         /* add the children */
1679                         
1680                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1681                                 
1682                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1683
1684                                 child_row[recent_session_columns.visible_name] = **i2;
1685                                 child_row[recent_session_columns.fullpath] = fullpath;
1686
1687                                 delete *i2;
1688                         }
1689                 }
1690
1691                 delete states;
1692         }
1693
1694         recent_session_display.set_model (recent_session_model);
1695         delete sessions;
1696 }
1697
1698 void
1699 ARDOUR_UI::build_session_selector ()
1700 {
1701         session_selector_window = new ArdourDialog ("session selector");
1702         
1703         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1704
1705         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1706         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1707
1708         recent_session_model = TreeStore::create (recent_session_columns);
1709         recent_session_display.set_model (recent_session_model);
1710         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1711         recent_session_display.set_headers_visible (false);
1712
1713         scroller->add (recent_session_display);
1714         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1715
1716         session_selector_window->set_name ("SessionSelectorWindow");
1717         session_selector_window->set_size_request (200, 400);
1718         session_selector_window->get_vbox()->pack_start (*scroller);
1719 }
1720
1721 void
1722 ARDOUR_UI::open_recent_session ()
1723 {
1724         /* popup selector window */
1725
1726         if (session_selector_window == 0) {
1727                 build_session_selector ();
1728         }
1729
1730         redisplay_recent_sessions ();
1731
1732         ResponseType r = (ResponseType) session_selector_window->run ();
1733
1734         session_selector_window->hide();
1735
1736         switch (r) {
1737         case RESPONSE_ACCEPT:
1738                 break;
1739         default:
1740                 return;
1741         }
1742
1743         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1744
1745         if (i == recent_session_model->children().end()) {
1746                 return;
1747         }
1748         
1749         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1750         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1751
1752         _session_is_new = false;
1753
1754         load_session (path, state);
1755 }
1756
1757 bool
1758 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1759 {
1760         struct stat statbuf;
1761         
1762         if (stat (info.filename.c_str(), &statbuf) != 0) {
1763                 return false;
1764         }
1765
1766         if (!S_ISDIR(statbuf.st_mode)) {
1767                 return false;
1768         }
1769
1770         string session_file = info.filename;
1771         session_file += '/';
1772         session_file += PBD::basename (info.filename);
1773         session_file += ".ardour";
1774         
1775         if (stat (session_file.c_str(), &statbuf) != 0) {
1776                 return false;
1777         }
1778
1779         return S_ISREG (statbuf.st_mode);
1780 }
1781
1782 void
1783 ARDOUR_UI::open_session ()
1784 {
1785         /* popup selector window */
1786
1787         if (open_session_selector == 0) {
1788                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1789                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1790                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1791                 
1792                 FileFilter filter_ardour;
1793                 filter_ardour.set_name (_("Ardour sessions"));
1794                 filter_ardour.add_custom (FILE_FILTER_FILENAME, mem_fun (*this, &ARDOUR_UI::filter_ardour_session_dirs));
1795
1796                 open_session_selector->add_filter (filter_ardour);
1797         }
1798
1799         switch (open_session_selector->run ()) {
1800         case RESPONSE_OK:
1801                 break;
1802         default:
1803                 return;
1804         }
1805
1806         string session_path = open_session_selector->get_filename();
1807         string path, name;
1808         bool isnew;
1809
1810         if (session_path.length() > 0) {
1811                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1812                         _session_is_new = isnew;
1813                         load_session (path, name);
1814                 }
1815         }
1816 }
1817
1818
1819 void
1820 ARDOUR_UI::session_add_midi_track ()
1821 {
1822         cerr << _("Patience is a virtue.\n");
1823 }
1824
1825 void
1826 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1827 {
1828         Route* route;
1829
1830         if (session == 0) {
1831                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1832                 return;
1833         }
1834
1835         try { 
1836                 if (disk) {
1837                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1838                                 error << _("could not create new audio track") << endmsg;
1839                         }
1840                 } else {
1841                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1842                                 error << _("could not create new audio bus") << endmsg;
1843                         }
1844                 }
1845                 
1846 #if CONTROLOUTS
1847                 if (need_control_room_outs) {
1848                         pan_t pans[2];
1849                         
1850                         pans[0] = 0.5;
1851                         pans[1] = 0.5;
1852                         
1853                         route->set_stereo_control_outs (control_lr_channels);
1854                         route->control_outs()->set_stereo_pan (pans, this);
1855                 }
1856 #endif /* CONTROLOUTS */
1857         }
1858
1859         catch (...) {
1860                 ArdourMessage msg (editor, X_("noport dialog"),
1861                                    _("There are insufficient JACK ports available\n\
1862 to create a new track or bus.\n\
1863 You should save Ardour, exit and\n\
1864 restart JACK with more ports."));
1865         }
1866 }
1867
1868 void
1869 ARDOUR_UI::diskstream_added (DiskStream* ds)
1870 {
1871 }
1872
1873 void
1874 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1875 {
1876         jack_nframes_t _preroll;
1877
1878         if (session) {
1879                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1880
1881                 if (new_position > _preroll) {
1882                         new_position -= _preroll;
1883                 } else {
1884                         new_position = 0;
1885                 }
1886
1887                 session->request_locate (new_position);
1888         }
1889 }
1890
1891 void
1892 ARDOUR_UI::transport_goto_start ()
1893 {
1894         if (session) {
1895                 session->request_locate (0);
1896
1897                 
1898                 /* force displayed area in editor to start no matter
1899                    what "follow playhead" setting is.
1900                 */
1901                 
1902                 if (editor) {
1903                         editor->reposition_x_origin (0);
1904                 }
1905         }
1906 }
1907
1908 void
1909 ARDOUR_UI::transport_goto_end ()
1910 {
1911         if (session) {
1912                 jack_nframes_t frame = session->current_end_frame();
1913                 session->request_locate (frame);
1914
1915                 /* force displayed area in editor to start no matter
1916                    what "follow playhead" setting is.
1917                 */
1918                 
1919                 if (editor) {
1920                         editor->reposition_x_origin (frame);
1921                 }
1922         }
1923 }
1924
1925 gint 
1926 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1927 {
1928
1929
1930         if (session) {
1931                         if (session->transport_stopped()) {
1932                         session->request_locate (session->last_transport_start());
1933                 } else {
1934                         if (session->get_auto_loop()) {
1935                                 session->request_auto_loop (false);
1936                         }
1937
1938                         Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1939                         session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1940                         }
1941         }
1942
1943         return TRUE;
1944 }
1945
1946 gint
1947 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1948 {
1949         transport_roll ();
1950         return TRUE;
1951 }
1952
1953 void
1954 ARDOUR_UI::transport_stop ()
1955 {
1956         if (!session) {
1957                 return;
1958         }
1959
1960         if (session->is_auditioning()) {
1961                 session->cancel_audition ();
1962                 return;
1963         }
1964         
1965         if (session->get_auto_loop()) {
1966                 session->request_auto_loop (false);
1967         }
1968         
1969         session->request_stop ();
1970 }
1971
1972 void
1973 ARDOUR_UI::transport_stop_and_forget_capture ()
1974 {
1975         if (session) {
1976                 session->request_stop (true);
1977         }
1978 }
1979
1980 void
1981 ARDOUR_UI::remove_last_capture()
1982 {
1983         if (editor) {
1984                 editor->remove_last_capture();
1985         }
1986 }
1987
1988 void
1989 ARDOUR_UI::transport_record ()
1990 {
1991         if (session) {
1992                 switch (session->record_status()) {
1993                 case Session::Disabled:
1994                         if (session->ntracks() == 0) {
1995                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1996                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1997                                 return;
1998                         }
1999                         session->maybe_enable_record ();
2000                         break;
2001                 case Session::Recording:
2002                 case Session::Enabled:
2003                         session->disable_record ();
2004                 }
2005         }
2006 }
2007
2008 void
2009 ARDOUR_UI::transport_roll ()
2010 {
2011         bool rolling;
2012
2013         if (!session) {
2014                 return;
2015         }
2016
2017         rolling = session->transport_rolling ();
2018
2019         if (session->get_auto_loop()) {
2020                 session->request_auto_loop (false);
2021                 auto_loop_button.set_active (false);
2022                 roll_button.set_active (true);
2023         } else if (session->get_play_range ()) {
2024                 session->request_play_range (false);
2025                 play_selection_button.set_active (false);
2026         } else if (rolling) {
2027                 session->request_locate (session->last_transport_start(), true);
2028         }
2029
2030         session->request_transport_speed (1.0f);
2031 }
2032
2033 void
2034 ARDOUR_UI::transport_loop()
2035 {
2036         if (session) {
2037                 if (session->get_auto_loop()) {
2038                         if (session->transport_rolling()) {
2039                                 Location * looploc = session->locations()->auto_loop_location();
2040                                 if (looploc) {
2041                                         session->request_locate (looploc->start(), true);
2042                                 }
2043                         }
2044                 }
2045                 else {
2046                         session->request_auto_loop (true);
2047                 }
2048         }
2049 }
2050
2051 void
2052 ARDOUR_UI::transport_play_selection ()
2053 {
2054         if (!session) {
2055                 return;
2056         }
2057
2058         if (!session->get_play_range()) {
2059                 session->request_stop ();
2060         }
2061
2062         editor->play_selection ();
2063 }
2064
2065 void
2066 ARDOUR_UI::transport_rewind (int option)
2067 {
2068         float current_transport_speed;
2069  
2070         if (session) {
2071                 current_transport_speed = session->transport_speed();
2072                 
2073                 if (current_transport_speed >= 0.0f) {
2074                         switch (option) {
2075                         case 0:
2076                                 session->request_transport_speed (-1.0f);
2077                                 break;
2078                         case 1:
2079                                 session->request_transport_speed (-4.0f);
2080                                 break;
2081                         case -1:
2082                                 session->request_transport_speed (-0.5f);
2083                                 break;
2084                         }
2085                 } else {
2086                         /* speed up */
2087                         session->request_transport_speed (current_transport_speed * 1.5f);
2088                 }
2089         }
2090 }
2091
2092 void
2093 ARDOUR_UI::transport_forward (int option)
2094 {
2095         float current_transport_speed;
2096         
2097         if (session) {
2098                 current_transport_speed = session->transport_speed();
2099                 
2100                 if (current_transport_speed <= 0.0f) {
2101                         switch (option) {
2102                         case 0:
2103                                 session->request_transport_speed (1.0f);
2104                                 break;
2105                         case 1:
2106                                 session->request_transport_speed (4.0f);
2107                                 break;
2108                         case -1:
2109                                 session->request_transport_speed (0.5f);
2110                                 break;
2111                         }
2112                 } else {
2113                         /* speed up */
2114                         session->request_transport_speed (current_transport_speed * 1.5f);
2115                 }
2116         }
2117 }
2118
2119 void
2120 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2121 {
2122         if (session == 0) {
2123                 return;
2124         }
2125
2126         DiskStream *ds;
2127
2128         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2129                 Port *port = ds->io()->input (0);
2130                 port->request_monitor_input (!port->monitoring_input());
2131         }
2132 }
2133
2134 void
2135 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2136 {
2137         if (session == 0) {
2138                 return;
2139         }
2140
2141         DiskStream *ds;
2142
2143         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2144                 ds->set_record_enabled (!ds->record_enabled(), this);
2145         }
2146 }
2147
2148 void
2149 ARDOUR_UI::queue_transport_change ()
2150 {
2151         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2152 }
2153
2154 void
2155 ARDOUR_UI::map_transport_state ()
2156 {
2157         float sp = session->transport_speed();
2158
2159         if (sp == 1.0f) {
2160                 transport_rolling ();
2161         } else if (sp < 0.0f) {
2162                 transport_rewinding ();
2163         } else if (sp > 0.0f) {
2164                 transport_forwarding ();
2165         } else {
2166                 transport_stopped ();
2167         }
2168 }
2169
2170 void
2171 ARDOUR_UI::send_all_midi_feedback ()
2172 {
2173         if (session) {
2174                 session->send_all_midi_feedback();
2175         }
2176 }
2177
2178 void
2179 ARDOUR_UI::allow_local_only ()
2180 {
2181
2182 }
2183
2184 void
2185 ARDOUR_UI::allow_mmc_only ()
2186 {
2187
2188 }
2189
2190 void
2191 ARDOUR_UI::allow_mmc_and_local ()
2192 {
2193
2194 }
2195
2196 void
2197 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2198 {
2199         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2200                 (int) adj.get_value()].c_str());
2201 }
2202
2203 void
2204 ARDOUR_UI::engine_stopped ()
2205 {
2206         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2207         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2208         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2209 }
2210
2211
2212 void
2213 ARDOUR_UI::engine_running ()
2214 {
2215         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2216         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2217         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2218 }
2219
2220 void
2221 ARDOUR_UI::engine_halted ()
2222 {
2223         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2224
2225         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2226         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2227
2228         update_sample_rate (0);
2229
2230         ArdourMessage msg (editor, X_("halted"),
2231                            _("\
2232 JACK has either been shutdown or it\n\
2233 disconnected Ardour because Ardour\n\
2234 was not fast enough. You can save the\n\
2235 session and/or try to reconnect to JACK ."));
2236 }
2237
2238 int32_t
2239 ARDOUR_UI::do_engine_start ()
2240 {
2241         try { 
2242                 engine->start();
2243         }
2244
2245         catch (AudioEngine::PortRegistrationFailure& err) {
2246                 engine->stop ();
2247                 error << _("Unable to create all required ports")
2248                       << endmsg;
2249                 unload_session ();
2250                 return -1;
2251         }
2252
2253         catch (...) {
2254                 engine->stop ();
2255                 error << _("Unable to start the session running")
2256                       << endmsg;
2257                 unload_session ();
2258                 return -2;
2259         }
2260         
2261         return 0;
2262 }
2263
2264 gint
2265 ARDOUR_UI::start_engine ()
2266 {
2267         if (do_engine_start () == 0) {
2268                 if (session && _session_is_new) {
2269                         /* we need to retain initial visual 
2270                            settings for a new session 
2271                         */
2272                         session->save_state ("");
2273                 }
2274
2275                 /* there is too much going on, in too many threads, for us to 
2276                    end up with a clean session. So wait 1 second after loading,
2277                    and fix it up. its ugly, but until i come across a better
2278                    solution, its what we have.
2279                 */
2280
2281                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2282         }
2283
2284         return FALSE;
2285 }
2286
2287 void
2288 ARDOUR_UI::update_clocks ()
2289 {
2290          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2291 }
2292
2293 void
2294 ARDOUR_UI::start_clocking ()
2295 {
2296         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2297 }
2298
2299 void
2300 ARDOUR_UI::stop_clocking ()
2301 {
2302         clock_signal_connection.disconnect ();
2303 }
2304         
2305 void
2306 ARDOUR_UI::toggle_clocking ()
2307 {
2308 #if 0
2309         if (clock_button.get_active()) {
2310                 start_clocking ();
2311         } else {
2312                 stop_clocking ();
2313         }
2314 #endif
2315 }
2316
2317 gint
2318 ARDOUR_UI::_blink (void *arg)
2319
2320 {
2321         ((ARDOUR_UI *) arg)->blink ();
2322         return TRUE;
2323 }
2324
2325 void
2326 ARDOUR_UI::blink ()
2327 {
2328          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2329 }
2330
2331 void
2332 ARDOUR_UI::start_blinking ()
2333 {
2334         /* Start the blink signal. Everybody with a blinking widget
2335            uses Blink to drive the widget's state.
2336         */
2337
2338         if (blink_timeout_tag < 0) {
2339                 blink_on = false;       
2340                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2341         }
2342 }
2343
2344 void
2345 ARDOUR_UI::stop_blinking ()
2346 {
2347         if (blink_timeout_tag >= 0) {
2348                 gtk_timeout_remove (blink_timeout_tag);
2349                 blink_timeout_tag = -1;
2350         }
2351 }
2352
2353
2354 void
2355 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2356 {
2357         using namespace Gtk;
2358         using namespace Menu_Helpers;
2359
2360         if (dstream.hidden()) {
2361                 return;
2362         }
2363
2364         MenuList& items = diskstream_menu->items();
2365         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2366 }
2367         
2368 void
2369 ARDOUR_UI::diskstream_selected (gint32 id)
2370 {
2371         selected_dstream = id;
2372         Main::quit ();
2373 }
2374
2375 gint32
2376 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2377 {
2378         using namespace Gtk;
2379         using namespace Menu_Helpers;
2380
2381         if (session == 0) {
2382                 return -1;
2383         }
2384
2385         diskstream_menu = new Menu();
2386         diskstream_menu->set_name ("ArdourContextMenu");
2387         using namespace Gtk;
2388         using namespace Menu_Helpers;
2389
2390         MenuList& items = diskstream_menu->items();
2391         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2392
2393         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2394
2395         if (ev) {
2396                 diskstream_menu->popup (ev->button, ev->time);
2397         } else {
2398                 diskstream_menu->popup (0, 0);
2399         }
2400
2401         selected_dstream = -1;
2402
2403         Main::run ();
2404
2405         delete diskstream_menu;
2406
2407         return selected_dstream;
2408 }
2409
2410 void
2411 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2412                           string& buf,
2413                           IO& io,
2414                           bool in)
2415 {
2416         if (in) {
2417                 if (io.n_inputs() == 0) {
2418                         buf = _("none");
2419                         return;
2420                 }
2421                 
2422                 /* XXX we're not handling multiple ports yet. */
2423
2424                 const char **connections = io.input(0)->get_connections();
2425                 
2426                 if (connections == 0 || connections[0] == '\0') {
2427                         buf = _("off");
2428                 } else {
2429                         buf = connections[0];
2430                 }
2431
2432                 free (connections);
2433
2434         } else {
2435
2436                 if (io.n_outputs() == 0) {
2437                         buf = _("none");
2438                         return;
2439                 }
2440                 
2441                 /* XXX we're not handling multiple ports yet. */
2442
2443                 const char **connections = io.output(0)->get_connections();
2444                 
2445                 if (connections == 0 || connections[0] == '\0') {
2446                         buf = _("off");
2447                 } else {
2448                         buf = connections[0];
2449                 }
2450
2451                 free (connections);
2452         }
2453 }
2454
2455 void
2456 ARDOUR_UI::snapshot_session ()
2457 {
2458         ArdourPrompter prompter (true);
2459         string snapname;
2460         string now;
2461         time_t n;
2462
2463         time (&n);
2464         now = ctime (&n);
2465         now = now.substr (0, now.length() - 1);
2466
2467         prompter.set_name ("Prompter");
2468         prompter.set_prompt (_("Name for snapshot"));
2469         prompter.set_initial_text (now);
2470         
2471         switch (prompter.run()) {
2472         case RESPONSE_ACCEPT:
2473                 prompter.get_result (snapname);
2474                 if (snapname.length()){
2475                         save_state (snapname);
2476                 }
2477                 break;
2478
2479         default:
2480                 break;
2481         }
2482 }
2483
2484 void
2485 ARDOUR_UI::save_state (string name)
2486 {
2487         (void) save_state_canfail (name);
2488 }
2489                 
2490 int
2491 ARDOUR_UI::save_state_canfail (string name)
2492 {
2493         if (session) {
2494                 int ret;
2495
2496                 if (name.length() == 0) {
2497                         name = session->snap_name();
2498                 }
2499
2500                 if ((ret = session->save_state (name)) != 0) {
2501                         return ret;
2502                 }
2503         }
2504         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2505         return 0;
2506 }
2507
2508 void
2509 ARDOUR_UI::restore_state (string name)
2510 {
2511         if (session) {
2512                 if (name.length() == 0) {
2513                         name = session->name();
2514                 }
2515                 session->restore_state (name);
2516         }
2517 }
2518
2519 void
2520 ARDOUR_UI::primary_clock_value_changed ()
2521 {
2522         if (session) {
2523                 session->request_locate (primary_clock.current_time ());
2524         }
2525 }
2526
2527 void
2528 ARDOUR_UI::secondary_clock_value_changed ()
2529 {
2530         if (session) {
2531                 session->request_locate (secondary_clock.current_time ());
2532         }
2533 }
2534
2535 void
2536 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2537 {
2538         if (session && dstream && dstream->record_enabled()) {
2539
2540                 Session::RecordState rs;
2541                 
2542                 rs = session->record_status ();
2543
2544                 switch (rs) {
2545                 case Session::Disabled:
2546                 case Session::Enabled:
2547                         if (w->get_state() != STATE_SELECTED) {
2548                                 w->set_state (STATE_SELECTED);
2549                         }
2550                         break;
2551
2552                 case Session::Recording:
2553                         if (w->get_state() != STATE_ACTIVE) {
2554                                 w->set_state (STATE_ACTIVE);
2555                         }
2556                         break;
2557                 }
2558
2559         } else {
2560                 if (w->get_state() != STATE_NORMAL) {
2561                         w->set_state (STATE_NORMAL);
2562                 }
2563         }
2564 }
2565
2566 void
2567 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2568 {
2569         if (session == 0) {
2570                 return;
2571         }
2572         
2573         switch (session->record_status()) {
2574         case Session::Enabled:
2575                 if (onoff) {
2576                         rec_button.set_state (STATE_ACTIVE);
2577                 } else {
2578                         rec_button.set_state (STATE_NORMAL);
2579                 }
2580                 break;
2581
2582         case Session::Recording:
2583                 rec_button.set_state (STATE_ACTIVE);
2584                 break;
2585
2586         default:
2587                 rec_button.set_active (false);
2588                 rec_button.set_state (STATE_NORMAL);
2589                 break;
2590         }
2591 }
2592
2593 gint
2594 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2595 {
2596         window->hide();
2597         Gtk::Main::quit ();
2598         return TRUE;
2599 }
2600
2601 void
2602 ARDOUR_UI::start_keyboard_prefix ()
2603 {
2604         keyboard->start_prefix();
2605 }
2606
2607 void
2608 ARDOUR_UI::save_template ()
2609
2610 {
2611         ArdourPrompter prompter (true);
2612         string name;
2613
2614         prompter.set_name (X_("Prompter"));
2615         prompter.set_prompt (_("Name for mix template:"));
2616         prompter.set_initial_text(session->name() + _("-template"));
2617         
2618         switch (prompter.run()) {
2619         case RESPONSE_ACCEPT:
2620                 prompter.get_result (name);
2621                 
2622                 if (name.length()) {
2623                         session->save_template (name);
2624                 }
2625                 break;
2626
2627         default:
2628                 break;
2629         }
2630 }
2631
2632 void
2633 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2634 {
2635         m_new_session_dialog->show_all();
2636         m_new_session_dialog->set_transient_for(*editor);
2637         m_new_session_dialog->set_name(predetermined_path);
2638
2639         int response = Gtk::RESPONSE_CANCEL;
2640
2641         do {
2642                 response = m_new_session_dialog->run ();
2643         
2644                 if(response == Gtk::RESPONSE_OK) {
2645
2646                         _session_is_new = true;
2647                         
2648                         std::string session_name = m_new_session_dialog->session_name();
2649                         std::string session_path = m_new_session_dialog->session_folder();
2650                         
2651                         /*
2652                           XXX This is needed because session constructor wants a 
2653                           non-existant path. hopefully this will be fixed at some point.
2654                         */
2655                         session_path = Glib::build_filename(session_path, session_name);
2656                         
2657                         std::string template_name = m_new_session_dialog->session_template_name();
2658                         
2659                         if (m_new_session_dialog->use_session_template()) {
2660                                 
2661                                 load_session (session_path, session_name, &template_name);
2662                                 
2663                         } else {
2664                                 
2665                                 uint32_t cchns;
2666                                 uint32_t mchns;
2667                                 Session::AutoConnectOption iconnect;
2668                                 Session::AutoConnectOption oconnect;
2669                                 
2670                                 if (m_new_session_dialog->create_control_bus()) {
2671                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2672                                 } else {
2673                                         cchns = 0;
2674                                 }
2675                                 
2676                                 if (m_new_session_dialog->create_master_bus()) {
2677                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2678                                 } else {
2679                                         mchns = 0;
2680                                 }
2681                                 
2682                                 if (m_new_session_dialog->connect_inputs()) {
2683                                         iconnect = Session::AutoConnectPhysical;
2684                                 } else {
2685                                         iconnect = Session::AutoConnectOption (0);
2686                                 }
2687                                 
2688                                 /// @todo some minor tweaks.
2689
2690                                 if (m_new_session_dialog->connect_outs_to_master()) {
2691                                         oconnect = Session::AutoConnectMaster;
2692                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2693                                         oconnect = Session::AutoConnectPhysical;
2694                                 } else {
2695                                         oconnect = Session::AutoConnectOption (0);
2696                                 } 
2697                                 
2698                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2699                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2700                                 
2701                                 build_session (session_path,
2702                                                session_name,
2703                                                cchns,
2704                                                mchns,
2705                                                iconnect,
2706                                                oconnect,
2707                                                nphysin,
2708                                                nphysout, 
2709                                                engine->frame_rate() * 60 * 5);
2710                         }               
2711                 }
2712
2713         } while(response == Gtk::RESPONSE_HELP);
2714         m_new_session_dialog->hide_all();
2715 }
2716
2717 int
2718 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2719 {
2720         Session *new_session;
2721         int x;
2722         session_loaded = false;
2723         x = unload_session ();
2724
2725         if (x < 0) {
2726                 return -1;
2727         } else if (x > 0) {
2728                 return 0;
2729         }
2730
2731         /* if it already exists, we must have write access */
2732
2733         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2734                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2735 You do not have write access to this session.\n\
2736 This prevents the session from being loaded."));
2737                 return -1;
2738         }
2739
2740         try {
2741                 new_session = new Session (*engine, path, snap_name, mix_template);
2742         }
2743
2744         catch (...) {
2745
2746                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2747                 return -1;
2748         }
2749
2750         connect_to_session (new_session);
2751
2752         //if (engine->running()) {
2753         //mixer->show_window();
2754         //}
2755         session_loaded = true;
2756         return 0;
2757 }
2758
2759 int
2760 ARDOUR_UI::make_session_clean ()
2761 {
2762         if (session) {
2763                 session->set_clean ();
2764         }
2765
2766         return FALSE;
2767 }
2768
2769 int
2770 ARDOUR_UI::build_session (string path, string snap_name, 
2771                           uint32_t control_channels,
2772                           uint32_t master_channels, 
2773                           Session::AutoConnectOption input_connect,
2774                           Session::AutoConnectOption output_connect,
2775                           uint32_t nphysin,
2776                           uint32_t nphysout,
2777                           jack_nframes_t initial_length)
2778 {
2779         Session *new_session;
2780         int x;
2781
2782         session_loaded = false;
2783         x = unload_session ();
2784         if (x < 0) {
2785                 return -1;
2786         } else if (x > 0) {
2787                 return 0;
2788         }
2789         
2790         _session_is_new = true;
2791
2792         try {
2793                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2794                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2795         }
2796
2797         catch (...) {
2798
2799                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2800                 return -1;
2801         }
2802
2803         connect_to_session (new_session);
2804
2805         //if (engine->running()) {
2806         //mixer->show_window();
2807         //}
2808         session_loaded = true;
2809         return 0;
2810 }
2811
2812 void
2813 ARDOUR_UI::show ()
2814 {
2815         if (editor) {
2816                 editor->show_window ();
2817                 shown_flag = true;
2818         }
2819
2820         if (session && mixer) {
2821                 // mixer->show_window ();
2822         }
2823         
2824         if (about) {
2825                 about->present ();
2826         }
2827 }
2828
2829 void
2830 ARDOUR_UI::show_splash ()
2831 {
2832         if (about == 0) {
2833                 about = new About();
2834         }
2835         about->present();
2836 }
2837
2838 void
2839 ARDOUR_UI::hide_splash ()
2840 {
2841         if (about) {
2842                 // about->hide();
2843         }
2844 }
2845
2846 void
2847 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2848 {
2849         size_t removed;
2850
2851         removed = rep.paths.size();
2852
2853         if (removed == 0) {
2854                 ArdourMessage msg (editor, X_("cleanupresults"),
2855                                    _("\
2856 No audio files were ready for cleanup\n\n\
2857 If this seems suprising, check for any existing\n\
2858 snapshots. These may still include regions that\n\
2859 require some unused files to continue to exist."));
2860                 return;
2861         } 
2862
2863         ArdourDialog results (_("ardour: cleanup"), true);
2864         
2865         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2866             CleanupResultsModelColumns() { 
2867                     add (visible_name);
2868                     add (fullpath);
2869             }
2870             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2871             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2872         };
2873
2874         
2875         Glib::RefPtr<Gtk::ListStore> results_model;
2876         CleanupResultsModelColumns results_columns;
2877         Gtk::TreeView results_display;
2878         
2879         results_model = ListStore::create (results_columns);
2880         results_display.set_model (results_model);
2881         results_display.append_column (list_title, results_columns.visible_name);
2882         results_display.set_headers_visible (true);
2883
2884         Gtk::ScrolledWindow list_scroller;
2885         Gtk::Label txt;
2886
2887         if (rep.space < 1048576.0f) {
2888                 if (removed > 1) {
2889                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2890                 } else {
2891                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2892                 }
2893         } else {
2894                 if (removed > 1) {
2895                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2896                 } else {
2897                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2898                 }
2899         }
2900
2901         results.get_vbox()->pack_start (txt, false, false);
2902         
2903         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2904                 TreeModel::Row row = *(results_model->append());
2905                 row[results_columns.visible_name] = *i;
2906                 row[results_columns.fullpath] = *i;
2907         }
2908         
2909         list_scroller.add (results_display);
2910         list_scroller.set_size_request (-1, 250);
2911         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2912         
2913         results.get_vbox()->pack_start (list_scroller, true, true);
2914         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2915         results.set_position (Gtk::WIN_POS_MOUSE);
2916
2917         results.run ();
2918 }
2919
2920 void
2921 ARDOUR_UI::cleanup ()
2922 {
2923         if (session == 0) {
2924                 /* shouldn't happen: menu item is insensitive */
2925                 return;
2926         }
2927
2928         ArdourDialog checker (_("ardour cleanup"));
2929         Gtk::Label label (_("\
2930 Cleanup is a destructive operation.\n\
2931 ALL undo/redo information will be lost if you cleanup.\n\
2932 Unused audio files will be moved to a \"dead sounds\" location."));
2933         
2934         checker.get_vbox()->pack_start (label, false, false);
2935         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2936         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2937
2938         checker.set_name (_("CleanupDialog"));
2939         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2940         checker.set_position (Gtk::WIN_POS_MOUSE);
2941
2942         switch (checker.run()) {
2943         case RESPONSE_ACCEPT:
2944                 break;
2945         default:
2946                 return;
2947         }
2948
2949         Session::cleanup_report rep;
2950
2951         editor->prepare_for_cleanup ();
2952
2953         if (session->cleanup_sources (rep)) {
2954                 return;
2955         }
2956
2957         display_cleanup_results (rep, 
2958                                  _("cleaned files"),
2959                                  _("\
2960 The following %1 %2 were not in use.\n\
2961 The next time you flush the wastebasket\n\
2962 it will release an additional %3 %4bytes\n\
2963 of disk space"
2964                                          ));
2965 }
2966
2967 void
2968 ARDOUR_UI::flush_trash ()
2969 {
2970         if (session == 0) {
2971                 /* shouldn't happen: menu item is insensitive */
2972                 return;
2973         }
2974
2975         Session::cleanup_report rep;
2976
2977         if (session->cleanup_trash_sources (rep)) {
2978                 return;
2979         }
2980
2981         display_cleanup_results (rep, 
2982                                  _("deleted file"),
2983                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2984 }
2985
2986 void
2987 ARDOUR_UI::add_route ()
2988 {
2989         int count;
2990
2991         if (!session) {
2992                 return;
2993         }
2994
2995         if (add_route_dialog == 0) {
2996                 add_route_dialog = new AddRouteDialog;
2997                 editor->ensure_float (*add_route_dialog);
2998         }
2999
3000         if (add_route_dialog->is_visible()) {
3001                 /* we're already doing this */
3002                 return;
3003         }
3004
3005         ResponseType r = (ResponseType) add_route_dialog->run ();
3006         
3007         add_route_dialog->hide();
3008
3009         switch (r) {
3010         case RESPONSE_ACCEPT:
3011                 break;
3012         default:
3013                 return;
3014                 break;
3015         }
3016
3017         if ((count = add_route_dialog->count()) <= 0) {
3018                 return;
3019         }
3020
3021         uint32_t input_chan = add_route_dialog->channels ();
3022         uint32_t output_chan;
3023         string name_template = add_route_dialog->name_template ();
3024         bool track = add_route_dialog->track ();
3025
3026         Session::AutoConnectOption oac = session->get_output_auto_connect();
3027
3028         if (oac & Session::AutoConnectMaster) {
3029                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3030         } else {
3031                 output_chan = input_chan;
3032         }
3033
3034         /* XXX do something with name template */
3035
3036         while (count) {
3037                 if (track) {
3038                         session_add_audio_track (input_chan, output_chan);
3039                 } else {
3040                         session_add_audio_bus (input_chan, output_chan);
3041                 }
3042                 --count;
3043                 
3044                 while (Main::events_pending()) {
3045                         Main::iteration ();
3046                 }
3047         }
3048 }
3049
3050 XMLNode*
3051 ARDOUR_UI::mixer_settings () const
3052 {
3053         XMLNode* node = 0;
3054
3055         if (session) {
3056                 node = session->instant_xml(X_("Mixer"), session->path());
3057         } else {
3058                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3059         }
3060
3061         if (!node) {
3062                 node = new XMLNode (X_("Mixer"));
3063         }
3064
3065         return node;
3066 }
3067
3068 XMLNode*
3069 ARDOUR_UI::editor_settings () const
3070 {
3071         XMLNode* node = 0;
3072
3073         if (session) {
3074                 node = session->instant_xml(X_("Editor"), session->path());
3075         } else {
3076                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3077         }
3078
3079         if (!node) {
3080                 node = new XMLNode (X_("Editor"));
3081         }
3082         return node;
3083 }
3084
3085 XMLNode*
3086 ARDOUR_UI::keyboard_settings () const
3087 {
3088         XMLNode* node = 0;
3089
3090         node = Config->extra_xml(X_("Keyboard"));
3091         
3092         if (!node) {
3093                 node = new XMLNode (X_("Keyboard"));
3094         }
3095         return node;
3096 }
3097
3098 void
3099 ARDOUR_UI::halt_on_xrun_message ()
3100 {
3101         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3102
3103         ArdourMessage msg (editor, X_("haltonxrun"),
3104                            _("Recording was stopped because your system could not keep up."));
3105 }
3106
3107 void 
3108 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3109 {
3110         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3111
3112         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3113                 delete *i;
3114         }
3115
3116         delete deletion_list;
3117 }
3118
3119 void
3120 ARDOUR_UI::disk_overrun_handler ()
3121 {
3122         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3123
3124         if (!have_disk_overrun_displayed) {
3125                 have_disk_overrun_displayed = true;
3126                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3127 The disk system on your computer\n\
3128 was not able to keep up with Ardour.\n\
3129 \n\
3130 Specifically, it failed to write data to disk\n\
3131 quickly enough to keep up with recording.\n"));
3132                 have_disk_overrun_displayed = false;
3133         }
3134 }
3135
3136 void
3137 ARDOUR_UI::disk_underrun_handler ()
3138 {
3139         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3140
3141         if (!have_disk_underrun_displayed) {
3142                 have_disk_underrun_displayed = true;
3143                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3144                         (_("The disk system on your computer\n\
3145 was not able to keep up with Ardour.\n\
3146 \n\
3147 Specifically, it failed to read data from disk\n\
3148 quickly enough to keep up with playback.\n")));
3149                 have_disk_underrun_displayed = false;
3150         } 
3151 }
3152
3153 void
3154 ARDOUR_UI::disk_underrun_message_gone ()
3155 {
3156         have_disk_underrun_displayed = false;
3157 }
3158
3159 void
3160 ARDOUR_UI::disk_overrun_message_gone ()
3161 {
3162         have_disk_underrun_displayed = false;
3163 }
3164
3165 int
3166 ARDOUR_UI::pending_state_dialog ()
3167 {
3168         ArdourDialog dialog ("pending state dialog");
3169         Label  message (_("\
3170 This session appears to have been in\n\
3171 middle of recording when ardour or\n\
3172 the computer was shutdown.\n\
3173 \n\
3174 Ardour can recover any captured audio for\n\
3175 you, or it can ignore it. Please decide\n\
3176 what you would like to do.\n"));
3177
3178         dialog.get_vbox()->pack_start (message);
3179         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3180         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3181
3182         dialog.set_position (WIN_POS_CENTER);
3183         dialog.show_all ();
3184         
3185         switch (dialog.run ()) {
3186         case RESPONSE_ACCEPT:
3187                 break;
3188         default:
3189                 return 1;
3190         }
3191
3192         return 0;
3193 }
3194         
3195         
3196 void
3197 ARDOUR_UI::disconnect_from_jack ()
3198 {
3199         if (engine) {
3200                 if( engine->disconnect_from_jack ()) {
3201                         ArdourMessage msg (editor, X_("nojack dialog"),
3202                                            _("Could not disconnect from JACK"));
3203                 }
3204
3205                 update_sample_rate (0);
3206         }
3207 }
3208
3209 void
3210 ARDOUR_UI::reconnect_to_jack ()
3211 {
3212         if (engine) {
3213                 if (engine->reconnect_to_jack ()) {
3214                         ArdourMessage msg (editor, X_("nojack dialog"),
3215                                            _("Could not reconnect to JACK"));
3216                 }
3217
3218                 update_sample_rate (0);
3219         }
3220 }
3221
3222 void
3223 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3224 {
3225         engine->request_buffer_size (nframes);
3226         update_sample_rate (0);
3227 }
3228
3229 int
3230 ARDOUR_UI::cmdline_new_session (string path)
3231 {
3232         if (path[0] != '/') {
3233                 char buf[PATH_MAX+1];
3234                 string str;
3235
3236                 getcwd (buf, sizeof (buf));
3237                 str = buf;
3238                 str += '/';
3239                 str += path;
3240                 path = str;
3241         }
3242
3243         new_session (false, path);
3244
3245         _will_create_new_session_automatically = false; /* done it */
3246         return FALSE; /* don't call it again */
3247 }