d010c90219a60a78c52483c8713d96d88cf96d02
[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         ActionManager::init ();
836         
837         m_new_session_dialog = 0;
838         m_new_session_dialog_ref = NewSessionDialogFactory::create();
839         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
840         editor = 0;
841         mixer = 0;
842         session = 0;
843         _session_is_new = false;
844         big_clock_window = 0;
845         session_selector_window = 0;
846         last_key_press_time = 0;
847         connection_editor = 0;
848         add_route_dialog = 0;
849         route_params = 0;
850         option_editor = 0;
851         location_ui = 0;
852         open_session_selector = 0;
853         have_configure_timeout = false;
854         have_disk_overrun_displayed = false;
855         have_disk_underrun_displayed = false;
856         _will_create_new_session_automatically = false;
857         session_loaded = false;
858
859
860         last_configure_time.tv_sec = 0;
861         last_configure_time.tv_usec = 0;
862
863         shuttle_grabbed = false;
864         shuttle_fract = 0.0;
865
866         set_shuttle_units (Percentage);
867         set_shuttle_behaviour (Sprung);
868
869         Glib::RefPtr<ActionGroup> shuttle_actions = ActionGroup::create ("ShuttleActions");
870         
871         shuttle_actions->add (Action::create (X_("SetShuttleUnitsPercentage"), _("Percentage")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_units), Percentage));
872         shuttle_actions->add (Action::create (X_("SetShuttleUnitsSemitones"), _("Semitones")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_units), Semitones));
873         shuttle_actions->add (Action::create (X_("SetShuttleActionSprung"), _("Sprung")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_behaviour), Sprung));
874         shuttle_actions->add (Action::create (X_("SetShuttleActionWheel"), _("Wheel")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_behaviour), Wheel));
875         
876         ActionManager::add_action_group (shuttle_actions);
877
878         shuttle_style_menu = dynamic_cast<Menu*> (ActionManager::get_widget ("ShuttleStylePopup"));
879         shuttle_unit_menu = dynamic_cast<Menu*> (ActionManager::get_widget ("ShuttleUnitPopup"));
880         
881         gettimeofday (&last_peak_grab, 0);
882         gettimeofday (&last_shuttle_request, 0);
883
884         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
885         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
886         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
887         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
888
889         /* handle pending state with a dialog */
890
891         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
892
893         channel_combo_strings = internationalize (channel_setup_names);
894         
895         /* have to wait for AudioEngine and Configuration before proceeding */
896 }
897
898 void
899 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
900 {
901         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
902         
903         string msg = string_compose (_("\
904 You cannot record-enable\n\
905 track %1\n\
906 because it has no input connections.\n\
907 You would be wasting space recording silence."),
908                               ds->name());
909
910         ArdourMessage message (editor, X_("cannotrecord"), msg);
911 }
912
913 void
914 ARDOUR_UI::set_engine (AudioEngine& e)
915 {
916         engine = &e;
917
918         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
919         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
920         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
921         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
922
923         _tooltips.enable();
924
925         keyboard = new Keyboard;
926         install_keybindings ();
927
928         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
929         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
930
931         if (setup_windows ()) {
932                 throw failed_constructor ();
933         }
934
935         if (GTK_ARDOUR::show_key_actions) {
936                 // GTK2FIX
937                 // show_all_actions ();
938                 exit (0);
939         }
940
941         /* start with timecode, metering enabled
942         */
943         
944         blink_timeout_tag = -1;
945
946         /* this being a GUI and all, we want peakfiles */
947
948         FileSource::set_build_peakfiles (true);
949         FileSource::set_build_missing_peakfiles (true);
950
951         if (Source::start_peak_thread ()) {
952                 throw failed_constructor();
953         }
954
955         /* start the time-of-day-clock */
956         
957         update_wall_clock ();
958         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
959
960         update_disk_space ();
961         update_cpu_load ();
962         update_sample_rate (engine->frame_rate());
963
964         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
965         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
966 }
967
968 ARDOUR_UI::~ARDOUR_UI ()
969 {
970         save_ardour_state ();
971
972         if (keyboard) {
973                 delete keyboard;
974         }
975
976         if (editor) {
977                 delete editor;
978         }
979
980         if (mixer) {
981                 delete mixer;
982         }
983
984         if (add_route_dialog) {
985                 delete add_route_dialog;
986         }
987
988         Source::stop_peak_thread ();
989 }
990
991 gint
992 ARDOUR_UI::configure_timeout ()
993 {
994         struct timeval now;
995         struct timeval diff;
996
997         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
998                 /* no configure events yet */
999                 return TRUE;
1000         }
1001
1002         gettimeofday (&now, 0);
1003         timersub (&now, &last_configure_time, &diff);
1004
1005         /* force a gap of 0.5 seconds since the last configure event
1006          */
1007
1008         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1009                 return TRUE;
1010         } else {
1011                 have_configure_timeout = false;
1012                 save_ardour_state ();
1013                 return FALSE;
1014         }
1015 }
1016
1017 gboolean
1018 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1019 {
1020         if (have_configure_timeout) {
1021                 gettimeofday (&last_configure_time, 0);
1022         } else {
1023                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1024                 have_configure_timeout = true;
1025         }
1026                 
1027         return FALSE;
1028 }
1029
1030 void
1031 ARDOUR_UI::save_ardour_state ()
1032 {
1033         if (!keyboard || !mixer || !editor) {
1034                 return;
1035         }
1036         
1037         /* XXX this is all a bit dubious. add_extra_xml() uses
1038            a different lifetime model from add_instant_xml().
1039         */
1040
1041         XMLNode* node = new XMLNode (keyboard->get_state());
1042         Config->add_extra_xml (*node);
1043         Config->save_state();
1044
1045         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1046         XMLNode& mnode (mixer->get_state());
1047
1048         if (session) {
1049                 session->add_instant_xml(enode, session->path());
1050                 session->add_instant_xml(mnode, session->path());
1051         } else {
1052                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1053                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1054         }
1055 }
1056
1057 void
1058 ARDOUR_UI::startup ()
1059 {
1060         /* Once the UI is up and running, start the audio engine. Doing
1061            this before the UI is up and running can cause problems
1062            when not running with SCHED_FIFO, because the amount of
1063            CPU and disk work needed to get the UI started can interfere
1064            with the scheduling of the audio thread.
1065         */
1066
1067         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1068 }
1069
1070 void
1071 ARDOUR_UI::finish()
1072 {
1073         if (session && session->dirty()) {
1074                 switch (ask_about_saving_session(_("quit"))) {
1075                 case -1:
1076                         return;
1077                         break;
1078                 case 1:
1079                         /* use the default name */
1080                         if (save_state_canfail ("")) {
1081                                 /* failed - don't quit */
1082                                 ArdourMessage (editor, X_("badsave dialog"),
1083                                                _("\
1084 Ardour was unable to save your session.\n\n\
1085 If you still wish to quit, please use the\n\n\
1086 \"Just quit\" option."));
1087                                 return;
1088                         }
1089                         break;
1090                 case 0:
1091                         break;
1092                 }
1093         }
1094
1095         quit();
1096 }
1097
1098 int
1099 ARDOUR_UI::ask_about_saving_session (string what)
1100 {
1101         ArdourDialog window (_("ardour: save session?"));
1102         Gtk::Label  prompt_label;
1103         string msg;
1104
1105         msg = string_compose(_("Save and %1"), what);
1106         window.add_button (msg, RESPONSE_ACCEPT);
1107         msg = string_compose(_("Just %1"), what);
1108         window.add_button (msg, RESPONSE_REJECT);
1109         msg = string_compose(_("Don't %1"), what);
1110         window.add_button (msg, RESPONSE_REJECT);
1111
1112         Gtk::Button noquit_button (msg);
1113         noquit_button.set_name ("EditorGTKButton");
1114
1115         string prompt;
1116         string type;
1117
1118         if (session->snap_name() == session->name()) {
1119                 type = _("session");
1120         } else {
1121                 type = _("snapshot");
1122         }
1123         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?"), 
1124                          type, session->snap_name());
1125         
1126         prompt_label.set_text (prompt);
1127         prompt_label.set_alignment (0.5, 0.5);
1128         prompt_label.set_name (X_("PrompterLabel"));
1129         
1130         window.get_vbox()->pack_start (prompt_label);
1131
1132         window.set_name (_("Prompter"));
1133         window.set_position (Gtk::WIN_POS_MOUSE);
1134         window.set_modal (true);
1135         window.show_all ();
1136
1137         save_the_session = 0;
1138
1139         editor->ensure_float (window);
1140
1141         ResponseType r = (ResponseType) window.run();
1142
1143         window.hide ();
1144
1145         switch (r) {
1146         case RESPONSE_ACCEPT:
1147                 return 0;
1148         default:
1149                 break;
1150         }
1151
1152         return -1;
1153 }
1154         
1155 gint
1156 ARDOUR_UI::every_second ()
1157 {
1158         update_cpu_load ();
1159         update_buffer_load ();
1160         update_disk_space ();
1161         // update_disk_rate ();
1162         return TRUE;
1163 }
1164
1165 gint
1166 ARDOUR_UI::every_point_one_seconds ()
1167 {
1168         struct timeval now;
1169         struct timeval diff;
1170         
1171         /* do not attempt to grab peak power more than once per cycle.
1172          */
1173
1174         gettimeofday (&now, 0);
1175         timersub (&now, &last_peak_grab, &diff);
1176
1177         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1178                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1179                 last_peak_grab = now;
1180         } 
1181
1182         update_speed_display ();
1183         RapidScreenUpdate(); /* EMIT_SIGNAL */
1184         return TRUE;
1185 }
1186
1187 gint
1188 ARDOUR_UI::every_point_zero_one_seconds ()
1189 {
1190         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1191         return TRUE;
1192 }
1193
1194 void
1195 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1196 {
1197         char buf[32];
1198
1199         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1200
1201         if (!engine->connected()) {
1202
1203                 snprintf (buf, sizeof (buf), _("disconnected"));
1204
1205         } else {
1206
1207                 jack_nframes_t rate = engine->frame_rate();
1208                 
1209                 if (fmod (rate, 1000.0) != 0.0) {
1210                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1211                                   (float) rate/1000.0f,
1212                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1213                 } else {
1214                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1215                                   rate/1000,
1216                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1217                 }
1218         }
1219
1220         sample_rate_label.set_text (buf);
1221 }
1222
1223 void
1224 ARDOUR_UI::update_cpu_load ()
1225 {
1226         char buf[32];
1227         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1228         cpu_load_label.set_text (buf);
1229 }
1230
1231 void
1232 ARDOUR_UI::update_disk_rate ()
1233 {
1234         char buf[64];
1235
1236         if (session) {
1237                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1238                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1239                 disk_rate_label.set_text (buf);
1240         } else {
1241                 disk_rate_label.set_text ("");
1242         }
1243 }
1244
1245 void
1246 ARDOUR_UI::update_buffer_load ()
1247 {
1248         char buf[64];
1249
1250         if (session) {
1251                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1252                           session->playback_load(), session->capture_load());
1253                 buffer_load_label.set_text (buf);
1254         } else {
1255                 buffer_load_label.set_text ("");
1256         }
1257 }
1258
1259 void
1260 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1261 {
1262         if (ds.record_enabled()) {
1263                 rec_enabled_diskstreams++;
1264         }
1265 }
1266
1267 void
1268 ARDOUR_UI::update_disk_space()
1269 {
1270         if (session == 0) {
1271                 return;
1272         }
1273
1274         jack_nframes_t frames = session->available_capture_duration();
1275         char buf[64];
1276
1277         if (frames == max_frames) {
1278                 strcpy (buf, _("space: 24hrs+"));
1279         } else {
1280                 int hrs;
1281                 int mins;
1282                 int secs;
1283                 jack_nframes_t fr = session->frame_rate();
1284                 
1285                 if (session->actively_recording()){
1286                         
1287                         rec_enabled_diskstreams = 0;
1288                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1289                         
1290                         if (rec_enabled_diskstreams) {
1291                                 frames /= rec_enabled_diskstreams;
1292                         }
1293                         
1294                 } else {
1295                         
1296                         /* hmmm. shall we divide by the route count? or the diskstream count?
1297                            or what? for now, do nothing ...
1298                         */
1299                         
1300                 }
1301                 
1302                 hrs  = frames / (fr * 3600);
1303                 frames -= hrs * fr * 3600;
1304                 mins = frames / (fr * 60);
1305                 frames -= mins * fr * 60;
1306                 secs = frames / fr;
1307                 
1308                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1309         }
1310
1311         disk_space_label.set_text (buf);
1312 }                 
1313
1314 gint
1315 ARDOUR_UI::update_wall_clock ()
1316 {
1317         time_t now;
1318         struct tm *tm_now;
1319         char buf[16];
1320
1321         time (&now);
1322         tm_now = localtime (&now);
1323
1324         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1325         wall_clock_label.set_text (buf);
1326
1327         return TRUE;
1328 }
1329
1330 void
1331 ARDOUR_UI::toggle_recording_plugins ()
1332 {
1333         /* XXX use toggle_some_session_state */
1334
1335         if (session == 0) {
1336                 return;
1337         }
1338
1339         session->set_recording_plugins (!session->get_recording_plugins());
1340 }
1341         
1342 void
1343 ARDOUR_UI::toggle_auto_play ()
1344
1345 {
1346         toggle_some_session_state (auto_play_button,
1347                                    &Session::get_auto_play,
1348                                    &Session::set_auto_play);
1349 }
1350
1351 void
1352 ARDOUR_UI::toggle_auto_return ()
1353
1354 {
1355         toggle_some_session_state (auto_return_button,
1356                                    &Session::get_auto_return,
1357                                    &Session::set_auto_return);
1358 }
1359
1360 void
1361 ARDOUR_UI::toggle_click ()
1362 {
1363         toggle_some_session_state (click_button,
1364                                    &Session::get_clicking,
1365                                    &Session::set_clicking);
1366 }
1367
1368 void
1369 ARDOUR_UI::follow_changed ()
1370 {
1371         bool x;
1372
1373         if (!editor) {
1374                 return;
1375         }
1376
1377         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1378                 follow_button.set_active (x);
1379         }
1380 }
1381
1382 void
1383 ARDOUR_UI::toggle_follow ()
1384 {
1385         bool x;
1386
1387         if (!editor) {
1388                 return;
1389         }
1390
1391         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1392                 editor->set_follow_playhead (x);
1393         }
1394 }
1395
1396 void
1397 ARDOUR_UI::toggle_session_auto_loop ()
1398 {
1399         if (session) {
1400                 if (session->get_auto_loop()) {
1401                         if (session->transport_rolling()) {
1402                                 transport_roll();
1403                         }
1404                         else {
1405                                 session->request_auto_loop (false);
1406                         }
1407                 }
1408                 else {
1409                         session->request_auto_loop (true);
1410                 }
1411         }
1412 }
1413
1414 void
1415 ARDOUR_UI::toggle_session_punch_in ()
1416 {
1417         if (session) {
1418                 session->set_punch_in (!session->get_punch_in());
1419         }
1420 }
1421
1422 void
1423 ARDOUR_UI::toggle_punch_out ()
1424 {
1425         toggle_some_session_state (punch_out_button,
1426                                    &Session::get_punch_out,
1427                                    &Session::set_punch_out);
1428 }
1429
1430 void
1431 ARDOUR_UI::toggle_punch_in ()
1432 {
1433         toggle_some_session_state (punch_in_button,
1434                                    &Session::get_punch_in,
1435                                    &Session::set_punch_in);
1436 }
1437
1438 void
1439 ARDOUR_UI::map_button_state ()
1440
1441 {
1442         map_some_session_state (auto_return_button,
1443                                 &Session::get_auto_return);
1444         map_some_session_state (auto_play_button,
1445                                 &Session::get_auto_play);
1446         map_some_session_state (auto_input_button,
1447                                 &Session::get_auto_input);
1448         map_some_session_state (punch_in_button,
1449                                 &Session::get_punch_in);
1450         map_some_session_state (punch_out_button,
1451                                 &Session::get_punch_out);
1452         map_some_session_state (click_button,
1453                                 &Session::get_clicking);
1454 }
1455
1456 void
1457 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1458 {
1459         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1460 }
1461
1462 void
1463 ARDOUR_UI::map_control_change (Session::ControlType t)
1464 {
1465         switch (t) {
1466         case Session::AutoPlay:
1467                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1468                 break;
1469
1470         case Session::AutoLoop:
1471                 break;
1472
1473         case Session::AutoReturn:
1474                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1475                 break;
1476
1477         case Session::AutoInput:
1478                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1479                 break;
1480
1481         case Session::PunchOut:
1482                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1483                 break;
1484
1485         case Session::PunchIn:
1486                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1487                 break;
1488
1489         case Session::Clicking:
1490                 map_some_session_state (click_button, &Session::get_clicking);
1491                 break;
1492
1493         case Session::SlaveType:
1494 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1495                 break;
1496
1497         case Session::SendMTC:
1498 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1499                 break;
1500
1501         case Session::SendMMC:
1502 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1503                 break;
1504
1505         case Session::MMCControl:       
1506 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1507                 break;
1508
1509         case Session::MidiFeedback:       
1510 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1511                 break;
1512         case Session::MidiControl:       
1513 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1514                 break;
1515                 
1516         case Session::Live:
1517                 break;
1518
1519         case Session::RecordingPlugins:
1520                 break;
1521
1522         case Session::CrossFadesActive:
1523                 break;
1524                 
1525         case Session::EditingMode:
1526                 break;
1527
1528         case Session::PlayRange:
1529                 break;
1530
1531         case Session::AlignChoice:
1532                 /* don't care, this is handled by the options editor */
1533                 break;
1534         case Session::SeamlessLoop:
1535                 /* don't care, this is handled by the options editor */
1536                 break;
1537                
1538         }
1539 }
1540
1541 void
1542 ARDOUR_UI::control_methods_adjusted ()
1543
1544 {
1545         int which_method;
1546
1547         which_method = (int) online_control_button->adjustment.get_value();
1548         switch (which_method) {
1549         case 0:
1550                 allow_mmc_and_local ();
1551                 break;
1552         case 1:
1553                 allow_mmc_only ();
1554                 break;
1555         case 2:
1556                 allow_local_only ();
1557                 break;
1558         default:
1559                 fatal << _("programming error: impossible control method") << endmsg;
1560         }
1561 }
1562         
1563
1564 void
1565 ARDOUR_UI::mmc_device_id_adjusted ()
1566
1567 {
1568 #if 0
1569         if (mmc) {
1570                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1571                 mmc->set_device_id (dev_id);
1572         }
1573 #endif
1574 }
1575
1576 void
1577 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1578                                    bool (Session::*get)() const)
1579         
1580 {
1581         bool x;
1582
1583         if (session == 0) {
1584                 return;
1585         }
1586         
1587         if (button.get_active() != (x = (session->*get)())) {
1588                 button.set_active (x);
1589         }
1590 }
1591
1592 void
1593 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1594                                       bool (Session::*get)() const,
1595                                       void (Session::*set)(bool))
1596
1597 {
1598         bool button_state;
1599         bool session_state;
1600
1601         if (session == 0) {
1602                 return;
1603         }
1604
1605         button_state = button.get_active ();
1606         session_state = (session->*get)();
1607
1608         if (button_state != session_state) {
1609                 (session->*set) (button_state);
1610 #if 0
1611         
1612                 /* check that it worked, and reverse
1613                    the button state if it didn't
1614                 */
1615
1616                 if ((session->*get)() != button_state) {
1617                         button->set_active (!button_state);
1618                 }
1619 #endif
1620
1621         }
1622 }       
1623
1624 gint
1625 ARDOUR_UI::session_menu (GdkEventButton *ev)
1626 {
1627         session_popup_menu->popup (0, 0);
1628         return TRUE;
1629 }
1630
1631 void
1632 ARDOUR_UI::redisplay_recent_sessions ()
1633 {
1634         vector<string *> *sessions;
1635         vector<string *>::iterator i;
1636         RecentSessionsSorter cmp;
1637         
1638         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1639         recent_session_model->clear ();
1640
1641         RecentSessions rs;
1642         ARDOUR::read_recent_sessions (rs);
1643
1644         if (rs.empty()) {
1645                 recent_session_display.set_model (recent_session_model);
1646                 return;
1647         }
1648
1649         /* sort them alphabetically */
1650         sort (rs.begin(), rs.end(), cmp);
1651         sessions = new vector<string*>;
1652
1653         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1654                 sessions->push_back (new string ((*i).second));
1655         }
1656
1657         for (i = sessions->begin(); i != sessions->end(); ++i) {
1658
1659                 vector<string*>* states;
1660                 vector<const gchar*> item;
1661                 string fullpath = *(*i);
1662                 
1663                 /* remove any trailing / */
1664
1665                 if (fullpath[fullpath.length()-1] == '/') {
1666                         fullpath = fullpath.substr (0, fullpath.length()-1);
1667                 }
1668
1669                 /* now get available states for this session */
1670
1671                 if ((states = Session::possible_states (fullpath)) == 0) {
1672                         /* no state file? */
1673                         continue;
1674                 }
1675
1676                 TreeModel::Row row = *(recent_session_model->append());
1677
1678                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1679                 row[recent_session_columns.fullpath] = fullpath;
1680
1681                 if (states->size() > 1) {
1682
1683                         /* add the children */
1684                         
1685                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1686                                 
1687                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1688
1689                                 child_row[recent_session_columns.visible_name] = **i2;
1690                                 child_row[recent_session_columns.fullpath] = fullpath;
1691
1692                                 delete *i2;
1693                         }
1694                 }
1695
1696                 delete states;
1697         }
1698
1699         recent_session_display.set_model (recent_session_model);
1700         delete sessions;
1701 }
1702
1703 void
1704 ARDOUR_UI::build_session_selector ()
1705 {
1706         session_selector_window = new ArdourDialog ("session selector");
1707         
1708         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1709
1710         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1711         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1712
1713         recent_session_model = TreeStore::create (recent_session_columns);
1714         recent_session_display.set_model (recent_session_model);
1715         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1716         recent_session_display.set_headers_visible (false);
1717
1718         scroller->add (recent_session_display);
1719         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1720
1721         session_selector_window->set_name ("SessionSelectorWindow");
1722         session_selector_window->set_size_request (200, 400);
1723         session_selector_window->get_vbox()->pack_start (*scroller);
1724 }
1725
1726 void
1727 ARDOUR_UI::open_recent_session ()
1728 {
1729         /* popup selector window */
1730
1731         if (session_selector_window == 0) {
1732                 build_session_selector ();
1733         }
1734
1735         redisplay_recent_sessions ();
1736
1737         ResponseType r = (ResponseType) session_selector_window->run ();
1738
1739         session_selector_window->hide();
1740
1741         switch (r) {
1742         case RESPONSE_ACCEPT:
1743                 break;
1744         default:
1745                 return;
1746         }
1747
1748         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1749
1750         if (i == recent_session_model->children().end()) {
1751                 return;
1752         }
1753         
1754         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1755         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1756
1757         _session_is_new = false;
1758
1759         load_session (path, state);
1760 }
1761
1762 bool
1763 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1764 {
1765         struct stat statbuf;
1766         
1767         if (stat (info.filename.c_str(), &statbuf) != 0) {
1768                 return false;
1769         }
1770
1771         if (!S_ISDIR(statbuf.st_mode)) {
1772                 return false;
1773         }
1774
1775         string session_file = info.filename;
1776         session_file += '/';
1777         session_file += PBD::basename (info.filename);
1778         session_file += ".ardour";
1779         
1780         if (stat (session_file.c_str(), &statbuf) != 0) {
1781                 return false;
1782         }
1783
1784         return S_ISREG (statbuf.st_mode);
1785 }
1786
1787 void
1788 ARDOUR_UI::open_session ()
1789 {
1790         /* popup selector window */
1791
1792         if (open_session_selector == 0) {
1793                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1794                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1795                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1796                 
1797                 FileFilter filter_ardour;
1798                 filter_ardour.set_name (_("Ardour sessions"));
1799                 filter_ardour.add_custom (FILE_FILTER_FILENAME, mem_fun (*this, &ARDOUR_UI::filter_ardour_session_dirs));
1800
1801                 open_session_selector->add_filter (filter_ardour);
1802         }
1803
1804         switch (open_session_selector->run ()) {
1805         case RESPONSE_OK:
1806                 break;
1807         default:
1808                 return;
1809         }
1810
1811         string session_path = open_session_selector->get_filename();
1812         string path, name;
1813         bool isnew;
1814
1815         if (session_path.length() > 0) {
1816                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1817                         _session_is_new = isnew;
1818                         load_session (path, name);
1819                 }
1820         }
1821 }
1822
1823
1824 void
1825 ARDOUR_UI::session_add_midi_track ()
1826 {
1827         cerr << _("Patience is a virtue.\n");
1828 }
1829
1830 void
1831 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1832 {
1833         Route* route;
1834
1835         if (session == 0) {
1836                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1837                 return;
1838         }
1839
1840         try { 
1841                 if (disk) {
1842                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1843                                 error << _("could not create new audio track") << endmsg;
1844                         }
1845                 } else {
1846                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1847                                 error << _("could not create new audio bus") << endmsg;
1848                         }
1849                 }
1850                 
1851 #if CONTROLOUTS
1852                 if (need_control_room_outs) {
1853                         pan_t pans[2];
1854                         
1855                         pans[0] = 0.5;
1856                         pans[1] = 0.5;
1857                         
1858                         route->set_stereo_control_outs (control_lr_channels);
1859                         route->control_outs()->set_stereo_pan (pans, this);
1860                 }
1861 #endif /* CONTROLOUTS */
1862         }
1863
1864         catch (...) {
1865                 ArdourMessage msg (editor, X_("noport dialog"),
1866                                    _("There are insufficient JACK ports available\n\
1867 to create a new track or bus.\n\
1868 You should save Ardour, exit and\n\
1869 restart JACK with more ports."));
1870         }
1871 }
1872
1873 void
1874 ARDOUR_UI::diskstream_added (DiskStream* ds)
1875 {
1876 }
1877
1878 void
1879 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1880 {
1881         jack_nframes_t _preroll;
1882
1883         if (session) {
1884                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1885
1886                 if (new_position > _preroll) {
1887                         new_position -= _preroll;
1888                 } else {
1889                         new_position = 0;
1890                 }
1891
1892                 session->request_locate (new_position);
1893         }
1894 }
1895
1896 void
1897 ARDOUR_UI::transport_goto_start ()
1898 {
1899         if (session) {
1900                 session->request_locate (0);
1901
1902                 
1903                 /* force displayed area in editor to start no matter
1904                    what "follow playhead" setting is.
1905                 */
1906                 
1907                 if (editor) {
1908                         editor->reposition_x_origin (0);
1909                 }
1910         }
1911 }
1912
1913 void
1914 ARDOUR_UI::transport_goto_end ()
1915 {
1916         if (session) {
1917                 jack_nframes_t frame = session->current_end_frame();
1918                 session->request_locate (frame);
1919
1920                 /* force displayed area in editor to start no matter
1921                    what "follow playhead" setting is.
1922                 */
1923                 
1924                 if (editor) {
1925                         editor->reposition_x_origin (frame);
1926                 }
1927         }
1928 }
1929
1930 gint 
1931 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1932 {
1933
1934
1935         if (session) {
1936                         if (session->transport_stopped()) {
1937                         session->request_locate (session->last_transport_start());
1938                 } else {
1939                         if (session->get_auto_loop()) {
1940                                 session->request_auto_loop (false);
1941                         }
1942
1943                         Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1944                         session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1945                         }
1946         }
1947
1948         return TRUE;
1949 }
1950
1951 gint
1952 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1953 {
1954         transport_roll ();
1955         return TRUE;
1956 }
1957
1958 void
1959 ARDOUR_UI::transport_stop ()
1960 {
1961         if (!session) {
1962                 return;
1963         }
1964
1965         if (session->is_auditioning()) {
1966                 session->cancel_audition ();
1967                 return;
1968         }
1969         
1970         if (session->get_auto_loop()) {
1971                 session->request_auto_loop (false);
1972         }
1973         
1974         session->request_stop ();
1975 }
1976
1977 void
1978 ARDOUR_UI::transport_stop_and_forget_capture ()
1979 {
1980         if (session) {
1981                 session->request_stop (true);
1982         }
1983 }
1984
1985 void
1986 ARDOUR_UI::remove_last_capture()
1987 {
1988         if (editor) {
1989                 editor->remove_last_capture();
1990         }
1991 }
1992
1993 void
1994 ARDOUR_UI::transport_record ()
1995 {
1996         if (session) {
1997                 switch (session->record_status()) {
1998                 case Session::Disabled:
1999                         if (session->ntracks() == 0) {
2000                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
2001                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2002                                 return;
2003                         }
2004                         session->maybe_enable_record ();
2005                         break;
2006                 case Session::Recording:
2007                 case Session::Enabled:
2008                         session->disable_record ();
2009                 }
2010         }
2011 }
2012
2013 void
2014 ARDOUR_UI::transport_roll ()
2015 {
2016         bool rolling;
2017
2018         if (!session) {
2019                 return;
2020         }
2021
2022         rolling = session->transport_rolling ();
2023
2024         if (session->get_auto_loop()) {
2025                 session->request_auto_loop (false);
2026                 auto_loop_button.set_active (false);
2027                 roll_button.set_active (true);
2028         } else if (session->get_play_range ()) {
2029                 session->request_play_range (false);
2030                 play_selection_button.set_active (false);
2031         } else if (rolling) {
2032                 session->request_locate (session->last_transport_start(), true);
2033         }
2034
2035         session->request_transport_speed (1.0f);
2036 }
2037
2038 void
2039 ARDOUR_UI::transport_loop()
2040 {
2041         if (session) {
2042                 if (session->get_auto_loop()) {
2043                         if (session->transport_rolling()) {
2044                                 Location * looploc = session->locations()->auto_loop_location();
2045                                 if (looploc) {
2046                                         session->request_locate (looploc->start(), true);
2047                                 }
2048                         }
2049                 }
2050                 else {
2051                         session->request_auto_loop (true);
2052                 }
2053         }
2054 }
2055
2056 void
2057 ARDOUR_UI::transport_play_selection ()
2058 {
2059         if (!session) {
2060                 return;
2061         }
2062
2063         if (!session->get_play_range()) {
2064                 session->request_stop ();
2065         }
2066
2067         editor->play_selection ();
2068 }
2069
2070 void
2071 ARDOUR_UI::transport_rewind (int option)
2072 {
2073         float current_transport_speed;
2074  
2075         if (session) {
2076                 current_transport_speed = session->transport_speed();
2077                 
2078                 if (current_transport_speed >= 0.0f) {
2079                         switch (option) {
2080                         case 0:
2081                                 session->request_transport_speed (-1.0f);
2082                                 break;
2083                         case 1:
2084                                 session->request_transport_speed (-4.0f);
2085                                 break;
2086                         case -1:
2087                                 session->request_transport_speed (-0.5f);
2088                                 break;
2089                         }
2090                 } else {
2091                         /* speed up */
2092                         session->request_transport_speed (current_transport_speed * 1.5f);
2093                 }
2094         }
2095 }
2096
2097 void
2098 ARDOUR_UI::transport_forward (int option)
2099 {
2100         float current_transport_speed;
2101         
2102         if (session) {
2103                 current_transport_speed = session->transport_speed();
2104                 
2105                 if (current_transport_speed <= 0.0f) {
2106                         switch (option) {
2107                         case 0:
2108                                 session->request_transport_speed (1.0f);
2109                                 break;
2110                         case 1:
2111                                 session->request_transport_speed (4.0f);
2112                                 break;
2113                         case -1:
2114                                 session->request_transport_speed (0.5f);
2115                                 break;
2116                         }
2117                 } else {
2118                         /* speed up */
2119                         session->request_transport_speed (current_transport_speed * 1.5f);
2120                 }
2121         }
2122 }
2123
2124 void
2125 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2126 {
2127         if (session == 0) {
2128                 return;
2129         }
2130
2131         DiskStream *ds;
2132
2133         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2134                 Port *port = ds->io()->input (0);
2135                 port->request_monitor_input (!port->monitoring_input());
2136         }
2137 }
2138
2139 void
2140 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2141 {
2142         if (session == 0) {
2143                 return;
2144         }
2145
2146         DiskStream *ds;
2147
2148         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2149                 ds->set_record_enabled (!ds->record_enabled(), this);
2150         }
2151 }
2152
2153 void
2154 ARDOUR_UI::queue_transport_change ()
2155 {
2156         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2157 }
2158
2159 void
2160 ARDOUR_UI::map_transport_state ()
2161 {
2162         float sp = session->transport_speed();
2163
2164         if (sp == 1.0f) {
2165                 transport_rolling ();
2166         } else if (sp < 0.0f) {
2167                 transport_rewinding ();
2168         } else if (sp > 0.0f) {
2169                 transport_forwarding ();
2170         } else {
2171                 transport_stopped ();
2172         }
2173 }
2174
2175 void
2176 ARDOUR_UI::send_all_midi_feedback ()
2177 {
2178         if (session) {
2179                 session->send_all_midi_feedback();
2180         }
2181 }
2182
2183 void
2184 ARDOUR_UI::allow_local_only ()
2185 {
2186
2187 }
2188
2189 void
2190 ARDOUR_UI::allow_mmc_only ()
2191 {
2192
2193 }
2194
2195 void
2196 ARDOUR_UI::allow_mmc_and_local ()
2197 {
2198
2199 }
2200
2201 void
2202 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2203 {
2204         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2205                 (int) adj.get_value()].c_str());
2206 }
2207
2208 void
2209 ARDOUR_UI::engine_stopped ()
2210 {
2211         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2212
2213         jack_disconnect_item->set_sensitive (false);
2214         jack_reconnect_item->set_sensitive (true);
2215         jack_bufsize_menu->set_sensitive (false);
2216 }
2217
2218
2219 void
2220 ARDOUR_UI::engine_running ()
2221 {
2222         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2223
2224         jack_disconnect_item->set_sensitive (true);
2225         jack_reconnect_item->set_sensitive (false);
2226         jack_bufsize_menu->set_sensitive (true);
2227 }
2228
2229 void
2230 ARDOUR_UI::engine_halted ()
2231 {
2232         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2233
2234         jack_disconnect_item->set_sensitive (false);
2235         jack_reconnect_item->set_sensitive (true);
2236         jack_bufsize_menu->set_sensitive (false);
2237
2238         update_sample_rate (0);
2239
2240         ArdourMessage msg (editor, X_("halted"),
2241                            _("\
2242 JACK has either been shutdown or it\n\
2243 disconnected Ardour because Ardour\n\
2244 was not fast enough. You can save the\n\
2245 session and/or try to reconnect to JACK ."));
2246 }
2247
2248 int32_t
2249 ARDOUR_UI::do_engine_start ()
2250 {
2251         try { 
2252                 engine->start();
2253         }
2254
2255         catch (AudioEngine::PortRegistrationFailure& err) {
2256                 engine->stop ();
2257                 error << _("Unable to create all required ports")
2258                       << endmsg;
2259                 unload_session ();
2260                 return -1;
2261         }
2262
2263         catch (...) {
2264                 engine->stop ();
2265                 error << _("Unable to start the session running")
2266                       << endmsg;
2267                 unload_session ();
2268                 return -2;
2269         }
2270         
2271         return 0;
2272 }
2273
2274 gint
2275 ARDOUR_UI::start_engine ()
2276 {
2277         if (do_engine_start () == 0) {
2278                 if (session && _session_is_new) {
2279                         /* we need to retain initial visual 
2280                            settings for a new session 
2281                         */
2282                         session->save_state ("");
2283                 }
2284
2285                 /* there is too much going on, in too many threads, for us to 
2286                    end up with a clean session. So wait 1 second after loading,
2287                    and fix it up. its ugly, but until i come across a better
2288                    solution, its what we have.
2289                 */
2290
2291                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2292         }
2293
2294         return FALSE;
2295 }
2296
2297 void
2298 ARDOUR_UI::update_clocks ()
2299 {
2300          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2301 }
2302
2303 void
2304 ARDOUR_UI::start_clocking ()
2305 {
2306         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2307 }
2308
2309 void
2310 ARDOUR_UI::stop_clocking ()
2311 {
2312         clock_signal_connection.disconnect ();
2313 }
2314         
2315 void
2316 ARDOUR_UI::toggle_clocking ()
2317 {
2318 #if 0
2319         if (clock_button.get_active()) {
2320                 start_clocking ();
2321         } else {
2322                 stop_clocking ();
2323         }
2324 #endif
2325 }
2326
2327 gint
2328 ARDOUR_UI::_blink (void *arg)
2329
2330 {
2331         ((ARDOUR_UI *) arg)->blink ();
2332         return TRUE;
2333 }
2334
2335 void
2336 ARDOUR_UI::blink ()
2337 {
2338          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2339 }
2340
2341 void
2342 ARDOUR_UI::start_blinking ()
2343 {
2344         /* Start the blink signal. Everybody with a blinking widget
2345            uses Blink to drive the widget's state.
2346         */
2347
2348         if (blink_timeout_tag < 0) {
2349                 blink_on = false;       
2350                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2351         }
2352 }
2353
2354 void
2355 ARDOUR_UI::stop_blinking ()
2356 {
2357         if (blink_timeout_tag >= 0) {
2358                 gtk_timeout_remove (blink_timeout_tag);
2359                 blink_timeout_tag = -1;
2360         }
2361 }
2362
2363
2364 void
2365 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2366 {
2367         using namespace Gtk;
2368         using namespace Menu_Helpers;
2369
2370         if (dstream.hidden()) {
2371                 return;
2372         }
2373
2374         MenuList& items = diskstream_menu->items();
2375         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2376 }
2377         
2378 void
2379 ARDOUR_UI::diskstream_selected (gint32 id)
2380 {
2381         selected_dstream = id;
2382         Main::quit ();
2383 }
2384
2385 gint32
2386 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2387 {
2388         using namespace Gtk;
2389         using namespace Menu_Helpers;
2390
2391         if (session == 0) {
2392                 return -1;
2393         }
2394
2395         diskstream_menu = new Menu();
2396         diskstream_menu->set_name ("ArdourContextMenu");
2397         using namespace Gtk;
2398         using namespace Menu_Helpers;
2399
2400         MenuList& items = diskstream_menu->items();
2401         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2402
2403         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2404
2405         if (ev) {
2406                 diskstream_menu->popup (ev->button, ev->time);
2407         } else {
2408                 diskstream_menu->popup (0, 0);
2409         }
2410
2411         selected_dstream = -1;
2412
2413         Main::run ();
2414
2415         delete diskstream_menu;
2416
2417         return selected_dstream;
2418 }
2419
2420 void
2421 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2422                           string& buf,
2423                           IO& io,
2424                           bool in)
2425 {
2426         if (in) {
2427                 if (io.n_inputs() == 0) {
2428                         buf = _("none");
2429                         return;
2430                 }
2431                 
2432                 /* XXX we're not handling multiple ports yet. */
2433
2434                 const char **connections = io.input(0)->get_connections();
2435                 
2436                 if (connections == 0 || connections[0] == '\0') {
2437                         buf = _("off");
2438                 } else {
2439                         buf = connections[0];
2440                 }
2441
2442                 free (connections);
2443
2444         } else {
2445
2446                 if (io.n_outputs() == 0) {
2447                         buf = _("none");
2448                         return;
2449                 }
2450                 
2451                 /* XXX we're not handling multiple ports yet. */
2452
2453                 const char **connections = io.output(0)->get_connections();
2454                 
2455                 if (connections == 0 || connections[0] == '\0') {
2456                         buf = _("off");
2457                 } else {
2458                         buf = connections[0];
2459                 }
2460
2461                 free (connections);
2462         }
2463 }
2464
2465 void
2466 ARDOUR_UI::snapshot_session ()
2467 {
2468         ArdourPrompter prompter (true);
2469         string snapname;
2470         string now;
2471         time_t n;
2472
2473         time (&n);
2474         now = ctime (&n);
2475         now = now.substr (0, now.length() - 1);
2476
2477         prompter.set_name ("Prompter");
2478         prompter.set_prompt (_("Name for snapshot"));
2479         prompter.set_initial_text (now);
2480         
2481         switch (prompter.run()) {
2482         case RESPONSE_ACCEPT:
2483                 prompter.get_result (snapname);
2484                 if (snapname.length()){
2485                         save_state (snapname);
2486                 }
2487                 break;
2488
2489         default:
2490                 break;
2491         }
2492 }
2493
2494 void
2495 ARDOUR_UI::save_state (string name)
2496 {
2497         (void) save_state_canfail (name);
2498 }
2499                 
2500 int
2501 ARDOUR_UI::save_state_canfail (string name)
2502 {
2503         if (session) {
2504                 int ret;
2505
2506                 if (name.length() == 0) {
2507                         name = session->snap_name();
2508                 }
2509
2510                 if ((ret = session->save_state (name)) != 0) {
2511                         return ret;
2512                 }
2513         }
2514         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2515         return 0;
2516 }
2517
2518 void
2519 ARDOUR_UI::restore_state (string name)
2520 {
2521         if (session) {
2522                 if (name.length() == 0) {
2523                         name = session->name();
2524                 }
2525                 session->restore_state (name);
2526         }
2527 }
2528
2529 void
2530 ARDOUR_UI::primary_clock_value_changed ()
2531 {
2532         if (session) {
2533                 session->request_locate (primary_clock.current_time ());
2534         }
2535 }
2536
2537 void
2538 ARDOUR_UI::secondary_clock_value_changed ()
2539 {
2540         if (session) {
2541                 session->request_locate (secondary_clock.current_time ());
2542         }
2543 }
2544
2545 void
2546 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2547 {
2548         if (session && dstream && dstream->record_enabled()) {
2549
2550                 Session::RecordState rs;
2551                 
2552                 rs = session->record_status ();
2553
2554                 switch (rs) {
2555                 case Session::Disabled:
2556                 case Session::Enabled:
2557                         if (w->get_state() != STATE_SELECTED) {
2558                                 w->set_state (STATE_SELECTED);
2559                         }
2560                         break;
2561
2562                 case Session::Recording:
2563                         if (w->get_state() != STATE_ACTIVE) {
2564                                 w->set_state (STATE_ACTIVE);
2565                         }
2566                         break;
2567                 }
2568
2569         } else {
2570                 if (w->get_state() != STATE_NORMAL) {
2571                         w->set_state (STATE_NORMAL);
2572                 }
2573         }
2574 }
2575
2576 void
2577 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2578 {
2579         if (session == 0) {
2580                 return;
2581         }
2582         
2583         switch (session->record_status()) {
2584         case Session::Enabled:
2585                 if (onoff) {
2586                         rec_button.set_state (STATE_ACTIVE);
2587                 } else {
2588                         rec_button.set_state (STATE_NORMAL);
2589                 }
2590                 break;
2591
2592         case Session::Recording:
2593                 rec_button.set_state (STATE_ACTIVE);
2594                 break;
2595
2596         default:
2597                 rec_button.set_active (false);
2598                 rec_button.set_state (STATE_NORMAL);
2599                 break;
2600         }
2601 }
2602
2603 gint
2604 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2605 {
2606         window->hide();
2607         Gtk::Main::quit ();
2608         return TRUE;
2609 }
2610
2611 void
2612 ARDOUR_UI::start_keyboard_prefix ()
2613 {
2614         keyboard->start_prefix();
2615 }
2616
2617 void
2618 ARDOUR_UI::save_template ()
2619
2620 {
2621         ArdourPrompter prompter (true);
2622         string name;
2623
2624         prompter.set_name (X_("Prompter"));
2625         prompter.set_prompt (_("Name for mix template:"));
2626         prompter.set_initial_text(session->name() + _("-template"));
2627         
2628         switch (prompter.run()) {
2629         case RESPONSE_ACCEPT:
2630                 prompter.get_result (name);
2631                 
2632                 if (name.length()) {
2633                         session->save_template (name);
2634                 }
2635                 break;
2636
2637         default:
2638                 break;
2639         }
2640 }
2641
2642 void
2643 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2644 {
2645         m_new_session_dialog->show_all();
2646         m_new_session_dialog->set_transient_for(*editor);
2647         m_new_session_dialog->set_name(predetermined_path);
2648
2649         int response = Gtk::RESPONSE_CANCEL;
2650
2651         do {
2652                 response = m_new_session_dialog->run ();
2653         
2654                 if(response == Gtk::RESPONSE_OK) {
2655
2656                         _session_is_new = true;
2657                         
2658                         std::string session_name = m_new_session_dialog->session_name();
2659                         std::string session_path = m_new_session_dialog->session_folder();
2660                         std::string template_name = m_new_session_dialog->session_template_name();
2661                         
2662                         if (m_new_session_dialog->use_session_template()) {
2663                                 
2664                                 load_session (session_path, session_name, &template_name);
2665                                 
2666                         } else {
2667                                 
2668                                 uint32_t cchns;
2669                                 uint32_t mchns;
2670                                 Session::AutoConnectOption iconnect;
2671                                 Session::AutoConnectOption oconnect;
2672                                 
2673                                 if (m_new_session_dialog->create_control_bus()) {
2674                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2675                                 } else {
2676                                         cchns = 0;
2677                                 }
2678                                 
2679                                 if (m_new_session_dialog->create_master_bus()) {
2680                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2681                                 } else {
2682                                         mchns = 0;
2683                                 }
2684                                 
2685                                 if (m_new_session_dialog->connect_inputs()) {
2686                                         iconnect = Session::AutoConnectPhysical;
2687                                 } else {
2688                                         iconnect = Session::AutoConnectOption (0);
2689                                 }
2690                                 
2691                                 /// @todo some minor tweaks.
2692
2693                                 if (m_new_session_dialog->connect_outs_to_master()) {
2694                                         oconnect = Session::AutoConnectMaster;
2695                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2696                                         oconnect = Session::AutoConnectPhysical;
2697                                 } else {
2698                                         oconnect = Session::AutoConnectOption (0);
2699                                 } 
2700                                 
2701                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2702                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2703                                 
2704                                 build_session (session_path,
2705                                                session_name,
2706                                                cchns,
2707                                                mchns,
2708                                                iconnect,
2709                                                oconnect,
2710                                                nphysin,
2711                                                nphysout, 
2712                                                engine->frame_rate() * 60 * 5);
2713                         }               
2714                 }
2715
2716         } while(response == Gtk::RESPONSE_HELP);
2717         m_new_session_dialog->hide_all();
2718 }
2719
2720 int
2721 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2722 {
2723         Session *new_session;
2724         int x;
2725         session_loaded = false;
2726         x = unload_session ();
2727
2728         if (x < 0) {
2729                 return -1;
2730         } else if (x > 0) {
2731                 return 0;
2732         }
2733
2734         /* if it already exists, we must have write access */
2735
2736         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2737                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2738 You do not have write access to this session.\n\
2739 This prevents the session from being loaded."));
2740                 return -1;
2741         }
2742
2743         try {
2744                 new_session = new Session (*engine, path, snap_name, mix_template);
2745         }
2746
2747         catch (...) {
2748
2749                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2750                 return -1;
2751         }
2752
2753         connect_to_session (new_session);
2754
2755         //if (engine->running()) {
2756         //mixer->show_window();
2757         //}
2758         session_loaded = true;
2759         return 0;
2760 }
2761
2762 int
2763 ARDOUR_UI::make_session_clean ()
2764 {
2765         if (session) {
2766                 session->set_clean ();
2767         }
2768
2769         return FALSE;
2770 }
2771
2772 int
2773 ARDOUR_UI::build_session (string path, string snap_name, 
2774                           uint32_t control_channels,
2775                           uint32_t master_channels, 
2776                           Session::AutoConnectOption input_connect,
2777                           Session::AutoConnectOption output_connect,
2778                           uint32_t nphysin,
2779                           uint32_t nphysout,
2780                           jack_nframes_t initial_length)
2781 {
2782         Session *new_session;
2783         int x;
2784
2785         session_loaded = false;
2786         x = unload_session ();
2787         if (x < 0) {
2788                 return -1;
2789         } else if (x > 0) {
2790                 return 0;
2791         }
2792         
2793         _session_is_new = true;
2794
2795         try {
2796                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2797                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2798         }
2799
2800         catch (...) {
2801
2802                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2803                 return -1;
2804         }
2805
2806         connect_to_session (new_session);
2807
2808         //if (engine->running()) {
2809         //mixer->show_window();
2810         //}
2811         session_loaded = true;
2812         return 0;
2813 }
2814
2815 void
2816 ARDOUR_UI::show ()
2817 {
2818         if (editor) {
2819                 editor->show_window ();
2820                 shown_flag = true;
2821         }
2822
2823         if (session && mixer) {
2824                 mixer->show_window ();
2825         }
2826         
2827         if (about) {
2828                 about->present ();
2829         }
2830 }
2831
2832 void
2833 ARDOUR_UI::show_splash ()
2834 {
2835         if (about == 0) {
2836                 about = new About();
2837         }
2838         about->present();
2839 }
2840
2841 void
2842 ARDOUR_UI::hide_splash ()
2843 {
2844         if (about) {
2845                 // about->hide();
2846         }
2847 }
2848
2849 void
2850 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2851 {
2852         size_t removed;
2853
2854         removed = rep.paths.size();
2855
2856         if (removed == 0) {
2857                 ArdourMessage msg (editor, X_("cleanupresults"),
2858                                    _("\
2859 No audio files were ready for cleanup\n\n\
2860 If this seems suprising, check for any existing\n\
2861 snapshots. These may still include regions that\n\
2862 require some unused files to continue to exist."));
2863                 return;
2864         } 
2865
2866         ArdourDialog results (_("ardour: cleanup"), true);
2867         
2868         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2869             CleanupResultsModelColumns() { 
2870                     add (visible_name);
2871                     add (fullpath);
2872             }
2873             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2874             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2875         };
2876
2877         
2878         Glib::RefPtr<Gtk::ListStore> results_model;
2879         CleanupResultsModelColumns results_columns;
2880         Gtk::TreeView results_display;
2881         
2882         results_model = ListStore::create (results_columns);
2883         results_display.set_model (results_model);
2884         results_display.append_column (list_title, results_columns.visible_name);
2885         results_display.set_headers_visible (true);
2886
2887         Gtk::ScrolledWindow list_scroller;
2888         Gtk::Label txt;
2889
2890         if (rep.space < 1048576.0f) {
2891                 if (removed > 1) {
2892                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2893                 } else {
2894                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2895                 }
2896         } else {
2897                 if (removed > 1) {
2898                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2899                 } else {
2900                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2901                 }
2902         }
2903
2904         results.get_vbox()->pack_start (txt, false, false);
2905         
2906         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2907                 TreeModel::Row row = *(results_model->append());
2908                 row[results_columns.visible_name] = *i;
2909                 row[results_columns.fullpath] = *i;
2910         }
2911         
2912         list_scroller.add (results_display);
2913         list_scroller.set_size_request (-1, 250);
2914         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2915         
2916         results.get_vbox()->pack_start (list_scroller, true, true);
2917         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2918         results.set_position (Gtk::WIN_POS_MOUSE);
2919
2920         results.run ();
2921 }
2922
2923 void
2924 ARDOUR_UI::cleanup ()
2925 {
2926         if (session == 0) {
2927                 /* shouldn't happen: menu item is insensitive */
2928                 return;
2929         }
2930
2931         ArdourDialog checker (_("ardour cleanup"));
2932         Gtk::Label label (_("\
2933 Cleanup is a destructive operation.\n\
2934 ALL undo/redo information will be lost if you cleanup.\n\
2935 Unused audio files will be moved to a \"dead sounds\" location."));
2936         
2937         checker.get_vbox()->pack_start (label, false, false);
2938         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2939         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2940
2941         checker.set_name (_("CleanupDialog"));
2942         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2943         checker.set_position (Gtk::WIN_POS_MOUSE);
2944
2945         switch (checker.run()) {
2946         case RESPONSE_ACCEPT:
2947                 break;
2948         default:
2949                 return;
2950         }
2951
2952         Session::cleanup_report rep;
2953
2954         editor->prepare_for_cleanup ();
2955
2956         if (session->cleanup_sources (rep)) {
2957                 return;
2958         }
2959
2960         display_cleanup_results (rep, 
2961                                  _("cleaned files"),
2962                                  _("\
2963 The following %1 %2 were not in use.\n\
2964 The next time you flush the wastebasket\n\
2965 it will release an additional %3 %4bytes\n\
2966 of disk space"
2967                                          ));
2968 }
2969
2970 void
2971 ARDOUR_UI::flush_trash ()
2972 {
2973         if (session == 0) {
2974                 /* shouldn't happen: menu item is insensitive */
2975                 return;
2976         }
2977
2978         Session::cleanup_report rep;
2979
2980         if (session->cleanup_trash_sources (rep)) {
2981                 return;
2982         }
2983
2984         display_cleanup_results (rep, 
2985                                  _("deleted file"),
2986                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2987 }
2988
2989 void
2990 ARDOUR_UI::add_route ()
2991 {
2992         int count;
2993
2994         if (!session) {
2995                 return;
2996         }
2997
2998         if (add_route_dialog == 0) {
2999                 add_route_dialog = new AddRouteDialog;
3000                 editor->ensure_float (*add_route_dialog);
3001         }
3002
3003         if (add_route_dialog->is_visible()) {
3004                 /* we're already doing this */
3005                 return;
3006         }
3007
3008         ResponseType r = (ResponseType) add_route_dialog->run ();
3009         
3010         add_route_dialog->hide();
3011
3012         switch (r) {
3013         case RESPONSE_ACCEPT:
3014                 break;
3015         default:
3016                 return;
3017                 break;
3018         }
3019
3020         if ((count = add_route_dialog->count()) <= 0) {
3021                 return;
3022         }
3023
3024         uint32_t input_chan = add_route_dialog->channels ();
3025         uint32_t output_chan;
3026         string name_template = add_route_dialog->name_template ();
3027         bool track = add_route_dialog->track ();
3028
3029         Session::AutoConnectOption oac = session->get_output_auto_connect();
3030
3031         if (oac & Session::AutoConnectMaster) {
3032                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3033         } else {
3034                 output_chan = input_chan;
3035         }
3036
3037         /* XXX do something with name template */
3038
3039         while (count) {
3040                 if (track) {
3041                         session_add_audio_track (input_chan, output_chan);
3042                 } else {
3043                         session_add_audio_bus (input_chan, output_chan);
3044                 }
3045                 --count;
3046                 
3047                 while (Main::events_pending()) {
3048                         Main::iteration ();
3049                 }
3050         }
3051 }
3052
3053 XMLNode*
3054 ARDOUR_UI::mixer_settings () const
3055 {
3056         XMLNode* node = 0;
3057
3058         if (session) {
3059                 node = session->instant_xml(X_("Mixer"), session->path());
3060         } else {
3061                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3062         }
3063
3064         if (!node) {
3065                 node = new XMLNode (X_("Mixer"));
3066         }
3067
3068         return node;
3069 }
3070
3071 XMLNode*
3072 ARDOUR_UI::editor_settings () const
3073 {
3074         XMLNode* node = 0;
3075
3076         if (session) {
3077                 node = session->instant_xml(X_("Editor"), session->path());
3078         } else {
3079                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3080         }
3081
3082         if (!node) {
3083                 node = new XMLNode (X_("Editor"));
3084         }
3085         return node;
3086 }
3087
3088 XMLNode*
3089 ARDOUR_UI::keyboard_settings () const
3090 {
3091         XMLNode* node = 0;
3092
3093         node = Config->extra_xml(X_("Keyboard"));
3094         
3095         if (!node) {
3096                 node = new XMLNode (X_("Keyboard"));
3097         }
3098         return node;
3099 }
3100
3101 void
3102 ARDOUR_UI::halt_on_xrun_message ()
3103 {
3104         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3105
3106         ArdourMessage msg (editor, X_("haltonxrun"),
3107                            _("Recording was stopped because your system could not keep up."));
3108 }
3109
3110 void 
3111 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3112 {
3113         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3114
3115         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3116                 delete *i;
3117         }
3118
3119         delete deletion_list;
3120 }
3121
3122 void
3123 ARDOUR_UI::disk_overrun_handler ()
3124 {
3125         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3126
3127         if (!have_disk_overrun_displayed) {
3128                 have_disk_overrun_displayed = true;
3129                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3130 The disk system on your computer\n\
3131 was not able to keep up with Ardour.\n\
3132 \n\
3133 Specifically, it failed to write data to disk\n\
3134 quickly enough to keep up with recording.\n"));
3135                 have_disk_overrun_displayed = false;
3136         }
3137 }
3138
3139 void
3140 ARDOUR_UI::disk_underrun_handler ()
3141 {
3142         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3143
3144         if (!have_disk_underrun_displayed) {
3145                 have_disk_underrun_displayed = true;
3146                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3147                         (_("The disk system on your computer\n\
3148 was not able to keep up with Ardour.\n\
3149 \n\
3150 Specifically, it failed to read data from disk\n\
3151 quickly enough to keep up with playback.\n")));
3152                 have_disk_underrun_displayed = false;
3153         } 
3154 }
3155
3156 void
3157 ARDOUR_UI::disk_underrun_message_gone ()
3158 {
3159         have_disk_underrun_displayed = false;
3160 }
3161
3162 void
3163 ARDOUR_UI::disk_overrun_message_gone ()
3164 {
3165         have_disk_underrun_displayed = false;
3166 }
3167
3168 int
3169 ARDOUR_UI::pending_state_dialog ()
3170 {
3171         ArdourDialog dialog ("pending state dialog");
3172         Label  message (_("\
3173 This session appears to have been in\n\
3174 middle of recording when ardour or\n\
3175 the computer was shutdown.\n\
3176 \n\
3177 Ardour can recover any captured audio for\n\
3178 you, or it can ignore it. Please decide\n\
3179 what you would like to do.\n"));
3180
3181         dialog.get_vbox()->pack_start (message);
3182         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3183         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3184
3185         dialog.set_position (WIN_POS_CENTER);
3186         dialog.show_all ();
3187         
3188         switch (dialog.run ()) {
3189         case RESPONSE_ACCEPT:
3190                 break;
3191         default:
3192                 return 1;
3193         }
3194
3195         return 0;
3196 }
3197         
3198         
3199 void
3200 ARDOUR_UI::disconnect_from_jack ()
3201 {
3202         if (engine) {
3203                 if( engine->disconnect_from_jack ()) {
3204                         ArdourMessage msg (editor, X_("nojack dialog"),
3205                                            _("Could not disconnect from JACK"));
3206                 }
3207
3208                 update_sample_rate (0);
3209         }
3210 }
3211
3212 void
3213 ARDOUR_UI::reconnect_to_jack ()
3214 {
3215         if (engine) {
3216                 if (engine->reconnect_to_jack ()) {
3217                         ArdourMessage msg (editor, X_("nojack dialog"),
3218                                            _("Could not reconnect to JACK"));
3219                 }
3220
3221                 update_sample_rate (0);
3222         }
3223 }
3224
3225 void
3226 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3227 {
3228         engine->request_buffer_size (nframes);
3229         update_sample_rate (0);
3230 }
3231
3232 int
3233 ARDOUR_UI::cmdline_new_session (string path)
3234 {
3235         if (path[0] != '/') {
3236                 char buf[PATH_MAX+1];
3237                 string str;
3238
3239                 getcwd (buf, sizeof (buf));
3240                 str = buf;
3241                 str += '/';
3242                 str += path;
3243                 path = str;
3244         }
3245
3246         new_session (false, path);
3247
3248         _will_create_new_session_automatically = false; /* done it */
3249         return FALSE; /* don't call it again */
3250 }