[pitivi] Add a custom user interface for chroma keying with the Alpha filter
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] Add a custom user interface for chroma keying with the Alpha filter
- Date: Tue, 5 Sep 2017 22:54:46 +0000 (UTC)
commit b6e72e2f321f9fb0c13f2518ebe05a0f6a6b1d17
Author: Suhas Nayak <suhas2go gmail com>
Date: Wed Aug 23 20:08:20 2017 +0530
Add a custom user interface for chroma keying with the Alpha filter
Co-authored-by: Jean-François Fortin Tam <nekohayo gmail com>
Co-authored-by: Thibault Saunier <thibault saunier collabora com>
Differential Revision: https://phabricator.freedesktop.org/D1745
data/ui/customwidgets/alpha.ui | 496 +++++++++++++++++++++++++++++++++
pitivi/utils/custom_effect_widgets.py | 104 +++++++-
pitivi/utils/widgets.py | 9 +-
3 files changed, 603 insertions(+), 6 deletions(-)
---
diff --git a/data/ui/customwidgets/alpha.ui b/data/ui/customwidgets/alpha.ui
new file mode 100644
index 0000000..51cac3e
--- /dev/null
+++ b/data/ui/customwidgets/alpha.ui
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkAdjustment" id="alpha_adjustment">
+ <property name="upper">1</property>
+ <property name="value">1</property>
+ <property name="step_increment">0.01</property>
+ <property name="page_increment">0.10000000000000001</property>
+ </object>
+ <object class="GtkAdjustment" id="angle_adjustment">
+ <property name="upper">90</property>
+ <property name="value">20</property>
+ <property name="step_increment">0.10000000000000001</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="black_sens_adjustment">
+ <property name="upper">128</property>
+ <property name="value">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="blue_color_adjustment">
+ <property name="upper">255</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="green_color_adjustment">
+ <property name="upper">255</property>
+ <property name="value">255</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-clear-all-symbolic</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-clear-all-symbolic</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-clear-all-symbolic</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-clear-all-symbolic</property>
+ </object>
+ <object class="GtkImage" id="image5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-clear-all-symbolic</property>
+ </object>
+ <object class="GtkListStore" id="liststore1"/>
+ <object class="GtkAdjustment" id="noise_adjustment">
+ <property name="upper">64</property>
+ <property name="value">2</property>
+ <property name="step_increment">0.10000000000000001</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="red_color_adjustment">
+ <property name="upper">255</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="white_sens_adjustment">
+ <property name="upper">128</property>
+ <property name="value">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkGrid" id="base_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkButton" id="GstAlpha::angle::reset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image1</property>
+ <property name="relief">none</property>
+ <property name="image_position">top</property>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="GstAlpha::noise-level::reset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image2</property>
+ <property name="relief">none</property>
+ <property name="image_position">top</property>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="GstAlpha::white-sensitivity::reset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image3</property>
+ <property name="relief">none</property>
+ <property name="image_position">top</property>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="GstAlpha::black-sensitivity::reset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image4</property>
+ <property name="relief">none</property>
+ <property name="image_position">top</property>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Angle:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Noise level:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">White sensitivity:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Black sensitivity:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="GstAlpha::angle">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">angle_adjustment</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">1</property>
+ <property name="round_digits">2</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="GstAlpha::noise-level">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">noise_adjustment</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">1</property>
+ <property name="round_digits">2</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="GstAlpha::white-sensitivity">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">white_sens_adjustment</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">1</property>
+ <property name="round_digits">2</property>
+ <property name="digits">0</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="GstAlpha::black-sensitivity">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">black_sens_adjustment</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">1</property>
+ <property name="round_digits">2</property>
+ <property name="digits">0</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="GstAlpha::angle::keyframe">
+ <property name="label" translatable="yes">◇</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="image_position">top</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="GstAlpha::noise-level::keyframe">
+ <property name="label" translatable="yes">◇</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="GstAlpha::white-sensitivity::keyframe">
+ <property name="label" translatable="yes">◇</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="GstAlpha::black-sensitivity::keyframe">
+ <property name="label" translatable="yes">◇</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Alpha:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="GstAlpha::alpha">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">alpha_adjustment</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">1</property>
+ <property name="round_digits">1</property>
+ <property name="digits">2</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Target chroma key:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Red</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Green</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="GstAlpha::target-b">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">blue_color_adjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="colorbutton">
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="title" translatable="yes">Select a color</property>
+ <property name="rgba">rgb(0,255,0)</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Blue</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="GstAlpha::target-g">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">green_color_adjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="GstAlpha::target-r">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">red_color_adjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="GstAlpha::alpha::reset">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image5</property>
+ <property name="relief">none</property>
+ <property name="image_position">top</property>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAspectFrame" id="color_picker_frame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/pitivi/utils/custom_effect_widgets.py b/pitivi/utils/custom_effect_widgets.py
index ebcdb14..1be7c8a 100644
--- a/pitivi/utils/custom_effect_widgets.py
+++ b/pitivi/utils/custom_effect_widgets.py
@@ -19,9 +19,12 @@
"""Utility methods for custom effect UI."""
import os
+from gi.repository import Gdk
from gi.repository import Gtk
from pitivi import configure
+from pitivi.utils.loggable import Loggable
+from pitivi.utils.widgets import ColorPickerButton
CUSTOM_WIDGETS_DIR = os.path.join(configure.get_ui_dir(), "customwidgets")
@@ -50,13 +53,18 @@ def create_custom_prop_widget_cb(unused_effect_prop_manager, effect_widget, effe
return create_custom_alpha_prop_widget(effect_widget, effect, prop, prop_value)
-def create_custom_widget_cb(unused_effect_prop_manager, effect_widget, effect):
+def create_custom_widget_cb(effect_prop_manager, effect_widget, effect):
"""Creates custom effect UI."""
effect_name = effect.get_property("bin-description")
path = os.path.join(CUSTOM_WIDGETS_DIR, effect_name + ".ui")
if not os.path.isfile(path):
return None
+ # Write individual effect callbacks here
+ if effect_name == "alpha":
+ widget = create_alpha_widget(effect_prop_manager, effect_widget, effect)
+ return widget
+
# Check if there is a UI file available as a glade file
# Assuming a GtkGrid called base_table exists
builder = setup_from_ui_file(effect_widget, path)
@@ -64,10 +72,96 @@ def create_custom_widget_cb(unused_effect_prop_manager, effect_widget, effect):
return widget
-def create_alpha_widget(unused_element_setting_widget, unused_element):
- """Not implemented yet."""
- # Main alpha widget would go here
- return None
+def create_alpha_widget(effect_prop_manager, element_setting_widget, element):
+ """Creates the UI for the `alpha` effect."""
+ builder = setup_from_ui_file(element_setting_widget, os.path.join(CUSTOM_WIDGETS_DIR, "alpha.ui"))
+
+ color_picker = ColorPickerButton(0, 255, 0)
+ color_picker_frame = builder.get_object("color_picker_frame")
+ color_picker_frame.add(color_picker)
+
+ # Additional Setup
+
+ # All modes other than custom RGB chroma keying are useless to us.
+ # "ALPHA_METHOD_CUSTOM" corresponds to "3"
+ Loggable().debug("Setting alpha's method to 3 (custom RGB chroma keying)")
+ element.set_child_property("method", 3)
+
+ # Color button and picker has to be connected manually!
+
+ def get_current_rgba():
+ """Gets the color used by the effect."""
+ color = Gdk.RGBA()
+ res, red = element.get_child_property("target-r")
+ assert res
+ res, green = element.get_child_property("target-g")
+ assert res
+ res, blue = element.get_child_property("target-b")
+ assert res
+ color.red = red / 255
+ color.green = green / 255
+ color.blue = blue / 255
+ return color
+
+ def color_button_color_set_cb(color_button):
+ """Handles the selection of a color with the color button."""
+ color = color_button.get_rgba()
+ red = int(color.red * 255)
+ green = int(color.green * 255)
+ blue = int(color.blue * 255)
+ from pitivi.undo.timeline import CommitTimelineFinalizingAction
+ pipeline = effect_prop_manager.app.project_manager.current_project.pipeline
+ action_log = effect_prop_manager.app.action_log
+ with action_log.started("Effect property change",
+ finalizing_action=CommitTimelineFinalizingAction(pipeline),
+ toplevel=True):
+ element.set_child_property("target-r", red)
+ element.set_child_property("target-g", green)
+ element.set_child_property("target-b", blue)
+
+ color_button = builder.get_object("colorbutton")
+ color_button.connect("color-set", color_button_color_set_cb)
+
+ def color_picker_value_changed_cb(unused_color_picker_button):
+ """Handles the selection of a color with the color picker button."""
+ from pitivi.undo.timeline import CommitTimelineFinalizingAction
+ pipeline = effect_prop_manager.app.project_manager.current_project.pipeline
+ action_log = effect_prop_manager.app.action_log
+ with action_log.started("Color Picker Change",
+ finalizing_action=CommitTimelineFinalizingAction(pipeline),
+ toplevel=True):
+ element.set_child_property("target-r", color_picker.color_r)
+ element.set_child_property("target-g", color_picker.color_g)
+ element.set_child_property("target-b", color_picker.color_b)
+
+ color_picker.connect("value-changed", color_picker_value_changed_cb)
+
+ def property_changed_cb(unused_effect, gst_element, pspec):
+ """Handles the change of a GObject property."""
+ if gst_element.get_control_binding(pspec.name):
+ Loggable().log("%s controlled, not displaying value", pspec.name)
+ return
+
+ widget = element_setting_widget.properties.get(pspec)
+ if not widget:
+ return
+
+ res, value = element_setting_widget.element.get_child_property(pspec.name)
+ assert res
+
+ if pspec.name in ("target-r", "target-g", "target-b"):
+ color_button.set_rgba(get_current_rgba())
+ widget.block_signals()
+ try:
+ widget.setWidgetValue(value)
+ finally:
+ widget.unblock_signals()
+ else:
+ widget.setWidgetValue(value)
+
+ element.connect("deep-notify", property_changed_cb)
+
+ return builder.get_object("base_table")
def create_custom_alpha_prop_widget(unused_element_setting_widget, unused_element, unused_prop,
unused_prop_value):
diff --git a/pitivi/utils/widgets.py b/pitivi/utils/widgets.py
index 9bf3a0a..039006f 100644
--- a/pitivi/utils/widgets.py
+++ b/pitivi/utils/widgets.py
@@ -225,6 +225,7 @@ class NumericWidget(Gtk.Box, DynamicWidget):
self.set_spacing(SPACING)
self._type = None
self.spinner = None
+ self.handler_id = None
if adjustment:
self.adjustment = adjustment
@@ -264,8 +265,14 @@ class NumericWidget(Gtk.Box, DynamicWidget):
self.spinner.show()
disable_scroll(self.spinner)
+ def block_signals(self):
+ self.adjustment.handler_block(self.handler_id)
+
+ def unblock_signals(self):
+ self.adjustment.handler_unblock(self.handler_id)
+
def connectValueChanged(self, callback, *args):
- self.adjustment.connect("value-changed", callback, *args)
+ self.handler_id = self.adjustment.connect("value-changed", callback, *args)
def getWidgetValue(self):
if self._type:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]