[pitivi] viewer: Add overlay for GESTitleSource.



commit 92c799eb2ed31cf575b897fecad63ea8b2acbbd2
Author: Lubosz Sarnecki <lubosz sarnecki collabora co uk>
Date:   Fri Jan 29 15:43:00 2016 +0100

    viewer: Add overlay for GESTitleSource.
    
    Depends on gst-plugins-base patches:
    https://bugzilla.gnome.org/show_bug.cgi?id=761251
    
    Differential Revision: https://phabricator.freedesktop.org/D727
    
    ui: make titleeditor x/y range bigger
    titleoverlay: Update at async done.
    
    Review changes:
    
    * Use GES children properties for text dimensions.
    * Add doc description.

 data/ui/titleeditor.ui         |    6 +-
 pitivi/utils/pipeline.py       |    2 +
 pitivi/viewer/overlay_stack.py |    7 ++-
 pitivi/viewer/title_overlay.py |  157 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+), 4 deletions(-)
---
diff --git a/data/ui/titleeditor.ui b/data/ui/titleeditor.ui
index 1bd55bc..ae76fa9 100644
--- a/data/ui/titleeditor.ui
+++ b/data/ui/titleeditor.ui
@@ -3,13 +3,15 @@
 <interface>
   <requires lib="gtk+" version="3.10"/>
   <object class="GtkAdjustment" id="position_x_adj">
-    <property name="upper">1</property>
+    <property name="upper">2</property>
+    <property name="lower">-2</property>
     <property name="value">0.5</property>
     <property name="step_increment">0.050000000000000003</property>
     <property name="page_increment">0.10000000000000001</property>
   </object>
   <object class="GtkAdjustment" id="position_y_adj">
-    <property name="upper">1</property>
+    <property name="upper">2</property>
+    <property name="lower">-2</property>
     <property name="value">0.5</property>
     <property name="step_increment">0.050000000000000003</property>
     <property name="page_increment">0.10000000000000001</property>
diff --git a/pitivi/utils/pipeline.py b/pitivi/utils/pipeline.py
index e3c3624..f73212e 100644
--- a/pitivi/utils/pipeline.py
+++ b/pitivi/utils/pipeline.py
@@ -44,6 +44,7 @@ PIPELINE_SIGNALS = {
     "eos": (GObject.SignalFlags.RUN_LAST, None, ()),
     "error": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)),
     "died": (GObject.SignalFlags.RUN_LAST, None, ()),
+    "async-done": (GObject.SignalFlags.RUN_LAST, None, ()),
 }
 
 MAX_RECOVERIES = 3
@@ -433,6 +434,7 @@ class SimplePipeline(GObject.Object, Loggable):
             self.debug("Duration might have changed, querying it")
             GLib.idle_add(self._queryDurationAsync)
         elif message.type == Gst.MessageType.ASYNC_DONE:
+            self.emit("async-done")
             if self._recovery_state == self.RecoveryState.SEEKED_AFTER_RECOVERING:
                 self._recovery_state = self.RecoveryState.NOT_RECOVERING
                 self._attempted_recoveries = 0
diff --git a/pitivi/viewer/overlay_stack.py b/pitivi/viewer/overlay_stack.py
index 9495bf0..ae7dfef 100644
--- a/pitivi/viewer/overlay_stack.py
+++ b/pitivi/viewer/overlay_stack.py
@@ -27,6 +27,7 @@ from gi.repository import Gdk
 from gi.repository import Gtk
 
 from pitivi.viewer.move_scale_overlay import MoveScaleOverlay
+from pitivi.viewer.title_overlay import TitleOverlay
 
 
 class OverlayStack(Gtk.Overlay):
@@ -56,8 +57,10 @@ class OverlayStack(Gtk.Overlay):
             overlay.update_from_source()
 
     def __create_overlay_for_source(self, source):
-        overlay = MoveScaleOverlay(self, source)
-
+        if type(source) == GES.TitleSource:
+            overlay = TitleOverlay(self, source)
+        else:
+            overlay = MoveScaleOverlay(self, source)
         self.add_overlay(overlay)
         self.__overlays[source] = overlay
 
