proxy cpus usage, unlock win before render_proxy, snap tweaks
[goodguy/history.git] / cinelerra-5.1 / cinelerra / mwindowmove.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 "automation.h"
23 #include "clip.h"
24 #include "cplayback.h"
25 #include "cwindow.h"
26 #include "cwindowgui.h"
27 #include "edits.h"
28 #include "edl.h"
29 #include "edlsession.h"
30 #include "labels.h"
31 #include "localsession.h"
32 #include "maincursor.h"
33 #include "mainmenu.h"
34 #include "mainsession.h"
35 #include "mtimebar.h"
36 #include "mwindow.h"
37 #include "mwindowgui.h"
38 #include "patchbay.h"
39 #include "playbackengine.h"
40 #include "plugin.h"
41 #include "resourcethread.h"
42 #include "samplescroll.h"
43 #include "theme.h"
44 #include "trackcanvas.h"
45 #include "tracks.h"
46 #include "transportque.h"
47 #include "zoombar.h"
48
49
50 void MWindow::update_plugins()
51 {
52 // Show plugins which are visible and hide plugins which aren't
53 // Update plugin pointers in plugin servers
54 }
55
56
57 int MWindow::expand_sample()
58 {
59         if(gui)
60         {
61                 if(edl->local_session->zoom_sample < 0x100000)
62                 {
63                         edl->local_session->zoom_sample *= 2;
64                         gui->zoombar->sample_zoom->update(edl->local_session->zoom_sample);
65                         zoom_sample(edl->local_session->zoom_sample);
66                 }
67         }
68         return 0;
69 }
70
71 int MWindow::zoom_in_sample()
72 {
73         if(gui)
74         {
75                 if(edl->local_session->zoom_sample > 1)
76                 {
77                         edl->local_session->zoom_sample /= 2;
78                         gui->zoombar->sample_zoom->update(edl->local_session->zoom_sample);
79                         zoom_sample(edl->local_session->zoom_sample);
80                 }
81         }
82         return 0;
83 }
84
85 int MWindow::zoom_sample(int64_t zoom_sample)
86 {
87         CLAMP(zoom_sample, 1, 0x100000);
88         edl->local_session->zoom_sample = zoom_sample;
89                 find_cursor();
90
91         TimelinePane *pane = gui->get_focused_pane();
92         samplemovement(edl->local_session->view_start[pane->number], pane->number);
93         return 0;
94 }
95
96 void MWindow::find_cursor()
97 {
98         TimelinePane *pane = gui->get_focused_pane();
99         edl->local_session->view_start[pane->number] =
100                 Units::round((edl->local_session->get_selectionend(1) +
101                 edl->local_session->get_selectionstart(1)) /
102                 2 *
103                 edl->session->sample_rate /
104                 edl->local_session->zoom_sample -
105                 (double)pane->canvas->get_w() /
106                 2);
107
108         if(edl->local_session->view_start[pane->number] < 0)
109                 edl->local_session->view_start[pane->number] = 0;
110 }
111
112
113 void MWindow::fit_selection()
114 {
115         if(EQUIV(edl->local_session->get_selectionstart(1),
116                 edl->local_session->get_selectionend(1)))
117         {
118                 double total_samples = edl->tracks->total_length() *
119                         edl->session->sample_rate;
120                 TimelinePane *pane = gui->get_focused_pane();
121                 for(edl->local_session->zoom_sample = 1;
122                         pane->canvas->get_w() * edl->local_session->zoom_sample < total_samples;
123                         edl->local_session->zoom_sample *= 2)
124                         ;
125         }
126         else
127         {
128                 double total_samples = (edl->local_session->get_selectionend(1) -
129                         edl->local_session->get_selectionstart(1)) *
130                         edl->session->sample_rate;
131                 TimelinePane *pane = gui->get_focused_pane();
132                 for(edl->local_session->zoom_sample = 1;
133                         pane->canvas->get_w() * edl->local_session->zoom_sample < total_samples;
134                         edl->local_session->zoom_sample *= 2)
135                         ;
136         }
137
138         edl->local_session->zoom_sample = MIN(0x100000,
139                 edl->local_session->zoom_sample);
140         zoom_sample(edl->local_session->zoom_sample);
141 }
142
143
144 void MWindow::fit_autos(int doall)
145 {
146         float min = 0, max = 0;
147         double start, end;
148
149 // Test all autos
150         if(EQUIV(edl->local_session->get_selectionstart(1),
151                 edl->local_session->get_selectionend(1)))
152         {
153                 start = 0;
154                 end = edl->tracks->total_length();
155         }
156         else
157 // Test autos in highlighting only
158         {
159                 start = edl->local_session->get_selectionstart(1);
160                 end = edl->local_session->get_selectionend(1);
161         }
162
163         int forstart = edl->local_session->zoombar_showautotype;
164         int forend   = edl->local_session->zoombar_showautotype + 1;
165
166         if (doall) {
167                 forstart = 0;
168                 forend   = AUTOGROUPTYPE_COUNT;
169         }
170
171         for (int i = forstart; i < forend; i++)
172         {
173 // Adjust min and max
174                 edl->tracks->get_automation_extents(&min, &max, start, end, i);
175 //printf("MWindow::fit_autos %d %f %f results in ", i, min, max);
176
177                 float range = max - min;
178                 switch (i)
179                 {
180                 case AUTOGROUPTYPE_AUDIO_FADE:
181                 case AUTOGROUPTYPE_VIDEO_FADE:
182                         if (range < 0.1) {
183                                 min = MIN(min, edl->local_session->automation_mins[i]);
184                                 max = MAX(max, edl->local_session->automation_maxs[i]);
185                         }
186                         break;
187                 case AUTOGROUPTYPE_ZOOM:
188                         if (range < 0.001) {
189                                 min = floor(min*50)/100;
190                                 max = floor(max*200)/100;
191                         }
192                         break;
193                 case AUTOGROUPTYPE_SPEED:
194                         if (range < 0.001) {
195                                 min = floor(min*5)/100;
196                                 max = floor(max*300)/100;
197                         }
198                         break;
199                 case AUTOGROUPTYPE_X:
200                 case AUTOGROUPTYPE_Y:
201                         if (range < 5) {
202                                 min = floor((min+max)/2) - 50;
203                                 max = floor((min+max)/2) + 50;
204                         }
205                         break;
206                 }
207 //printf("%f %f\n", min, max);
208                 if (!Automation::autogrouptypes_fixedrange[i])
209                 {
210                         edl->local_session->automation_mins[i] = min;
211                         edl->local_session->automation_maxs[i] = max;
212                 }
213         }
214
215 // Show range in zoombar
216         gui->zoombar->update();
217
218 // Draw
219         gui->draw_overlays(1);
220 }
221
222
223 void MWindow::change_currentautorange(int autogrouptype, int increment, int changemax)
224 {
225         float val;
226         if (changemax) {
227                 val = edl->local_session->automation_maxs[autogrouptype];
228         } else {
229                 val = edl->local_session->automation_mins[autogrouptype];
230         }
231
232         if (increment)
233         {
234                 switch (autogrouptype) {
235                 case AUTOGROUPTYPE_AUDIO_FADE:
236                         val += 2;
237                         break;
238                 case AUTOGROUPTYPE_VIDEO_FADE:
239                         val += 1;
240                         break;
241                 case AUTOGROUPTYPE_ZOOM:
242                 case AUTOGROUPTYPE_SPEED:
243                         if (val == 0)
244                                 val = 0.001;
245                         else
246                                 val = val*2;
247                         break;
248                 case AUTOGROUPTYPE_X:
249                 case AUTOGROUPTYPE_Y:
250                         val = floor(val + 5);
251                         break;
252                 }
253         }
254         else
255         { // decrement
256                 switch (autogrouptype) {
257                 case AUTOGROUPTYPE_AUDIO_FADE:
258                         val -= 2;
259                         break;
260                 case AUTOGROUPTYPE_VIDEO_FADE:
261                         val -= 1;
262                         break;
263                 case AUTOGROUPTYPE_ZOOM:
264                 case AUTOGROUPTYPE_SPEED:
265                         if (val > 0) val = val/2;
266                         break;
267                 case AUTOGROUPTYPE_X:
268                 case AUTOGROUPTYPE_Y:
269                         val = floor(val-5);
270                         break;
271                 }
272         }
273
274         AUTOMATIONVIEWCLAMPS(val, autogrouptype);
275
276         if (changemax) {
277                 if (val > edl->local_session->automation_mins[autogrouptype])
278                         edl->local_session->automation_maxs[autogrouptype] = val;
279         }
280         else
281         {
282                 if (val < edl->local_session->automation_maxs[autogrouptype])
283                         edl->local_session->automation_mins[autogrouptype] = val;
284         }
285 }
286
287
288 void MWindow::expand_autos(int changeall, int domin, int domax)
289 {
290         if (changeall)
291                 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
292                         if (domin) change_currentautorange(i, 1, 0);
293                         if (domax) change_currentautorange(i, 1, 1);
294                 }
295         else
296         {
297                 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 0);
298                 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 1);
299         }
300         gui->zoombar->update_autozoom();
301         gui->draw_overlays(0);
302         gui->update_patchbay();
303         gui->flash_canvas(1);
304 }
305
306 void MWindow::shrink_autos(int changeall, int domin, int domax)
307 {
308         if (changeall)
309                 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
310                         if (domin) change_currentautorange(i, 0, 0);
311                         if (domax) change_currentautorange(i, 0, 1);
312                 }
313         else
314         {
315                 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 0);
316                 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 1);
317         }
318         gui->zoombar->update_autozoom();
319         gui->draw_overlays(0);
320         gui->update_patchbay();
321         gui->flash_canvas(1);
322 }
323
324
325 void MWindow::zoom_autos(float min, float max)
326 {
327         int i = edl->local_session->zoombar_showautotype;
328         edl->local_session->automation_mins[i] = min;
329         edl->local_session->automation_maxs[i] = max;
330         gui->zoombar->update_autozoom();
331         gui->draw_overlays(1);
332 }
333
334
335 void MWindow::zoom_amp(int64_t zoom_amp)
336 {
337         edl->local_session->zoom_y = zoom_amp;
338         gui->draw_canvas(0, 0);
339         gui->flash_canvas(0);
340         gui->update_patchbay();
341         gui->flush();
342 }
343
344 void MWindow::zoom_track(int64_t zoom_track)
345 {
346 // scale waveforms
347         edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y *
348                 zoom_track /
349                 edl->local_session->zoom_track);
350         CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
351
352 // scale tracks
353         double scale = (double)zoom_track / edl->local_session->zoom_track;
354         edl->local_session->zoom_track = zoom_track;
355
356 // shift row position
357         for(int i = 0; i < TOTAL_PANES; i++)
358         {
359                 edl->local_session->track_start[i] *= scale;
360         }
361         edl->tracks->update_y_pixels(theme);
362         gui->draw_trackmovement();
363 //printf("MWindow::zoom_track %d %d\n", edl->local_session->zoom_y, edl->local_session->zoom_track);
364 }
365
366 void MWindow::trackmovement(int offset, int pane_number)
367 {
368         edl->local_session->track_start[pane_number] += offset;
369         if(edl->local_session->track_start[pane_number] < 0)
370                 edl->local_session->track_start[pane_number] = 0;
371
372         if(pane_number == TOP_RIGHT_PANE ||
373                 pane_number == TOP_LEFT_PANE)
374         {
375                 edl->local_session->track_start[TOP_LEFT_PANE] =
376                         edl->local_session->track_start[TOP_RIGHT_PANE] =
377                         edl->local_session->track_start[pane_number];
378         }
379         else
380         if(pane_number == BOTTOM_RIGHT_PANE ||
381                 pane_number == BOTTOM_LEFT_PANE)
382         {
383                 edl->local_session->track_start[BOTTOM_LEFT_PANE] =
384                         edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
385                         edl->local_session->track_start[pane_number];
386         }
387
388
389         edl->tracks->update_y_pixels(theme);
390         gui->draw_trackmovement();
391 }
392
393 void MWindow::move_up(int64_t distance)
394 {
395         TimelinePane *pane = gui->get_focused_pane();
396         if(distance == 0) distance = edl->local_session->zoom_track;
397
398         trackmovement(-distance, pane->number);
399 }
400
401 void MWindow::move_down(int64_t distance)
402 {
403         TimelinePane *pane = gui->get_focused_pane();
404         if(distance == 0) distance = edl->local_session->zoom_track;
405
406         trackmovement(distance, pane->number);
407 }
408
409 int MWindow::goto_end()
410 {
411         TimelinePane *pane = gui->get_focused_pane();
412         int64_t old_view_start = edl->local_session->view_start[pane->number];
413
414         if(edl->tracks->total_length() > (double)pane->canvas->get_w() *
415                 edl->local_session->zoom_sample /
416                 edl->session->sample_rate)
417         {
418                 edl->local_session->view_start[pane->number] =
419                         Units::round(edl->tracks->total_length() *
420                                 edl->session->sample_rate /
421                                 edl->local_session->zoom_sample -
422                                 pane->canvas->get_w() /
423                                 2);
424         }
425         else
426         {
427                 edl->local_session->view_start[pane->number] = 0;
428         }
429
430         if(gui->shift_down())
431         {
432                 edl->local_session->set_selectionend(edl->tracks->total_length());
433         }
434         else
435         {
436                 edl->local_session->set_selectionstart(edl->tracks->total_length());
437                 edl->local_session->set_selectionend(edl->tracks->total_length());
438         }
439
440         if(edl->local_session->view_start[pane->number] != old_view_start)
441         {
442                 samplemovement(edl->local_session->view_start[pane->number], pane->number);
443                 gui->draw_samplemovement();
444         }
445
446         update_plugin_guis();
447
448         gui->update_patchbay();
449         gui->update_cursor();
450         gui->activate_timeline();
451         gui->zoombar->update();
452         gui->update_timebar(1);
453         cwindow->update(1, 0, 0, 0, 1);
454         return 0;
455 }
456
457 int MWindow::goto_start()
458 {
459         TimelinePane *pane = gui->get_focused_pane();
460         int64_t old_view_start = edl->local_session->view_start[pane->number];
461
462         edl->local_session->view_start[pane->number] = 0;
463         if(gui->shift_down())
464         {
465                 edl->local_session->set_selectionstart(0);
466         }
467         else
468         {
469                 edl->local_session->set_selectionstart(0);
470                 edl->local_session->set_selectionend(0);
471         }
472
473         if(edl->local_session->view_start[pane->number] != old_view_start)
474         {
475                 samplemovement(edl->local_session->view_start[pane->number], pane->number);
476                 gui->draw_samplemovement();
477         }
478
479         update_plugin_guis();
480         gui->update_patchbay();
481         gui->update_cursor();
482         gui->activate_timeline();
483         gui->zoombar->update();
484         gui->update_timebar(1);
485         cwindow->update(1, 0, 0, 0, 1);
486         return 0;
487 }
488
489 int MWindow::goto_position(double position)
490 {
491         TimelinePane *pane = gui->get_focused_pane();
492         int64_t old_view_start = edl->local_session->view_start[pane->number];
493         edl->local_session->set_selectionstart(position);
494         edl->local_session->set_selectionend(position);
495         find_cursor();
496         int64_t new_view_start = edl->local_session->view_start[pane->number];
497         if(new_view_start != old_view_start)
498                 samplemovement(new_view_start, pane->number);
499         update_plugin_guis();
500         gui->update_patchbay();
501         gui->update_cursor();
502         gui->activate_timeline();
503         gui->zoombar->update();
504         gui->update_timebar(1);
505         cwindow->update(1, 0, 0, 0, 1);
506         return 0;
507 }
508
509 int MWindow::samplemovement(int64_t view_start, int pane_number)
510 {
511         if( view_start < 0 ) view_start = 0;
512         edl->local_session->view_start[pane_number] = view_start;
513         if(edl->local_session->view_start[pane_number] < 0)
514                 edl->local_session->view_start[pane_number] = 0;
515
516         if(pane_number == TOP_LEFT_PANE ||
517                 pane_number == BOTTOM_LEFT_PANE)
518         {
519                 edl->local_session->view_start[TOP_LEFT_PANE] =
520                         edl->local_session->view_start[BOTTOM_LEFT_PANE] =
521                         edl->local_session->view_start[pane_number];
522         }
523         else
524         {
525                 edl->local_session->view_start[TOP_RIGHT_PANE] =
526                         edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
527                         edl->local_session->view_start[pane_number];
528         }
529
530         gui->draw_samplemovement();
531
532         return 0;
533 }
534
535 int MWindow::move_left(int64_t distance)
536 {
537         TimelinePane *pane = gui->get_focused_pane();
538         if(!distance)
539                 distance = pane->canvas->get_w() /
540                         10;
541         edl->local_session->view_start[pane->number] -= distance;
542         samplemovement(edl->local_session->view_start[pane->number],
543                 pane->number);
544         return 0;
545 }
546
547 int MWindow::move_right(int64_t distance)
548 {
549         TimelinePane *pane = gui->get_focused_pane();
550         if(!distance)
551                 distance = pane->canvas->get_w() /
552                         10;
553         edl->local_session->view_start[pane->number] += distance;
554         samplemovement(edl->local_session->view_start[pane->number],
555                 pane->number);
556         return 0;
557 }
558
559 void MWindow::select_all()
560 {
561         if( edl->local_session->get_selectionstart(1) == 0 &&
562             edl->local_session->get_selectionend(1) == edl->tracks->total_length() )
563                 edl->local_session->set_selectionend(0);
564         else {
565                 edl->local_session->set_selectionstart(0);
566                 edl->local_session->set_selectionend(edl->tracks->total_length());
567         }
568         gui->update(0, 1, 1, 1, 0, 1, 0);
569         gui->activate_timeline();
570         cwindow->update(1, 0, 0, 0, 1);
571         update_plugin_guis();
572 }
573
574 int MWindow::next_label(int shift_down)
575 {
576         double cursor_position = edl->local_session->get_selectionstart(1);
577         Label *current = edl->labels->next_label(cursor_position);
578         double position = !current ? -1 : current->position;
579
580 // last playback endpoints as fake label positions
581         double playback_start = edl->local_session->playback_start;
582         double playback_end = edl->local_session->playback_end;
583         if( playback_start > cursor_position && ( position < 0 || playback_start < position ) )
584                 position = playback_start;
585         else if( playback_end > cursor_position && ( position < 0 || playback_end < position ) )
586                 position = playback_end;
587
588         if( position >= 0 ) {
589                 edl->local_session->set_selectionend(position);
590                 if(!shift_down)
591                         edl->local_session->set_selectionstart(
592                                 edl->local_session->get_selectionend(1));
593
594                 update_plugin_guis();
595                 TimelinePane *pane = gui->get_focused_pane();
596                 if(edl->local_session->get_selectionend(1) >=
597                         (double)edl->local_session->view_start[pane->number] *
598                                 edl->local_session->zoom_sample /
599                                 edl->session->sample_rate +
600                                 pane->canvas->time_visible() ||
601                         edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
602                                 edl->local_session->zoom_sample /
603                                 edl->session->sample_rate)
604                 {
605                         samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
606                                 edl->session->sample_rate /
607                                 edl->local_session->zoom_sample -
608                                 pane->canvas->get_w() /
609                                 2),
610                                 pane->number);
611                         cwindow->update(1, 0, 0, 0, 0);
612                 }
613                 else
614                 {
615                         gui->update_patchbay();
616                         gui->update_timebar(0);
617                         gui->hide_cursor(0);
618                         gui->draw_cursor(0);
619                         gui->zoombar->update();
620                         gui->flash_canvas(1);
621                         cwindow->update(1, 0, 0, 0, 1);
622                 }
623         }
624         else
625         {
626                 goto_end();
627         }
628         return 0;
629 }
630
631 int MWindow::prev_label(int shift_down)
632 {
633         double cursor_position = edl->local_session->get_selectionstart(1);
634         Label *current = edl->labels->prev_label(cursor_position);
635         double position = !current ? -1 : current->position;
636
637 // last playback endpoints as fake label positions
638         double playback_start = edl->local_session->playback_start;
639         double playback_end = edl->local_session->playback_end;
640         if( playback_end < cursor_position && ( position < 0 || playback_end > position ) )
641                 position = playback_end;
642         else if( playback_start < cursor_position && ( position < 0 || playback_start > position ) )
643                 position = playback_start;
644
645         if( position >= 0 ) {
646                 edl->local_session->set_selectionstart(position);
647                 if(!shift_down)
648                         edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
649
650                 update_plugin_guis();
651                 TimelinePane *pane = gui->get_focused_pane();
652                 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
653                         edl->local_session->zoom_sample /
654                         edl->session->sample_rate +
655                         pane->canvas->time_visible()
656                 ||
657                         edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
658                         edl->local_session->zoom_sample /
659                         edl->session->sample_rate)
660                 {
661                         samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
662                                 edl->session->sample_rate /
663                                 edl->local_session->zoom_sample -
664                                 pane->canvas->get_w() /
665                                 2),
666                                 pane->number);
667                         cwindow->update(1, 0, 0, 0, 0);
668                 }
669                 else
670 // Don't scroll the display
671                 {
672                         gui->update_patchbay();
673                         gui->update_timebar(0);
674                         gui->hide_cursor(0);
675                         gui->draw_cursor(0);
676                         gui->zoombar->update();
677                         gui->flash_canvas(1);
678                         cwindow->update(1, 0, 0, 0, 1);
679                 }
680         }
681         else
682         {
683                 goto_start();
684         }
685         return 0;
686 }
687
688
689
690
691
692
693 int MWindow::next_edit_handle(int shift_down)
694 {
695         double position = edl->local_session->get_selectionend(1);
696         Units::fix_double(&position);
697         double new_position = INFINITY;
698
699         double max_rate = edl->get_frame_rate();
700         int sample_rate = edl->get_sample_rate();
701         if( sample_rate > max_rate ) max_rate = sample_rate;
702         double min_movement = max_rate > 0 ? 1. / max_rate : 1e-6;
703
704 // Test for edit handles after cursor position
705         for (Track *track = edl->tracks->first; track; track = track->next)
706         {
707                 if (track->record)
708                 {
709                         for (Edit *edit = track->edits->first; edit; edit = edit->next)
710                         {
711                                 double edit_end = track->from_units(edit->startproject + edit->length);
712                                 Units::fix_double(&edit_end);
713                                 if( fabs(edit_end-position) < min_movement ) continue;
714                                 if (edit_end > position && edit_end < new_position)
715                                         new_position = edit_end;
716                         }
717                 }
718         }
719
720         if(new_position != INFINITY)
721         {
722
723                 edl->local_session->set_selectionend(new_position);
724 //printf("MWindow::next_edit_handle %d\n", shift_down);
725                 if(!shift_down)
726                         edl->local_session->set_selectionstart(
727                                 edl->local_session->get_selectionend(1));
728
729                 update_plugin_guis();
730                 TimelinePane *pane = gui->get_focused_pane();
731                 if(edl->local_session->get_selectionend(1) >=
732                         (double)edl->local_session->view_start[pane->number] *
733                         edl->local_session->zoom_sample /
734                         edl->session->sample_rate +
735                         pane->canvas->time_visible() ||
736                         edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
737                         edl->local_session->zoom_sample /
738                         edl->session->sample_rate)
739                 {
740                         samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
741                                 edl->session->sample_rate /
742                                 edl->local_session->zoom_sample -
743                                 pane->canvas->get_w() /
744                                 2),
745                                 pane->number);
746                         cwindow->update(1, 0, 0, 0, 0);
747                 }
748                 else
749                 {
750                         gui->update_patchbay();
751                         gui->update_timebar(0);
752                         gui->hide_cursor(0);
753                         gui->draw_cursor(0);
754                         gui->zoombar->update();
755                         gui->flash_canvas(1);
756                         cwindow->update(1, 0, 0, 0, 1);
757                 }
758         }
759         else
760         {
761                 goto_end();
762         }
763         return 0;
764 }
765
766 int MWindow::prev_edit_handle(int shift_down)
767 {
768         double position = edl->local_session->get_selectionstart(1);
769         double new_position = -1;
770         Units::fix_double(&position);
771
772         double max_rate = edl->get_frame_rate();
773         int sample_rate = edl->get_sample_rate();
774         if( sample_rate > max_rate ) max_rate = sample_rate;
775         double min_movement = max_rate > 0 ? 1. / max_rate : 1e-6;
776
777 // Test for edit handles before cursor position
778         for (Track *track = edl->tracks->first; track; track = track->next)
779         {
780                 if (track->record)
781                 {
782                         for (Edit *edit = track->edits->first; edit; edit = edit->next)
783                         {
784                                 double edit_end = track->from_units(edit->startproject);
785                                 Units::fix_double(&edit_end);
786                                 if( fabs(edit_end-position) < min_movement ) continue;
787                                 if (edit_end < position && edit_end > new_position)
788                                         new_position = edit_end;
789                         }
790                 }
791         }
792
793         if(new_position != -1)
794         {
795
796                 edl->local_session->set_selectionstart(new_position);
797 //printf("MWindow::next_edit_handle %d\n", shift_down);
798                 if(!shift_down)
799                         edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
800
801                 update_plugin_guis();
802 // Scroll the display
803                 TimelinePane *pane = gui->get_focused_pane();
804                 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
805                         edl->local_session->zoom_sample /
806                         edl->session->sample_rate +
807                         pane->canvas->time_visible()
808                 ||
809                         edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
810                         edl->local_session->zoom_sample /
811                         edl->session->sample_rate)
812                 {
813                         samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
814                                 edl->session->sample_rate /
815                                 edl->local_session->zoom_sample -
816                                 pane->canvas->get_w() /
817                                 2),
818                                 pane->number);
819                         cwindow->update(1, 0, 0, 0, 0);
820                 }
821                 else
822 // Don't scroll the display
823                 {
824                         gui->update_patchbay();
825                         gui->update_timebar(0);
826                         gui->hide_cursor(0);
827                         gui->draw_cursor(0);
828                         gui->zoombar->update();
829                         gui->flash_canvas(1);
830                         cwindow->update(1, 0, 0, 0, 1);
831                 }
832         }
833         else
834         {
835                 goto_start();
836         }
837         return 0;
838 }
839
840
841
842
843
844
845
846
847 int MWindow::expand_y()
848 {
849         int result = edl->local_session->zoom_y * 2;
850         result = MIN(result, MAX_AMP_ZOOM);
851         zoom_amp(result);
852         gui->zoombar->update();
853         return 0;
854 }
855
856 int MWindow::zoom_in_y()
857 {
858         int result = edl->local_session->zoom_y / 2;
859         result = MAX(result, MIN_AMP_ZOOM);
860         zoom_amp(result);
861         gui->zoombar->update();
862         return 0;
863 }
864
865 int MWindow::expand_t()
866 {
867         int result = edl->local_session->zoom_track * 2;
868         result = MIN(result, MAX_TRACK_ZOOM);
869         zoom_track(result);
870         gui->zoombar->update();
871         return 0;
872 }
873
874 int MWindow::zoom_in_t()
875 {
876         int result = edl->local_session->zoom_track / 2;
877         result = MAX(result, MIN_TRACK_ZOOM);
878         zoom_track(result);
879         gui->zoombar->update();
880         return 0;
881 }
882
883 void MWindow::split_x()
884 {
885         gui->resource_thread->stop_draw(1);
886
887         if(gui->pane[TOP_RIGHT_PANE])
888         {
889                 gui->delete_x_pane(theme->mcanvas_w);
890                 edl->local_session->x_pane = -1;
891         }
892         else
893         {
894                 gui->create_x_pane(theme->mcanvas_w / 2);
895                 edl->local_session->x_pane = theme->mcanvas_w / 2;
896         }
897
898         gui->mainmenu->update_toggles(0);
899         gui->update_pane_dividers();
900         gui->update_cursor();
901         gui->draw_samplemovement();
902 // required to get new widgets to appear
903         gui->show_window();
904
905         gui->resource_thread->start_draw();
906 }
907
908 void MWindow::split_y()
909 {
910         gui->resource_thread->stop_draw(1);
911         if(gui->pane[BOTTOM_LEFT_PANE])
912         {
913                 gui->delete_y_pane(theme->mcanvas_h);
914                 edl->local_session->y_pane = -1;
915         }
916         else
917         {
918                 gui->create_y_pane(theme->mcanvas_h / 2);
919                 edl->local_session->y_pane = theme->mcanvas_h / 2;
920         }
921
922         gui->mainmenu->update_toggles(0);
923         gui->update_pane_dividers();
924         gui->update_cursor();
925         gui->draw_trackmovement();
926 // required to get new widgets to appear
927         gui->show_window();
928         gui->resource_thread->start_draw();
929 }
930
931