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