diff --git a/pitivi/viewer/title_overlay.py b/pitivi/viewer/title_overlay.py
new file mode 100644
index 0000000..4aec33c
--- /dev/null
+++ b/pitivi/viewer/title_overlay.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+# Pitivi video editor
+#
+#       pitivi/viewer/title_overlay.py
+#
+# Copyright (c) 2016, Lubosz Sarnecki <lubosz sarnecki collabora co uk>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import cairo
+import numpy
+
+from pitivi.viewer.overlay import Overlay
+
+
+class TitleOverlay(Overlay):
+    """
+    Viewer overlays class for GESTitleSource
+    """
+    def __init__(self, stack, source):
+        Overlay.__init__(self, stack, source)
+        self.__corners = []
+        self.__position = numpy.array([0, 0])
+        self.__size = None
+        self.__click_source_position = None
+        self.__click_window_position = None
+        self.update_from_source()
+
+        stack.app.project_manager.current_project.pipeline.connect("async-done", self.on_async_done)
+
+    def on_async_done(self, unused_pipeline):
+        # Only update on_async when we are not dragging
+        if isinstance(self.stack.click_position, numpy.ndarray):
+                return
+        self.update_from_source()
+
+    def __draw_rectangle(self, cr):
+        for corner in self.__corners:
+            cr.line_to(*corner.tolist())
+        cr.line_to(*self.__position.tolist())
+
+    def __get_source_position(self):
+        res_x, x = self._source.get_child_property("xpos")
+        res_y, y = self._source.get_child_property("ypos")
+        assert res_x and res_y
+        return numpy.array([x, y])
+
+    def __get_text_position(self):
+        res_x, x = self._source.get_child_property("text-x")
+        res_y, y = self._source.get_child_property("text-y")
+        assert res_x and res_y
+        return numpy.array([x, y])
+
+    def __get_text_size(self):
+        res_w, w = self._source.get_child_property("text-width")
+        res_h, h = self._source.get_child_property("text-height")
+        assert res_w and res_h
+        return numpy.array([w, h])
+
+    def __set_source_position(self, position):
+        self._source.set_child_property("xpos", float(position[0]))
+        self._source.set_child_property("ypos", float(position[1]))
+
+    def __update_corners(self):
+        self.__corners = [
+            self.__position,
+            self.__position + numpy.array([self.__size[0], 0]),
+            self.__position + self.__size,
+            self.__position + numpy.array([0, self.__size[1]])
+        ]
+
+    def __update_from_motion(self, title_position):
+        self.__position = title_position
+        self.__update_corners()
+
+    def update_from_source(self):
+        position = self.__get_text_position()
+        size = self.__get_text_size()
+
+        self.__position = position * self.stack.window_size / self.project_size
+        self.__size = size * self.stack.window_size / self.project_size
+        self.__update_corners()
+        self.queue_draw()
+
+    def on_hover(self, cursor_position):
+        if (self.__position < cursor_position).all() and (cursor_position < self.__position + 
self.__size).all():
+            if self._is_selected():
+                self.stack.set_cursor("grab")
+            self._hover()
+        else:
+            self.unhover()
+        self.queue_draw()
+        return self._is_hovered()
+
+    def on_button_press(self):
+        self.__click_source_position = self.__get_source_position()
+        self.__click_window_position = self.__position
+        if self._is_hovered():
+            self._select()
+            self.stack.set_cursor("grabbing")
+            self.stack.selected_overlay = self
+        elif self._is_selected():
+            self._deselect()
+
+    def on_button_release(self, cursor_position):
+        self.__click_source_position = None
+        self.on_hover(cursor_position)
+        if self._is_hovered():
+            self.stack.set_cursor("grab")
+        self.queue_draw()
+
+    def on_motion_notify(self, cursor_position):
+        if not isinstance(self.stack.click_position, numpy.ndarray):
+                return
+        title_position = self.__click_source_position + 
self.stack.get_normalized_drag_distance(cursor_position)
+        self.__update_from_motion(self.__click_window_position + 
self.stack.get_drag_distance(cursor_position))
+        self.queue_draw()
+        self.__set_source_position(title_position)
+        self._commit()
+
+    def do_draw(self, cr):
+        if not self._is_selected() and not self._is_hovered():
+            return
+
+        cr.save()
+        # clear background
+        cr.set_operator(cairo.OPERATOR_OVER)
+        cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
+        cr.paint()
+
+        if self._is_hovered():
+            brightness = 0.65
+        else:
+            brightness = 0.3
+
+        # clip away outer mask
+        self.__draw_rectangle(cr)
+        cr.clip()
+        cr.set_source_rgba(brightness, brightness, brightness, 0.6)
+        self.__draw_rectangle(cr)
+
+        cr.set_line_width(16)
+        cr.stroke()
+        cr.restore()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]