merge: mask fixes/upgrades, overlay plugin rework, popup menu tweak
authorGood Guy <good1.2guy@gmail.com>
Mon, 28 Mar 2016 23:07:04 +0000 (17:07 -0600)
committerGood Guy <good1.2guy@gmail.com>
Mon, 28 Mar 2016 23:07:04 +0000 (17:07 -0600)
18 files changed:
cinelerra-5.1/bld_scripts/bld_dynamic.sh
cinelerra-5.1/bld_scripts/bld_prepare.sh
cinelerra-5.1/bld_scripts/bld_static.sh
cinelerra-5.1/cinelerra/commercials.C
cinelerra-5.1/cinelerra/cwindowgui.C
cinelerra-5.1/cinelerra/cwindowtool.C
cinelerra-5.1/cinelerra/cwindowtool.h
cinelerra-5.1/cinelerra/edits.C
cinelerra-5.1/cinelerra/edits.h
cinelerra-5.1/cinelerra/edlsession.h
cinelerra-5.1/cinelerra/maskengine.C
cinelerra-5.1/cinelerra/playback3d.C
cinelerra-5.1/cinelerra/vwindowgui.C
cinelerra-5.1/guicast/bcpopupmenu.C
cinelerra-5.1/guicast/vframe.C
cinelerra-5.1/guicast/vframe.h
cinelerra-5.1/guicast/vframe3d.C
cinelerra-5.1/plugins/overlay/overlay.C

index fdf546798fa8b52e78c9a15164a444be9123c0c0..ad08e782374526d8824baa8bfb4c5fb424731c98 100755 (executable)
@@ -14,25 +14,25 @@ fi
 
 cd "$path/$dir/$bld"
 rm -rf "$proj"
-git clone --depth 1 "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj"
-#rsh host tar -C /mnt0/cinelerra5 -cf - cinelerra | tar -xf -
-#mv cinelerra cinelerra5
+git clone "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj"
+#rsh host tar -C /mnt0 -cf - cinelerra5 | tar -xf -
 if [ $? -ne 0 ]; then
   echo "git clone $proj failed"
   exit 1
 fi
 
 cd "$proj/$base"
-if [ "$dir" = "ubuntu" ]; then
- echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config
-fi
-if [ "$dir" = "centos" ]; then
- echo "EXTRA_LIBS += -lnuma" >> global_config
- echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config
-fi
-if [ "$dir" = "suse" ]; then
- echo "EXTRA_LIBS += -lnuma" >> global_config
-fi
+case "$dir" in
+  "ubuntu" | "mint" | "ub14" | "ub15")
+     echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config ;;
+  "centos")
+     echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config
+     echo "EXTRA_LIBS += -lnuma" >> global_config ;;
+  "suse" | "leap")
+     echo "EXTRA_LIBS += -lnuma" >> global_config ;;
+  "fedora")
+     echo "EXTRA_LIBS += -lnuma" >> global_config ;;
+esac
 
 STATIC_LIBRARIES=0 ./configure >& log
 make >> log 2>&1 $@
index e276b8c524f9269cce4add613a3b8425c1a38dfd..65c40d2f7d8fa2b4d7b8189289e4e6f53a4012bc 100755 (executable)
@@ -31,7 +31,20 @@ case "$dir" in
     yum -y install /tmp/$yasm
     rm -f /tmp/$yasm
   ;;
-"suse")
+"fedora")
+  dnf -y install nasm yasm libavc1394-devel libusb-devel flac-devel \
+    libjpeg-devel libdv-devel libdvdnav-devel libdvdread-devel \
+    libtheora-devel libiec61883-devel esound-devel uuid-devel \
+    giflib-devel ncurses-devel ilmbase-devel fftw-devel OpenEXR-devel \
+    libsndfile-devel libXft-devel libXinerama-devel libXv-devel \
+    xorg-x11-fonts-misc xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 \
+    xorg-x11-fonts-ISO8859-1-100dpi xorg-x11-fonts-ISO8859-1-75dpi \
+    libpng-devel bzip2-devel zlib-devel kernel-headers libavc1394 \
+    festival-devel libdc1394-devel libiec61883-devel esound-devel \
+    flac-devel libsndfile-devel libtheora-devel linux-firmware \
+    ivtv-firmware libvorbis-devel texinfo xz-devel lzma-devel cmake
+  ;;
+"suse" | "leap")
   zypper -n install nasm gcc gcc-c++ zlib-devel texinfo libpng16-devel \
     freeglut-devel libXv-devel alsa-devel libbz2-devel ncurses-devel \
     libXinerama-devel freetype-devel libXft-devel giflib-devel ctags \
@@ -44,9 +57,9 @@ case "$dir" in
       ln -s libtermcap.so.2 /usr/lib64/libtermcap.so
     fi
   ;;
-"ubuntu")
-  apt-get -y install apt-file sox nasm yasm g++ build-essential libz-dev texinfo \
-    libpng-dev freeglut3-dev libxv-dev libasound2-dev libbz2-dev \
+"ubuntu" | "mint" | "ub14" | "ub15")
+  apt-get -y install apt-file sox nasm yasm g++ build-essential libz-dev \
+    texinfo libpng-dev freeglut3-dev libxv-dev libasound2-dev libbz2-dev \
     libncurses5-dev libxinerama-dev libfreetype6-dev libxft-dev libgif-dev \
     libtiff5-dev exuberant-ctags ttf-bitstream-vera xfonts-75dpi xfonts-100dpi \
     fonts-dejavu libopenexr-dev libavc1394-dev festival-dev fftw3-dev \
index e41df88c1816a41ee4490ef3e7ee44833b04c339..cca4acfc091d3bd6a271cbd45dbd2a4a68d00996 100755 (executable)
@@ -14,25 +14,25 @@ fi
 
 cd "$path/$dir/$bld"
 rm -rf "$proj"
-git clone --depth 1 "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj"
-#rsh host tar -C /mnt0/cinelerra5 -cf - cinelerra | tar -xf -
-#mv cinelerra cinelerra5
+git clone "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj"
+#rsh host tar -C /mnt0 -cf - cinelerra5 | tar -xf -
 if [ $? -ne 0 ]; then
   echo "git clone $proj failed"
   exit 1
 fi
 
 cd "$proj/$base"
-if [ "$dir" = "ubuntu" ]; then
- echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config
-fi
-if [ "$dir" = "centos" ]; then
- echo "EXTRA_LIBS += -lnuma" >> global_config
- echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config
-fi
-if [ "$dir" = "suse" ]; then
- echo "EXTRA_LIBS += -lnuma" >> global_config
-fi
+case "$dir" in
+  "ubuntu" | "mint" | "ub14" | "ub15")
+     echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config ;;
+  "centos")
+     echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config
+     echo "EXTRA_LIBS += -lnuma" >> global_config ;;
+  "suse" | "leap")
+     echo "EXTRA_LIBS += -lnuma" >> global_config ;;
+  "fedora")
+     echo "EXTRA_LIBS += -lnuma" >> global_config ;;
+esac
 
 STATIC_LIBRARIES=1 ./configure >& log
 make >> log 2>&1 $@
index e74275b5db6f3c80a01605773fd81013f7f584d6..a08ec02921e1e058c1d07c78470d23affe75a9c3 100644 (file)
@@ -533,7 +533,7 @@ cut_edit(Track *track, Edit *edit, int64_t clip_start, int64_t clip_end)
                }
        }
        // cut edit
-       Edit *next_edit = track->edits->split_edit(edit, cut_start);
+       Edit *next_edit = edit->edits->split_edit(cut_start);
        int64_t cut_length = cut_end - cut_start;
        next_edit->length -= cut_length;
        next_edit->startsource += cut_length;
index 8df8e594961325ba6218a77ce99a449a436f3812..13a1ca763a7281d4bbb1246020bb345b7aa0a43b 100644 (file)
@@ -1369,17 +1369,17 @@ int CWindowCanvas::do_ruler(int draw,
 }
 
 
