4 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "automation.h"
24 #include "cplayback.h"
26 #include "cwindowgui.h"
29 #include "edlsession.h"
31 #include "localsession.h"
32 #include "maincursor.h"
34 #include "mainsession.h"
37 #include "mwindowgui.h"
39 #include "playbackengine.h"
41 #include "resourcethread.h"
42 #include "samplescroll.h"
44 #include "trackcanvas.h"
46 #include "transportque.h"
50 void MWindow::update_plugins()
52 // Show plugins which are visible and hide plugins which aren't
53 // Update plugin pointers in plugin servers
57 int MWindow::expand_sample()
61 if(edl->local_session->zoom_sample < 0x100000)
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);
71 int MWindow::zoom_in_sample()
75 if(edl->local_session->zoom_sample > 1)
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);
85 int MWindow::zoom_sample(int64_t zoom_sample)
87 CLAMP(zoom_sample, 1, 0x100000);
88 edl->local_session->zoom_sample = zoom_sample;
91 TimelinePane *pane = gui->get_focused_pane();
92 samplemovement(edl->local_session->view_start[pane->number], pane->number);
96 void MWindow::find_cursor()
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)) /
103 edl->session->sample_rate /
104 edl->local_session->zoom_sample -
105 (double)pane->canvas->get_w() /
108 if(edl->local_session->view_start[pane->number] < 0)
109 edl->local_session->view_start[pane->number] = 0;
113 void MWindow::fit_selection()
115 if(EQUIV(edl->local_session->get_selectionstart(1),
116 edl->local_session->get_selectionend(1)))
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)
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)
138 edl->local_session->zoom_sample = MIN(0x100000,
139 edl->local_session->zoom_sample);
140 zoom_sample(edl->local_session->zoom_sample);
144 void MWindow::fit_autos(int doall)
146 float min = 0, max = 0;
150 if(EQUIV(edl->local_session->get_selectionstart(1),
151 edl->local_session->get_selectionend(1)))
154 end = edl->tracks->total_length();
157 // Test autos in highlighting only
159 start = edl->local_session->get_selectionstart(1);
160 end = edl->local_session->get_selectionend(1);
163 int forstart = edl->local_session->zoombar_showautotype;
164 int forend = edl->local_session->zoombar_showautotype + 1;
168 forend = AUTOGROUPTYPE_COUNT;
171 for (int i = forstart; i < forend; i++)
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);
177 float range = max - min;
180 case AUTOGROUPTYPE_AUDIO_FADE:
181 case AUTOGROUPTYPE_VIDEO_FADE:
183 min = MIN(min, edl->local_session->automation_mins[i]);
184 max = MAX(max, edl->local_session->automation_maxs[i]);
187 case AUTOGROUPTYPE_ZOOM:
189 min = floor(min*50)/100;
190 max = floor(max*200)/100;
193 case AUTOGROUPTYPE_X:
194 case AUTOGROUPTYPE_Y:
196 min = floor((min+max)/2) - 50;
197 max = floor((min+max)/2) + 50;
201 //printf("%f %f\n", min, max);
202 if (!Automation::autogrouptypes_fixedrange[i])
204 edl->local_session->automation_mins[i] = min;
205 edl->local_session->automation_maxs[i] = max;
209 // Show range in zoombar
210 gui->zoombar->update();
213 gui->draw_overlays(1);
217 void MWindow::change_currentautorange(int autogrouptype, int increment, int changemax)
221 val = edl->local_session->automation_maxs[autogrouptype];
223 val = edl->local_session->automation_mins[autogrouptype];
228 switch (autogrouptype) {
229 case AUTOGROUPTYPE_AUDIO_FADE:
232 case AUTOGROUPTYPE_VIDEO_FADE:
235 case AUTOGROUPTYPE_ZOOM:
241 case AUTOGROUPTYPE_X:
242 case AUTOGROUPTYPE_Y:
243 val = floor(val + 5);
249 switch (autogrouptype) {
250 case AUTOGROUPTYPE_AUDIO_FADE:
253 case AUTOGROUPTYPE_VIDEO_FADE:
256 case AUTOGROUPTYPE_ZOOM:
257 if (val > 0) val = val/2;
259 case AUTOGROUPTYPE_X:
260 case AUTOGROUPTYPE_Y:
266 AUTOMATIONVIEWCLAMPS(val, autogrouptype);
269 if (val > edl->local_session->automation_mins[autogrouptype])
270 edl->local_session->automation_maxs[autogrouptype] = val;
274 if (val < edl->local_session->automation_maxs[autogrouptype])
275 edl->local_session->automation_mins[autogrouptype] = val;
280 void MWindow::expand_autos(int changeall, int domin, int domax)
283 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
284 if (domin) change_currentautorange(i, 1, 0);
285 if (domax) change_currentautorange(i, 1, 1);
289 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 0);
290 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 1);
292 gui->zoombar->update_autozoom();
293 gui->draw_overlays(0);
294 gui->update_patchbay();
295 gui->flash_canvas(1);
298 void MWindow::shrink_autos(int changeall, int domin, int domax)
301 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
302 if (domin) change_currentautorange(i, 0, 0);
303 if (domax) change_currentautorange(i, 0, 1);
307 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 0);
308 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 1);
310 gui->zoombar->update_autozoom();
311 gui->draw_overlays(0);
312 gui->update_patchbay();
313 gui->flash_canvas(1);
317 void MWindow::zoom_autos(float min, float max)
319 int i = edl->local_session->zoombar_showautotype;
320 edl->local_session->automation_mins[i] = min;
321 edl->local_session->automation_maxs[i] = max;
322 gui->zoombar->update_autozoom();
323 gui->draw_overlays(1);
327 void MWindow::zoom_amp(int64_t zoom_amp)
329 edl->local_session->zoom_y = zoom_amp;
330 gui->draw_canvas(0, 0);
331 gui->flash_canvas(0);
332 gui->update_patchbay();
336 void MWindow::zoom_track(int64_t zoom_track)
339 edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y *
341 edl->local_session->zoom_track);
342 CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
345 double scale = (double)zoom_track / edl->local_session->zoom_track;
346 edl->local_session->zoom_track = zoom_track;
348 // shift row position
349 for(int i = 0; i < TOTAL_PANES; i++)
351 edl->local_session->track_start[i] *= scale;
353 edl->tracks->update_y_pixels(theme);
354 gui->draw_trackmovement();
355 //printf("MWindow::zoom_track %d %d\n", edl->local_session->zoom_y, edl->local_session->zoom_track);
358 void MWindow::trackmovement(int offset, int pane_number)
360 edl->local_session->track_start[pane_number] += offset;
361 if(edl->local_session->track_start[pane_number] < 0)
362 edl->local_session->track_start[pane_number] = 0;
364 if(pane_number == TOP_RIGHT_PANE ||
365 pane_number == TOP_LEFT_PANE)
367 edl->local_session->track_start[TOP_LEFT_PANE] =
368 edl->local_session->track_start[TOP_RIGHT_PANE] =
369 edl->local_session->track_start[pane_number];
372 if(pane_number == BOTTOM_RIGHT_PANE ||
373 pane_number == BOTTOM_LEFT_PANE)
375 edl->local_session->track_start[BOTTOM_LEFT_PANE] =
376 edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
377 edl->local_session->track_start[pane_number];
381 edl->tracks->update_y_pixels(theme);
382 gui->draw_trackmovement();
385 void MWindow::move_up(int64_t distance)
387 TimelinePane *pane = gui->get_focused_pane();
388 if(distance == 0) distance = edl->local_session->zoom_track;
390 trackmovement(-distance, pane->number);
393 void MWindow::move_down(int64_t distance)
395 TimelinePane *pane = gui->get_focused_pane();
396 if(distance == 0) distance = edl->local_session->zoom_track;
398 trackmovement(distance, pane->number);
401 int MWindow::goto_end()
403 TimelinePane *pane = gui->get_focused_pane();
404 int64_t old_view_start = edl->local_session->view_start[pane->number];
406 if(edl->tracks->total_length() > (double)pane->canvas->get_w() *
407 edl->local_session->zoom_sample /
408 edl->session->sample_rate)
410 edl->local_session->view_start[pane->number] =
411 Units::round(edl->tracks->total_length() *
412 edl->session->sample_rate /
413 edl->local_session->zoom_sample -
414 pane->canvas->get_w() /
419 edl->local_session->view_start[pane->number] = 0;
422 if(gui->shift_down())
424 edl->local_session->set_selectionend(edl->tracks->total_length());
428 edl->local_session->set_selectionstart(edl->tracks->total_length());
429 edl->local_session->set_selectionend(edl->tracks->total_length());
432 if(edl->local_session->view_start[pane->number] != old_view_start)
434 samplemovement(edl->local_session->view_start[pane->number], pane->number);
435 gui->draw_samplemovement();
438 update_plugin_guis();
440 gui->update_patchbay();
441 gui->update_cursor();
442 gui->activate_timeline();
443 gui->zoombar->update();
444 gui->update_timebar(1);
445 cwindow->update(1, 0, 0, 0, 1);
449 int MWindow::goto_start()
451 TimelinePane *pane = gui->get_focused_pane();
452 int64_t old_view_start = edl->local_session->view_start[pane->number];
454 edl->local_session->view_start[pane->number] = 0;
455 if(gui->shift_down())
457 edl->local_session->set_selectionstart(0);
461 edl->local_session->set_selectionstart(0);
462 edl->local_session->set_selectionend(0);
465 if(edl->local_session->view_start[pane->number] != old_view_start)
467 samplemovement(edl->local_session->view_start[pane->number], pane->number);
468 gui->draw_samplemovement();
471 update_plugin_guis();
472 gui->update_patchbay();
473 gui->update_cursor();
474 gui->activate_timeline();
475 gui->zoombar->update();
476 gui->update_timebar(1);
477 cwindow->update(1, 0, 0, 0, 1);
481 int MWindow::goto_position(double position)
483 TimelinePane *pane = gui->get_focused_pane();
484 int64_t old_view_start = edl->local_session->view_start[pane->number];
485 edl->local_session->set_selectionstart(position);
486 edl->local_session->set_selectionend(position);
488 int64_t new_view_start = edl->local_session->view_start[pane->number];
489 if(new_view_start != old_view_start)
490 samplemovement(new_view_start, pane->number);
491 update_plugin_guis();
492 gui->update_patchbay();
493 gui->update_cursor();
494 gui->activate_timeline();
495 gui->zoombar->update();
496 gui->update_timebar(1);
497 cwindow->update(1, 0, 0, 0, 1);
501 int MWindow::samplemovement(int64_t view_start, int pane_number)
503 if( view_start < 0 ) view_start = 0;
504 edl->local_session->view_start[pane_number] = view_start;
505 if(edl->local_session->view_start[pane_number] < 0)
506 edl->local_session->view_start[pane_number] = 0;
508 if(pane_number == TOP_LEFT_PANE ||
509 pane_number == BOTTOM_LEFT_PANE)
511 edl->local_session->view_start[TOP_LEFT_PANE] =
512 edl->local_session->view_start[BOTTOM_LEFT_PANE] =
513 edl->local_session->view_start[pane_number];
517 edl->local_session->view_start[TOP_RIGHT_PANE] =
518 edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
519 edl->local_session->view_start[pane_number];
522 gui->draw_samplemovement();
527 int MWindow::move_left(int64_t distance)
529 TimelinePane *pane = gui->get_focused_pane();
531 distance = pane->canvas->get_w() /
533 edl->local_session->view_start[pane->number] -= distance;
534 samplemovement(edl->local_session->view_start[pane->number],
539 int MWindow::move_right(int64_t distance)
541 TimelinePane *pane = gui->get_focused_pane();
543 distance = pane->canvas->get_w() /
545 edl->local_session->view_start[pane->number] += distance;
546 samplemovement(edl->local_session->view_start[pane->number],
551 void MWindow::select_all()
553 if( edl->local_session->get_selectionstart(1) == 0 &&
554 edl->local_session->get_selectionend(1) == edl->tracks->total_length() )
555 edl->local_session->set_selectionend(0);
557 edl->local_session->set_selectionstart(0);
558 edl->local_session->set_selectionend(edl->tracks->total_length());
560 gui->update(0, 1, 1, 1, 0, 1, 0);
561 gui->activate_timeline();
562 cwindow->update(1, 0, 0, 0, 1);
563 update_plugin_guis();
566 int MWindow::next_label(int shift_down)
568 double cursor_position = edl->local_session->get_selectionstart(1);
569 Label *current = edl->labels->next_label(cursor_position);
570 double position = !current ? -1 : current->position;
572 // last playback endpoints as fake label positions
573 double playback_start = edl->local_session->playback_start;
574 double playback_end = edl->local_session->playback_end;
575 if( playback_start > cursor_position && ( position < 0 || playback_start < position ) )
576 position = playback_start;
577 else if( playback_end > cursor_position && ( position < 0 || playback_end < position ) )
578 position = playback_end;
580 if( position >= 0 ) {
581 edl->local_session->set_selectionend(position);
583 edl->local_session->set_selectionstart(
584 edl->local_session->get_selectionend(1));
586 update_plugin_guis();
587 TimelinePane *pane = gui->get_focused_pane();
588 if(edl->local_session->get_selectionend(1) >=
589 (double)edl->local_session->view_start[pane->number] *
590 edl->local_session->zoom_sample /
591 edl->session->sample_rate +
592 pane->canvas->time_visible() ||
593 edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
594 edl->local_session->zoom_sample /
595 edl->session->sample_rate)
597 samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
598 edl->session->sample_rate /
599 edl->local_session->zoom_sample -
600 pane->canvas->get_w() /
603 cwindow->update(1, 0, 0, 0, 0);
607 gui->update_patchbay();
608 gui->update_timebar(0);
611 gui->zoombar->update();
612 gui->flash_canvas(1);
613 cwindow->update(1, 0, 0, 0, 1);
623 int MWindow::prev_label(int shift_down)
625 double cursor_position = edl->local_session->get_selectionstart(1);
626 Label *current = edl->labels->prev_label(cursor_position);
627 double position = !current ? -1 : current->position;
629 // last playback endpoints as fake label positions
630 double playback_start = edl->local_session->playback_start;
631 double playback_end = edl->local_session->playback_end;
632 if( playback_end < cursor_position && ( position < 0 || playback_end > position ) )
633 position = playback_end;
634 else if( playback_start < cursor_position && ( position < 0 || playback_start > position ) )
635 position = playback_start;
637 if( position >= 0 ) {
638 edl->local_session->set_selectionstart(position);
640 edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
642 update_plugin_guis();
643 TimelinePane *pane = gui->get_focused_pane();
644 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
645 edl->local_session->zoom_sample /
646 edl->session->sample_rate +
647 pane->canvas->time_visible()
649 edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
650 edl->local_session->zoom_sample /
651 edl->session->sample_rate)
653 samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
654 edl->session->sample_rate /
655 edl->local_session->zoom_sample -
656 pane->canvas->get_w() /
659 cwindow->update(1, 0, 0, 0, 0);
662 // Don't scroll the display
664 gui->update_patchbay();
665 gui->update_timebar(0);
668 gui->zoombar->update();
669 gui->flash_canvas(1);
670 cwindow->update(1, 0, 0, 0, 1);
685 int MWindow::next_edit_handle(int shift_down)
687 double position = edl->local_session->get_selectionend(1);
688 Units::fix_double(&position);
689 double new_position = INFINITY;
690 // Test for edit handles after cursor position
691 for (Track *track = edl->tracks->first; track; track = track->next)
695 for (Edit *edit = track->edits->first; edit; edit = edit->next)
697 double edit_end = track->from_units(edit->startproject + edit->length);
698 Units::fix_double(&edit_end);
699 if (edit_end > position && edit_end < new_position)
700 new_position = edit_end;
705 if(new_position != INFINITY)
708 edl->local_session->set_selectionend(new_position);
709 //printf("MWindow::next_edit_handle %d\n", shift_down);
711 edl->local_session->set_selectionstart(
712 edl->local_session->get_selectionend(1));
714 update_plugin_guis();
715 TimelinePane *pane = gui->get_focused_pane();
716 if(edl->local_session->get_selectionend(1) >=
717 (double)edl->local_session->view_start[pane->number] *
718 edl->local_session->zoom_sample /
719 edl->session->sample_rate +
720 pane->canvas->time_visible() ||
721 edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
722 edl->local_session->zoom_sample /
723 edl->session->sample_rate)
725 samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
726 edl->session->sample_rate /
727 edl->local_session->zoom_sample -
728 pane->canvas->get_w() /
731 cwindow->update(1, 0, 0, 0, 0);
735 gui->update_patchbay();
736 gui->update_timebar(0);
739 gui->zoombar->update();
740 gui->flash_canvas(1);
741 cwindow->update(1, 0, 0, 0, 1);
751 int MWindow::prev_edit_handle(int shift_down)
753 double position = edl->local_session->get_selectionstart(1);
754 double new_position = -1;
755 Units::fix_double(&position);
756 // Test for edit handles before cursor position
757 for (Track *track = edl->tracks->first; track; track = track->next)
761 for (Edit *edit = track->edits->first; edit; edit = edit->next)
763 double edit_end = track->from_units(edit->startproject);
764 Units::fix_double(&edit_end);
765 if (edit_end < position && edit_end > new_position)
766 new_position = edit_end;
771 if(new_position != -1)
774 edl->local_session->set_selectionstart(new_position);
775 //printf("MWindow::next_edit_handle %d\n", shift_down);
777 edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
779 update_plugin_guis();
780 // Scroll the display
781 TimelinePane *pane = gui->get_focused_pane();
782 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
783 edl->local_session->zoom_sample /
784 edl->session->sample_rate +
785 pane->canvas->time_visible()
787 edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
788 edl->local_session->zoom_sample /
789 edl->session->sample_rate)
791 samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
792 edl->session->sample_rate /
793 edl->local_session->zoom_sample -
794 pane->canvas->get_w() /
797 cwindow->update(1, 0, 0, 0, 0);
800 // Don't scroll the display
802 gui->update_patchbay();
803 gui->update_timebar(0);
806 gui->zoombar->update();
807 gui->flash_canvas(1);
808 cwindow->update(1, 0, 0, 0, 1);
825 int MWindow::expand_y()
827 int result = edl->local_session->zoom_y * 2;
828 result = MIN(result, MAX_AMP_ZOOM);
830 gui->zoombar->update();
834 int MWindow::zoom_in_y()
836 int result = edl->local_session->zoom_y / 2;
837 result = MAX(result, MIN_AMP_ZOOM);
839 gui->zoombar->update();
843 int MWindow::expand_t()
845 int result = edl->local_session->zoom_track * 2;
846 result = MIN(result, MAX_TRACK_ZOOM);
848 gui->zoombar->update();
852 int MWindow::zoom_in_t()
854 int result = edl->local_session->zoom_track / 2;
855 result = MAX(result, MIN_TRACK_ZOOM);
857 gui->zoombar->update();
861 void MWindow::split_x()
863 gui->resource_thread->stop_draw(1);
865 if(gui->pane[TOP_RIGHT_PANE])
867 gui->delete_x_pane(theme->mcanvas_w);
868 edl->local_session->x_pane = -1;
872 gui->create_x_pane(theme->mcanvas_w / 2);
873 edl->local_session->x_pane = theme->mcanvas_w / 2;
876 gui->mainmenu->update_toggles(0);
877 gui->update_pane_dividers();
878 gui->update_cursor();
879 // required to get new widgets to appear
882 gui->resource_thread->start_draw();
885 void MWindow::split_y()
887 gui->resource_thread->stop_draw(1);
888 if(gui->pane[BOTTOM_LEFT_PANE])
890 gui->delete_y_pane(theme->mcanvas_h);
891 edl->local_session->y_pane = -1;
895 gui->create_y_pane(theme->mcanvas_h / 2);
896 edl->local_session->y_pane = theme->mcanvas_h / 2;
899 gui->mainmenu->update_toggles(0);
900 gui->update_pane_dividers();
901 gui->update_cursor();
902 // required to get new widgets to appear
904 gui->resource_thread->start_draw();