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