-static inline bool test_bbox(int cx, int cy, int tx, int ty)
-{
-       return (llabs(cx-tx) < (CONTROL_W/2) && llabs(cy-ty) < (CONTROL_H/2));
-}
-
 static inline double line_dist(float cx,float cy, float tx,float ty)
 {
-       int dx = tx-cx, dy = ty-cy;
+       double dx = tx-cx, dy = ty-cy;
        return sqrt(dx*dx + dy*dy);
 }
 
+static inline bool test_bbox(int cx, int cy, int tx, int ty)
+{
+//     printf("test_bbox %d,%d - %d,%d = %f\n",cx,cy,tx,ty,line_dist(cx,cy,tx,ty));
+       return (llabs(cx-tx) < CONTROL_W/2 && llabs(cy-ty) < CONTROL_H/2);
+}
 
 int CWindowCanvas::do_mask(int &redraw, int &rerender,
                int button_press, int cursor_motion, int draw)
@@ -1459,15 +1459,14 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
 
 
 // Get position of cursor relative to mask
-       float cursor_x = get_cursor_x();
-       float cursor_y = get_cursor_y();
-       canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
+       float cursor_x = get_cursor_x(), cursor_y = get_cursor_y();
+       float mask_cursor_x = cursor_x, mask_cursor_y = cursor_y;
+       canvas_to_output(mwindow->edl, 0, mask_cursor_x, mask_cursor_y);
 
        projector_x += mwindow->edl->session->output_w / 2;
        projector_y += mwindow->edl->session->output_h / 2;
