43b95cbbd57a9db35c247f0e425c5e40bd90b64c
[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 '!':
1240                 if( !ctrl_down() || !shift_down() ) break;
1241 /* code to execute is same as lines 383-401 in editpopup.C */
1242                 result = 1;
1243                 break;
1244
1245         case UP:
1246                 if( ctrl_down() && !alt_down() )
1247                         mwindow->expand_y();
1248                 else if( !ctrl_down() && alt_down() )
1249                         mwindow->expand_autos(0,1,1);
1250                 else if( ctrl_down() && alt_down() )
1251                         mwindow->expand_autos(1,1,1);
1252                 else
1253                         mwindow->expand_sample();
1254                 result = 1;
1255                 break;
1256
1257         case DOWN:
1258                 if( ctrl_down() && !alt_down() )
1259                         mwindow->zoom_in_y();
1260                 else if( !ctrl_down() && alt_down() )
1261                         mwindow->shrink_autos(0,1,1);
1262                 else if( ctrl_down() && alt_down() )
1263                         mwindow->shrink_autos(1,1,1);
1264                 else
1265                         mwindow->zoom_in_sample();
1266                 result = 1;
1267                 break;
1268
1269         case PGUP:
1270                 if( !ctrl_down() )
1271                         mwindow->move_up();
1272                 else
1273                         mwindow->expand_t();
1274                 result = 1;
1275                 break;
1276
1277         case PGDN:
1278                 if( !ctrl_down() )
1279                         mwindow->move_down();
1280                 else
1281                         mwindow->zoom_in_t();
1282                 result = 1;
1283                 break;
1284
1285         case TAB:
1286         case LEFTTAB:
1287                 for( int i=0; i<TOTAL_PANES; ++i ) {
1288                         if( !pane[i] ) continue;
1289                         if( (this_track = pane[i]->over_track()) != 0 ) break;
1290                         if( (this_track = pane[i]->over_patchbay()) != 0 ) break;
1291                 }
1292
1293                 if( get_keypress() == TAB ) { // Switch the armed button
1294                         if( this_track )
1295                                 this_track->armed = !this_track->armed ? 1 : 0;
1296                 }
1297                 else {
1298                         int total_selected = mwindow->edl->tracks->total_of(Tracks::RECORD);
1299                         // all selected if nothing previously selected or
1300                         // if this patch was previously the only one selected and armed
1301                         int selected = !total_selected || (total_selected == 1 &&
1302                                 this_track && this_track->armed ) ? 1 : 0;
1303                         mwindow->edl->tracks->select_all(Tracks::RECORD, selected);
1304                         if( !selected && this_track ) this_track->armed = 1;
1305                 }
1306
1307                 update(0, NORMAL_DRAW, 0, 0, 1, 0, 1);
1308                 unlock_window();
1309                 mwindow->cwindow->update(0, 1, 1);
1310                 lock_window("MWindowGUI::keypress_event 3");
1311
1312                 result = 1;
1313                 break;
1314
1315         case KEY_F1 ... KEY_F12:
1316                 resend_event(mwindow->cwindow->gui);
1317                 return 1;
1318         }
1319
1320 // since things under cursor have changed...
1321         if(result)
1322                 cursor_motion_event();
1323
1324         if(!result)
1325                 result = context_help_check_and_show();
1326
1327         return result;
1328 }
1329
1330 int MWindowGUI::keyboard_listener(BC_WindowBase *wp)
1331 {
1332         return key_listener(wp->get_keypress());
1333 }
1334
1335 int MWindowGUI::key_listener(int key)
1336 {
1337         int result = 1;
1338         switch( key ) {
1339         case KPTV:
1340                 if( !record->running() )
1341                         record->start();
1342                 else
1343                         record->record_gui->interrupt_thread->start(0);
1344                 break;
1345         case KPHAND:
1346                 mwindow->quit();
1347                 break;
1348 #ifdef HAVE_DVB
1349         case KPBOOK:
1350                 channel_info->toggle_scan();
1351                 break;
1352 #endif
1353         case KPMENU:
1354                 if( !remote_control->deactivate() )
1355                         remote_control->activate();
1356                 break;
1357         default:
1358                 result = 0;
1359                 break;
1360         }
1361         return result;
1362 }
1363
1364
1365 void MWindowGUI::use_android_remote(int on)
1366 {
1367         if( !on ) {
1368                 delete android_control;
1369                 android_control = 0;
1370                 return;
1371         }
1372         if( android_control ) return;
1373         android_control = new AndroidControl(this);
1374 }
1375 int MWindowGUI::keyev_grab_remote()
1376 {
1377         if( cwindow_remote_handler && cwindow_remote_handler->is_keytv() &&
1378             record_remote_handler  && record_remote_handler->is_keytv() )
1379                 return 0;
1380         delete cwindow_remote_handler;
1381         delete record_remote_handler;
1382         cwindow_remote_handler = (RemoteHandler*)
1383                 new CWindowKeyEvHandler(mwindow->gui->remote_control);
1384         record_remote_handler = (RemoteHandler*)
1385                 new RecordKeyEvHandler(mwindow->gui->remote_control);
1386         return 1;
1387 }
1388
1389 int MWindowGUI::close_event()
1390 {
1391         mainmenu->quit();
1392         return 0;
1393 }
1394
1395 void MWindowGUI::stop_drawing()
1396 {
1397         resource_thread->stop_draw(1);
1398 }
1399
1400 int MWindowGUI::menu_w()
1401 {
1402         return mainmenu->get_w();
1403 }
1404
1405 int MWindowGUI::menu_h()
1406 {
1407         return mainmenu->get_h();
1408 }
1409
1410 void MWindowGUI::start_x_pane_drag()
1411 {
1412         if(!x_pane_drag)
1413         {
1414                 x_pane_drag = new BC_Popup(this,
1415                         get_abs_cursor_x(0) - mwindow->theme->pane_w,
1416                         BC_DisplayInfo::get_top_border() +
1417                                 get_y() +
1418                                 mwindow->theme->mcanvas_y,
1419                         mwindow->theme->pane_w,
1420                         mwindow->theme->mcanvas_h,
1421                         mwindow->theme->drag_pane_color);
1422                 x_pane_drag->draw_3segmentv(0,
1423                         0,
1424                         x_pane_drag->get_h(),
1425                         mwindow->theme->get_image_set("xpane")[BUTTON_DOWNHI]);
1426                 x_pane_drag->flash(1);
1427         }
1428         dragging_pane = 1;
1429 }
1430
1431 void MWindowGUI::start_y_pane_drag()
1432 {
1433         if(!y_pane_drag)
1434         {
1435 //printf("MWindowGUI::start_y_pane_drag %d %d %d\n", __LINE__, get_x(), get_y());
1436                 y_pane_drag = new BC_Popup(this,
1437                         BC_DisplayInfo::get_left_border() +
1438                                 get_x() +
1439                                 mwindow->theme->mcanvas_x,
1440                         get_abs_cursor_y(0) - mwindow->theme->pane_h,
1441                         mwindow->theme->mcanvas_w,
1442                         mwindow->theme->pane_h,
1443                         mwindow->theme->drag_pane_color);
1444                 y_pane_drag->draw_3segmenth(0,
1445                         0,
1446                         y_pane_drag->get_w(),
1447                         mwindow->theme->get_image_set("ypane")[BUTTON_DOWNHI]);
1448                 y_pane_drag->flash(1);
1449         }
1450         dragging_pane = 1;
1451 }
1452
1453 void MWindowGUI::handle_pane_drag()
1454 {
1455         if(dragging_pane)
1456         {
1457                 if(x_pane_drag)
1458                 {
1459                         x_pane_drag->reposition_window(
1460                                 get_abs_cursor_x(0) - mwindow->theme->pane_w,
1461                                 x_pane_drag->get_y());
1462                 }
1463
1464                 if(y_pane_drag)
1465                 {
1466                         y_pane_drag->reposition_window(
1467                                 y_pane_drag->get_x(),
1468                                 get_abs_cursor_y(0) - mwindow->theme->pane_h);
1469                 }
1470         }
1471 }
1472
1473
1474 void MWindowGUI::create_x_pane(int cursor_x)
1475 {
1476         if(total_panes() == 1)
1477         {
1478 // create a horizontal pane
1479 // do this 1st so the resize_event knows there are 2 panes
1480                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1481                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1482                         cursor_x -
1483                         mwindow->theme->patchbay_w;
1484                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1485                         TOP_RIGHT_PANE,
1486                         mwindow->theme->mcanvas_x +
1487                                 cursor_x,
1488                         mwindow->theme->mcanvas_y,
1489                         mwindow->theme->mcanvas_x +
1490                                 mwindow->theme->mcanvas_w -
1491                                 cursor_x,
1492                         mwindow->theme->mcanvas_h);
1493                 pane[TOP_LEFT_PANE]->resize_event(
1494                         mwindow->theme->mcanvas_x,
1495                         mwindow->theme->mcanvas_y,
1496                         cursor_x - mwindow->theme->pane_w,
1497                         mwindow->theme->mcanvas_h);
1498                 pane[TOP_RIGHT_PANE]->create_objects();
1499         }
1500         else
1501         if(vertical_panes())
1502         {
1503 // create 2 horizontal panes
1504                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1505                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1506                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1507                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1508                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1509                         mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1510                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1511                         cursor_x -
1512                         mwindow->theme->patchbay_w;
1513                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1514                         TOP_RIGHT_PANE,
1515                         mwindow->theme->mcanvas_x +
1516                                 cursor_x,
1517                         pane[TOP_LEFT_PANE]->y,
1518                         mwindow->theme->mcanvas_x +
1519                                 mwindow->theme->mcanvas_w -
1520                                 cursor_x,
1521                         pane[TOP_LEFT_PANE]->h);
1522                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1523                         BOTTOM_RIGHT_PANE,
1524                         mwindow->theme->mcanvas_x +
1525                                 cursor_x,
1526                         pane[BOTTOM_LEFT_PANE]->y,
1527                         mwindow->theme->mcanvas_x +
1528                                 mwindow->theme->mcanvas_w -
1529                                 cursor_x,
1530                         pane[BOTTOM_LEFT_PANE]->h);
1531                 pane[TOP_LEFT_PANE]->resize_event(
1532                         pane[TOP_LEFT_PANE]->x,
1533                         pane[TOP_LEFT_PANE]->y,
1534                         cursor_x - mwindow->theme->pane_w,
1535                         pane[TOP_LEFT_PANE]->h);
1536                 pane[BOTTOM_LEFT_PANE]->resize_event(
1537                         pane[BOTTOM_LEFT_PANE]->x,
1538                         pane[BOTTOM_LEFT_PANE]->y,
1539                         cursor_x - mwindow->theme->pane_w,
1540                         pane[BOTTOM_LEFT_PANE]->h);
1541                 pane[TOP_RIGHT_PANE]->create_objects();
1542                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1543         }
1544         else
1545         if(horizontal_panes())
1546         {
1547 // resize a horizontal pane
1548                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1549                         cursor_x -
1550                         pane[TOP_RIGHT_PANE]->x;
1551                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1552                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1553                 pane[TOP_LEFT_PANE]->resize_event(
1554                         mwindow->theme->mcanvas_x,
1555                         mwindow->theme->mcanvas_y,
1556                         cursor_x - mwindow->theme->pane_w,
1557                         mwindow->theme->mcanvas_h);
1558                 pane[TOP_RIGHT_PANE]->resize_event(
1559                         mwindow->theme->mcanvas_x +
1560                                 cursor_x,
1561                         pane[TOP_RIGHT_PANE]->y,
1562                         mwindow->theme->mcanvas_x +
1563                                 mwindow->theme->mcanvas_w -
1564                                 cursor_x,
1565                         mwindow->theme->mcanvas_h);
1566         }
1567         else
1568         {
1569 // resize 2 horizontal panes
1570                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1571                         cursor_x -
1572                         pane[TOP_RIGHT_PANE]->x;
1573                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1574                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1575                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1576                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1577
1578                 pane[TOP_LEFT_PANE]->resize_event(
1579                         mwindow->theme->mcanvas_x,
1580                         pane[TOP_LEFT_PANE]->y,
1581                         cursor_x - mwindow->theme->pane_w,
1582                         pane[TOP_LEFT_PANE]->h);
1583                 pane[TOP_RIGHT_PANE]->resize_event(
1584                         mwindow->theme->mcanvas_x +
1585                                 cursor_x,
1586                         pane[TOP_RIGHT_PANE]->y,
1587                         mwindow->theme->mcanvas_x +
1588                                 mwindow->theme->mcanvas_w -
1589                                 cursor_x,
1590                         pane[TOP_RIGHT_PANE]->h);
1591                 pane[BOTTOM_LEFT_PANE]->resize_event(
1592                         mwindow->theme->mcanvas_x,
1593                         pane[BOTTOM_LEFT_PANE]->y,
1594                         cursor_x - mwindow->theme->pane_w,
1595                         pane[BOTTOM_LEFT_PANE]->h);
1596                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1597                         mwindow->theme->mcanvas_x +
1598                                 cursor_x,
1599                         pane[BOTTOM_RIGHT_PANE]->y,
1600                         mwindow->theme->mcanvas_x +
1601                                 mwindow->theme->mcanvas_w -
1602                                 cursor_x,
1603                         pane[BOTTOM_RIGHT_PANE]->h);
1604
1605         }
1606 }
1607
1608
1609 void MWindowGUI::delete_x_pane(int cursor_x)
1610 {
1611 // give left panes coordinates of right pane
1612         if(cursor_x < mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1613                 pane[TOP_RIGHT_PANE])
1614         {
1615                 mwindow->edl->local_session->view_start[TOP_LEFT_PANE] =
1616                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] -
1617                         pane[TOP_RIGHT_PANE]->x + mwindow->theme->patchbay_w;
1618                 if(mwindow->edl->local_session->view_start[TOP_LEFT_PANE] < 0)
1619                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] = 0;
1620                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1621                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1622         }
1623
1624         switch(total_panes())
1625         {
1626                 case 2:
1627                         if(pane[TOP_LEFT_PANE] && pane[TOP_RIGHT_PANE])
1628                         {
1629 // delete right pane
1630                                 delete pane[TOP_RIGHT_PANE];
1631                                 pane[TOP_RIGHT_PANE] = 0;
1632                                 pane[TOP_LEFT_PANE]->resize_event(
1633                                         mwindow->theme->mcanvas_x,
1634                                         mwindow->theme->mcanvas_y,
1635                                         mwindow->theme->mcanvas_w,
1636                                         mwindow->theme->mcanvas_h);
1637
1638                         }
1639                         break;
1640
1641                 case 4:
1642 // delete right panes
1643                         delete pane[TOP_RIGHT_PANE];
1644                         pane[TOP_RIGHT_PANE] = 0;
1645                         delete pane[BOTTOM_RIGHT_PANE];
1646                         pane[BOTTOM_RIGHT_PANE] = 0;
1647                         pane[TOP_LEFT_PANE]->resize_event(
1648                                 mwindow->theme->mcanvas_x,
1649                                 pane[TOP_LEFT_PANE]->y,
1650                                 mwindow->theme->mcanvas_w,
1651                                 pane[TOP_LEFT_PANE]->h);
1652                         pane[BOTTOM_LEFT_PANE]->resize_event(
1653                                 mwindow->theme->mcanvas_x,
1654                                 pane[BOTTOM_LEFT_PANE]->y,
1655                                 mwindow->theme->mcanvas_w,
1656                                 pane[BOTTOM_LEFT_PANE]->h);
1657                         break;
1658         }
1659 }
1660
1661 void MWindowGUI::create_y_pane(int cursor_y)
1662 {
1663         if(total_panes() == 1)
1664         {
1665                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1666                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1667                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1668                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1669                         cursor_y -
1670                         mwindow->theme->mtimebar_h;
1671 // do this 1st so the resize_event knows there are 2 panes
1672                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1673                         BOTTOM_LEFT_PANE,
1674                         mwindow->theme->mcanvas_x,
1675                         mwindow->theme->mcanvas_y +
1676                                 cursor_y,
1677                         mwindow->theme->mcanvas_w,
1678                         mwindow->theme->mcanvas_h -
1679                                 cursor_y);
1680                 pane[TOP_LEFT_PANE]->resize_event(
1681                         mwindow->theme->mcanvas_x,
1682                         mwindow->theme->mcanvas_y,
1683                         mwindow->theme->mcanvas_w,
1684                         pane[BOTTOM_LEFT_PANE]->y -
1685                                 mwindow->theme->mcanvas_y -
1686                                 mwindow->theme->pane_h);
1687                 pane[BOTTOM_LEFT_PANE]->create_objects();
1688         }
1689         else
1690         if(horizontal_panes())
1691         {
1692 // create 2 panes
1693                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1694                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1695                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1696                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1697                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1698                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1699                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1700                         cursor_y -
1701                         mwindow->theme->mtimebar_h;
1702
1703                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1704                         BOTTOM_LEFT_PANE,
1705                         pane[TOP_LEFT_PANE]->x,
1706                         mwindow->theme->mcanvas_y +
1707                                 cursor_y,
1708                         pane[TOP_LEFT_PANE]->w,
1709                         mwindow->theme->mcanvas_h -
1710                                 cursor_y);
1711                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1712                         BOTTOM_RIGHT_PANE,
1713                         pane[TOP_RIGHT_PANE]->x,
1714                         mwindow->theme->mcanvas_y +
1715                                 cursor_y,
1716                         pane[TOP_RIGHT_PANE]->w,
1717                         mwindow->theme->mcanvas_h -
1718                                 cursor_y);
1719
1720                 pane[TOP_LEFT_PANE]->resize_event(
1721                         pane[TOP_LEFT_PANE]->x,
1722                         pane[TOP_LEFT_PANE]->y,
1723                         pane[TOP_LEFT_PANE]->w,
1724                         pane[BOTTOM_LEFT_PANE]->y -
1725                                 mwindow->theme->mcanvas_y -
1726                                 mwindow->theme->pane_h);
1727                 pane[TOP_RIGHT_PANE]->resize_event(
1728                         pane[TOP_RIGHT_PANE]->x,
1729                         pane[TOP_RIGHT_PANE]->y,
1730                         pane[TOP_RIGHT_PANE]->w,
1731                         pane[BOTTOM_RIGHT_PANE]->y -
1732                                 mwindow->theme->mcanvas_y -
1733                                 mwindow->theme->pane_h);
1734
1735                 pane[BOTTOM_LEFT_PANE]->create_objects();
1736                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1737         }
1738         else
1739         if(vertical_panes())
1740         {
1741 // resize a pane
1742                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1743                         cursor_y -
1744                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1745                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1746                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1747                 pane[TOP_LEFT_PANE]->resize_event(
1748                         mwindow->theme->mcanvas_x,
1749                         mwindow->theme->mcanvas_y,
1750                         mwindow->theme->mcanvas_w,
1751                         cursor_y - mwindow->theme->pane_h);
1752                 pane[BOTTOM_LEFT_PANE]->resize_event(
1753                         pane[BOTTOM_LEFT_PANE]->x,
1754                         cursor_y +
1755                                 mwindow->theme->mcanvas_y,
1756                         mwindow->theme->mcanvas_w,
1757                         mwindow->theme->mcanvas_h -
1758                                 cursor_y);
1759         }
1760         else
1761         {
1762 // resize 2 panes
1763                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1764                         cursor_y -
1765                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1766                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1767                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1768                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1769                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1770                 pane[TOP_LEFT_PANE]->resize_event(
1771                         pane[TOP_LEFT_PANE]->x,
1772                         pane[TOP_LEFT_PANE]->y,
1773                         pane[TOP_LEFT_PANE]->w,
1774                         cursor_y - mwindow->theme->pane_h);
1775                 pane[BOTTOM_LEFT_PANE]->resize_event(
1776                         pane[BOTTOM_LEFT_PANE]->x,
1777                         cursor_y +
1778                                 mwindow->theme->mcanvas_y,
1779                         pane[BOTTOM_LEFT_PANE]->w,
1780                         mwindow->theme->mcanvas_h -
1781                                         cursor_y);
1782                 pane[TOP_RIGHT_PANE]->resize_event(
1783                         pane[TOP_RIGHT_PANE]->x,
1784                         pane[TOP_RIGHT_PANE]->y,
1785                         pane[TOP_RIGHT_PANE]->w,
1786                         cursor_y - mwindow->theme->pane_h);
1787                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1788                         pane[BOTTOM_RIGHT_PANE]->x,
1789                         cursor_y +
1790                                 mwindow->theme->mcanvas_y,
1791                         pane[BOTTOM_RIGHT_PANE]->w,
1792                         mwindow->theme->mcanvas_h -
1793                                         cursor_y);
1794         }
1795 }
1796
1797 void MWindowGUI::delete_y_pane(int cursor_y)
1798 {
1799         if(cursor_y < mwindow->theme->mtimebar_h +
1800                 PANE_DRAG_MARGIN &&
1801                 pane[BOTTOM_LEFT_PANE])
1802         {
1803 // give top pane coordinates of bottom pane
1804                 mwindow->edl->local_session->track_start[TOP_LEFT_PANE] =
1805                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] -
1806                         pane[BOTTOM_LEFT_PANE]->y;
1807                 if(mwindow->edl->local_session->track_start[TOP_LEFT_PANE] < 0)
1808                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] = 0;
1809                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1810                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1811         }
1812
1813 // delete a pane
1814         switch(total_panes())
1815         {
1816                 case 2:
1817                         delete pane[BOTTOM_LEFT_PANE];
1818                         pane[BOTTOM_LEFT_PANE] = 0;
1819                         pane[TOP_LEFT_PANE]->resize_event(
1820                                 mwindow->theme->mcanvas_x,
1821                                 mwindow->theme->mcanvas_y,
1822                                 mwindow->theme->mcanvas_w,
1823                                 mwindow->theme->mcanvas_h);
1824                         break;
1825
1826                 case 4:
1827 // delete bottom 2 panes
1828
1829                         delete pane[BOTTOM_LEFT_PANE];
1830                         pane[BOTTOM_LEFT_PANE] = 0;
1831                         delete pane[BOTTOM_RIGHT_PANE];
1832                         pane[BOTTOM_RIGHT_PANE] = 0;
1833                         pane[TOP_LEFT_PANE]->resize_event(
1834                                 pane[TOP_LEFT_PANE]->x,
1835                                 mwindow->theme->mcanvas_y,
1836                                 pane[TOP_LEFT_PANE]->w,
1837                                 mwindow->theme->mcanvas_h);
1838                         pane[TOP_RIGHT_PANE]->resize_event(
1839                                 pane[TOP_RIGHT_PANE]->x,
1840                                 mwindow->theme->mcanvas_y,
1841                                 pane[TOP_RIGHT_PANE]->w,
1842                                 mwindow->theme->mcanvas_h);
1843                         break;
1844         }
1845 }
1846
1847 void MWindowGUI::stop_pane_drag()
1848 {
1849         if( !dragging_pane ) return;
1850         dragging_pane = 0;
1851         resource_thread->stop_draw(0);
1852
1853         if(x_pane_drag)
1854         {
1855 // cursor position relative to canvas
1856                 int cursor_x = x_pane_drag->get_x() -
1857                         get_x() -
1858                         BC_DisplayInfo::get_left_border() -
1859                         mwindow->theme->mcanvas_x +
1860                         mwindow->theme->pane_w;
1861                 delete x_pane_drag;
1862                 x_pane_drag = 0;
1863
1864
1865                 if(cursor_x >= mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1866                         cursor_x < mwindow->theme->mcanvas_w -
1867                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1868                                 PANE_DRAG_MARGIN)
1869                 {
1870                         create_x_pane(cursor_x);
1871                         mwindow->edl->local_session->x_pane = cursor_x;
1872                 }
1873                 else
1874 // deleted a pane
1875                 {
1876                         delete_x_pane(cursor_x);
1877                         mwindow->edl->local_session->x_pane = -1;
1878                 }
1879
1880
1881         }
1882
1883         if(y_pane_drag)
1884         {
1885 // cursor position relative to canvas
1886                 int cursor_y = y_pane_drag->get_y() -
1887                         get_y() -
1888                         BC_DisplayInfo::get_top_border() -
1889                         mwindow->theme->mcanvas_y +
1890                         mwindow->theme->pane_h;
1891                 delete y_pane_drag;
1892                 y_pane_drag = 0;
1893
1894
1895
1896                 if(cursor_y >= mwindow->theme->mtimebar_h +
1897                                 PANE_DRAG_MARGIN &&
1898                         cursor_y < mwindow->theme->mcanvas_h -
1899                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1900                                 PANE_DRAG_MARGIN)
1901                 {
1902                         create_y_pane(cursor_y);
1903                         mwindow->edl->local_session->y_pane = cursor_y;
1904                 }
1905                 else
1906                 {
1907                         delete_y_pane(cursor_y);
1908                         mwindow->edl->local_session->y_pane = -1;
1909                 }
1910         }
1911
1912         update_pane_dividers();
1913         update_cursor();
1914 // required to get new widgets to appear
1915         show_window();
1916         resource_thread->start_draw();
1917 }
1918
1919 // create panes from EDL
1920 void MWindowGUI::load_panes()
1921 {
1922         int need_x_panes = 0;
1923         int need_y_panes = 0;
1924 // use names from create functions
1925         int cursor_x = mwindow->edl->local_session->x_pane;
1926         int cursor_y = mwindow->edl->local_session->y_pane;
1927
1928         resource_thread->stop_draw(1);
1929         if(cursor_x >=
1930                 mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1931                 cursor_x <
1932                 mwindow->theme->mcanvas_w -
1933                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1934                                 PANE_DRAG_MARGIN)
1935         {
1936                 need_x_panes = 1;
1937         }
1938
1939         if(cursor_y >=
1940                 mwindow->theme->mtimebar_h + PANE_DRAG_MARGIN &&
1941                 cursor_y <
1942                 mwindow->theme->mcanvas_h -
1943                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1944                                 PANE_DRAG_MARGIN)
1945         {
1946                 need_y_panes = 1;
1947         }
1948
1949 //printf("MWindowGUI::load_panes %d %d %d\n", __LINE__, need_x_panes, need_y_panes);
1950
1951
1952         if(need_x_panes)
1953         {
1954                 if(need_y_panes)
1955                 {
1956 // 4 panes
1957                         if(total_panes() == 1)
1958                         {
1959 // create 4 panes
1960 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1961                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1962                                         TOP_RIGHT_PANE,
1963                                         mwindow->theme->mcanvas_x +
1964                                                 cursor_x,
1965                                         mwindow->theme->mcanvas_y,
1966                                         mwindow->theme->mcanvas_x +
1967                                                 mwindow->theme->mcanvas_w -
1968                                                 cursor_x,
1969                                         cursor_y - mwindow->theme->pane_h);
1970                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1971                                         BOTTOM_LEFT_PANE,
1972                                         mwindow->theme->mcanvas_x,
1973                                         mwindow->theme->mcanvas_y +
1974                                                 cursor_y,
1975                                         cursor_x - mwindow->theme->pane_w,
1976                                         mwindow->theme->mcanvas_h -
1977                                                 cursor_y);
1978                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1979                                         BOTTOM_RIGHT_PANE,
1980                                         pane[TOP_RIGHT_PANE]->x,
1981                                         mwindow->theme->mcanvas_y +
1982                                                 cursor_y,
1983                                         pane[TOP_RIGHT_PANE]->w,
1984                                         mwindow->theme->mcanvas_h -
1985                                                 cursor_y);
1986                                 pane[TOP_LEFT_PANE]->resize_event(
1987                                         pane[TOP_LEFT_PANE]->x,
1988                                         pane[TOP_LEFT_PANE]->y,
1989                                         cursor_x - mwindow->theme->pane_w,
1990                                         cursor_y - mwindow->theme->pane_h);
1991                                 pane[TOP_RIGHT_PANE]->create_objects();
1992                                 pane[BOTTOM_LEFT_PANE]->create_objects();
1993                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1994                         }
1995                         else
1996                         if(horizontal_panes())
1997                         {
1998 // create vertical panes
1999 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2000                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
2001                                         BOTTOM_LEFT_PANE,
2002                                         mwindow->theme->mcanvas_x,
2003                                         mwindow->theme->mcanvas_y +
2004                                                 cursor_y,
2005                                         cursor_x - mwindow->theme->pane_w,
2006                                         mwindow->theme->mcanvas_h -
2007                                                 cursor_y);
2008                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
2009                                         BOTTOM_RIGHT_PANE,
2010                                         pane[TOP_RIGHT_PANE]->x,
2011                                         mwindow->theme->mcanvas_y +
2012                                                 cursor_y,
2013                                         pane[TOP_RIGHT_PANE]->w,
2014                                         mwindow->theme->mcanvas_h -
2015                                                 cursor_y);
2016                                 pane[TOP_LEFT_PANE]->resize_event(
2017                                         pane[TOP_LEFT_PANE]->x,
2018                                         pane[TOP_LEFT_PANE]->y,
2019                                         cursor_x - mwindow->theme->pane_w,
2020                                         cursor_y - mwindow->theme->pane_h);
2021                                 pane[TOP_RIGHT_PANE]->resize_event(
2022                                         mwindow->theme->mcanvas_x +
2023                                                 cursor_x,
2024                                         mwindow->theme->mcanvas_y,
2025                                         mwindow->theme->mcanvas_x +
2026                                                 mwindow->theme->mcanvas_w -
2027                                                 cursor_x,
2028                                         cursor_y - mwindow->theme->pane_h);
2029                                 pane[BOTTOM_LEFT_PANE]->create_objects();
2030                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2031                         }
2032                         else
2033                         if(vertical_panes())
2034                         {
2035 // create horizontal panes
2036 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2037                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2038                                         TOP_RIGHT_PANE,
2039                                         mwindow->theme->mcanvas_x +
2040                                                 cursor_x,
2041                                         mwindow->theme->mcanvas_y,
2042                                         mwindow->theme->mcanvas_x +
2043                                                 mwindow->theme->mcanvas_w -
2044                                                 cursor_x,
2045                                         cursor_y - mwindow->theme->pane_h);
2046                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
2047                                         BOTTOM_RIGHT_PANE,
2048                                         pane[TOP_RIGHT_PANE]->x,
2049                                         mwindow->theme->mcanvas_y +
2050                                                 cursor_y,
2051                                         pane[TOP_RIGHT_PANE]->w,
2052                                         mwindow->theme->mcanvas_h -
2053                                                 cursor_y);
2054                                 pane[TOP_LEFT_PANE]->resize_event(
2055                                         pane[TOP_LEFT_PANE]->x,
2056                                         pane[TOP_LEFT_PANE]->y,
2057                                         cursor_x - mwindow->theme->pane_w,
2058                                         cursor_y - mwindow->theme->pane_h);
2059                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2060                                         pane[TOP_LEFT_PANE]->x,
2061                                         mwindow->theme->mcanvas_y +
2062                                                 cursor_y,
2063                                         mwindow->theme->mcanvas_x +
2064                                                 mwindow->theme->mcanvas_w -
2065                                                 cursor_x -  mwindow->theme->pane_w,
2066                                         mwindow->theme->mcanvas_h -
2067                                                 cursor_y);
2068                                 pane[TOP_RIGHT_PANE]->create_objects();
2069                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2070
2071
2072                         }
2073                         else
2074                         {
2075 // resize all panes
2076 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2077                                 pane[TOP_LEFT_PANE]->resize_event(
2078                                         pane[TOP_LEFT_PANE]->x,
2079                                         pane[TOP_LEFT_PANE]->y,
2080                                         cursor_x - mwindow->theme->pane_w,
2081                                         cursor_y - mwindow->theme->pane_h);
2082                                 pane[TOP_RIGHT_PANE]->resize_event(
2083                                         mwindow->theme->mcanvas_x +
2084                                                 cursor_x,
2085                                         mwindow->theme->mcanvas_y,
2086                                         mwindow->theme->mcanvas_x +
2087                                                 mwindow->theme->mcanvas_w -
2088                                                 cursor_x,
2089                                         cursor_y - mwindow->theme->pane_h);
2090                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2091                                         pane[TOP_LEFT_PANE]->x,
2092                                         mwindow->theme->mcanvas_y +
2093                                                 cursor_y,
2094                                         mwindow->theme->mcanvas_x +
2095                                                 mwindow->theme->mcanvas_w -
2096                                                 cursor_x - mwindow->theme->pane_w,
2097                                         mwindow->theme->mcanvas_h -
2098                                                 cursor_y);
2099                                 pane[BOTTOM_RIGHT_PANE]->resize_event(
2100                                         pane[TOP_RIGHT_PANE]->x,
2101                                         mwindow->theme->mcanvas_y +
2102                                                 cursor_y,
2103                                         pane[TOP_RIGHT_PANE]->w,
2104                                         mwindow->theme->mcanvas_h -
2105                                                 cursor_y);
2106
2107
2108                         }
2109                 }
2110                 else
2111                 {
2112 // 2 X panes
2113                         if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2114                         if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2115                         pane[BOTTOM_LEFT_PANE] = 0;
2116                         pane[BOTTOM_RIGHT_PANE] = 0;
2117
2118                         if(!pane[TOP_RIGHT_PANE])
2119                         {
2120                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2121                                         TOP_RIGHT_PANE,
2122                                         mwindow->theme->mcanvas_x +
2123                                                 cursor_x,
2124                                         mwindow->theme->mcanvas_y,
2125                                         mwindow->theme->mcanvas_x +
2126                                                 mwindow->theme->mcanvas_w -
2127                                                 cursor_x,
2128                                         mwindow->theme->mcanvas_h);
2129                                 pane[TOP_LEFT_PANE]->resize_event(
2130                                         mwindow->theme->mcanvas_x,
2131                                         mwindow->theme->mcanvas_y,
2132                                         cursor_x - mwindow->theme->pane_w,
2133                                         mwindow->theme->mcanvas_h);
2134                                 pane[TOP_RIGHT_PANE]->create_objects();
2135                         }
2136                         else
2137                         {
2138                                 pane[TOP_LEFT_PANE]->resize_event(
2139                                         mwindow->theme->mcanvas_x,
2140                                         mwindow->theme->mcanvas_y,
2141                                         cursor_x - mwindow->theme->pane_w,
2142                                         mwindow->theme->mcanvas_h);
2143                                 pane[TOP_RIGHT_PANE]->resize_event(
2144                                         mwindow->theme->mcanvas_x +
2145                                                 cursor_x,
2146                                         pane[TOP_RIGHT_PANE]->y,
2147                                         mwindow->theme->mcanvas_x +
2148                                                 mwindow->theme->mcanvas_w -
2149                                                 cursor_x,
2150                                         mwindow->theme->mcanvas_h);
2151                         }
2152                 }
2153         }
2154         else
2155         if(need_y_panes)
2156         {
2157 // 2 Y panes
2158                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2159                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2160                 pane[TOP_RIGHT_PANE] = 0;
2161                 pane[BOTTOM_RIGHT_PANE] = 0;
2162
2163                 if(!pane[BOTTOM_LEFT_PANE])
2164                 {
2165 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2166                         pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
2167                                 BOTTOM_LEFT_PANE,
2168                                 mwindow->theme->mcanvas_x,
2169                                 mwindow->theme->mcanvas_y +
2170                                         cursor_y,
2171                                 mwindow->theme->mcanvas_w,
2172                                 mwindow->theme->mcanvas_h -
2173                                         cursor_y);
2174                         pane[TOP_LEFT_PANE]->resize_event(
2175                                 mwindow->theme->mcanvas_x,
2176                                 mwindow->theme->mcanvas_y,
2177                                 mwindow->theme->mcanvas_w,
2178                                 pane[BOTTOM_LEFT_PANE]->y -
2179                                         mwindow->theme->mcanvas_y -
2180                                         mwindow->theme->pane_h);
2181                         pane[BOTTOM_LEFT_PANE]->create_objects();
2182                 }
2183                 else
2184                 {
2185                         pane[TOP_LEFT_PANE]->resize_event(
2186                                 mwindow->theme->mcanvas_x,
2187                                 mwindow->theme->mcanvas_y,
2188                                 mwindow->theme->mcanvas_w,
2189                                 cursor_y - mwindow->theme->pane_h);
2190                         pane[BOTTOM_LEFT_PANE]->resize_event(
2191                                 pane[BOTTOM_LEFT_PANE]->x,
2192                                 cursor_y +
2193                                         mwindow->theme->mcanvas_y,
2194                                 mwindow->theme->mcanvas_w,
2195                                 mwindow->theme->mcanvas_h -
2196                                         cursor_y);
2197                 }
2198         }
2199         else
2200         {
2201 // 1 pane
2202                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2203                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2204                 if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2205                 pane[TOP_RIGHT_PANE] = 0;
2206                 pane[BOTTOM_RIGHT_PANE] = 0;
2207                 pane[BOTTOM_LEFT_PANE] = 0;
2208                 pane[TOP_LEFT_PANE]->resize_event(
2209                         mwindow->theme->mcanvas_x,
2210                         mwindow->theme->mcanvas_y,
2211                         mwindow->theme->mcanvas_w,
2212                         mwindow->theme->mcanvas_h);
2213         }
2214
2215         update_pane_dividers();
2216         show_window();
2217
2218         resource_thread->start_draw();
2219 }
2220
2221 void MWindowGUI::update_pane_dividers()
2222 {
2223
2224         if(horizontal_panes() || total_panes() == 4)
2225         {
2226                 int x = pane[TOP_RIGHT_PANE]->x - mwindow->theme->pane_w;
2227                 int y = mwindow->theme->mcanvas_y;
2228                 int h = mwindow->theme->mcanvas_h;
2229
2230                 if(!x_divider)
2231                 {
2232                         add_subwindow(x_divider = new PaneDivider(
2233                                 mwindow, x, y, h, 1));
2234                         x_divider->create_objects();
2235                 }
2236                 else
2237                 {
2238                         x_divider->reposition_window(x, y, h);
2239                         x_divider->draw(0);
2240                 }
2241         }
2242         else
2243         {
2244                 if(x_divider)
2245                 {
2246                         delete x_divider;
2247                         x_divider = 0;
2248                 }
2249         }
2250
2251         if(vertical_panes() || total_panes() == 4)
2252         {
2253                 int x = mwindow->theme->mcanvas_x;
2254                 int y = pane[BOTTOM_LEFT_PANE]->y -
2255                         mwindow->theme->pane_h;
2256                 int w = mwindow->theme->mcanvas_w;
2257                 if(!y_divider)
2258                 {
2259                         add_subwindow(y_divider = new PaneDivider(
2260                                 mwindow, x, y, w, 0));
2261                         y_divider->create_objects();
2262                 }
2263                 else
2264                 {
2265                         y_divider->reposition_window(x, y, w);
2266                         y_divider->draw(0);
2267                 }
2268         }
2269         else
2270         {
2271                 if(y_divider)
2272                 {
2273                         delete y_divider;
2274                         y_divider = 0;
2275                 }
2276         }
2277 }
2278
2279 void MWindowGUI::draw_samplemovement()
2280 {
2281         draw_canvas(0, 1);
2282         show_cursor(1);
2283         flash_canvas(0);
2284         update_timebar(0);
2285         zoombar->update();
2286         update_scrollbars(1);
2287 }
2288
2289 void MWindowGUI::draw_trackmovement()
2290 {
2291         update_scrollbars(0);
2292         draw_canvas(0, 0);
2293         update_patchbay();
2294         flash_canvas(1);
2295 }
2296
2297
2298 void MWindowGUI::update_mixers(Track *track, int v)
2299 {
2300         for( int i=0; i<TOTAL_PANES;  ++i ) {
2301                 if( !pane[i] ) continue;
2302                 PatchBay *patchbay = pane[i]->patchbay;
2303                 if( !patchbay ) continue;
2304                 for( int j=0; j<patchbay->patches.total; ++j ) {
2305                         PatchGUI *patchgui = patchbay->patches.values[j];
2306                         if( !patchgui->mix ) continue;
2307                         if( !track || patchgui->track == track ) {
2308                                 patchgui->mix->update(v>=0 ? v :
2309                                         mwindow->mixer_track_active(patchgui->track));
2310                         }
2311                 }
2312         }
2313 }
2314
2315 void MWindowGUI::stop_transport(const char *lock_msg)
2316 {
2317         if( !mbuttons->transport->is_stopped() ) {
2318                 if( lock_msg ) unlock_window();
2319                 mbuttons->transport->handle_transport(STOP, 1);
2320                 if( lock_msg ) lock_window(lock_msg);
2321         }
2322 }
2323
2324 void MWindowGUI::close_keyvalue_popup()
2325 {
2326         if( !keyvalue_popup ) return;
2327         delete keyvalue_popup;
2328         keyvalue_popup = 0;
2329 }
2330
2331 void MWindowGUI::open_keyvalue_popup(BC_SubWindow *popup)
2332 {
2333         close_keyvalue_popup();
2334         keyvalue_popup = popup;
2335 }
2336
2337 PaneButton::PaneButton(MWindow *mwindow, int x, int y)
2338  : BC_Button(x, y, mwindow->theme->get_image_set("pane"))
2339 {
2340         this->mwindow = mwindow;
2341 }
2342
2343 int PaneButton::cursor_motion_event()
2344 {
2345         if(get_top_level()->get_button_down() &&
2346                 is_event_win() &&
2347                 get_status() == BUTTON_DOWNHI &&
2348                 !cursor_inside())
2349         {
2350 //              printf("PaneButton::cursor_motion_event %d\n", __LINE__);
2351 // create drag bar
2352                 if(get_cursor_x() < 0 && !mwindow->gui->dragging_pane)
2353                 {
2354                         mwindow->gui->start_x_pane_drag();
2355                 }
2356                 else
2357                 if(get_cursor_y() < 0 && !mwindow->gui->dragging_pane)
2358                 {
2359                         mwindow->gui->start_y_pane_drag();
2360                 }
2361         }
2362
2363         mwindow->gui->handle_pane_drag();
2364
2365         int result = BC_Button::cursor_motion_event();
2366         return result;
2367 }
2368
2369 int PaneButton::button_release_event()
2370 {
2371         if( get_buttonpress() != WHEEL_DOWN && get_buttonpress() != WHEEL_UP )
2372                 mwindow->gui->stop_pane_drag();
2373         int result = BC_Button::button_release_event();
2374         return result;
2375 }
2376
2377
2378 FFMpegToggle::FFMpegToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2379  : BC_Toggle(x, y, mwindow->theme->ffmpeg_toggle,
2380          mwindow->preferences->get_file_probe_armed("FFMPEG_Early") > 0 ? 1 : 0)
2381 {
2382         this->mwindow = mwindow;
2383         this->mbuttons = mbuttons;
2384         set_tooltip(get_value() ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2385 // *** CONTEXT_HELP ***
2386         context_help_set_keyword("FFmpeg Early Probe Explanation");
2387 }
2388
2389 FFMpegToggle::~FFMpegToggle()
2390 {
2391 }
2392
2393 int FFMpegToggle::handle_event()
2394 {
2395         int ffmpeg_early_probe = get_value();
2396         set_tooltip(ffmpeg_early_probe ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2397         mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe);
2398         mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe);
2399         mwindow->update_preferences(mwindow->preferences);
2400         mwindow->show_warning(&mwindow->preferences->warn_indexes,
2401                 _("Changing the base codecs may require rebuilding indexes."));
2402         return 1;
2403 }
2404
2405
2406 StackButton::StackButton(MWindow *mwindow, int x, int y)
2407  : BC_GenericButton(x, y, mwindow->theme->stack_button_w, "0")
2408 {
2409         this->mwindow = mwindow;
2410         set_tooltip(_("Close EDL"));
2411 // *** CONTEXT_HELP ***
2412         context_help_set_keyword("OpenEDL");
2413 }
2414
2415 int StackButton::handle_event()
2416 {
2417         mwindow->save_backup();
2418         mwindow->stack_pop();
2419         return 1;
2420 }
2421
2422 void StackButton::update()
2423 {
2424         char text[BCSTRLEN];
2425         int i = mwindow->stack.size();
2426         sprintf(text, "%d", i);
2427         set_text(text);
2428         draw_face();
2429 }
2430
2431
2432 ProxyToggle::ProxyToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2433  : BC_Toggle(x, y, ( !mwindow->edl->session->proxy_use_scaler ?
2434                         mwindow->theme->proxy_p_toggle :
2435                         mwindow->theme->proxy_s_toggle ),
2436                 mwindow->edl->session->proxy_state == PROXY_DISABLED)
2437 {
2438         this->mwindow = mwindow;
2439         this->mbuttons = mbuttons;
2440         scaler_images = mwindow->edl->session->proxy_use_scaler;
2441         set_tooltip(mwindow->edl->session->proxy_state!=PROXY_DISABLED ?
2442                 _("Disable proxy") : _("Enable proxy"));
2443 // *** CONTEXT_HELP ***
2444         context_help_set_keyword("Proxy");
2445 }
2446
2447 void ProxyToggle::show()
2448 {
2449         int use_scaler = mwindow->edl->session->proxy_use_scaler;
2450         if( scaler_images != use_scaler )
2451                 set_images(!(scaler_images=use_scaler) ?
2452                         mwindow->theme->proxy_p_toggle :
2453                         mwindow->theme->proxy_s_toggle );
2454         draw_face(1, 0);
2455         if( is_hidden() )
2456                 show_window();
2457 }
2458
2459 void ProxyToggle::hide()
2460 {
2461         if( !is_hidden() )
2462                 hide_window();
2463 }
2464
2465 ProxyToggle::~ProxyToggle()
2466 {
2467 }
2468
2469 int ProxyToggle::handle_event()
2470 {
2471         int disabled = get_value();
2472         mwindow->gui->unlock_window();
2473         if( disabled )
2474                 mwindow->disable_proxy();
2475         else
2476                 mwindow->enable_proxy();
2477         mwindow->gui->lock_window("ProxyToggle::handle_event");
2478         set_tooltip(!disabled ? _("Disable proxy") : _("Enable proxy"));
2479         ProxyDialog *dialog = mwindow->gui->mainmenu->proxy->dialog;
2480         if( dialog && dialog->gui ) {
2481                 dialog->gui->lock_window("ProxyToggle::handle_event");
2482                 dialog->gui->update();
2483                 dialog->gui->unlock_window();
2484         }
2485         return 1;
2486 }
2487
2488 int ProxyToggle::keypress_event()
2489 {
2490         if( ctrl_down() && !shift_down() && !alt_down() ) {
2491                 int key = get_keypress();
2492                 if( key == 'r' ) {
2493                         int value = get_value() ? 0 : 1;
2494                         set_value(value);
2495                         return handle_event();
2496                 }
2497         }
2498         return context_help_check_and_show();
2499 }
2500