Exciting new Alt/h help key provided by sge (Georgy) with many thanks!
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mwindowgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "androidcontrol.h"
23 #include "awindowgui.h"
24 #include "awindow.h"
25 #include "bcdisplayinfo.h"
26 #include "bchash.h"
27 #include "bcsignals.h"
28 #include "clip.h"
29 #include "cwindowgui.h"
30 #include "cwindow.h"
31 #include "channelinfo.h"
32 #include "dbwindow.h"
33 #include "edit.h"
34 #include "editpopup.h"
35 #include "edits.h"
36 #include "edl.h"
37 #include "edlsession.h"
38 #include "filesystem.h"
39 #include "filexml.h"
40 #include "keyframepopup.h"
41 #include "keys.h"
42 #include "language.h"
43 #include "localsession.h"
44 #include "mainclock.h"
45 #include "maincursor.h"
46 #include "mainmenu.h"
47 #include "mainsession.h"
48 #include "mainundo.h"
49 #include "mbuttons.h"
50 #include "mtimebar.h"
51 #include "mwindowgui.h"
52 #include "mwindow.h"
53 #include "panedividers.h"
54 #include "patchbay.h"
55 #include "plugin.h"
56 #include "pluginpopup.h"
57 #include "pluginset.h"
58 #include "preferences.h"
59 #include "proxy.h"
60 #include "record.h"
61 #include "recordgui.h"
62 #include "renderengine.h"
63 #include "remotecontrol.h"
64 #include "resourcethread.h"
65 #include "samplescroll.h"
66 #include "shbtnprefs.h"
67 #include "statusbar.h"
68 #include "swindow.h"
69 #include "theme.h"
70 #include "trackcanvas.h"
71 #include "trackpopup.h"
72 #include "trackscroll.h"
73 #include "tracks.h"
74 #include "transitionpopup.h"
75 #include "vwindowgui.h"
76 #include "vwindow.h"
77 #include "wintv.h"
78 #include "x10tv.h"
79 #include "zoombar.h"
80
81 #define PANE_DRAG_MARGIN MAX(mwindow->theme->pane_w, mwindow->theme->pane_h)
82
83
84 // the main window uses its own private colormap for video
85 MWindowGUI::MWindowGUI(MWindow *mwindow)
86  : BC_Window(_(PROGRAM_NAME ": Program"),
87                 mwindow->session->mwindow_x, mwindow->session->mwindow_y,
88                 mwindow->session->mwindow_w, mwindow->session->mwindow_h,
89                 xS(100), yS(100), 1, 1, 1)
90 {
91         this->mwindow = mwindow;
92 //      samplescroll = 0;
93 //      trackscroll = 0;
94 //      cursor = 0;
95 //      patchbay = 0;
96 //      timebar = 0;
97 //      canvas = 0;
98         focused_pane = TOP_LEFT_PANE;
99         x_divider = 0;
100         y_divider = 0;
101         x_pane_drag = 0;
102         y_pane_drag = 0;
103         dragging_pane = 0;
104         drag_popup = 0;
105
106         render_engine = 0;
107         render_engine_id = -1;
108         for(int i = 0; i < TOTAL_PANES; i++)
109                 pane[i] = 0;
110
111         record = 0;
112         channel_info = 0;
113         swindow = 0;
114         db_window = 0;
115 // subwindows
116         mbuttons = 0;
117         statusbar = 0;
118         zoombar = 0;
119         mainclock = 0;
120         track_menu = 0;
121         edit_menu = 0;
122         plugin_menu = 0;
123         keyframe_menu = 0;
124         keyframe_hide = 0;
125         keyvalue_popup = 0;
126         transition_menu = 0;
127         remote_control = 0;
128         cwindow_remote_handler = 0;
129         record_remote_handler = 0;
130         android_control = 0;
131 // *** CONTEXT_HELP ***
132         context_help_set_keyword("Program Window");
133 }
134
135
136 MWindowGUI::~MWindowGUI()
137 {
138         delete android_control;
139         delete cwindow_remote_handler;
140         delete record_remote_handler;
141         delete remote_control;
142         delete keyvalue_popup;
143 //      delete samplescroll;
144 //      delete trackscroll;
145         for(int i = 0; i < TOTAL_PANES; i++)
146                 if(pane[i]) delete pane[i];
147 //      delete cursor;
148         delete render_engine;
149         delete resource_thread;
150         resource_pixmaps.remove_all_objects();
151         delete swindow;
152 #ifdef HAVE_DVB
153         delete channel_info;
154 #endif
155         delete db_window;
156         delete x_divider;
157         delete y_divider;
158 }
159
160 void MWindowGUI::create_objects()
161 {
162         lock_window("MWindowGUI::create_objects");
163         const int debug = 0;
164
165         resource_thread = new ResourceThread(mwindow);
166         resource_thread->create_objects();
167
168
169         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
170         set_icon(mwindow->theme->get_image("mwindow_icon"));
171         remote_control = new RemoteControl(this);
172         cwindow_remote_handler = 0;
173         record_remote_handler = 0;
174 #ifdef HAVE_X10TV
175 // should be first, use if plugged
176         if( !cwindow_remote_handler && mwindow->x10tv ) {
177                 cwindow_remote_handler = (RemoteHandler*)
178                         new X10TVCWindowHandler(mwindow->x10tv, remote_control);
179                 record_remote_handler = (RemoteHandler*)
180                         new X10TVRecordHandler(mwindow->x10tv, remote_control);
181         }
182 #endif
183 #ifdef HAVE_WINTV
184         if( !cwindow_remote_handler && mwindow->wintv ) {
185                 cwindow_remote_handler = (RemoteHandler*)
186                         new WinTVCWindowHandler(mwindow->wintv, remote_control);
187                 record_remote_handler = (RemoteHandler*)
188                         new WinTVRecordHandler(mwindow->wintv, remote_control);
189         }
190 #endif
191         mwindow->reset_android_remote();
192         if( !cwindow_remote_handler )
193                 cwindow_remote_handler = (RemoteHandler*)
194                         new CWindowKeyEvHandler(mwindow->gui->remote_control);
195         if( !record_remote_handler )
196                 record_remote_handler = (RemoteHandler*)
197                         new RecordKeyEvHandler(mwindow->gui->remote_control);
198         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
199
200         int x1 = get_w() - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
201         add_subwindow(mainshbtns = new MainShBtns(mwindow, x1, -1));
202         mainshbtns->load(mwindow->preferences);
203         int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
204         add_subwindow(stack_button = new StackButton(mwindow, x2, yS(2)));
205         add_subwindow(mainmenu = new MainMenu(mwindow, this, x2));
206         mainmenu->create_objects();
207         mwindow->theme->get_mwindow_sizes(this, get_w(), get_h());
208         mwindow->theme->draw_mwindow_bg(this);
209         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
210
211         add_subwindow(mbuttons = new MButtons(mwindow, this));
212         mbuttons->create_objects();
213         int y1 = mbuttons->get_y()+yS(2);
214         add_subwindow(proxy_toggle = new ProxyToggle(mwindow, mbuttons, x2, y1));
215         add_subwindow(ffmpeg_toggle = new FFMpegToggle(mwindow, mbuttons, x1, y1));
216
217         pane[TOP_LEFT_PANE] = new TimelinePane(mwindow,
218                 TOP_LEFT_PANE,
219                 mwindow->theme->mcanvas_x,
220                 mwindow->theme->mcanvas_y,
221                 mwindow->theme->mcanvas_w,
222                 mwindow->theme->mcanvas_h);
223         pane[TOP_LEFT_PANE]->create_objects();
224
225         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
226         add_subwindow(zoombar = new ZoomBar(mwindow, this));
227         zoombar->create_objects();
228
229
230         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
231         add_subwindow(statusbar = new StatusBar(mwindow, this));
232         statusbar->create_objects();
233
234
235
236         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
237         add_subwindow(mainclock = new MainClock(mwindow,
238                 mwindow->theme->mclock_x, mwindow->theme->mclock_y,
239                 mwindow->theme->mclock_w));
240         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
241         mainclock->update(0);
242
243
244
245 //      if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
246 //      cursor = new MainCursor(mwindow, this);
247 //      cursor->create_objects();
248
249
250         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
251         add_subwindow(track_menu = new TrackPopup(mwindow, this));
252         track_menu->create_objects();
253         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
254         add_subwindow(edit_menu = new EditPopup(mwindow, this));
255         edit_menu->create_objects();
256
257
258         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
259         add_subwindow(plugin_menu = new PluginPopup(mwindow, this));
260         plugin_menu->create_objects();
261
262
263         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
264         add_subwindow(keyframe_menu = new KeyframePopup(mwindow, this));
265         keyframe_menu->create_objects();
266         add_subwindow(keyframe_hide = new KeyframeHidePopup(mwindow, this));
267         keyframe_hide->create_objects();
268
269
270         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
271         add_subwindow(transition_menu = new TransitionPopup(mwindow, this));
272         transition_menu->create_objects();
273
274 #ifdef HAVE_DVB
275         channel_info = new ChannelInfo(mwindow);
276 #endif
277 #ifdef HAVE_COMMERCIAL
278         db_window = new DbWindow(mwindow);
279 #endif
280         swindow = new SWindow(mwindow);
281
282         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
283
284         add_subwindow(pane_button = new PaneButton(mwindow,
285                 get_w() - mwindow->theme->get_image_set("pane")[0]->get_w(),
286                 mwindow->theme->mzoom_y + 1 - mwindow->theme->get_image_set("pane")[0]->get_h()));
287
288         pane[TOP_LEFT_PANE]->canvas->activate();
289
290         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
291         unlock_window();
292 }
293
294 void MWindowGUI::redraw_time_dependancies()
295 {
296         zoombar->redraw_time_dependancies();
297         for(int i = 0; i < TOTAL_PANES; i++)
298                 if(pane[i] && pane[i]->timebar) pane[i]->timebar->update(0);
299         mainclock->update(mwindow->edl->local_session->get_selectionstart(1));
300 }
301
302 int MWindowGUI::focus_in_event()
303 {
304         for(int i = 0; i < TOTAL_PANES; i++)
305                 if(pane[i] && pane[i]->cursor) pane[i]->cursor->focus_in_event();
306         return 1;
307 }
308
309 int MWindowGUI::focus_out_event()
310 {
311         for(int i = 0; i < TOTAL_PANES; i++)
312                 if(pane[i] && pane[i]->cursor) pane[i]->cursor->focus_out_event();
313         return 1;
314 }
315
316
317 int MWindowGUI::resize_event(int w, int h)
318 {
319 //printf("MWindowGUI::resize_event %d\n", __LINE__);
320         mwindow->session->mwindow_w = w;
321         mwindow->session->mwindow_h = h;
322         int x1 = w - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
323         mainshbtns->reposition_window(x1, -1);
324         int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
325         stack_button->reposition_window(x2, stack_button->get_y());
326         mainmenu->resize_event(x2, mainmenu->get_h());
327         mwindow->theme->get_mwindow_sizes(this, w, h);
328         mwindow->theme->draw_mwindow_bg(this);
329         mbuttons->resize_event();
330         int y1 = mbuttons->get_y()+yS(2);
331         proxy_toggle->reposition_window(x2, y1);
332         ffmpeg_toggle->reposition_window(x1, y1);
333         statusbar->resize_event();
334         zoombar->resize_event();
335
336         resource_thread->stop_draw(1);
337
338         if(total_panes() > 1)
339         {
340                 if(horizontal_panes())
341                 {
342 //                      printf("MWindowGUI::resize_event %d %d %d\n",
343 //                              __LINE__,
344 //                              pane[TOP_RIGHT_PANE]->x,
345 //                              mwindow->theme->mcanvas_w -
346 //                                      BC_ScrollBar::get_span(SCROLL_VERT) -
347 //                                      PANE_DRAG_MARGIN);
348                         if(pane[TOP_RIGHT_PANE]->x >= mwindow->theme->mcanvas_w -
349                                 BC_ScrollBar::get_span(SCROLL_VERT) -
350                                 PANE_DRAG_MARGIN)
351                         {
352                                 delete_x_pane(pane[TOP_RIGHT_PANE]->x);
353                                 mwindow->edl->local_session->x_pane = -1;
354                         }
355                 }
356                 else
357                 if(vertical_panes())
358                 {
359                         if(pane[BOTTOM_LEFT_PANE]->y >= mwindow->theme->mzoom_y -
360                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
361                                 PANE_DRAG_MARGIN)
362                         {
363                                 delete_y_pane(pane[BOTTOM_LEFT_PANE]->y);
364                                 mwindow->edl->local_session->y_pane = -1;
365                         }
366                 }
367                 else
368                 {
369                         if(pane[TOP_RIGHT_PANE]->x >= mwindow->theme->mcanvas_w -
370                                         BC_ScrollBar::get_span(SCROLL_VERT) -
371                                         PANE_DRAG_MARGIN)
372                         {
373                                 delete_x_pane(pane[TOP_RIGHT_PANE]->x);
374                                 mwindow->edl->local_session->x_pane = -1;
375                         }
376
377                         if(pane[BOTTOM_LEFT_PANE]->y >= mwindow->theme->mzoom_y -
378                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
379                                 PANE_DRAG_MARGIN)
380                         {
381                                 delete_y_pane(pane[BOTTOM_LEFT_PANE]->y);
382                                 mwindow->edl->local_session->y_pane = -1;
383                         }
384                 }
385         }
386
387         if(total_panes() == 1)
388         {
389                 pane[TOP_LEFT_PANE]->resize_event(
390                         mwindow->theme->mcanvas_x,
391                         mwindow->theme->mcanvas_y,
392                         mwindow->theme->mcanvas_w,
393                         mwindow->theme->mcanvas_h);
394         }
395         else
396         if(horizontal_panes())
397         {
398                 pane[TOP_LEFT_PANE]->resize_event(
399                         pane[TOP_LEFT_PANE]->x,
400                         pane[TOP_LEFT_PANE]->y,
401                         pane[TOP_LEFT_PANE]->w,
402                         mwindow->theme->mcanvas_h);
403                 pane[TOP_RIGHT_PANE]->resize_event(
404                         pane[TOP_RIGHT_PANE]->x,
405                         pane[TOP_RIGHT_PANE]->y,
406                         mwindow->theme->mcanvas_w - pane[TOP_RIGHT_PANE]->x,
407                         mwindow->theme->mcanvas_h);
408         }
409         else
410         if(vertical_panes())
411         {
412                 pane[TOP_LEFT_PANE]->resize_event(
413                         pane[TOP_LEFT_PANE]->x,
414                         pane[TOP_LEFT_PANE]->y,
415                         mwindow->theme->mcanvas_w,
416                         pane[TOP_LEFT_PANE]->h);
417                 pane[BOTTOM_LEFT_PANE]->resize_event(
418                         pane[BOTTOM_LEFT_PANE]->x,
419                         pane[BOTTOM_LEFT_PANE]->y,
420                         mwindow->theme->mcanvas_w,
421                         mwindow->theme->mcanvas_y +
422                                 mwindow->theme->mcanvas_h -
423                                 pane[BOTTOM_LEFT_PANE]->y);
424         }
425         else
426         {
427                 pane[TOP_LEFT_PANE]->resize_event(
428                         pane[TOP_LEFT_PANE]->x,
429                         pane[TOP_LEFT_PANE]->y,
430                         pane[TOP_LEFT_PANE]->w,
431                         pane[TOP_LEFT_PANE]->h);
432                 pane[TOP_RIGHT_PANE]->resize_event(
433                         pane[TOP_RIGHT_PANE]->x,
434                         pane[TOP_RIGHT_PANE]->y,
435                         mwindow->theme->mcanvas_w - pane[TOP_RIGHT_PANE]->x,
436                         pane[TOP_RIGHT_PANE]->h);
437                 pane[BOTTOM_LEFT_PANE]->resize_event(
438                         pane[BOTTOM_LEFT_PANE]->x,
439                         pane[BOTTOM_LEFT_PANE]->y,
440                         pane[BOTTOM_LEFT_PANE]->w,
441                         mwindow->theme->mcanvas_y +
442                                 mwindow->theme->mcanvas_h -
443                                 pane[BOTTOM_LEFT_PANE]->y);
444                 pane[BOTTOM_RIGHT_PANE]->resize_event(
445                         pane[BOTTOM_RIGHT_PANE]->x,
446                         pane[BOTTOM_RIGHT_PANE]->y,
447                         mwindow->theme->mcanvas_w -
448                                 pane[BOTTOM_RIGHT_PANE]->x,
449                         mwindow->theme->mcanvas_y +
450                                 mwindow->theme->mcanvas_h -
451                                 pane[BOTTOM_RIGHT_PANE]->y);
452         }
453
454         update_pane_dividers();
455         pane_button->reposition_window(w - mwindow->theme->get_image_set("pane")[0]->get_w(),
456                 mwindow->theme->mzoom_y + 1 - mwindow->theme->get_image_set("pane")[0]->get_h());
457         resource_thread->start_draw();
458
459         flash(1);
460         return 0;
461 }
462
463 int MWindowGUI::total_panes()
464 {
465         int total = 0;
466         for(int i = 0; i < TOTAL_PANES; i++)
467                 if(pane[i]) total++;
468         return total;
469 }
470
471 int MWindowGUI::vertical_panes()
472 {
473         return total_panes() == 2 &&
474                 pane[TOP_LEFT_PANE] &&
475                 pane[BOTTOM_LEFT_PANE];
476 }
477
478 int MWindowGUI::horizontal_panes()
479 {
480         return total_panes() == 2 &&
481                 pane[TOP_LEFT_PANE] &&
482                 pane[TOP_RIGHT_PANE];
483 }
484
485 TimelinePane* MWindowGUI::get_focused_pane()
486 {
487         if(pane[focused_pane]) return pane[focused_pane];
488         for(int i = 0; i < TOTAL_PANES; i++)
489         {
490                 if(pane[i]) return pane[i];
491         }
492         return 0;
493 }
494
495 void MWindowGUI::activate_timeline()
496 {
497         if(pane[focused_pane])
498         {
499                 pane[focused_pane]->activate();
500         }
501         else
502         {
503                 for(int i = 0; i < TOTAL_PANES; i++)
504                 {
505                         if(pane[i])
506                         {
507                                 pane[i]->activate();
508                                 return;
509                         }
510                 }
511         }
512 }
513
514 void MWindowGUI::deactivate_timeline()
515 {
516         for(int i = 0; i < TOTAL_PANES; i++)
517         {
518                 if(pane[i] && pane[i]->canvas)
519                 {
520                         pane[i]->canvas->deactivate();
521                 }
522         }
523 }
524
525 void MWindowGUI::update_title(char *path)
526 {
527         FileSystem fs;
528         char filename[BCTEXTLEN], string[BCTEXTLEN];
529         fs.extract_name(filename, path);
530         sprintf(string, _(PROGRAM_NAME ": %s"), filename);
531         set_title(string);
532 //printf("MWindowGUI::update_title %s\n", string);
533         flush();
534 }
535
536 void MWindowGUI::draw_overlays(int flash_it)
537 {
538         for(int i = 0; i < TOTAL_PANES; i++)
539         {
540                 if(pane[i] && pane[i]->canvas)
541                 {
542                         pane[i]->canvas->draw_overlays();
543                         if(flash_it) pane[i]->canvas->flash();
544                 }
545         }
546 }
547
548 void MWindowGUI::update_timebar(int flush_it)
549 {
550         for(int i = 0; i < TOTAL_PANES; i++)
551         {
552                 if(pane[i] && pane[i]->timebar)
553                 {
554                         pane[i]->timebar->update(flush_it);
555                 }
556         }
557 }
558
559 void MWindowGUI::update_timebar_highlights()
560 {
561         for(int i = 0; i < TOTAL_PANES; i++)
562         {
563                 if(pane[i] && pane[i]->timebar)
564                 {
565                         pane[i]->timebar->update_highlights();
566                 }
567         }
568 }
569
570
571 void MWindowGUI::update_patchbay()
572 {
573         for(int i = 0; i < TOTAL_PANES; i++)
574         {
575                 if(pane[i] && pane[i]->patchbay)
576                 {
577                         pane[i]->patchbay->update();
578                 }
579         }
580 }
581
582 void MWindowGUI::update_proxy_toggle()
583 {
584         int value = mwindow->edl->session->proxy_state == PROXY_ACTIVE ? 0 : 1;
585         proxy_toggle->set_value(value);
586         if( mwindow->edl->session->proxy_state == PROXY_INACTIVE )
587                 proxy_toggle->hide();
588         else
589                 proxy_toggle->show();
590 }
591
592 void MWindowGUI::update_plugintoggles()
593 {
594         for(int i = 0; i < TOTAL_PANES; i++)
595         {
596                 if(pane[i] && pane[i]->canvas)
597                 {
598                         pane[i]->canvas->refresh_plugintoggles();
599                 }
600         }
601
602 }
603
604 void MWindowGUI::draw_indexes(Indexable *indexable)
605 {
606         for(int i = 0; i < TOTAL_PANES; i++)
607         {
608                 if(pane[i] && pane[i]->canvas)
609                 {
610                         pane[i]->canvas->draw_indexes(indexable);
611                 }
612         }
613 }
614
615 void MWindowGUI::draw_canvas(int redraw, int hide_cursor)
616 {
617         resource_thread->stop_draw(0);
618         int mode = NORMAL_DRAW;
619         if( redraw ) {
620                 mode = FORCE_REDRAW;
621                 resource_pixmaps.remove_all_objects();
622         }
623         for(int i = 0; i < TOTAL_PANES; i++) {
624                 if( pane[i] )
625                         pane[i]->canvas->draw(mode, hide_cursor);
626         }
627
628         resource_thread->start_draw();
629 }
630
631 void MWindowGUI::flash_canvas(int flush)
632 {
633         for(int i = 0; i < TOTAL_PANES; i++)
634         {
635                 if(pane[i] && pane[i]->canvas)
636                 {
637                         pane[i]->canvas->flash(flush);
638                 }
639         }
640 }
641
642 int MWindowGUI::show_window(int flush)
643 {
644         int ret = BC_WindowBase::show_window(flush);
645         stack_button->update();
646         update_proxy_toggle();
647         return ret;
648 }
649
650 void MWindowGUI::draw_cursor(int do_plugintoggles)
651 {
652         for(int i = 0; i < TOTAL_PANES; i++)
653         {
654                 if(pane[i] && pane[i]->cursor)
655                 {
656                         pane[i]->cursor->draw(do_plugintoggles);
657                 }
658         }
659 }
660
661 void MWindowGUI::show_cursor(int do_plugintoggles)
662 {
663         for(int i = 0; i < TOTAL_PANES; i++)
664         {
665                 if(pane[i] && pane[i]->cursor)
666                 {
667                         pane[i]->cursor->show(do_plugintoggles);
668                 }
669         }
670 }
671
672 void MWindowGUI::hide_cursor(int do_plugintoggles)
673 {
674         for(int i = 0; i < TOTAL_PANES; i++)
675         {
676                 if(pane[i] && pane[i]->cursor)
677                 {
678                         pane[i]->cursor->hide(do_plugintoggles);
679                 }
680         }
681 }
682
683 void MWindowGUI::update_cursor()
684 {
685         for(int i = 0; i < TOTAL_PANES; i++)
686         {
687                 if(pane[i] && pane[i]->cursor)
688                 {
689                         pane[i]->cursor->update();
690                 }
691         }
692 }
693
694 void MWindowGUI::set_playing_back(int value)
695 {
696         for(int i = 0; i < TOTAL_PANES; i++)
697         {
698                 if(pane[i] && pane[i]->cursor)
699                 {
700                         pane[i]->cursor->playing_back = value;
701                 }
702         }
703 }
704
705 void MWindowGUI::update_scrollbars(int flush)
706 {
707         for(int i = 0; i < TOTAL_PANES; i++)
708         {
709                 if(pane[i])
710                 {
711                         pane[i]->update(1, NO_DRAW, 0, 0);
712                 }
713         }
714         if(flush) this->flush();
715 }
716
717 void MWindowGUI::reset_meters()
718 {
719         for(int i = 0; i < TOTAL_PANES; i++)
720         {
721                 if(pane[i] && pane[i]->patchbay)
722                 {
723                         pane[i]->patchbay->reset_meters();
724                 }
725         }
726 }
727
728 void MWindowGUI::stop_meters()
729 {
730         for(int i = 0; i < TOTAL_PANES; i++)
731         {
732                 if(pane[i] && pane[i]->patchbay)
733                 {
734                         pane[i]->patchbay->stop_meters();
735                 }
736         }
737 }
738
739 void MWindowGUI::update_meters(ArrayList<double> *module_levels)
740 {
741         for(int i = 0; i < TOTAL_PANES; i++)
742         {
743                 if(pane[i] && pane[i]->patchbay)
744                 {
745                         pane[i]->patchbay->update_meters(module_levels);
746                 }
747         }
748 }
749
750 void MWindowGUI::set_editing_mode(int flush)
751 {
752         for(int i = 0; i < TOTAL_PANES; i++)
753         {
754                 if(pane[i] && pane[i]->canvas)
755                 {
756                         pane[i]->canvas->update_cursor(flush);
757                 }
758         }
759 }
760
761 void MWindowGUI::set_meter_format(int mode, int min, int max)
762 {
763         for(int i = 0; i < TOTAL_PANES; i++)
764         {
765                 if(pane[i] && pane[i]->patchbay)
766                 {
767                         pane[i]->patchbay->set_meter_format(mode, min, max);
768                 }
769         }
770 }
771
772 void MWindowGUI::update(int scrollbars,
773         int do_canvas,
774         int timebar,
775         int zoombar,
776         int patchbay,
777         int clock,
778         int buttonbar)
779 {
780         const int debug = 0;
781         if(debug) PRINT_TRACE
782
783
784
785         mwindow->edl->tracks->update_y_pixels(mwindow->theme);
786
787         if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
788                 resource_thread->stop_draw(1);
789
790         if( do_canvas == FORCE_REDRAW )
791                 resource_pixmaps.remove_all_objects();
792
793         for(int i = 0; i < TOTAL_PANES; i++)
794         {
795                 if(pane[i]) pane[i]->update(scrollbars,
796                         do_canvas,
797                         timebar,
798                         patchbay);
799         }
800
801         if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
802                 resource_thread->start_draw();
803
804 //      if(scrollbars) this->get_scrollbars(0);
805 //      if(timebar) this->timebar->update(0);
806         if(zoombar) this->zoombar->update();
807 //      if(patchbay) this->patchbay->update();
808         if(clock) this->mainclock->update(
809                 mwindow->edl->local_session->get_selectionstart(1));
810         if(debug) PRINT_TRACE
811
812
813
814 //      if(do_canvas)
815 //      {
816 //              this->canvas->draw(do_canvas);
817 //              this->cursor->show();
818 //              this->canvas->flash(0);
819 // Activate causes the menubar to deactivate.  Don't want this for
820 // picon thread.
821 //              if(canvas != IGNORE_THREAD) this->canvas->activate();
822 //      }
823         if(debug) PRINT_TRACE
824
825
826
827         if(buttonbar) mbuttons->update();
828         if(debug) PRINT_TRACE
829
830 // Can't age if the cache called this to draw missing picons
831 // or the GUI is updating the status of the draw toggle.
832         if( do_canvas != FORCE_REDRAW && do_canvas != IGNORE_THREAD ) {
833                 unlock_window();
834                 mwindow->age_caches();
835                 lock_window("MWindowGUI::update");
836         }
837
838         flush();
839         if(debug) PRINT_TRACE
840 }
841
842 int MWindowGUI::visible(int64_t x1, int64_t x2, int64_t view_x1, int64_t view_x2)
843 {
844         return (x1 >= view_x1 && x1 < view_x2) ||
845                 (x2 > view_x1 && x2 <= view_x2) ||
846                 (x1 <= view_x1 && x2 >= view_x2);
847 }
848
849
850 void MWindowGUI::show_message(const char *message, int msg_color, int bar_color)
851 {
852         statusbar->show_message(message, msg_color, bar_color);
853 }
854
855 void MWindowGUI::update_default_message()
856 {
857         statusbar->update_default_message();
858 }
859
860 void MWindowGUI::reset_default_message()
861 {
862         statusbar->reset_default_message();
863 }
864
865 void MWindowGUI::default_message()
866 {
867         statusbar->default_message();
868 }
869
870 // Drag motion called from other window
871 int MWindowGUI::drag_motion()
872 {
873         if(get_hidden()) return 0;
874
875         Track *over_track = 0;
876         Edit *over_edit = 0;
877         PluginSet *over_pluginset = 0;
878         Plugin *over_plugin = 0;
879         int redraw = 0;
880
881         if(drag_popup)
882         {
883                 drag_popup->cursor_motion_event();
884         }
885
886
887 // there's no point in drawing highlights has until drag operation has been set
888         if (!mwindow->session->current_operation)
889                 return 0;
890
891         for(int i = 0; i < TOTAL_PANES; i++)
892         {
893                 if(pane[i] && pane[i]->canvas)
894                         pane[i]->canvas->drag_motion(&over_track, &over_edit,
895                                         &over_pluginset, &over_plugin);
896         }
897
898         if(mwindow->session->track_highlighted != over_track)
899         {
900                 mwindow->session->track_highlighted = over_track;
901                 redraw = 1;
902         }
903
904         if(mwindow->session->edit_highlighted != over_edit)
905         {
906                 mwindow->session->edit_highlighted = over_edit;
907                 redraw = 1;
908         }
909
910         if(mwindow->session->pluginset_highlighted != over_pluginset)
911         {
912                 mwindow->session->pluginset_highlighted = over_pluginset;
913                 redraw = 1;
914         }
915
916         if(mwindow->session->plugin_highlighted != over_plugin)
917         {
918                 mwindow->session->plugin_highlighted = over_plugin;
919                 redraw = 1;
920         }
921
922         if( mwindow->session->current_operation == DRAG_ASSET ||
923             mwindow->session->current_operation == DRAG_EDIT ||
924             mwindow->session->current_operation == DRAG_GROUP ||
925             mwindow->session->current_operation == DRAG_AEFFECT_COPY ||
926             mwindow->session->current_operation == DRAG_VEFFECT_COPY ) {
927                 redraw = 1;
928         }
929
930
931 // printf("drag_motion %d %d over_track=%p over_edit=%p\n",
932 // __LINE__,
933 // redraw,
934 // over_track,
935 // over_edit);
936         if(redraw)
937         {
938                 lock_window("MWindowGUI::drag_motion");
939                 draw_overlays(1);
940                 unlock_window();
941         }
942         return 0;
943 }
944
945 int MWindowGUI::drag_stop()
946 {
947         if(get_hidden()) return 0;
948         int result = 0, redraw = 0;
949
950         for(int i = 0; i < TOTAL_PANES; i++)
951         {
952                 if(pane[i] && pane[i]->canvas)
953                         result |= pane[i]->canvas->drag_stop(&redraw);
954         }
955         mwindow->edl->optimize();
956
957 // since we don't have subwindows we have to terminate any drag operation
958         if(result)
959         {
960                 if (mwindow->session->track_highlighted
961                         || mwindow->session->edit_highlighted
962                         || mwindow->session->plugin_highlighted
963                         || mwindow->session->pluginset_highlighted)
964                         redraw = 1;
965                 mwindow->session->track_highlighted = 0;
966                 mwindow->session->edit_highlighted = 0;
967                 mwindow->session->plugin_highlighted = 0;
968                 mwindow->session->pluginset_highlighted = 0;
969                 mwindow->session->current_operation = NO_OPERATION;
970         }
971
972
973 //printf("MWindowGUI::drag_stop %d %d\n", redraw, mwindow->session->current_operation);
974         if(redraw)
975         {
976                 mwindow->edl->tracks->update_y_pixels(mwindow->theme);
977                 update_scrollbars(0);
978                 update_patchbay();
979                 draw_canvas(1, 1);
980                 update_cursor();
981                 flash_canvas(1);
982         }
983
984         if(drag_popup)
985         {
986                 delete drag_popup;
987                 drag_popup = 0;
988         }
989         return result;
990 }
991
992 void MWindowGUI::default_positions()
993 {
994 //printf("MWindowGUI::default_positions 1\n");
995         VWindow *vwindow = mwindow->vwindows.size() > DEFAULT_VWINDOW ?
996                 mwindow->vwindows.get(DEFAULT_VWINDOW) : 0;
997         if( vwindow && !vwindow->is_running() ) vwindow = 0;
998         if( vwindow ) vwindow->gui->lock_window("MWindowGUI::default_positions");
999         mwindow->cwindow->gui->lock_window("MWindowGUI::default_positions");
1000         mwindow->awindow->gui->lock_window("MWindowGUI::default_positions");
1001
1002 // printf("MWindowGUI::default_positions 1 %d %d %d %d\n", mwindow->session->vwindow_x,
1003 // mwindow->session->vwindow_y,
1004 // mwindow->session->vwindow_w,
1005 // mwindow->session->vwindow_h);
1006         reposition_window(mwindow->session->mwindow_x,
1007                 mwindow->session->mwindow_y,
1008                 mwindow->session->mwindow_w,
1009                 mwindow->session->mwindow_h);
1010         if( vwindow ) vwindow->gui->reposition_window(mwindow->session->vwindow_x,
1011                 mwindow->session->vwindow_y,
1012                 mwindow->session->vwindow_w,
1013                 mwindow->session->vwindow_h);
1014         mwindow->cwindow->gui->reposition_window(mwindow->session->cwindow_x,
1015                 mwindow->session->cwindow_y,
1016                 mwindow->session->cwindow_w,
1017                 mwindow->session->cwindow_h);
1018         mwindow->awindow->gui->reposition_window(mwindow->session->awindow_x,
1019                 mwindow->session->awindow_y,
1020                 mwindow->session->awindow_w,
1021                 mwindow->session->awindow_h);
1022 //printf("MWindowGUI::default_positions 1\n");
1023
1024         resize_event(mwindow->session->mwindow_w,
1025                 mwindow->session->mwindow_h);
1026 //printf("MWindowGUI::default_positions 1\n");
1027         if( vwindow ) vwindow->gui->resize_event(mwindow->session->vwindow_w,
1028                 mwindow->session->vwindow_h);
1029 //printf("MWindowGUI::default_positions 1\n");
1030         mwindow->cwindow->gui->resize_event(mwindow->session->cwindow_w,
1031                 mwindow->session->cwindow_h);
1032 //printf("MWindowGUI::default_positions 1\n");
1033         mwindow->awindow->gui->resize_event(mwindow->session->awindow_w,
1034                 mwindow->session->awindow_h);
1035
1036 //printf("MWindowGUI::default_positions 1\n");
1037
1038         flush();
1039         if( vwindow ) vwindow->gui->flush();
1040         mwindow->cwindow->gui->flush();
1041         mwindow->awindow->gui->flush();
1042
1043         if( vwindow ) vwindow->gui->unlock_window();
1044         mwindow->cwindow->gui->unlock_window();
1045         mwindow->awindow->gui->unlock_window();
1046 //printf("MWindowGUI::default_positions 2\n");
1047         mwindow->tile_mixers();
1048 }
1049
1050
1051 int MWindowGUI::repeat_event(int64_t duration)
1052 {
1053 // if(duration == 100)
1054 // mwindow->sync_parameters(CHANGE_ALL);
1055         int result = 0;
1056         for(int i = 0; i < TOTAL_PANES; i++)
1057         {
1058                 if(pane[i] && pane[i]->cursor)
1059                         result = pane[i]->cursor->repeat_event(duration);
1060         }
1061         return result;
1062 }
1063
1064
1065 int MWindowGUI::translation_event()
1066 {
1067 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
1068         mwindow->session->mwindow_x = get_x();
1069         mwindow->session->mwindow_y = get_y();
1070         return 0;
1071 }
1072
1073
1074 int MWindowGUI::save_defaults(BC_Hash *defaults)
1075 {
1076         defaults->update("MWINDOWWIDTH", get_w());
1077         defaults->update("MWINDOWHEIGHT", get_h());
1078         mainmenu->save_defaults(defaults);
1079         BC_WindowBase::save_defaults(defaults);
1080         return 0;
1081 }
1082
1083 int MWindowGUI::keypress_event()
1084 {
1085 //printf("MWindowGUI::keypress_event 1 %d\n", get_keypress());
1086         int result = mbuttons->keypress_event();
1087         if( result ) return result;
1088
1089         Track *this_track = 0, *first_track = 0;
1090         int packed = 0, overwrite = 0, plugins = 0;
1091         double position = 0;
1092
1093         switch( get_keypress() ) {
1094         case 'A':
1095                 if( !alt_down() ) {
1096                         if( !ctrl_down() || !shift_down() ) break;
1097                         mwindow->edl->tracks->clear_selected_edits();
1098                         draw_overlays(1);
1099                         result = 1;
1100                         break;
1101                 } // fall thru
1102         case 'a':
1103                 if( !alt_down() ) break;
1104                 stop_transport("MWindowGUI::keypress_event 1");
1105                 mwindow->nearest_auto_keyframe(shift_down(),
1106                         !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
1107                 result = 1;
1108                 break;
1109
1110         case '\'':
1111                 if( ctrl_down() && alt_down() ) {
1112                         mwindow->select_edits(1);
1113                         result = 1;
1114                 }
1115                 break;
1116
1117         case 'e':
1118                 if( ctrl_down() || alt_down() ) break;
1119                 mwindow->toggle_editing_mode();
1120                 result = 1;
1121                 break;
1122
1123         case 'k': case 'K':
1124                 if( alt_down() ) break;
1125                 stop_transport("MWindowGUI::keypress_event 2");
1126                 mwindow->nearest_plugin_keyframe(shift_down(),
1127                         !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
1128                 result = 1;
1129                 break;
1130
1131         case 'C':
1132                 packed = 1;
1133         case 'c':
1134                 if( !ctrl_down() || alt_down() ) break;
1135                 mwindow->selected_edits_to_clipboard(packed);
1136                 result = 1;
1137                 break;
1138         case 'P':
1139                 plugins = 1;
1140         case 'b':
1141                 overwrite = -1; // fall thru
1142         case 'v':
1143                 if( !ctrl_down() || alt_down() ) break;
1144                 if( mwindow->session->current_operation == DROP_TARGETING ) {
1145                         mwindow->session->current_operation = NO_OPERATION;
1146                         mwindow->gui->set_editing_mode(1);
1147                         int pane_no = 0;
1148                         for( ; pane_no<TOTAL_PANES; ++pane_no  ) {
1149                                 if( !pane[pane_no] ) continue;
1150                                 first_track = pane[pane_no]->over_track();
1151                                 if( first_track ) break;
1152                         }
1153                         if( first_track ) {
1154                                 int cursor_x = pane[pane_no]->canvas->get_relative_cursor_x();
1155                                 position = mwindow->edl->get_cursor_position(cursor_x, pane_no);
1156                         }
1157                 }
1158                 else
1159                         position = mwindow->edl->local_session->get_selectionstart();
1160                 if( !plugins )
1161                         mwindow->paste(position, first_track, 0, overwrite);
1162                 else
1163                         mwindow->paste_clipboard(first_track, position, 1, 0, 1, 1, 1);
1164                 mwindow->edl->tracks->clear_selected_edits();
1165                 draw_overlays(1);
1166                 result = 1;
1167                 break;
1168         case 'M':
1169                 mwindow->cut_selected_edits(0, 1);
1170                 result = 1;
1171                 break;
1172         case BACKSPACE:
1173         case 'm':
1174                 mwindow->cut_selected_edits(0, 0);
1175                 result = 1;
1176                 break;
1177         case 'z':
1178                 if( !alt_down() ) {
1179                         // z and ctrl-z both are undo, z mainmenu item
1180                         if( mwindow->session->current_operation == NO_OPERATION )
1181                                 mwindow->undo_entry(this);
1182                         result = 1;
1183                 }
1184                 else if( ctrl_down() ) {
1185                         mwindow->cut_selected_edits(1, 1);
1186                         result = 1;
1187                 }
1188                 break;
1189         case 'x':
1190                 if( !ctrl_down() || alt_down() ) break;
1191                 mwindow->cut_selected_edits(1, 0);
1192                 result = 1;
1193                 break;
1194
1195         case '1' ... '8':
1196                 if( !alt_down() || shift_down() ) break;
1197                 if( !mwindow->select_asset(get_keypress()-'1',1) )
1198                         result = 1;
1199                 break;
1200
1201         case LEFT:
1202                 if( !ctrl_down() ) {
1203                         if( alt_down() ) {
1204                                 stop_transport("MWindowGUI::keypress_event 1");
1205                                 mwindow->prev_edit_handle(shift_down());
1206                         }
1207                         else
1208                                 mwindow->move_left();
1209                         result = 1;
1210                 }
1211                 break;
1212
1213         case ',':
1214                 if( !ctrl_down() && !alt_down() ) {
1215                         mwindow->move_left();
1216                         result = 1;
1217                 }
1218                 break;
1219
1220         case RIGHT:
1221                 if( !ctrl_down() ) {
1222                         if( alt_down() ) {
1223                                 stop_transport("MWindowGUI::keypress_event 2");
1224                                 mwindow->next_edit_handle(shift_down());
1225                         }
1226                         else
1227                                 mwindow->move_right();
1228                         result = 1;
1229                 }
1230                 break;
1231
1232         case '.':
1233                 if( !ctrl_down() && !alt_down() ) {
1234                         mwindow->move_right();
1235                         result = 1;
1236                 }
1237                 break;
1238
1239         case UP:
1240                 if( ctrl_down() && !alt_down() )
1241                         mwindow->expand_y();
1242                 else if( !ctrl_down() && alt_down() )
1243                         mwindow->expand_autos(0,1,1);
1244                 else if( ctrl_down() && alt_down() )
1245                         mwindow->expand_autos(1,1,1);
1246                 else
1247                         mwindow->expand_sample();
1248                 result = 1;
1249                 break;
1250
1251         case DOWN:
1252                 if( ctrl_down() && !alt_down() )
1253                         mwindow->zoom_in_y();
1254                 else if( !ctrl_down() && alt_down() )
1255                         mwindow->shrink_autos(0,1,1);
1256                 else if( ctrl_down() && alt_down() )
1257                         mwindow->shrink_autos(1,1,1);
1258                 else
1259                         mwindow->zoom_in_sample();
1260                 result = 1;
1261                 break;
1262
1263         case PGUP:
1264                 if( !ctrl_down() )
1265                         mwindow->move_up();
1266                 else
1267                         mwindow->expand_t();
1268                 result = 1;
1269                 break;
1270
1271         case PGDN:
1272                 if( !ctrl_down() )
1273                         mwindow->move_down();
1274                 else
1275                         mwindow->zoom_in_t();
1276                 result = 1;
1277                 break;
1278
1279         case TAB:
1280         case LEFTTAB:
1281                 for( int i=0; i<TOTAL_PANES; ++i ) {
1282                         if( !pane[i] ) continue;
1283                         if( (this_track = pane[i]->over_track()) != 0 ) break;
1284                         if( (this_track = pane[i]->over_patchbay()) != 0 ) break;
1285                 }
1286
1287                 if( get_keypress() == TAB ) { // Switch the armed button
1288                         if( this_track )
1289                                 this_track->armed = !this_track->armed ? 1 : 0;
1290                 }
1291                 else {
1292                         int total_selected = mwindow->edl->tracks->total_of(Tracks::RECORD);
1293                         // all selected if nothing previously selected or
1294                         // if this patch was previously the only one selected and armed
1295                         int selected = !total_selected || (total_selected == 1 &&
1296                                 this_track && this_track->armed ) ? 1 : 0;
1297                         mwindow->edl->tracks->select_all(Tracks::RECORD, selected);
1298                         if( !selected && this_track ) this_track->armed = 1;
1299                 }
1300
1301                 update(0, NORMAL_DRAW, 0, 0, 1, 0, 1);
1302                 unlock_window();
1303                 mwindow->cwindow->update(0, 1, 1);
1304                 lock_window("MWindowGUI::keypress_event 3");
1305
1306                 result = 1;
1307                 break;
1308
1309         case KEY_F1 ... KEY_F12:
1310                 resend_event(mwindow->cwindow->gui);
1311                 return 1;
1312         }
1313
1314 // since things under cursor have changed...
1315         if(result)
1316                 cursor_motion_event();
1317
1318         if(!result)
1319                 result = context_help_check_and_show();
1320
1321         return result;
1322 }
1323
1324 int MWindowGUI::keyboard_listener(BC_WindowBase *wp)
1325 {
1326         return key_listener(wp->get_keypress());
1327 }
1328
1329 int MWindowGUI::key_listener(int key)
1330 {
1331         int result = 1;
1332         switch( key ) {
1333         case KPTV:
1334                 if( !record->running() )
1335                         record->start();
1336                 else
1337                         record->record_gui->interrupt_thread->start(0);
1338                 break;
1339         case KPHAND:
1340                 mwindow->quit();
1341                 break;
1342 #ifdef HAVE_DVB
1343         case KPBOOK:
1344                 channel_info->toggle_scan();
1345                 break;
1346 #endif
1347         case KPMENU:
1348                 if( !remote_control->deactivate() )
1349                         remote_control->activate();
1350                 break;
1351         default:
1352                 result = 0;
1353                 break;
1354         }
1355         return result;
1356 }
1357
1358
1359 void MWindowGUI::use_android_remote(int on)
1360 {
1361         if( !on ) {
1362                 delete android_control;
1363                 android_control = 0;
1364                 return;
1365         }
1366         if( android_control ) return;
1367         android_control = new AndroidControl(this);
1368 }
1369 int MWindowGUI::keyev_grab_remote()
1370 {
1371         if( cwindow_remote_handler && cwindow_remote_handler->is_keytv() &&
1372             record_remote_handler  && record_remote_handler->is_keytv() )
1373                 return 0;
1374         delete cwindow_remote_handler;
1375         delete record_remote_handler;
1376         cwindow_remote_handler = (RemoteHandler*)
1377                 new CWindowKeyEvHandler(mwindow->gui->remote_control);
1378         record_remote_handler = (RemoteHandler*)
1379                 new RecordKeyEvHandler(mwindow->gui->remote_control);
1380         return 1;
1381 }
1382
1383 int MWindowGUI::close_event()
1384 {
1385         mainmenu->quit();
1386         return 0;
1387 }
1388
1389 void MWindowGUI::stop_drawing()
1390 {
1391         resource_thread->stop_draw(1);
1392 }
1393
1394 int MWindowGUI::menu_w()
1395 {
1396         return mainmenu->get_w();
1397 }
1398
1399 int MWindowGUI::menu_h()
1400 {
1401         return mainmenu->get_h();
1402 }
1403
1404 void MWindowGUI::start_x_pane_drag()
1405 {
1406         if(!x_pane_drag)
1407         {
1408                 x_pane_drag = new BC_Popup(this,
1409                         get_abs_cursor_x(0) - mwindow->theme->pane_w,
1410                         BC_DisplayInfo::get_top_border() +
1411                                 get_y() +
1412                                 mwindow->theme->mcanvas_y,
1413                         mwindow->theme->pane_w,
1414                         mwindow->theme->mcanvas_h,
1415                         mwindow->theme->drag_pane_color);
1416                 x_pane_drag->draw_3segmentv(0,
1417                         0,
1418                         x_pane_drag->get_h(),
1419                         mwindow->theme->get_image_set("xpane")[BUTTON_DOWNHI]);
1420                 x_pane_drag->flash(1);
1421         }
1422         dragging_pane = 1;
1423 }
1424
1425 void MWindowGUI::start_y_pane_drag()
1426 {
1427         if(!y_pane_drag)
1428         {
1429 //printf("MWindowGUI::start_y_pane_drag %d %d %d\n", __LINE__, get_x(), get_y());
1430                 y_pane_drag = new BC_Popup(this,
1431                         BC_DisplayInfo::get_left_border() +
1432                                 get_x() +
1433                                 mwindow->theme->mcanvas_x,
1434                         get_abs_cursor_y(0) - mwindow->theme->pane_h,
1435                         mwindow->theme->mcanvas_w,
1436                         mwindow->theme->pane_h,
1437                         mwindow->theme->drag_pane_color);
1438                 y_pane_drag->draw_3segmenth(0,
1439                         0,
1440                         y_pane_drag->get_w(),
1441                         mwindow->theme->get_image_set("ypane")[BUTTON_DOWNHI]);
1442                 y_pane_drag->flash(1);
1443         }
1444         dragging_pane = 1;
1445 }
1446
1447 void MWindowGUI::handle_pane_drag()
1448 {
1449         if(dragging_pane)
1450         {
1451                 if(x_pane_drag)
1452                 {
1453                         x_pane_drag->reposition_window(
1454                                 get_abs_cursor_x(0) - mwindow->theme->pane_w,
1455                                 x_pane_drag->get_y());
1456                 }
1457
1458                 if(y_pane_drag)
1459                 {
1460                         y_pane_drag->reposition_window(
1461                                 y_pane_drag->get_x(),
1462                                 get_abs_cursor_y(0) - mwindow->theme->pane_h);
1463                 }
1464         }
1465 }
1466
1467
1468 void MWindowGUI::create_x_pane(int cursor_x)
1469 {
1470         if(total_panes() == 1)
1471         {
1472 // create a horizontal pane
1473 // do this 1st so the resize_event knows there are 2 panes
1474                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1475                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1476                         cursor_x -
1477                         mwindow->theme->patchbay_w;
1478                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1479                         TOP_RIGHT_PANE,
1480                         mwindow->theme->mcanvas_x +
1481                                 cursor_x,
1482                         mwindow->theme->mcanvas_y,
1483                         mwindow->theme->mcanvas_x +
1484                                 mwindow->theme->mcanvas_w -
1485                                 cursor_x,
1486                         mwindow->theme->mcanvas_h);
1487                 pane[TOP_LEFT_PANE]->resize_event(
1488                         mwindow->theme->mcanvas_x,
1489                         mwindow->theme->mcanvas_y,
1490                         cursor_x - mwindow->theme->pane_w,
1491                         mwindow->theme->mcanvas_h);
1492                 pane[TOP_RIGHT_PANE]->create_objects();
1493         }
1494         else
1495         if(vertical_panes())
1496         {
1497 // create 2 horizontal panes
1498                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1499                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1500                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1501                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1502                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1503                         mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1504                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1505                         cursor_x -
1506                         mwindow->theme->patchbay_w;
1507                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1508                         TOP_RIGHT_PANE,
1509                         mwindow->theme->mcanvas_x +
1510                                 cursor_x,
1511                         pane[TOP_LEFT_PANE]->y,
1512                         mwindow->theme->mcanvas_x +
1513                                 mwindow->theme->mcanvas_w -
1514                                 cursor_x,
1515                         pane[TOP_LEFT_PANE]->h);
1516                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1517                         BOTTOM_RIGHT_PANE,
1518                         mwindow->theme->mcanvas_x +
1519                                 cursor_x,
1520                         pane[BOTTOM_LEFT_PANE]->y,
1521                         mwindow->theme->mcanvas_x +
1522                                 mwindow->theme->mcanvas_w -
1523                                 cursor_x,
1524                         pane[BOTTOM_LEFT_PANE]->h);
1525                 pane[TOP_LEFT_PANE]->resize_event(
1526                         pane[TOP_LEFT_PANE]->x,
1527                         pane[TOP_LEFT_PANE]->y,
1528                         cursor_x - mwindow->theme->pane_w,
1529                         pane[TOP_LEFT_PANE]->h);
1530                 pane[BOTTOM_LEFT_PANE]->resize_event(
1531                         pane[BOTTOM_LEFT_PANE]->x,
1532                         pane[BOTTOM_LEFT_PANE]->y,
1533                         cursor_x - mwindow->theme->pane_w,
1534                         pane[BOTTOM_LEFT_PANE]->h);
1535                 pane[TOP_RIGHT_PANE]->create_objects();
1536                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1537         }
1538         else
1539         if(horizontal_panes())
1540         {
1541 // resize a horizontal pane
1542                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1543                         cursor_x -
1544                         pane[TOP_RIGHT_PANE]->x;
1545                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1546                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1547                 pane[TOP_LEFT_PANE]->resize_event(
1548                         mwindow->theme->mcanvas_x,
1549                         mwindow->theme->mcanvas_y,
1550                         cursor_x - mwindow->theme->pane_w,
1551                         mwindow->theme->mcanvas_h);
1552                 pane[TOP_RIGHT_PANE]->resize_event(
1553                         mwindow->theme->mcanvas_x +
1554                                 cursor_x,
1555                         pane[TOP_RIGHT_PANE]->y,
1556                         mwindow->theme->mcanvas_x +
1557                                 mwindow->theme->mcanvas_w -
1558                                 cursor_x,
1559                         mwindow->theme->mcanvas_h);
1560         }
1561         else
1562         {
1563 // resize 2 horizontal panes
1564                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1565                         cursor_x -
1566                         pane[TOP_RIGHT_PANE]->x;
1567                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1568                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1569                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1570                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1571
1572                 pane[TOP_LEFT_PANE]->resize_event(
1573                         mwindow->theme->mcanvas_x,
1574                         pane[TOP_LEFT_PANE]->y,
1575                         cursor_x - mwindow->theme->pane_w,
1576                         pane[TOP_LEFT_PANE]->h);
1577                 pane[TOP_RIGHT_PANE]->resize_event(
1578                         mwindow->theme->mcanvas_x +
1579                                 cursor_x,
1580                         pane[TOP_RIGHT_PANE]->y,
1581                         mwindow->theme->mcanvas_x +
1582                                 mwindow->theme->mcanvas_w -
1583                                 cursor_x,
1584                         pane[TOP_RIGHT_PANE]->h);
1585                 pane[BOTTOM_LEFT_PANE]->resize_event(
1586                         mwindow->theme->mcanvas_x,
1587                         pane[BOTTOM_LEFT_PANE]->y,
1588                         cursor_x - mwindow->theme->pane_w,
1589                         pane[BOTTOM_LEFT_PANE]->h);
1590                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1591                         mwindow->theme->mcanvas_x +
1592                                 cursor_x,
1593                         pane[BOTTOM_RIGHT_PANE]->y,
1594                         mwindow->theme->mcanvas_x +
1595                                 mwindow->theme->mcanvas_w -
1596                                 cursor_x,
1597                         pane[BOTTOM_RIGHT_PANE]->h);
1598
1599         }
1600 }
1601
1602
1603 void MWindowGUI::delete_x_pane(int cursor_x)
1604 {
1605 // give left panes coordinates of right pane
1606         if(cursor_x < mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1607                 pane[TOP_RIGHT_PANE])
1608         {
1609                 mwindow->edl->local_session->view_start[TOP_LEFT_PANE] =
1610                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] -
1611                         pane[TOP_RIGHT_PANE]->x + mwindow->theme->patchbay_w;
1612                 if(mwindow->edl->local_session->view_start[TOP_LEFT_PANE] < 0)
1613                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] = 0;
1614                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1615                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1616         }
1617
1618         switch(total_panes())
1619         {
1620                 case 2:
1621                         if(pane[TOP_LEFT_PANE] && pane[TOP_RIGHT_PANE])
1622                         {
1623 // delete right pane
1624                                 delete pane[TOP_RIGHT_PANE];
1625                                 pane[TOP_RIGHT_PANE] = 0;
1626                                 pane[TOP_LEFT_PANE]->resize_event(
1627                                         mwindow->theme->mcanvas_x,
1628                                         mwindow->theme->mcanvas_y,
1629                                         mwindow->theme->mcanvas_w,
1630                                         mwindow->theme->mcanvas_h);
1631
1632                         }
1633                         break;
1634
1635                 case 4:
1636 // delete right panes
1637                         delete pane[TOP_RIGHT_PANE];
1638                         pane[TOP_RIGHT_PANE] = 0;
1639                         delete pane[BOTTOM_RIGHT_PANE];
1640                         pane[BOTTOM_RIGHT_PANE] = 0;
1641                         pane[TOP_LEFT_PANE]->resize_event(
1642                                 mwindow->theme->mcanvas_x,
1643                                 pane[TOP_LEFT_PANE]->y,
1644                                 mwindow->theme->mcanvas_w,
1645                                 pane[TOP_LEFT_PANE]->h);
1646                         pane[BOTTOM_LEFT_PANE]->resize_event(
1647                                 mwindow->theme->mcanvas_x,
1648                                 pane[BOTTOM_LEFT_PANE]->y,
1649                                 mwindow->theme->mcanvas_w,
1650                                 pane[BOTTOM_LEFT_PANE]->h);
1651                         break;
1652         }
1653 }
1654
1655 void MWindowGUI::create_y_pane(int cursor_y)
1656 {
1657         if(total_panes() == 1)
1658         {
1659                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1660                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1661                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1662                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1663                         cursor_y -
1664                         mwindow->theme->mtimebar_h;
1665 // do this 1st so the resize_event knows there are 2 panes
1666                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1667                         BOTTOM_LEFT_PANE,
1668                         mwindow->theme->mcanvas_x,
1669                         mwindow->theme->mcanvas_y +
1670                                 cursor_y,
1671                         mwindow->theme->mcanvas_w,
1672                         mwindow->theme->mcanvas_h -
1673                                 cursor_y);
1674                 pane[TOP_LEFT_PANE]->resize_event(
1675                         mwindow->theme->mcanvas_x,
1676                         mwindow->theme->mcanvas_y,
1677                         mwindow->theme->mcanvas_w,
1678                         pane[BOTTOM_LEFT_PANE]->y -
1679                                 mwindow->theme->mcanvas_y -
1680                                 mwindow->theme->pane_h);
1681                 pane[BOTTOM_LEFT_PANE]->create_objects();
1682         }
1683         else
1684         if(horizontal_panes())
1685         {
1686 // create 2 panes
1687                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1688                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1689                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1690                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1691                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1692                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1693                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1694                         cursor_y -
1695                         mwindow->theme->mtimebar_h;
1696
1697                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1698                         BOTTOM_LEFT_PANE,
1699                         pane[TOP_LEFT_PANE]->x,
1700                         mwindow->theme->mcanvas_y +
1701                                 cursor_y,
1702                         pane[TOP_LEFT_PANE]->w,
1703                         mwindow->theme->mcanvas_h -
1704                                 cursor_y);
1705                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1706                         BOTTOM_RIGHT_PANE,
1707                         pane[TOP_RIGHT_PANE]->x,
1708                         mwindow->theme->mcanvas_y +
1709                                 cursor_y,
1710                         pane[TOP_RIGHT_PANE]->w,
1711                         mwindow->theme->mcanvas_h -
1712                                 cursor_y);
1713
1714                 pane[TOP_LEFT_PANE]->resize_event(
1715                         pane[TOP_LEFT_PANE]->x,
1716                         pane[TOP_LEFT_PANE]->y,
1717                         pane[TOP_LEFT_PANE]->w,
1718                         pane[BOTTOM_LEFT_PANE]->y -
1719                                 mwindow->theme->mcanvas_y -
1720                                 mwindow->theme->pane_h);
1721                 pane[TOP_RIGHT_PANE]->resize_event(
1722                         pane[TOP_RIGHT_PANE]->x,
1723                         pane[TOP_RIGHT_PANE]->y,
1724                         pane[TOP_RIGHT_PANE]->w,
1725                         pane[BOTTOM_RIGHT_PANE]->y -
1726                                 mwindow->theme->mcanvas_y -
1727                                 mwindow->theme->pane_h);
1728
1729                 pane[BOTTOM_LEFT_PANE]->create_objects();
1730                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1731         }
1732         else
1733         if(vertical_panes())
1734         {
1735 // resize a pane
1736                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1737                         cursor_y -
1738                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1739                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1740                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1741                 pane[TOP_LEFT_PANE]->resize_event(
1742                         mwindow->theme->mcanvas_x,
1743                         mwindow->theme->mcanvas_y,
1744                         mwindow->theme->mcanvas_w,
1745                         cursor_y - mwindow->theme->pane_h);
1746                 pane[BOTTOM_LEFT_PANE]->resize_event(
1747                         pane[BOTTOM_LEFT_PANE]->x,
1748                         cursor_y +
1749                                 mwindow->theme->mcanvas_y,
1750                         mwindow->theme->mcanvas_w,
1751                         mwindow->theme->mcanvas_h -
1752                                 cursor_y);
1753         }
1754         else
1755         {
1756 // resize 2 panes
1757                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1758                         cursor_y -
1759                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1760                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1761                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1762                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1763                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1764                 pane[TOP_LEFT_PANE]->resize_event(
1765                         pane[TOP_LEFT_PANE]->x,
1766                         pane[TOP_LEFT_PANE]->y,
1767                         pane[TOP_LEFT_PANE]->w,
1768                         cursor_y - mwindow->theme->pane_h);
1769                 pane[BOTTOM_LEFT_PANE]->resize_event(
1770                         pane[BOTTOM_LEFT_PANE]->x,
1771                         cursor_y +
1772                                 mwindow->theme->mcanvas_y,
1773                         pane[BOTTOM_LEFT_PANE]->w,
1774                         mwindow->theme->mcanvas_h -
1775                                         cursor_y);
1776                 pane[TOP_RIGHT_PANE]->resize_event(
1777                         pane[TOP_RIGHT_PANE]->x,
1778                         pane[TOP_RIGHT_PANE]->y,
1779                         pane[TOP_RIGHT_PANE]->w,
1780                         cursor_y - mwindow->theme->pane_h);
1781                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1782                         pane[BOTTOM_RIGHT_PANE]->x,
1783                         cursor_y +
1784                                 mwindow->theme->mcanvas_y,
1785                         pane[BOTTOM_RIGHT_PANE]->w,
1786                         mwindow->theme->mcanvas_h -
1787                                         cursor_y);
1788         }
1789 }
1790
1791 void MWindowGUI::delete_y_pane(int cursor_y)
1792 {
1793         if(cursor_y < mwindow->theme->mtimebar_h +
1794                 PANE_DRAG_MARGIN &&
1795                 pane[BOTTOM_LEFT_PANE])
1796         {
1797 // give top pane coordinates of bottom pane
1798                 mwindow->edl->local_session->track_start[TOP_LEFT_PANE] =
1799                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] -
1800                         pane[BOTTOM_LEFT_PANE]->y;
1801                 if(mwindow->edl->local_session->track_start[TOP_LEFT_PANE] < 0)
1802                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] = 0;
1803                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1804                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1805         }
1806
1807 // delete a pane
1808         switch(total_panes())
1809         {
1810                 case 2:
1811                         delete pane[BOTTOM_LEFT_PANE];
1812                         pane[BOTTOM_LEFT_PANE] = 0;
1813                         pane[TOP_LEFT_PANE]->resize_event(
1814                                 mwindow->theme->mcanvas_x,
1815                                 mwindow->theme->mcanvas_y,
1816                                 mwindow->theme->mcanvas_w,
1817                                 mwindow->theme->mcanvas_h);
1818                         break;
1819
1820                 case 4:
1821 // delete bottom 2 panes
1822
1823                         delete pane[BOTTOM_LEFT_PANE];
1824                         pane[BOTTOM_LEFT_PANE] = 0;
1825                         delete pane[BOTTOM_RIGHT_PANE];
1826                         pane[BOTTOM_RIGHT_PANE] = 0;
1827                         pane[TOP_LEFT_PANE]->resize_event(
1828                                 pane[TOP_LEFT_PANE]->x,
1829                                 mwindow->theme->mcanvas_y,
1830                                 pane[TOP_LEFT_PANE]->w,
1831                                 mwindow->theme->mcanvas_h);
1832                         pane[TOP_RIGHT_PANE]->resize_event(
1833                                 pane[TOP_RIGHT_PANE]->x,
1834                                 mwindow->theme->mcanvas_y,
1835                                 pane[TOP_RIGHT_PANE]->w,
1836                                 mwindow->theme->mcanvas_h);
1837                         break;
1838         }
1839 }
1840
1841 void MWindowGUI::stop_pane_drag()
1842 {
1843         if( !dragging_pane ) return;
1844         dragging_pane = 0;
1845         resource_thread->stop_draw(0);
1846
1847         if(x_pane_drag)
1848         {
1849 // cursor position relative to canvas
1850                 int cursor_x = x_pane_drag->get_x() -
1851                         get_x() -
1852                         BC_DisplayInfo::get_left_border() -
1853                         mwindow->theme->mcanvas_x +
1854                         mwindow->theme->pane_w;
1855                 delete x_pane_drag;
1856                 x_pane_drag = 0;
1857
1858
1859                 if(cursor_x >= mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1860                         cursor_x < mwindow->theme->mcanvas_w -
1861                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1862                                 PANE_DRAG_MARGIN)
1863                 {
1864                         create_x_pane(cursor_x);
1865                         mwindow->edl->local_session->x_pane = cursor_x;
1866                 }
1867                 else
1868 // deleted a pane
1869                 {
1870                         delete_x_pane(cursor_x);
1871                         mwindow->edl->local_session->x_pane = -1;
1872                 }
1873
1874
1875         }
1876
1877         if(y_pane_drag)
1878         {
1879 // cursor position relative to canvas
1880                 int cursor_y = y_pane_drag->get_y() -
1881                         get_y() -
1882                         BC_DisplayInfo::get_top_border() -
1883                         mwindow->theme->mcanvas_y +
1884                         mwindow->theme->pane_h;
1885                 delete y_pane_drag;
1886                 y_pane_drag = 0;
1887
1888
1889
1890                 if(cursor_y >= mwindow->theme->mtimebar_h +
1891                                 PANE_DRAG_MARGIN &&
1892                         cursor_y < mwindow->theme->mcanvas_h -
1893                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1894                                 PANE_DRAG_MARGIN)
1895                 {
1896                         create_y_pane(cursor_y);
1897                         mwindow->edl->local_session->y_pane = cursor_y;
1898                 }
1899                 else
1900                 {
1901                         delete_y_pane(cursor_y);
1902                         mwindow->edl->local_session->y_pane = -1;
1903                 }
1904         }
1905
1906         update_pane_dividers();
1907         update_cursor();
1908 // required to get new widgets to appear
1909         show_window();
1910         resource_thread->start_draw();
1911 }
1912
1913 // create panes from EDL
1914 void MWindowGUI::load_panes()
1915 {
1916         int need_x_panes = 0;
1917         int need_y_panes = 0;
1918 // use names from create functions
1919         int cursor_x = mwindow->edl->local_session->x_pane;
1920         int cursor_y = mwindow->edl->local_session->y_pane;
1921
1922         resource_thread->stop_draw(1);
1923         if(cursor_x >=
1924                 mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1925                 cursor_x <
1926                 mwindow->theme->mcanvas_w -
1927                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1928                                 PANE_DRAG_MARGIN)
1929         {
1930                 need_x_panes = 1;
1931         }
1932
1933         if(cursor_y >=
1934                 mwindow->theme->mtimebar_h + PANE_DRAG_MARGIN &&
1935                 cursor_y <
1936                 mwindow->theme->mcanvas_h -
1937                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1938                                 PANE_DRAG_MARGIN)
1939         {
1940                 need_y_panes = 1;
1941         }
1942
1943 //printf("MWindowGUI::load_panes %d %d %d\n", __LINE__, need_x_panes, need_y_panes);
1944
1945
1946         if(need_x_panes)
1947         {
1948                 if(need_y_panes)
1949                 {
1950 // 4 panes
1951                         if(total_panes() == 1)
1952                         {
1953 // create 4 panes
1954 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1955                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1956                                         TOP_RIGHT_PANE,
1957                                         mwindow->theme->mcanvas_x +
1958                                                 cursor_x,
1959                                         mwindow->theme->mcanvas_y,
1960                                         mwindow->theme->mcanvas_x +
1961                                                 mwindow->theme->mcanvas_w -
1962                                                 cursor_x,
1963                                         cursor_y - mwindow->theme->pane_h);
1964                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1965                                         BOTTOM_LEFT_PANE,
1966                                         mwindow->theme->mcanvas_x,
1967                                         mwindow->theme->mcanvas_y +
1968                                                 cursor_y,
1969                                         cursor_x - mwindow->theme->pane_w,
1970                                         mwindow->theme->mcanvas_h -
1971                                                 cursor_y);
1972                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1973                                         BOTTOM_RIGHT_PANE,
1974                                         pane[TOP_RIGHT_PANE]->x,
1975                                         mwindow->theme->mcanvas_y +
1976                                                 cursor_y,
1977                                         pane[TOP_RIGHT_PANE]->w,
1978                                         mwindow->theme->mcanvas_h -
1979                                                 cursor_y);
1980                                 pane[TOP_LEFT_PANE]->resize_event(
1981                                         pane[TOP_LEFT_PANE]->x,
1982                                         pane[TOP_LEFT_PANE]->y,
1983                                         cursor_x - mwindow->theme->pane_w,
1984                                         cursor_y - mwindow->theme->pane_h);
1985                                 pane[TOP_RIGHT_PANE]->create_objects();
1986                                 pane[BOTTOM_LEFT_PANE]->create_objects();
1987                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1988                         }
1989                         else
1990                         if(horizontal_panes())
1991                         {
1992 // create vertical panes
1993 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1994                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1995                                         BOTTOM_LEFT_PANE,
1996                                         mwindow->theme->mcanvas_x,
1997                                         mwindow->theme->mcanvas_y +
1998                                                 cursor_y,
1999                                         cursor_x - mwindow->theme->pane_w,
2000                                         mwindow->theme->mcanvas_h -
2001                                                 cursor_y);
2002                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
2003                                         BOTTOM_RIGHT_PANE,
2004                                         pane[TOP_RIGHT_PANE]->x,
2005                                         mwindow->theme->mcanvas_y +
2006                                                 cursor_y,
2007                                         pane[TOP_RIGHT_PANE]->w,
2008                                         mwindow->theme->mcanvas_h -
2009                                                 cursor_y);
2010                                 pane[TOP_LEFT_PANE]->resize_event(
2011                                         pane[TOP_LEFT_PANE]->x,
2012                                         pane[TOP_LEFT_PANE]->y,
2013                                         cursor_x - mwindow->theme->pane_w,
2014                                         cursor_y - mwindow->theme->pane_h);
2015                                 pane[TOP_RIGHT_PANE]->resize_event(
2016                                         mwindow->theme->mcanvas_x +
2017                                                 cursor_x,
2018                                         mwindow->theme->mcanvas_y,
2019                                         mwindow->theme->mcanvas_x +
2020                                                 mwindow->theme->mcanvas_w -
2021                                                 cursor_x,
2022                                         cursor_y - mwindow->theme->pane_h);
2023                                 pane[BOTTOM_LEFT_PANE]->create_objects();
2024                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2025                         }
2026                         else
2027                         if(vertical_panes())
2028                         {
2029 // create horizontal panes
2030 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2031                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2032                                         TOP_RIGHT_PANE,
2033                                         mwindow->theme->mcanvas_x +
2034                                                 cursor_x,
2035                                         mwindow->theme->mcanvas_y,
2036                                         mwindow->theme->mcanvas_x +
2037                                                 mwindow->theme->mcanvas_w -
2038                                                 cursor_x,
2039                                         cursor_y - mwindow->theme->pane_h);
2040                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
2041                                         BOTTOM_RIGHT_PANE,
2042                                         pane[TOP_RIGHT_PANE]->x,
2043                                         mwindow->theme->mcanvas_y +
2044                                                 cursor_y,
2045                                         pane[TOP_RIGHT_PANE]->w,
2046                                         mwindow->theme->mcanvas_h -
2047                                                 cursor_y);
2048                                 pane[TOP_LEFT_PANE]->resize_event(
2049                                         pane[TOP_LEFT_PANE]->x,
2050                                         pane[TOP_LEFT_PANE]->y,
2051                                         cursor_x - mwindow->theme->pane_w,
2052                                         cursor_y - mwindow->theme->pane_h);
2053                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2054                                         pane[TOP_LEFT_PANE]->x,
2055                                         mwindow->theme->mcanvas_y +
2056                                                 cursor_y,
2057                                         mwindow->theme->mcanvas_x +
2058                                                 mwindow->theme->mcanvas_w -
2059                                                 cursor_x -  mwindow->theme->pane_w,
2060                                         mwindow->theme->mcanvas_h -
2061                                                 cursor_y);
2062                                 pane[TOP_RIGHT_PANE]->create_objects();
2063                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2064
2065
2066                         }
2067                         else
2068                         {
2069 // resize all panes
2070 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2071                                 pane[TOP_LEFT_PANE]->resize_event(
2072                                         pane[TOP_LEFT_PANE]->x,
2073                                         pane[TOP_LEFT_PANE]->y,
2074                                         cursor_x - mwindow->theme->pane_w,
2075                                         cursor_y - mwindow->theme->pane_h);
2076                                 pane[TOP_RIGHT_PANE]->resize_event(
2077                                         mwindow->theme->mcanvas_x +
2078                                                 cursor_x,
2079                                         mwindow->theme->mcanvas_y,
2080                                         mwindow->theme->mcanvas_x +
2081                                                 mwindow->theme->mcanvas_w -
2082                                                 cursor_x,
2083                                         cursor_y - mwindow->theme->pane_h);
2084                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2085                                         pane[TOP_LEFT_PANE]->x,
2086                                         mwindow->theme->mcanvas_y +
2087                                                 cursor_y,
2088                                         mwindow->theme->mcanvas_x +
2089                                                 mwindow->theme->mcanvas_w -
2090                                                 cursor_x - mwindow->theme->pane_w,
2091                                         mwindow->theme->mcanvas_h -
2092                                                 cursor_y);
2093                                 pane[BOTTOM_RIGHT_PANE]->resize_event(
2094                                         pane[TOP_RIGHT_PANE]->x,
2095                                         mwindow->theme->mcanvas_y +
2096                                                 cursor_y,
2097                                         pane[TOP_RIGHT_PANE]->w,
2098                                         mwindow->theme->mcanvas_h -
2099                                                 cursor_y);
2100
2101
2102                         }
2103                 }
2104                 else
2105                 {
2106 // 2 X panes
2107                         if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2108                         if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2109                         pane[BOTTOM_LEFT_PANE] = 0;
2110                         pane[BOTTOM_RIGHT_PANE] = 0;
2111
2112                         if(!pane[TOP_RIGHT_PANE])
2113                         {
2114                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2115                                         TOP_RIGHT_PANE,
2116                                         mwindow->theme->mcanvas_x +
2117                                                 cursor_x,
2118                                         mwindow->theme->mcanvas_y,
2119                                         mwindow->theme->mcanvas_x +
2120                                                 mwindow->theme->mcanvas_w -
2121                                                 cursor_x,
2122                                         mwindow->theme->mcanvas_h);
2123                                 pane[TOP_LEFT_PANE]->resize_event(
2124                                         mwindow->theme->mcanvas_x,
2125                                         mwindow->theme->mcanvas_y,
2126                                         cursor_x - mwindow->theme->pane_w,
2127                                         mwindow->theme->mcanvas_h);
2128                                 pane[TOP_RIGHT_PANE]->create_objects();
2129                         }
2130                         else
2131                         {
2132                                 pane[TOP_LEFT_PANE]->resize_event(
2133                                         mwindow->theme->mcanvas_x,
2134                                         mwindow->theme->mcanvas_y,
2135                                         cursor_x - mwindow->theme->pane_w,
2136                                         mwindow->theme->mcanvas_h);
2137                                 pane[TOP_RIGHT_PANE]->resize_event(
2138                                         mwindow->theme->mcanvas_x +
2139                                                 cursor_x,
2140                                         pane[TOP_RIGHT_PANE]->y,
2141                                         mwindow->theme->mcanvas_x +
2142                                                 mwindow->theme->mcanvas_w -
2143                                                 cursor_x,
2144                                         mwindow->theme->mcanvas_h);
2145                         }
2146                 }
2147         }
2148         else
2149         if(need_y_panes)
2150         {
2151 // 2 Y panes
2152                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2153                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2154                 pane[TOP_RIGHT_PANE] = 0;
2155                 pane[BOTTOM_RIGHT_PANE] = 0;
2156
2157                 if(!pane[BOTTOM_LEFT_PANE])
2158                 {
2159 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2160                         pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
2161                                 BOTTOM_LEFT_PANE,
2162                                 mwindow->theme->mcanvas_x,
2163                                 mwindow->theme->mcanvas_y +
2164                                         cursor_y,
2165                                 mwindow->theme->mcanvas_w,
2166                                 mwindow->theme->mcanvas_h -
2167                                         cursor_y);
2168                         pane[TOP_LEFT_PANE]->resize_event(
2169                                 mwindow->theme->mcanvas_x,
2170                                 mwindow->theme->mcanvas_y,
2171                                 mwindow->theme->mcanvas_w,
2172                                 pane[BOTTOM_LEFT_PANE]->y -
2173                                         mwindow->theme->mcanvas_y -
2174                                         mwindow->theme->pane_h);
2175                         pane[BOTTOM_LEFT_PANE]->create_objects();
2176                 }
2177                 else
2178                 {
2179                         pane[TOP_LEFT_PANE]->resize_event(
2180                                 mwindow->theme->mcanvas_x,
2181                                 mwindow->theme->mcanvas_y,
2182                                 mwindow->theme->mcanvas_w,
2183                                 cursor_y - mwindow->theme->pane_h);
2184                         pane[BOTTOM_LEFT_PANE]->resize_event(
2185                                 pane[BOTTOM_LEFT_PANE]->x,
2186                                 cursor_y +
2187                                         mwindow->theme->mcanvas_y,
2188                                 mwindow->theme->mcanvas_w,
2189                                 mwindow->theme->mcanvas_h -
2190                                         cursor_y);
2191                 }
2192         }
2193         else
2194         {
2195 // 1 pane
2196                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2197                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2198                 if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2199                 pane[TOP_RIGHT_PANE] = 0;
2200                 pane[BOTTOM_RIGHT_PANE] = 0;
2201                 pane[BOTTOM_LEFT_PANE] = 0;
2202                 pane[TOP_LEFT_PANE]->resize_event(
2203                         mwindow->theme->mcanvas_x,
2204                         mwindow->theme->mcanvas_y,
2205                         mwindow->theme->mcanvas_w,
2206                         mwindow->theme->mcanvas_h);
2207         }
2208
2209         update_pane_dividers();
2210         show_window();
2211
2212         resource_thread->start_draw();
2213 }
2214
2215 void MWindowGUI::update_pane_dividers()
2216 {
2217
2218         if(horizontal_panes() || total_panes() == 4)
2219         {
2220                 int x = pane[TOP_RIGHT_PANE]->x - mwindow->theme->pane_w;
2221                 int y = mwindow->theme->mcanvas_y;
2222                 int h = mwindow->theme->mcanvas_h;
2223
2224                 if(!x_divider)
2225                 {
2226                         add_subwindow(x_divider = new PaneDivider(
2227                                 mwindow, x, y, h, 1));
2228                         x_divider->create_objects();
2229                 }
2230                 else
2231                 {
2232                         x_divider->reposition_window(x, y, h);
2233                         x_divider->draw(0);
2234                 }
2235         }
2236         else
2237         {
2238                 if(x_divider)
2239                 {
2240                         delete x_divider;
2241                         x_divider = 0;
2242                 }
2243         }
2244
2245         if(vertical_panes() || total_panes() == 4)
2246         {
2247                 int x = mwindow->theme->mcanvas_x;
2248                 int y = pane[BOTTOM_LEFT_PANE]->y -
2249                         mwindow->theme->pane_h;
2250                 int w = mwindow->theme->mcanvas_w;
2251                 if(!y_divider)
2252                 {
2253                         add_subwindow(y_divider = new PaneDivider(
2254                                 mwindow, x, y, w, 0));
2255                         y_divider->create_objects();
2256                 }
2257                 else
2258                 {
2259                         y_divider->reposition_window(x, y, w);
2260                         y_divider->draw(0);
2261                 }
2262         }
2263         else
2264         {
2265                 if(y_divider)
2266                 {
2267                         delete y_divider;
2268                         y_divider = 0;
2269                 }
2270         }
2271 }
2272
2273 void MWindowGUI::draw_samplemovement()
2274 {
2275         draw_canvas(0, 1);
2276         show_cursor(1);
2277         flash_canvas(0);
2278         update_timebar(0);
2279         zoombar->update();
2280         update_scrollbars(1);
2281 }
2282
2283 void MWindowGUI::draw_trackmovement()
2284 {
2285         update_scrollbars(0);
2286         draw_canvas(0, 0);
2287         update_patchbay();
2288         flash_canvas(1);
2289 }
2290
2291
2292 void MWindowGUI::update_mixers(Track *track, int v)
2293 {
2294         for( int i=0; i<TOTAL_PANES;  ++i ) {
2295                 if( !pane[i] ) continue;
2296                 PatchBay *patchbay = pane[i]->patchbay;
2297                 if( !patchbay ) continue;
2298                 for( int j=0; j<patchbay->patches.total; ++j ) {
2299                         PatchGUI *patchgui = patchbay->patches.values[j];
2300                         if( !patchgui->mix ) continue;
2301                         if( !track || patchgui->track == track ) {
2302                                 patchgui->mix->update(v>=0 ? v :
2303                                         mwindow->mixer_track_active(patchgui->track));
2304                         }
2305                 }
2306         }
2307 }
2308
2309 void MWindowGUI::stop_transport(const char *lock_msg)
2310 {
2311         if( !mbuttons->transport->is_stopped() ) {
2312                 if( lock_msg ) unlock_window();
2313                 mbuttons->transport->handle_transport(STOP, 1);
2314                 if( lock_msg ) lock_window(lock_msg);
2315         }
2316 }
2317
2318 void MWindowGUI::close_keyvalue_popup()
2319 {
2320         if( !keyvalue_popup ) return;
2321         delete keyvalue_popup;
2322         keyvalue_popup = 0;
2323 }
2324
2325 void MWindowGUI::open_keyvalue_popup(BC_SubWindow *popup)
2326 {
2327         close_keyvalue_popup();
2328         keyvalue_popup = popup;
2329 }
2330
2331 PaneButton::PaneButton(MWindow *mwindow, int x, int y)
2332  : BC_Button(x, y, mwindow->theme->get_image_set("pane"))
2333 {
2334         this->mwindow = mwindow;
2335 }
2336
2337 int PaneButton::cursor_motion_event()
2338 {
2339         if(get_top_level()->get_button_down() &&
2340                 is_event_win() &&
2341                 get_status() == BUTTON_DOWNHI &&
2342                 !cursor_inside())
2343         {
2344 //              printf("PaneButton::cursor_motion_event %d\n", __LINE__);
2345 // create drag bar
2346                 if(get_cursor_x() < 0 && !mwindow->gui->dragging_pane)
2347                 {
2348                         mwindow->gui->start_x_pane_drag();
2349                 }
2350                 else
2351                 if(get_cursor_y() < 0 && !mwindow->gui->dragging_pane)
2352                 {
2353                         mwindow->gui->start_y_pane_drag();
2354                 }
2355         }
2356
2357         mwindow->gui->handle_pane_drag();
2358
2359         int result = BC_Button::cursor_motion_event();
2360         return result;
2361 }
2362
2363 int PaneButton::button_release_event()
2364 {
2365         if( get_buttonpress() != WHEEL_DOWN && get_buttonpress() != WHEEL_UP )
2366                 mwindow->gui->stop_pane_drag();
2367         int result = BC_Button::button_release_event();
2368         return result;
2369 }
2370
2371
2372 FFMpegToggle::FFMpegToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2373  : BC_Toggle(x, y, mwindow->theme->ffmpeg_toggle,
2374          mwindow->preferences->get_file_probe_armed("FFMPEG_Early") > 0 ? 1 : 0)
2375 {
2376         this->mwindow = mwindow;
2377         this->mbuttons = mbuttons;
2378         set_tooltip(get_value() ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2379 // *** CONTEXT_HELP ***
2380         context_help_set_keyword("FFmpeg Early Probe Explanation");
2381 }
2382
2383 FFMpegToggle::~FFMpegToggle()
2384 {
2385 }
2386
2387 int FFMpegToggle::handle_event()
2388 {
2389         int ffmpeg_early_probe = get_value();
2390         set_tooltip(ffmpeg_early_probe ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2391         mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe);
2392         mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe);
2393         mwindow->update_preferences(mwindow->preferences);
2394         mwindow->show_warning(&mwindow->preferences->warn_indexes,
2395                 _("Changing the base codecs may require rebuilding indexes."));
2396         return 1;
2397 }
2398
2399
2400 StackButton::StackButton(MWindow *mwindow, int x, int y)
2401  : BC_GenericButton(x, y, mwindow->theme->stack_button_w, "0")
2402 {
2403         this->mwindow = mwindow;
2404         set_tooltip(_("Close EDL"));
2405 // *** CONTEXT_HELP ***
2406         context_help_set_keyword("OpenEDL");
2407 }
2408
2409 int StackButton::handle_event()
2410 {
2411         mwindow->save_backup();
2412         mwindow->stack_pop();
2413         return 1;
2414 }
2415
2416 void StackButton::update()
2417 {
2418         char text[BCSTRLEN];
2419         int i = mwindow->stack.size();
2420         sprintf(text, "%d", i);
2421         set_text(text);
2422         draw_face();
2423 }
2424
2425
2426 ProxyToggle::ProxyToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2427  : BC_Toggle(x, y, ( !mwindow->edl->session->proxy_use_scaler ?
2428                         mwindow->theme->proxy_p_toggle :
2429                         mwindow->theme->proxy_s_toggle ),
2430                 mwindow->edl->session->proxy_state == PROXY_DISABLED)
2431 {
2432         this->mwindow = mwindow;
2433         this->mbuttons = mbuttons;
2434         scaler_images = mwindow->edl->session->proxy_use_scaler;
2435         set_tooltip(mwindow->edl->session->proxy_state!=PROXY_DISABLED ?
2436                 _("Disable proxy") : _("Enable proxy"));
2437 // *** CONTEXT_HELP ***
2438         context_help_set_keyword("Proxy");
2439 }
2440
2441 void ProxyToggle::show()
2442 {
2443         int use_scaler = mwindow->edl->session->proxy_use_scaler;
2444         if( scaler_images != use_scaler )
2445                 set_images(!(scaler_images=use_scaler) ?
2446                         mwindow->theme->proxy_p_toggle :
2447                         mwindow->theme->proxy_s_toggle );
2448         draw_face(1, 0);
2449         if( is_hidden() )
2450                 show_window();
2451 }
2452
2453 void ProxyToggle::hide()
2454 {
2455         if( !is_hidden() )
2456                 hide_window();
2457 }
2458
2459 ProxyToggle::~ProxyToggle()
2460 {
2461 }
2462
2463 int ProxyToggle::handle_event()
2464 {
2465         int disabled = get_value();
2466         mwindow->gui->unlock_window();
2467         if( disabled )
2468                 mwindow->disable_proxy();
2469         else
2470                 mwindow->enable_proxy();
2471         mwindow->gui->lock_window("ProxyToggle::handle_event");
2472         set_tooltip(!disabled ? _("Disable proxy") : _("Enable proxy"));
2473         ProxyDialog *dialog = mwindow->gui->mainmenu->proxy->dialog;
2474         if( dialog && dialog->gui ) {
2475                 dialog->gui->lock_window("ProxyToggle::handle_event");
2476                 dialog->gui->update();
2477                 dialog->gui->unlock_window();
2478         }
2479         return 1;
2480 }
2481
2482 int ProxyToggle::keypress_event()
2483 {
2484         if( ctrl_down() && !shift_down() && !alt_down() ) {
2485                 int key = get_keypress();
2486                 if( key == 'r' ) {
2487                         int value = get_value() ? 0 : 1;
2488                         set_value(value);
2489                         return handle_event();
2490                 }
2491         }
2492         return context_help_check_and_show();
2493 }
2494