-
-       float mask_cursor_x = (cursor_x - projector_x) / projector_z + half_track_w;
-       float mask_cursor_y = (cursor_y - projector_y) / projector_z + half_track_h;
+       mask_cursor_x = (mask_cursor_x - projector_x) / projector_z + half_track_w;
+       mask_cursor_y = (mask_cursor_y - projector_y) / projector_z + half_track_h;
 
 // Fix cursor origin
        if(button_press) {
@@ -1551,7 +1550,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                y = (y - half_track_h) * projector_z + projector_y;
 // Test new point addition
                                if(button_press) {
-                                       float line_distance = line_dist(x,y, cursor_x,cursor_y);
+                                       float line_distance = line_dist(x,y, mask_cursor_x,mask_cursor_y);
 
 //printf("CWindowCanvas::do_mask 1 x=%f cursor_x=%f y=%f cursor_y=%f %f %f %d, %d\n",
 //  x, cursor_x, y, cursor_y, line_distance, shortest_line_distance, shortest_point1, shortest_point2);
@@ -1571,7 +1570,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                        if(gui->shift_down()) {
                                                float control_x = (x1 - half_track_w) * projector_z + projector_x;
                                                float control_y = (y1 - half_track_h) * projector_z + projector_y;
-                                               float distance = line_dist(control_x,control_y, cursor_x,cursor_y);
+                                               float distance = line_dist(control_x,control_y, mask_cursor_x,mask_cursor_y);
 
                                                if(distance < selected_control_point_distance) {
                                                        selected_point = i;
@@ -1596,7 +1595,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                        if(gui->shift_down()) {
                                                float control_x = (x2 - half_track_w) * projector_z + projector_x;
                                                float control_y = (y2 - half_track_h) * projector_z + projector_y;
-                                               float distance = line_dist(control_x,control_y, cursor_x,cursor_y);
+                                               float distance = line_dist(control_x,control_y, mask_cursor_x,mask_cursor_y);
 
 //printf("CWindowCanvas::do_mask %d %f %f\n", i, distance, selected_control_point_distance);
                                                if(distance < selected_control_point_distance) {
@@ -1779,7 +1778,8 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
 //printf("CWindowCanvas::do_mask %d %d\n", shortest_point1, shortest_point2);
 
 // Append to end of list
-                       if(labs(shortest_point1 - shortest_point2) > 1) {
+                       if( shortest_point1 == shortest_point2 ||
+                           labs(shortest_point1 - shortest_point2) > 1) {
 #ifdef USE_KEYFRAME_SPANNING
 
                                MaskPoint *new_point = new MaskPoint;
@@ -1865,6 +1865,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                MaskPoint *new_point = new MaskPoint;
                                points.append(new_point);
                                *new_point = *point;
+                               gui->affected_point = points.size() - 1;
 #else
                                for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto; current; ) {
                                        SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
@@ -1876,35 +1877,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
                                        else
                                                current = (MaskAuto*)NEXT;
                                }
-#endif
-
-//printf("CWindowCanvas::do_mask 2\n");
-// Create a second point if none existed before
-#ifdef USE_KEYFRAME_SPANNING
-                               if(points.size() < 2) {
-
-                                       MaskPoint *new_point = new MaskPoint;
-                                       points.append(new_point);
-                                       *new_point = *point;
-                               }
-
                                gui->affected_point = points.size() - 1;
-#else
-                               if(mask->points.size() < 2) {
-
-                                       for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto; current; ) {
-                                               SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
-                                               MaskPoint *new_point = new MaskPoint;
-                                               submask->points.append(new_point);
-                                               *new_point = *point;
-                                               if(current == (MaskAuto*)mask_autos->default_auto)
-                                                       current = (MaskAuto*)mask_autos->first;
-                                               else
-                                                       current = (MaskAuto*)NEXT;
-                                       }
-                               }
-
-                               gui->affected_point = mask->points.size() - 1;
 #endif
 
 //printf("CWindowCanvas::do_mask 3 %d\n", mask->points.size());
@@ -1958,7 +1931,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender,
 //printf("CWindowCanvas::do_mask %d %d\n", __LINE__, gui->affected_point);
 
                SubMask *mask = gui->mask_keyframe->get_submask(mwindow->edl->session->cwindow_mask);
-               if(gui->affected_point < mask->points.size() &&
+               if( gui->affected_point >= 0 && gui->affected_point < mask->points.size() &&
                        gui->current_operation != CWINDOW_NONE) {
 //                     mwindow->undo->update_undo_before(_("mask point"), this);
 #ifdef USE_KEYFRAME_SPANNING
index 4730d81de975816b71ab68391508ba2cf40f33b7..64c9f4f38710e0305a63ed991828a71a695d285c 100644 (file)
@@ -1679,6 +1679,7 @@ int CWindowMaskDelete::handle_event()
        Track *track;
        MaskPoint *point;
        SubMask *mask;
+       int total_points = 0;
 
 // Get existing keyframe
        ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
@@ -1705,6 +1706,8 @@ int CWindowMaskDelete::handle_event()
                        submask->points.remove_object(
                                submask->points.values[submask->points.total - 1]);
                }
+               total_points = submask->points.total;
+
 // Commit change to span of keyframes
                ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
 #else
@@ -1713,8 +1716,6 @@ int CWindowMaskDelete::handle_event()
                {
                        SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
 
-
-
                        for(int i = mwindow->cwindow->gui->affected_point;
                                i < submask->points.total - 1;
                                i++)
@@ -1727,7 +1728,7 @@ int CWindowMaskDelete::handle_event()
                                submask->points.remove_object(
                                        submask->points.values[submask->points.total - 1]);
                        }
-
+                       total_points = submask->points.total;
 
                        if(current == (MaskAuto*)autos->default_auto)
                                current = (MaskAuto*)autos->first;
@@ -1735,6 +1736,9 @@ int CWindowMaskDelete::handle_event()
                                current = (MaskAuto*)NEXT;
                }
 #endif
+               if( mwindow->cwindow->gui->affected_point >= total_points )
+                       mwindow->cwindow->gui->affected_point =
+                               total_points > 0 ? total_points-1 : 0;
 
                gui->update();
                gui->update_preview();
@@ -1860,6 +1864,47 @@ int CWindowMaskNumber::handle_event()
 }
 
 
+CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
+       CWindowToolGUI *gui, int x, int y)
+ : BC_TumbleTextBox(gui,
+               (int64_t)mwindow->cwindow->gui->affected_point,
+               (int64_t)0, INT64_MAX, x, y, 100)
+{
+       this->mwindow = mwindow;
+       this->gui = gui;
+}
+
+CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
+{
+}
+
+int CWindowMaskAffectedPoint::handle_event()
+{
+       int total_points = 0;
+       int affected_point = atol(get_text());
+       Track *track = mwindow->cwindow->calculate_affected_track();
+       if(track) {
+               MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
+               MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
+               if( keyframe ) {
+                       SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
+                       total_points = mask->points.size();
+               }
+       }
+       int active_point = affected_point;
+       if( affected_point >= total_points )
+               affected_point = total_points - 1;
+       else if( affected_point < 0 )
+               affected_point = 0;
+       if( active_point != affected_point )
+               update((int64_t)affected_point);
+       mwindow->cwindow->gui->affected_point = affected_point;
+       gui->update();
+       gui->update_preview();
+       return 1;
+}
+
+
 
 
 
@@ -2016,11 +2061,15 @@ CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
 {
        this->mwindow = mwindow;
        this->thread = thread;
+       number = 0;
+       active_point = 0;
+       feather = 0;
 }
 CWindowMaskGUI::~CWindowMaskGUI()
 {
        lock_window("CWindowMaskGUI::~CWindowMaskGUI");
        delete number;
+       delete active_point;
        delete feather;
        unlock_window();
 }
@@ -2044,6 +2093,11 @@ void CWindowMaskGUI::create_objects()
        add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
        y += value->get_h() + margin;
        add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
+       int x1 = x + delete_point->get_w() + 2*margin;
+       add_subwindow(title = new BC_Title(x1, y, _("Point:")));
+       x1 += title->get_w() + margin;
+       active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
+       active_point->create_objects();
        y += delete_point->get_h() + margin;
        add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
        number = new CWindowMaskNumber(mwindow,
@@ -2149,8 +2203,9 @@ void CWindowMaskGUI::update()
                        apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
                }
        }
-//printf("CWindowMaskGUI::update 1\n");
 
+//printf("CWindowMaskGUI::update 1\n");
+       active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
        number->update((int64_t)mwindow->edl->session->cwindow_mask);
 
 //printf("CWindowMaskGUI::update 1\n");
index 0e6b1a705921907a202fde4fc6a81f369a1a1103..2242b2bcc1b5a1b51d722d36230db2f7c2ab3795 100644 (file)
@@ -178,6 +178,18 @@ public:
        CWindowToolGUI *gui;
 };
 
+
+class CWindowMaskAffectedPoint : public BC_TumbleTextBox
+{
+public:
+       CWindowMaskAffectedPoint(MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
+       ~CWindowMaskAffectedPoint();
+       int handle_event();
+       MWindow *mwindow;
+       CWindowToolGUI *gui;
+};
+
+
 class CWindowMaskFeather : public BC_TumbleTextBox
 {
 public:
@@ -225,6 +237,7 @@ public:
        CWindowMaskMode *mode;
        CWindowMaskFeather *feather;
        CWindowMaskDelete *delete_point;
+       CWindowMaskAffectedPoint *active_point;
 // Not necessary if all keyframes have same points
 //     CWindowMaskCycleNext *next_point;
 //     CWindowMaskCyclePrev *prev_point;
index 1c12dc34116875f9163b34d9a17658ff106e0e07..7d152bc5ef0e59c50155e2a2a34bedbb78dd0863 100644 (file)
@@ -234,72 +234,33 @@ Edit* Edits::insert_new_edit(int64_t position)
        return new_edit;
 }
 
-
 Edit* Edits::split_edit(int64_t position)
 {
 // Get edit containing position
        Edit *edit = editof(position, PLAY_FORWARD, 0);
-// No edit found, make one - except when we are at zero position!
-       if(!edit && position != 0) {
-               if (length() == position) {
-                       edit = last; // we do not need any edit to extend past the last one
-               }
-               else if (!last || length() < position) {
-
-                       // Even when track is completely empty or split is beyond last edit, return correct edit
-                       Edit *empty = create_edit();
-                       if (last)
-                               empty->startproject = length(); // end of last edit
-                       else
-                               empty->startproject = 0; // empty track
-                       empty->length = position - empty->startproject;
-                       insert_after(last, empty);
-                       edit = empty;
-               }
-               else {
-                       // now we are now surely in situation where we have
-                       //  a) broken edit list or b) negative position... report error!
-                       printf("ERROR!\n");
-                       printf("Trying to insert edit at position, but failed: %ji\n", position);
-                       printf("Dump is here:\n");
-                       track->dump(stdout);
-                       return 0;
-               }
-       }
        if(!edit) return 0;
-       return split_edit(edit, position);
-}
-
-Edit* Edits::split_edit(Edit *edit, int64_t position)
-{
 // Split would have created a 0 length
 //     if(edit->startproject == position) return edit;
 // Create anyway so the return value comes before position
 
        Edit *new_edit = create_edit();
        insert_after(edit, new_edit);
-       if (edit)  // if we have actually split the edit, do the funky stuff!
-       {
-               new_edit->copy_from(edit);
-               new_edit->length = new_edit->startproject + new_edit->length - position;
-               edit->length = position - edit->startproject;
-               new_edit->startsource += edit->length;
-
+       new_edit->copy_from(edit);
+       new_edit->length = new_edit->startproject + new_edit->length - position;
+       edit->length = position - edit->startproject;
+       new_edit->startproject = position;
+       new_edit->startsource += edit->length;
 
 // Decide what to do with the transition
-               if(edit->length && edit->transition)
-               {
-                       delete new_edit->transition;
-                       new_edit->transition = 0;
-               }
+       if(edit->length && edit->transition) {
+               delete new_edit->transition;
+               new_edit->transition = 0;
+       }
 
-               if(edit->transition && edit->transition->length > edit->length)
-                       edit->transition->length = edit->length;
-               if(new_edit->transition && new_edit->transition->length > new_edit->length)
-                       new_edit->transition->length = new_edit->length;
-       } else
-               new_edit->length = 0;
-       new_edit->startproject = position;
+       if(edit->transition && edit->transition->length > edit->length)
+               edit->transition->length = edit->length;
+       if(new_edit->transition && new_edit->transition->length > new_edit->length)
+               new_edit->transition->length = new_edit->length;
        return new_edit;
 }
 
@@ -403,11 +364,10 @@ int Edits::optimize()
                result = 0;
 
 // delete 0 length edits
-               for(current = first; !result && current; ) {
+               for( current = first; !result && current; ) {
                        Edit* next = current->next;
-                       if(current->length == 0) {
-                               // Be smart with transitions!
-                               if (next && current->transition && !next->transition) {
+                       if( current->length == 0 ) {
+                               if( next && current->transition && !next->transition) {
                                        next->transition = current->transition;
                                        next->transition->edit = next;
                                        current->transition = 0;
@@ -431,10 +391,8 @@ int Edits::optimize()
 // current->channel, next_edit->channel, current->asset, next_edit->asset,
 // current->nested_edl, next_edit->nested_edl);
 
-
 // both edits are silence & not a plugin
-// source channels are identical
-// assets are identical
+// source channels are identical, assets are identical
                        if( (current->silence() && next_edit->silence() && !current->is_plugin) ||
                            (current->startsource + current->length == next_edit->startsource &&
                             current->channel == next_edit->channel &&
@@ -444,7 +402,7 @@ int Edits::optimize()
                                current->length += next_edit->length;
                                remove(next_edit);
                                result = 1;
-                               continue;
+                               break;
                        }
 
                        current = current->next;
@@ -471,8 +429,7 @@ void Edits::load(FileXML *file, int track_offset)
 
        while( !file->read_tag() ) {
 //printf("Edits::load 1 %s\n", file->tag.get_title());
-               if(!strcmp(file->tag.get_title(), "EDIT"))
-               {
+               if(!strcmp(file->tag.get_title(), "EDIT")) {
                        load_edit(file, startproject, track_offset);
                }
                else if(!strcmp(file->tag.get_title(), "/EDITS"))
@@ -487,51 +444,45 @@ int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
 {
        Edit* current = append_new_edit();
        current->load_properties(file, startproject);
+
        startproject += current->length;
 
        while( !file->read_tag() ) {
-               if(file->tag.title_is("NESTED_EDL"))
-               {
+               if(file->tag.title_is("NESTED_EDL")) {
                        char path[BCTEXTLEN];
                        path[0] = 0;
                        file->tag.get_property("SRC", path);
 //printf("Edits::load_edit %d path=%s\n", __LINE__, path);
-                       if(path[0] != 0)
-                       {
+                       if(path[0] != 0) {
                                current->nested_edl = edl->nested_edls->get(path);
                        }
 // printf("Edits::load_edit %d nested_edl->path=%s\n",
 // __LINE__,
 // current->nested_edl->path);
                }
-               else if(file->tag.title_is("FILE"))
-               {
+               else if(file->tag.title_is("FILE")) {
                        char filename[BCTEXTLEN];
                        filename[0] = 0;
                        file->tag.get_property("SRC", filename);
 // Extend path
-                       if(filename[0] != 0)
-                       {
+                       if(filename[0] != 0) {
                                char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
                                FileSystem fs;
                                fs.set_current_dir("");
                                fs.extract_dir(directory, filename);
-                               if(!strlen(directory))
-                               {
+                               if(!strlen(directory)) {
                                        fs.extract_dir(edl_directory, file->filename);
                                        fs.join_names(directory, edl_directory, filename);
                                        strcpy(filename, directory);
                                }
                                current->asset = edl->assets->get_asset(filename);
                        }
-                       else
-                       {
+                       else {
                                current->asset = 0;
                        }
 //printf("Edits::load_edit 5\n");
                }
-               else if(file->tag.title_is("TRANSITION"))
-               {
+               else if(file->tag.title_is("TRANSITION")) {
                        current->transition = new Transition(edl, current, "",
                                track->to_units(edl->session->default_transition_length, 1));
                                current->transition->load_xml(file);
@@ -560,19 +511,15 @@ Edit* Edits::editof(int64_t position, int direction, int use_nudge)
        Edit *current = 0;
        if(use_nudge && track) position += track->nudge;
 
-       if(direction == PLAY_FORWARD)
-       {
-               for(current = last; current; current = PREVIOUS)
-               {
+       if(direction == PLAY_FORWARD) {
+               for(current = last; current; current = PREVIOUS) {
                        if(current->startproject <= position && current->startproject + current->length > position)
                                return current;
                }
        }
        else
-       if(direction == PLAY_REVERSE)
-       {
-               for(current = first; current; current = NEXT)
-               {
+       if(direction == PLAY_REVERSE) {
+               for(current = first; current; current = NEXT) {
                        if(current->startproject < position && current->startproject + current->length >= position)
                                return current;
                }
@@ -587,8 +534,7 @@ Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
        if(track && use_nudge) position += track->nudge;
 
 // Get the current edit
-       for(current = first; current; current = NEXT)
-       {
+       for(current = first; current; current = NEXT) {
                if(current->startproject <= position &&
                        current->startproject + current->length > position)
                        break;
@@ -596,8 +542,7 @@ Edit* Edits::get_playable_edit(int64_t position, int use_nudge)
 
 // Get the edit's asset
 // TODO: descend into nested EDLs
-       if(current)
-       {
+       if(current) {
                if(!current->asset)
                        current = 0;
        }
@@ -638,11 +583,11 @@ void Edits::clear(int64_t start, int64_t end)
        Edit* edit2 = editof(end, PLAY_FORWARD, 0);
        Edit* current_edit;
 
+       if(end == start) return;        // nothing selected
        if(!edit1 && !edit2) return;       // nothing selected
 
 
-       if(!edit2)
-       {                // edit2 beyond end of track
+       if(!edit2) {                // edit2 beyond end of track
                edit2 = last;
                end = this->length();
        }
@@ -658,33 +603,27 @@ void Edits::clear(int64_t start, int64_t end)
                edit2->startproject += end - edit2->startproject;
 
 // delete
-               for(current_edit = edit1->next; current_edit && current_edit != edit2;)
-               {
+               for(current_edit = edit1->next; current_edit && current_edit != edit2;) {
                        Edit* next = current_edit->next;
                        remove(current_edit);
                        current_edit = next;
                }
 // shift
-               for(current_edit = edit2; current_edit; current_edit = current_edit->next)
-               {
+               for(current_edit = edit2; current_edit; current_edit = current_edit->next) {
                        current_edit->startproject -= end - start;
                }
        }
-       else
-       {
+       else {
 // in same edit. paste_edit depends on this
 // create a new edit
                current_edit = split_edit(start);
-
-               current_edit->length -= end - start;
-               current_edit->startsource += end - start;
-
+               if( current_edit ) {
+                       current_edit->length -= end - start;
+                       current_edit->startsource += end - start;
 // shift
-               for(current_edit = current_edit->next;
-                       current_edit;
-                       current_edit = current_edit->next)
-               {
-                       current_edit->startproject -= end - start;
+                       while( (current_edit=current_edit->next) != 0 ) {
+                               current_edit->startproject -= end - start;
+                       }
                }
        }
 
@@ -693,55 +632,37 @@ void Edits::clear(int64_t start, int64_t end)
 
 // Used by edit handle and plugin handle movement but plugin handle movement
 // can only effect other plugins.
-void Edits::clear_recursive(int64_t start,
-       int64_t end,
-       int edit_edits,
-       int edit_labels,
-       int edit_plugins,
-       int edit_autos,
+void Edits::clear_recursive(int64_t start, int64_t end,
+       int edit_edits, int edit_labels, int edit_plugins, int edit_autos,
        Edits *trim_edits)
 {
 //printf("Edits::clear_recursive 1\n");
-       track->clear(start,
-               end,
-               edit_edits,
-               edit_labels,
-               edit_plugins,
-               edit_autos,
-               0,
+       track->clear(start, end,
+               edit_edits, edit_labels, edit_plugins, edit_autos, 0,
                trim_edits);
 }
 
 
-int Edits::clear_handle(double start,
-       double end,
-       int edit_plugins,
-       int edit_autos,
-       double &distance)
+int Edits::clear_handle(double start, double end,
+       int edit_plugins, int edit_autos, double &distance)
 {
        Edit *current_edit;
 
        distance = 0.0; // if nothing is found, distance is 0!
        for(current_edit = first;
                current_edit && current_edit->next;
-               current_edit = current_edit->next)
-       {
+               current_edit = current_edit->next) {
 
 
 
-               if(current_edit->asset &&
-                       current_edit->next->asset)
-               {
+               if(current_edit->asset && current_edit->next->asset) {
 
                        if(current_edit->asset->equivalent(*current_edit->next->asset,
-                               0,
-                               0))
-                       {
+                               0, 0)) {
 
 // Got two consecutive edits in same source
                                if(edl->equivalent(track->from_units(current_edit->next->startproject),
-                                       start))
-                               {
+                                       start)) {
 // handle selected
                                        int length = -current_edit->length;
                                        current_edit->length = current_edit->next->startsource - current_edit->startsource;
@@ -774,35 +695,25 @@ int Edits::clear_handle(double start,
        return 0;
 }
 
-int Edits::modify_handles(double oldposition,
-       double newposition,
-       int currentend,
-       int edit_mode,
-       int edit_edits,
-       int edit_labels,
-       int edit_plugins,
-       int edit_autos,
+int Edits::modify_handles(double oldposition, double newposition, int currentend,
+       int edit_mode, int edit_edits, int edit_labels, int edit_plugins, int edit_autos,
        Edits *trim_edits)
 {
        int result = 0;
        Edit *current_edit;
 
 //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition);
-       if(currentend == 0)
-       {
+       if(currentend == 0) {
 // left handle
-               for(current_edit = first; current_edit && !result;)
-               {
+               for(current_edit = first; current_edit && !result;) {
                        if(edl->equivalent(track->from_units(current_edit->startproject),
-                               oldposition))
-                       {
+                               oldposition)) {
 // edit matches selection
 //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition);
                                oldposition = track->from_units(current_edit->startproject);
                                result = 1;
 
-                               if(newposition >= oldposition)
-                               {
+                               if(newposition >= oldposition) {
 //printf("Edits::modify_handle 1 %s %f %f\n", track->title, oldposition, newposition);
 // shift start of edit in
                                        current_edit->shift_start_in(edit_mode,
@@ -832,21 +743,17 @@ int Edits::modify_handles(double oldposition,
                        if(!result) current_edit = current_edit->next;
                }
        }
-       else
-       {
+       else {
 // right handle selected
-               for(current_edit = first; current_edit && !result;)
-               {
+               for(current_edit = first; current_edit && !result;) {
                        if(edl->equivalent(track->from_units(current_edit->startproject) +
-                               track->from_units(current_edit->length), oldposition))
-                       {
+                               track->from_units(current_edit->length), oldposition)) {
                oldposition = track->from_units(current_edit->startproject) +
                                        track->from_units(current_edit->length);
                                result = 1;
 
 //printf("Edits::modify_handle 3\n");
-                               if(newposition <= oldposition)
-                               {
+                               if(newposition <= oldposition) {
 // shift end of edit in
 //printf("Edits::modify_handle 4\n");
                                        current_edit->shift_end_in(edit_mode,
@@ -887,25 +794,20 @@ int Edits::modify_handles(double oldposition,
 
 void Edits::paste_silence(int64_t start, int64_t end)
 {
-       // paste silence does not do anything if
-       // a) paste silence is on empty track
-       // b) paste silence is after last edit
-       // in both cases editof returns NULL
        Edit *new_edit = editof(start, PLAY_FORWARD, 0);
        if (!new_edit) return;
 
-       if (!new_edit->asset)
-       { // in this case we extend already existing edit
-               new_edit->length += end - start;
-       } else
-       { // we are in fact creating a new edit
+       if( !new_edit->silence() ) {
                new_edit = insert_new_edit(start);
                new_edit->length = end - start;
        }
-       for(Edit *current = new_edit->next; current; current = NEXT)
-       {
+       else
+               new_edit->length += end - start;
+
+       for(Edit *current = new_edit->next; current; current = NEXT) {
                current->startproject += end - start;
        }
+
        return;
 }
 
@@ -913,23 +815,18 @@ Edit *Edits::create_silence(int64_t start, int64_t end)
 {
        Edit *new_edit = insert_new_edit(start);
        new_edit->length = end - start;
-       for(Edit *current = new_edit->next; current; current = NEXT)
-       {
+       for(Edit *current = new_edit->next; current; current = NEXT) {
                current->startproject += end - start;
        }
        return new_edit;
 }
-
+                                    
 Edit* Edits::shift(int64_t position, int64_t difference)
 {
        Edit *new_edit = split_edit(position);
 
-       for(Edit *current = first;
-               current;
-               current = NEXT)
-       {
-               if(current->startproject >= position)
-               {
+       for(Edit *current = first; current; current = NEXT) {
+               if(current->startproject >= position) {
                        current->shift(difference);
                }
        }
index cd1c61e73e66d835f216afa940648f06b7fcdfa3..d35917c71127c831c268ff7bf0a85df70eeb21ff 100644 (file)
@@ -56,9 +56,8 @@ public:
                int64_t sample,
                int track_number);
 // Split edit containing position.
-       Edit* split_edit(int64_t position);
 // Return the second edit in the split.
-       Edit* split_edit(Edit *edit, int64_t position);
+       Edit* split_edit(int64_t position);
 // Create a blank edit in the native data format
        int clear_handle(double start,
                double end,
index bf0acbb905b0037c70d025168ef648e73dd131a9..9affcfefff8071b762346c8f5efaf3d09b7ab009 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef EDLSESSION_H
 #define EDLSESSION_H
 
+#include "asset.inc"
 #include "autoconf.inc"
 #include "bcwindowbase.inc"
 #include "bchash.inc"
index 9f2861feae44c6dd580ecfb04dda7a9c5384e217..a8fd4acfec33b33674943ee3eafca5789b511fb4 100644 (file)
@@ -63,77 +63,6 @@ MaskUnit::~MaskUnit()
 
 #define OVERSAMPLE 8
 
-#if 1
-// Bresenham's
-void MaskUnit::draw_line_clamped(VFrame *frame,
-               int x1,int y1, int x2,int y2, unsigned char k)
-{
-       int w = frame->get_w(), h = frame->get_h();
-       unsigned char **rows = (unsigned char**)frame->get_rows();
-       int dx = x2-x1, dy = y2-y1;
-//printf("MaskUnit::draw_line_clamped(%d,%d -> %d,%d, 0x%02x\n", x1,y1, x2,y2, k);
-
-       int ax = 2*abs(dx), ay = 2*abs(dy);
-       if( ax > ay ) {         /* x dominant */
-               if( dx == 0 ) return;
-               if( x1 > x2 ) {
-                       int xx = x2;  x2 = x1;  x1 = xx;
-                       int yy = y2;  y2 = y1;  y1 = yy;
-               }
-               if( x1 >= w || x2 < 0 ) return;
-               if( dx < 0 ) {  dx = -dx;  dy = -dy; }
-               int x = x1,  y = y1, d = dx;
-               int sy = dy < 0 ? -1 : 1;
-               if( x1 < 0 ) {
-                       double py = -(double)dy/dx * x1 + y1 + 0.5;
-                       x = 0;  y = py;
-                       d = (py - y) * ay;
-               }
-
-               for( int y0=-1;;) {
-                       if( x >= w ) return;
-                       if( y != y0 && y >= 0 && y < h ) {
-                               y0 = y;
-                               unsigned char *bp = rows[y] + x;
-                               *bp = *bp == k ? 0 : k;
-                       }
-                       if( x == x2 ) return;
-                       if( d < 0 ) { d += ax;  y += sy; }
-                       d -= ay;  ++x;
-               }
-       }
-       else {                  /* y dominant */
-               if( dy == 0 ) return;
-               if( y1 > y2 ) {
-                       int xx = x2;  x2 = x1;  x1 = xx;
-                       int yy = y2;  y2 = y1;  y1 = yy;
-               }
-               if( y1 >= h || y2 < 0 ) return;
-               if( dy < 0 ) {  dx = -dx;  dy = -dy; }
-               int x = x1, y = y1, d = dy;
-               int sx = dx < 0 ? -1 : 1;
-               if( y1 < 0 ) {
-                       double px = -(double)dx/dy * y1 + x1 + 0.5;
-                       x = px;  y = 0;
-                       d = (px - x) * ax;
-               }
-
-               for(;;) {
-                       if( y >= h ) return;
-                       if( x >= 0 && x < w ) {
-                               unsigned char *bp = rows[y] + x;
-                               *bp = *bp == k ? 0 : k;
-                       }
-                       if( y == y2 ) return;
-                       if( d < 0 ) { d += ay;  x += sx; }
-                       d -= ax;  ++y;
-               }
-       }
-}
-
-#else
-
 void MaskUnit::draw_line_clamped(VFrame *frame, 
        int x1, int y1, int x2, int y2, unsigned char k)
 {
@@ -171,8 +100,6 @@ void MaskUnit::draw_line_clamped(VFrame *frame,
        }
 }
 
-#endif
-
 void MaskUnit::blur_strip(double *val_p, 
        double *val_m, 
        double *dst, 
index a6a721ba80feb38266e5c60ca0a30c7e2947ba69..35f4fd0ee1a6bfe269590aee30ad9660f8ae746c 100644 (file)
@@ -197,10 +197,10 @@ static const char *blend_divide_frag =
        "void main() {\n"
        "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
        "       vec4 result = gl_FragColor / canvas;\n"
-       "       if(!canvas.r) result.r = 1.0;\n"
-       "       if(!canvas.g) result.g = 1.0;\n"
-       "       if(!canvas.b) result.b = 1.0;\n"
-       "       if(!canvas.a) result.a = 1.0;\n"
+       "       if(canvas.r == 0.) result.r = 1.0;\n"
+       "       if(canvas.g == 0.) result.g = 1.0;\n"
+       "       if(canvas.b == 0.) result.b = 1.0;\n"
+       "       if(canvas.a == 0.) result.a = 1.0;\n"
        "       result = clamp(result, 0.0, 1.0);\n"
        "       gl_FragColor = mix(canvas, result, alpha);\n"
        "}\n";
@@ -219,7 +219,6 @@ static const char *blend_max_frag =
        "void main() {\n"
        "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
        "       vec4 result = max(canvas, gl_FragColor);\n"
-       "       result = clamp(result, 0.0, 1.0);\n"
        "       gl_FragColor = mix(canvas, result, alpha);\n"
        "}\n";
 
@@ -231,7 +230,6 @@ static const char *blend_min_frag =
        "void main() {\n"
        "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
        "       vec4 result = min(canvas, gl_FragColor);\n"
-       "       result = clamp(result, 0.0, 1.0);\n"
        "       gl_FragColor = mix(canvas, result, alpha);\n"
        "}\n";
 
@@ -243,7 +241,6 @@ static const char *blend_average_frag =
        "void main() {\n"
        "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
        "       vec4 result = (canvas + gl_FragColor) * 0.5;\n"
-       "       result = clamp(result, 0.0, 1.0);\n"
        "       gl_FragColor = mix(canvas, result, alpha);\n"
        "}\n";
 
@@ -400,7 +397,6 @@ static const char *blend_or_frag =
        "void main() {\n"
        "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
        "       vec4 result = canvas + gl_FragColor - canvas * gl_FragColor;\n"
-       "       result = clamp(result, 0.0, 1.0);\n"
        "       gl_FragColor = mix(canvas, result, alpha);\n"
        "}\n";
 
@@ -739,7 +735,7 @@ void Playback3D::copy_from_sync(Playback3DCommand *command)
 //                     command->frame->get_h(),
 //                     BC_RGB888,
 //                     -1);
-//             command->frame->to_ram();
+//             command->frame->screen_to_ram();
 //
 //             window->clear_box(0,
 //                                             0,
index 6bd71b1f5a6c307478d70b1a83f048b295be1a7c..7fcd82a264e75877385cb637e512a61fe6e4978c 100644 (file)
@@ -635,7 +635,7 @@ double VWindowEditing::get_position()
 void VWindowEditing::set_position(double position)
 {
        EDL *edl = vwindow->get_edl();
-       if( edl ) return;
+       if( !edl ) return;
        if( get_position() != position ) {
                position -= edl->session->get_frame_offset() / edl->session->frame_rate;
                if( position < 0 ) position = 0;
index beabdd3d4bcb27c7f6670a1ba798ccc9e63f2923..cefaea7f48e22be0e9667cb4f376d84e794d5509 100644 (file)
@@ -418,7 +418,10 @@ int BC_PopupMenu::button_release_event()
                }
        }
 
-       if(popup_down)
+       if( !use_title && status == BUTTON_DN ) {
+               result = 1;
+       }
+       else if(popup_down)
        {
 // Menu is down so dispatch to popup.
                result = menu_popup->dispatch_button_release();
index 1eec314bb0c7757468a98cdb23f65953cd10934e..7f57329bcce294a14265f8eb2b01222470c3c713 100644 (file)
@@ -790,6 +790,11 @@ int VFrame::write_png(const char *path)
                        png_cmodel = PNG_COLOR_TYPE_RGB;
                        break;
 
+               case BC_RGBA8888:
+               case BC_YUVA8888:
+                       png_cmodel = PNG_COLOR_TYPE_RGB_ALPHA;
+                       break;
+
                case BC_A8:
                        png_cmodel = PNG_COLOR_TYPE_GRAY;
                        break;
index 575968916c302476241c2bd5a7d966a38cd8df5f..f0d8877727f41543be4551fe294f85d7d63e39b2 100644 (file)
@@ -213,8 +213,9 @@ public:
 // Must be called from a synchronous opengl thread after enable_opengl.
        void to_texture();
 
-// Transfer from PBuffer to RAM.  Only used after Playback3D::overlay_sync
-       void to_ram();
+// Transfer from PBuffer to RAM.
+//   used in Playback3D::overlay_sync, plugin Overlay::handle_opengl
+       void screen_to_ram();
 
 // Transfer contents of current pbuffer to texture,
 // creating a new texture if necessary.
index 3ed62aca30548e2da45e096ed7649e7ffc6c8107..f6f0a440cf85fdf41364655287d660387e73465a 100644 (file)
@@ -152,33 +152,6 @@ void VFrame::to_texture()
 #endif
 }
 
-void VFrame::to_ram()
-{
-#ifdef HAVE_GL
-       switch(opengl_state)
-       {
-// Only pbuffer is supported since this is only called after the
-// overlay operation onto the pbuffer.
-               case VFrame::SCREEN:
-                       if(pbuffer)
-                       {
-                               enable_opengl();
-//printf("VFrame::to_ram %d %d\n", get_w(), get_h());
-                               glReadPixels(0,
-                                       0,
-                                       get_w(),
-                                       get_h(),
-                                       GL_RGB,
-                                       GL_UNSIGNED_BYTE,
-                                       get_rows()[0]);
-                               flip_vert();
-                       }
-                       opengl_state = VFrame::RAM;
-                       return;
-       }
-#endif
-}
-
 void VFrame::create_pbuffer()
 {
        if(pbuffer &&
@@ -220,12 +193,9 @@ void VFrame::screen_to_texture(int x, int y, int w, int h)
 #ifdef HAVE_GL
 // Create texture
        BC_Texture::new_texture(&texture,
-               get_w(),
-               get_h(),
-               get_color_model());
+               get_w(), get_h(), get_color_model());
 
-       if(pbuffer)
-       {
+       if(pbuffer) {
                glEnable(GL_TEXTURE_2D);
 
 // Read canvas into texture, use back texture for DOUBLE_BUFFER
@@ -247,6 +217,18 @@ void VFrame::screen_to_texture(int x, int y, int w, int h)
 #endif
 }
 
+void VFrame::screen_to_ram()
+{
+#ifdef HAVE_GL
+       enable_opengl();
+       glReadBuffer(GL_BACK);
+       int type = BC_CModels::is_float(color_model) ? GL_FLOAT : GL_UNSIGNED_BYTE;
+       int format = BC_CModels::has_alpha(color_model) ? GL_RGBA : GL_RGB;
+       glReadPixels(0, 0, get_w(), get_h(), format, type, get_rows()[0]);
+       opengl_state = VFrame::RAM;
+#endif
+}
+
 void VFrame::draw_texture(float in_x1,
                float in_y1,
                float in_x2,
index d3bdd92cf1d44db950710b387b992cd44203e2aa..e1ca0961f06d410598354baffc938d00762db24a 100644 (file)
@@ -22,6 +22,7 @@
 #include "bcdisplayinfo.h"
 #include "clip.h"
 #include "bchash.h"
+#include "edlsession.h"
 #include "filexml.h"
 #include "guicast.h"
 #include "keyframe.h"
@@ -136,9 +137,7 @@ public:
        VFrame *temp;
        int current_layer;
        int output_layer;
-// Inclusive layer numbers
-       int input_layer1;
-       int input_layer2;
+       int input_layer;
 };
 
 OverlayConfig::OverlayConfig()
@@ -419,93 +418,44 @@ int Overlay::process_buffer(VFrame **frame,
 {
        load_configuration();
 
-
-       if(!temp) temp = new VFrame(0,
-               -1,
-               frame[0]->get_w(),
-               frame[0]->get_h(),
-               frame[0]->get_color_model(),
-               -1);
-
-       if(!overlayer)
-               overlayer = new OverlayFrame(get_project_smp() + 1);
-
-       int step;
-       VFrame *output;
-
-       if(config.direction == OverlayConfig::BOTTOM_FIRST)
-       {
-               input_layer1 = get_total_buffers() - 1;
-               input_layer2 = -1;
-               step = -1;
-       }
-       else
-       {
-               input_layer1 = 0;
-               input_layer2 = get_total_buffers();
-               step = 1;
-       }
-
-       if(config.output_layer == OverlayConfig::TOP)
-       {
-               output_layer = 0;
-       }
-       else
-       {
-               output_layer = get_total_buffers() - 1;
-       }
-
-
-
-// Direct copy the first layer
-       output = frame[output_layer];
-       read_frame(output,
-               input_layer1,
-               start_position,
-               frame_rate,
-               get_use_opengl());
-
-       if(get_total_buffers() == 1) return 0;
-
-
-
-       current_layer = input_layer1;
-       if(get_use_opengl())
-               run_opengl();
-
-       for(int i = input_layer1 + step; i != input_layer2; i += step)
-       {
-               read_frame(temp,
-                       i,
-                       start_position,
-                       frame_rate,
-                       get_use_opengl());
-
-// Call the opengl handler once for each layer
-               if(get_use_opengl())
-               {
-                       current_layer = i;
-                       run_opengl();
-               }
-               else
-               {
-                       overlayer->overlay(output,
-                               temp,
-                               0,
-                               0,
-                               output->get_w(),
-                               output->get_h(),
-                               0,
-                               0,
-                               output->get_w(),
-                               output->get_h(),
-                               1,
-                               config.mode,
-                               NEAREST_NEIGHBOR);
+       EDLSession* session = get_edlsession();
+       int interpolation_type = session ? session->interpolation_type : NEAREST_NEIGHBOR;
+
+       int step = config.direction == OverlayConfig::BOTTOM_FIRST ?  -1 : 1;
+       int layers = get_total_buffers();
+       input_layer = config.direction == OverlayConfig::BOTTOM_FIRST ? layers-1 : 0;
+       output_layer = config.output_layer == OverlayConfig::TOP ?  0 : layers-1;
+       VFrame *output = frame[output_layer];
+
+       current_layer = input_layer;
+       read_frame(output, current_layer,  // Direct copy the first layer
+                        start_position, frame_rate, get_use_opengl());
+
+       if( --layers > 0 ) {    // need 2 layers to do overlay
+               if( !temp )
+                       temp = new VFrame(0, -1, frame[0]->get_w(), frame[0]->get_h(),
+                                       frame[0]->get_color_model(), -1);
+
+               while( --layers >= 0 ) {
+                       current_layer += step;
+                       read_frame(temp, current_layer,
+                                start_position, frame_rate, get_use_opengl());
+
+                       if(get_use_opengl()) {
+                               run_opengl();
+                               continue;
+                       }
+
+                       if(!overlayer)
+                               overlayer = new OverlayFrame(get_project_smp() + 1);
+                       
+                       overlayer->overlay(output, temp,
+                               0, 0, output->get_w(), output->get_h(),
+                               0, 0, output->get_w(), output->get_h(),
+                               1, config.mode, interpolation_type);
                }
        }
 
-
        return 0;
 }
 
@@ -519,132 +469,192 @@ int Overlay::handle_opengl()
                "uniform vec3 chroma_offset;\n"
                "void main()\n"
                "{\n"
-               "       vec4 result_color;\n"
                "       vec4 dst_color = texture2D(dst_tex, gl_FragCoord.xy / dst_tex_dimensions);\n"
                "       vec4 src_color = texture2D(src_tex, gl_TexCoord[0].st);\n"
                "       src_color.rgb -= chroma_offset;\n"
                "       dst_color.rgb -= chroma_offset;\n";
 
        static const char *put_pixels_frag =
-               "       result_color.rgb += chroma_offset;\n"
-               "       result_color.rgb = mix(dst_color.rgb, result_color.rgb, src_color.a);\n"
-               "       result_color.a = max(src_color.a, dst_color.a);\n"
-               "       gl_FragColor = result_color;\n"
+               "       result.rgb += chroma_offset;\n"
+               "       gl_FragColor = result;\n"
                "}\n";
 
-       static const char *blend_add_frag =
-               "       result_color.rgb = dst_color.rgb + src_color.rgb;\n";
-
-       static const char *blend_max_frag =
-               "       result_color.r = max(abs(dst_color.r, src_color.r);\n"
-               "       result_color.g = max(abs(dst_color.g, src_color.g);\n"
-               "       result_color.b = max(abs(dst_color.b, src_color.b);\n";
-
-       static const char *blend_min_frag =
-               "       result_color.r = min(abs(dst_color.r, src_color.r);\n"
-               "       result_color.g = min(abs(dst_color.g, src_color.g);\n"
-               "       result_color.b = min(abs(dst_color.b, src_color.b);\n";
-
-       static const char *blend_subtract_frag =
-               "       result_color.rgb = dst_color.rgb - src_color.rgb;\n";
-
-
-       static const char *blend_multiply_frag =
-               "       result_color.rgb = dst_color.rgb * src_color.rgb;\n";
-
-       static const char *blend_divide_frag =
-               "       result_color.rgb = dst_color.rgb / src_color.rgb;\n"
-               "       if(src_color.r == 0.0) result_color.r = 1.0;\n"
-               "       if(src_color.g == 0.0) result_color.g = 1.0;\n"
-               "       if(src_color.b == 0.0) result_color.b = 1.0;\n";
 
+// NORMAL
+static const char *blend_normal_frag =
+       "       vec4 result = mix(src_color, src_color, src_color.a);\n";
+
+// ADDITION
+static const char *blend_add_frag =
+       "       vec4 result = dst_color + src_color;\n"
+       "       result = clamp(result, 0.0, 1.0);\n";
+
+// SUBTRACT
+static const char *blend_subtract_frag =
+       "       vec4 result = dst_color - src_color;\n"
+       "       result = clamp(result, 0.0, 1.0);\n";
+
+// MULTIPLY
+static const char *blend_multiply_frag =
+       "       vec4 result = dst_color * src_color;\n";
+
+// DIVIDE
+static const char *blend_divide_frag =
+       "       vec4 result = dst_color / src_color;\n"
+       "       if(src_color.r == 0.) result.r = 1.0;\n"
+       "       if(src_color.g == 0.) result.g = 1.0;\n"
+       "       if(src_color.b == 0.) result.b = 1.0;\n"
+       "       if(src_color.a == 0.) result.a = 1.0;\n"
+       "       result = clamp(result, 0.0, 1.0);\n";
+
+// MAX
+static const char *blend_max_frag =
+       "       vec4 result = max(src_color, dst_color);\n";
+
+// MIN
+static const char *blend_min_frag =
+       "       vec4 result = min(src_color, dst_color);\n";
+
+// AVERAGE
+static const char *blend_average_frag =
+       "       vec4 result = (src_color + dst_color) * 0.5;\n";
+
+// DARKEN
+static const char *blend_darken_frag =
+       "       vec4 result = vec4(src_color.rgb * (1.0 - dst_color.a) +"
+                       " dst_color.rgb * (1.0 - src_color.a) +"
+                       " min(src_color.rgb, dst_color.rgb), "
+                       " src_color.a + dst_color.a - src_color.a * dst_color.a);\n"
+       "       result = clamp(result, 0.0, 1.0);\n";
+
+// LIGHTEN
+static const char *blend_lighten_frag =
+       "       vec4 result = vec4(src_color.rgb * (1.0 - dst_color.a) +"
+                       " dst_color.rgb * (1.0 - src_color.a) +"
+                       " max(src_color.rgb, dst_color.rgb), "
+                       " src_color.a + dst_color.a - src_color.a * dst_color.a);\n"
+       "       result = clamp(result, 0.0, 1.0);\n";
+
+// DST
+static const char *blend_dst_frag =
+       "       vec4 result = dst_color;\n";
+
+// DST_ATOP
+static const char *blend_dst_atop_frag =
+       "       vec4 result = vec4(src_color.rgb * dst_color.a + "
+                       "(1.0 - src_color.a) * dst_color.rgb, dst_color.a);\n";
+
+// DST_IN
+static const char *blend_dst_in_frag =
+       "       vec4 result = src_color * dst_color.a;\n";
+
+// DST_OUT
+static const char *blend_dst_out_frag =
+       "       vec4 result = src_color * (1.0 - dst_color.a);\n";
+
+// DST_OVER
+static const char *blend_dst_over_frag =
+       "       vec4 result = vec4(src_color.rgb + (1.0 - src_color.a) * dst_color.rgb, "
+                       " dst_color.a + src_color.a - dst_color.a * src_color.a);\n";
+
+// SRC
+static const char *blend_src_frag =
+       "       vec4 result = src_color;\n";
+
+// SRC_ATOP
+static const char *blend_src_atop_frag =
+       "       vec4 result = vec4(dst_color.rgb * src_color.a + "
+                       "src_color.rgb * (1.0 - dst_color.a), src_color.a);\n";
+
+// SRC_IN
+static const char *blend_src_in_frag =
+       "       vec4 result = dst_color * src_color.a;\n";
+
+// SRC_OUT
+static const char *blend_src_out_frag =
+       "       vec4 result = dst_color * (1.0 - src_color.a);\n";
+
+// SRC_OVER
+static const char *blend_src_over_frag =
+       "       vec4 result = vec4(dst_color.rgb + (1.0 - dst_color.a) * src_color.rgb, "
+                               "dst_color.a + src_color.a - dst_color.a * src_color.a);\n";
+
+// OR
+static const char *blend_or_frag =
+       "       vec4 result = src_color + dst_color - src_color * dst_color;\n";
+
+// XOR
+static const char *blend_xor_frag =
+       "       vec4 result = vec4(dst_color.rgb * (1.0 - src_color.a) + "
+                       "(1.0 - dst_color.a) * src_color.rgb, "
+                       "dst_color.a + src_color.a - 2.0 * dst_color.a * src_color.a);\n";
+
+static const char * const overlay_shaders[TRANSFER_TYPES] = {
+               blend_normal_frag,      // TRANSFER_NORMAL
+               blend_add_frag,         // TRANSFER_ADDITION
+               blend_subtract_frag,    // TRANSFER_SUBTRACT
+               blend_multiply_frag,    // TRANSFER_MULTIPLY
+               blend_divide_frag,      // TRANSFER_DIVIDE
+               blend_src_frag,         // TRANSFER_REPLACE
+               blend_max_frag,         // TRANSFER_MAX
+               blend_min_frag,         // TRANSFER_MIN
+               blend_average_frag,     // TRANSFER_AVERAGE
+               blend_darken_frag,      // TRANSFER_DARKEN
+               blend_lighten_frag,     // TRANSFER_LIGHTEN
+               blend_dst_frag,         // TRANSFER_DST
+               blend_dst_atop_frag,    // TRANSFER_DST_ATOP
+               blend_dst_in_frag,      // TRANSFER_DST_IN
+               blend_dst_out_frag,     // TRANSFER_DST_OUT
+               blend_dst_over_frag,    // TRANSFER_DST_OVER
+               blend_src_frag,         // TRANSFER_SRC
+               blend_src_atop_frag,    // TRANSFER_SRC_ATOP
+               blend_src_in_frag,      // TRANSFER_SRC_IN
+               blend_src_out_frag,     // TRANSFER_SRC_OUT
+               blend_src_over_frag,    // TRANSFER_SRC_OVER
+               blend_or_frag,          // TRANSFER_OR
+               blend_xor_frag          // TRANSFER_XOR
+       };
 
-       VFrame *src = temp;
+       glDisable(GL_BLEND);
        VFrame *dst = get_output(output_layer);
+        VFrame *src = temp;
 
-       dst->enable_opengl();
-       dst->init_screen();
-
-       const char *shader_stack[] = { 0, 0, 0 };
-       int current_shader = 0;
-
-
-
-
+       switch( config.mode ) {
+       case TRANSFER_REPLACE:
+       case TRANSFER_SRC:
 // Direct copy layer
-       if(config.mode == TRANSFER_REPLACE)
-       {
-               src->to_texture();
-               src->bind_texture(0);
-               dst->enable_opengl();
+               src->to_texture();
+               dst->enable_opengl();
                dst->init_screen();
-
-// Multiply alpha
-               glDisable(GL_BLEND);
                src->draw_texture();
-       }
-       else
-       if(config.mode == TRANSFER_NORMAL)
-       {
-               dst->enable_opengl();
-               dst->init_screen();
-
+               break;
+       case TRANSFER_NORMAL:
 // Move destination to screen
-               if(dst->get_opengl_state() != VFrame::SCREEN)
-               {
+               if( dst->get_opengl_state() != VFrame::SCREEN ) {
                        dst->to_texture();
-                       dst->bind_texture(0);
+                       dst->enable_opengl();
+                       dst->init_screen();
                        dst->draw_texture();
                }
-
-               src->to_texture();
-               src->bind_texture(0);
-               dst->enable_opengl();
+               src->to_texture();
+               dst->enable_opengl();
                dst->init_screen();
-
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                src->draw_texture();
-       }
-       else
-       {
-// Read destination back to texture
+               break;
+       default:
+               src->to_texture();
                dst->to_texture();
-
-               src->enable_opengl();
-               src->init_screen();
-               src->to_texture();
-
-               dst->enable_opengl();
+               dst->enable_opengl();
                dst->init_screen();
-               src->bind_texture(0);
-               dst->bind_texture(1);
-
+               src->bind_texture(0);
+               dst->bind_texture(1);
+               const char *shader_stack[] = { 0, 0, 0 };
+               int current_shader = 0;
 
                shader_stack[current_shader++] = get_pixels_frag;
-
-               switch(config.mode)
-               {
-                       case TRANSFER_ADDITION:
-                               shader_stack[current_shader++] = blend_add_frag;
-                               break;
-                       case TRANSFER_SUBTRACT:
-                               shader_stack[current_shader++] = blend_subtract_frag;
-                               break;
-                       case TRANSFER_MULTIPLY:
-                               shader_stack[current_shader++] = blend_multiply_frag;
-                               break;
-                       case TRANSFER_DIVIDE:
-                               shader_stack[current_shader++] = blend_divide_frag;
-                               break;
-                       case TRANSFER_MAX:
-                               shader_stack[current_shader++] = blend_max_frag;
-                               break;
-                       case TRANSFER_MIN:
-                               shader_stack[current_shader++] = blend_min_frag;
-                               break;
-               }
-
+               shader_stack[current_shader++] = overlay_shaders[config.mode];
                shader_stack[current_shader++] = put_pixels_frag;
 
                unsigned int shader_id = 0;
@@ -657,26 +667,26 @@ int Overlay::handle_opengl()
                glUseProgram(shader_id);
                glUniform1i(glGetUniformLocation(shader_id, "src_tex"), 0);
                glUniform1i(glGetUniformLocation(shader_id, "dst_tex"), 1);
-               if(BC_CModels::is_yuv(dst->get_color_model()))
-                       glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), 0.0, 0.5, 0.5);
-               else
-                       glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), 0.0, 0.0, 0.0);
                glUniform2f(glGetUniformLocation(shader_id, "dst_tex_dimensions"),
-                       (float)dst->get_texture_w(),
-                       (float)dst->get_texture_h());
+                               (float)dst->get_texture_w(), (float)dst->get_texture_h());
+               float chroma_offset = BC_CModels::is_yuv(dst->get_color_model()) ? 0.5 : 0.0;
+               glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"),
+                               0.0, chroma_offset, chroma_offset);
 
-               glDisable(GL_BLEND);
                src->draw_texture();
                glUseProgram(0);
+
+               glActiveTexture(GL_TEXTURE1);
+               glDisable(GL_TEXTURE_2D);
+               break;
        }
 
-       glDisable(GL_BLEND);
-       glActiveTexture(GL_TEXTURE1);
-       glDisable(GL_TEXTURE_2D);
        glActiveTexture(GL_TEXTURE0);
        glDisable(GL_TEXTURE_2D);
+       glDisable(GL_BLEND);
 
-       dst->set_opengl_state(VFrame::SCREEN);
+// get the data before something else uses the screen
+       dst->screen_to_ram();
 #endif
        return 0;
 }