pipeline: can now support pad properties

Can set pad property which will be used during the
pipeline generation.

Change port name to src_* or sink_*

Caps become an hidden property

Remove the ':' to separate value field, it does not
work properly with URI

Add funny graphs
This commit is contained in:
Stéphane Cerveau 2022-02-03 16:49:11 +01:00
parent 7db3b333ac
commit 59ecbb41a5
8 changed files with 281 additions and 53 deletions

View file

@ -62,6 +62,12 @@
- [x] Icon install - [x] Icon install
- [x] Flatpak infrastructure - [x] Flatpak infrastructure
## 0.2.1
### app
- [x] Can set pad properties to be used during the pipeline generation. See videomixer_alpha.xml
## TODO ## TODO
### Graphview ### Graphview

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 267 KiB

View file

@ -2,10 +2,10 @@
<Graph id="0"> <Graph id="0">
<Node name="timeoverlay" id="9" type="Transform" pos_x="1023.9133" pos_y="320.11438"> <Node name="timeoverlay" id="9" type="Transform" pos_x="1023.9133" pos_y="320.11438">
<Port name="out" id="17" direction="Output" presence="Always"> <Port name="out" id="17" direction="Output" presence="Always">
<Property name="caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw(ANY), format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" /> <Property name="_caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw(ANY), format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port> </Port>
<Port name="in" id="16" direction="Input" presence="Always"> <Port name="in" id="16" direction="Input" presence="Always">
<Property name="caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw(ANY), format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" /> <Property name="_caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw(ANY), format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port> </Port>
</Node> </Node>
<Node name="queue" id="7" type="Transform" pos_x="914.41705" pos_y="30.562256"> <Node name="queue" id="7" type="Transform" pos_x="914.41705" pos_y="30.562256">

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Graph id="0">
<Node name="videomixer" id="3" type="Transform" pos_x="658.78845" pos_y="194.22154">
<Port name="sink_1" id="10" direction="Input" presence="Sometimes">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV, BGRA, ARGB, RGBA, ABGR, Y444, Y42B, YUY2, UYVY, YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, RGBx, BGRx }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
<Property name="zorder" value="0" />
</Port>
<Port name="src_0" id="3" direction="Output" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV, BGRA, ARGB, RGBA, ABGR, Y444, Y42B, YUY2, UYVY, YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, RGBx, BGRx }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port>
<Port name="sink_0" id="9" direction="Input" presence="Sometimes">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV, BGRA, ARGB, RGBA, ABGR, Y444, Y42B, YUY2, UYVY, YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, RGBx, BGRx }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
<Property name="zorder" value="1" />
</Port>
</Node>
<Node name="autovideosink" id="5" type="Sink" pos_x="1393.3219" pos_y="200.00417">
<Port name="sink_0" id="6" direction="Input" presence="Always">
<Property name="_caps" value="ANY" />
</Port>
</Node>
<Node name="videotestsrc" id="1" type="Source" pos_x="-54.65982" pos_y="58.382446">
<Port name="src_0" id="1" direction="Output" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], multiview-mode=(string){ mono, left, right }; video/x-bayer, format=(string){ bggr, rggb, grbg, gbrg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], multiview-mode=(string){ mono, left, right }" />
</Port>
<Property name="pattern" value="13" />
</Node>
<Node name="videotestsrc" id="2" type="Source" pos_x="-27.72644" pos_y="379.1207">
<Port name="src_0" id="2" direction="Output" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], multiview-mode=(string){ mono, left, right }; video/x-bayer, format=(string){ bggr, rggb, grbg, gbrg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], multiview-mode=(string){ mono, left, right }" />
</Port>
<Property name="pattern" value="1" />
</Node>
<Node name="alpha" id="4" type="Transform" pos_x="290.85873" pos_y="58.17296">
<Port name="sink_0" id="4" direction="Input" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV, ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port>
<Port name="src_0" id="5" direction="Output" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV, ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port>
<Property name="method" value="1" />
</Node>
<Node name="videoconvert" id="6" type="Transform" pos_x="1016.99066" pos_y="196.31989">
<Port name="sink_0" id="7" direction="Input" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw(ANY), format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port>
<Port name="src_0" id="8" direction="Output" presence="Always">
<Property name="_caps" value="video/x-raw, format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw(ANY), format=(string){ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]" />
</Port>
</Node>
<Link id="2" node_from="4" node_to="3" port_from="5" port_to="9" active="true" />
<Link id="3" node_from="2" node_to="3" port_from="2" port_to="10" active="true" />
<Link id="4" node_from="3" node_to="6" port_from="3" port_to="7" active="true" />
<Link id="1" node_from="1" node_to="4" port_from="1" port_to="4" active="true" />
<Link id="5" node_from="6" node_to="5" port_from="8" port_to="6" active="true" />
</Graph>

View file

@ -288,6 +288,7 @@ impl GPSApp {
application.add_action(&gio::SimpleAction::new("graph.check", None)); application.add_action(&gio::SimpleAction::new("graph.check", None));
application.add_action(&gio::SimpleAction::new("port.delete", None)); application.add_action(&gio::SimpleAction::new("port.delete", None));
application.add_action(&gio::SimpleAction::new("port.properties", None));
application.add_action(&gio::SimpleAction::new("node.add-to-favorite", None)); application.add_action(&gio::SimpleAction::new("node.add-to-favorite", None));
application.add_action(&gio::SimpleAction::new("node.delete", None)); application.add_action(&gio::SimpleAction::new("node.delete", None));
@ -577,7 +578,7 @@ impl GPSApp {
let description = GPS::ElementInfo::element_description(&node.name()).ok(); let description = GPS::ElementInfo::element_description(&node.name()).ok();
node.set_tooltip_markup(description.as_deref()); node.set_tooltip_markup(description.as_deref());
for port in node.all_ports(GM::PortDirection::All) { for port in node.all_ports(GM::PortDirection::All) {
let caps = PropertyExt::property(&port, "caps"); let caps = PropertyExt::property(&port,"_caps");
GPS_TRACE!("caps={} for port id {}", caps.clone().unwrap_or_else(|| "caps unknown".to_string()), port.id()); GPS_TRACE!("caps={} for port id {}", caps.clone().unwrap_or_else(|| "caps unknown".to_string()), port.id());
port.set_tooltip_markup(caps.as_deref()); port.set_tooltip_markup(caps.as_deref());
} }
@ -598,7 +599,7 @@ impl GPSApp {
GPS_INFO!("Port added port id={} to node id={} in graph id={}", port_id, node_id, graph_id); GPS_INFO!("Port added port id={} to node id={} in graph id={}", port_id, node_id, graph_id);
if let Some(node) = app.graphview.borrow().node(node_id) { if let Some(node) = app.graphview.borrow().node(node_id) {
if let Some(port) = node.port(port_id) { if let Some(port) = node.port(port_id) {
let caps = PropertyExt::property(&port, "caps"); let caps = PropertyExt::property(&port, "_caps");
GPS_TRACE!("caps={} for port id {}", caps.clone().unwrap_or_else(|| "caps unknown".to_string()), port.id()); GPS_TRACE!("caps={} for port id {}", caps.clone().unwrap_or_else(|| "caps unknown".to_string()), port.id());
port.set_tooltip_markup(caps.as_deref()); port.set_tooltip_markup(caps.as_deref());
} }
@ -688,13 +689,27 @@ impl GPSApp {
let app_weak = app.downgrade(); let app_weak = app.downgrade();
app.connect_app_menu_action("port.delete", move |_, _| { app.connect_app_menu_action("port.delete", move |_, _| {
let app = upgrade_weak!(app_weak); let app = upgrade_weak!(app_weak);
GPS_DEBUG!("port.delete-link port {} node {}", port_id, node_id); GPS_TRACE!("port.delete-link port {} node {}", port_id, node_id);
app.graphview.borrow().remove_port(node_id, port_id); app.graphview.borrow().remove_port(node_id, port_id);
}); });
} else { } else {
app.disconnect_app_menu_action("port.delete"); app.disconnect_app_menu_action("port.delete");
} }
let app_weak = app.downgrade();
app.connect_app_menu_action("port.properties", move |_, _| {
let app = upgrade_weak!(app_weak);
GPS_TRACE!("port.properties port {} node {}", port_id, node_id);
let node = app.node(node_id);
let port = app.port(node_id, port_id);
GPSUI::properties::display_pad_properties(
&app,
&node.name(),
&port.name(),
node_id,
port_id,
);
});
pop_menu.show(); pop_menu.show();
None None
}, },
@ -711,7 +726,6 @@ impl GPSApp {
let app = upgrade_weak!(app_weak, None); let app = upgrade_weak!(app_weak, None);
let node_id = values[1].get::<u32>().expect("node id args[1]"); let node_id = values[1].get::<u32>().expect("node id args[1]");
let node = app.graphview.borrow().node(node_id).expect("Unable to find node with this ID");
let point = values[2].get::<graphene::Point>().expect("point in args[2]"); let point = values[2].get::<graphene::Point>().expect("point in args[2]");
let pop_menu = app.app_pop_menu_at_position(&*app.graphview.borrow(), point.to_vec2().x() as f64, point.to_vec2().y() as f64); let pop_menu = app.app_pop_menu_at_position(&*app.graphview.borrow(), point.to_vec2().x() as f64, point.to_vec2().y() as f64);
@ -740,41 +754,27 @@ impl GPSApp {
app.graphview.borrow_mut().remove_node(node_id); app.graphview.borrow_mut().remove_node(node_id);
} }
); );
let node = app.node(node_id);
if let Some(input) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Input) { if let Some(input) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Input) {
let app_weak = app.downgrade(); let app_weak = app.downgrade();
app.connect_app_menu_action("node.request-pad-input", app.connect_app_menu_action("node.request-pad-input",
move |_,_| { move |_,_| {
let app = upgrade_weak!(app_weak); let app = upgrade_weak!(app_weak);
let graphview = app.graphview.borrow();
GPS_DEBUG!("node.request-pad-input {}", node_id); GPS_DEBUG!("node.request-pad-input {}", node_id);
let properties: HashMap<String, String> = HashMap::from([ app.create_port_with_caps(node_id, GM::PortDirection::Input, GM::PortPresence::Sometimes, input.caps().to_string())
("caps".to_string(), input.caps().to_string())]);
let port = graphview.create_port("in", GM::PortDirection::Input, GM::PortPresence::Sometimes);
port.update_properties(&properties);
if let Some(mut node) = graphview.node(node_id) {
graphview.add_port_to_node(&mut node, port);
}
} }
); );
} else { } else {
app.disconnect_app_menu_action("node.request-pad-input"); app.disconnect_app_menu_action("node.request-pad-input");
} }
let node = app.node(node_id);
if let Some(output) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Output) { if let Some(output) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Output) {
let app_weak = app.downgrade(); let app_weak = app.downgrade();
app.connect_app_menu_action("node.request-pad-output", app.connect_app_menu_action("node.request-pad-output",
move |_,_| { move |_,_| {
let app = upgrade_weak!(app_weak); let app = upgrade_weak!(app_weak);
let graphview = app.graphview.borrow();
GPS_DEBUG!("node.request-pad-output {}", node_id); GPS_DEBUG!("node.request-pad-output {}", node_id);
let properties: HashMap<String, String> = HashMap::from([ app.create_port_with_caps(node_id, GM::PortDirection::Output, GM::PortPresence::Sometimes, output.caps().to_string());
("caps".to_string(), output.caps().to_string())]);
let port = graphview.create_port("out", GM::PortDirection::Output, GM::PortPresence::Sometimes);
port.update_properties(&properties);
if let Some(mut node) = graphview.node(node_id) {
graphview.add_port_to_node(&mut node, port);
}
} }
); );
} else { } else {
@ -823,7 +823,7 @@ impl GPSApp {
pub fn add_new_element(&self, element_name: &str) { pub fn add_new_element(&self, element_name: &str) {
let graphview = self.graphview.borrow(); let graphview = self.graphview.borrow();
let (inputs, outputs) = GPS::PadInfo::pads(element_name, false); let (inputs, outputs) = GPS::PadInfo::pads(element_name, false);
let mut node = let node =
graphview.create_node(element_name, GPS::ElementInfo::element_type(element_name)); graphview.create_node(element_name, GPS::ElementInfo::element_type(element_name));
let node_id = node.id(); let node_id = node.id();
if GPS::ElementInfo::element_is_uri_src_handler(element_name) { if GPS::ElementInfo::element_is_uri_src_handler(element_name) {
@ -837,36 +837,95 @@ impl GPSApp {
} }
}); });
} }
graphview.add_node(node);
for input in inputs { for input in inputs {
let properties: HashMap<String, String> = self.create_port_with_caps(
HashMap::from([("caps".to_string(), input.caps().to_string())]); node_id,
let port = GM::PortDirection::Input,
graphview.create_port("in", GM::PortDirection::Input, GM::PortPresence::Always); GM::PortPresence::Always,
port.update_properties(&properties); input.caps().to_string(),
graphview.add_port_to_node(&mut node, port); );
} }
for output in outputs { for output in outputs {
let properties: HashMap<String, String> = self.create_port_with_caps(
HashMap::from([("caps".to_string(), output.caps().to_string())]); node_id,
let port = GM::PortDirection::Output,
graphview.create_port("out", GM::PortDirection::Output, GM::PortPresence::Always); GM::PortPresence::Always,
port.update_properties(&properties); output.caps().to_string(),
graphview.add_port_to_node(&mut node, port); );
} }
graphview.add_node(node); }
fn node(&self, node_id: u32) -> GM::Node {
let node = self
.graphview
.borrow()
.node(node_id)
.unwrap_or_else(|| panic!("Unable to retrieve node with id {}", node_id));
node
}
fn port(&self, node_id: u32, port_id: u32) -> GM::Port {
let node = self.node(node_id);
node.port(port_id)
.unwrap_or_else(|| panic!("Unable to retrieve port with id {}", port_id))
} }
pub fn update_element_properties(&self, node_id: u32, properties: &HashMap<String, String>) { pub fn update_element_properties(&self, node_id: u32, properties: &HashMap<String, String>) {
let node = self.graphview.borrow().node(node_id).unwrap(); let node = self.node(node_id);
node.update_properties(properties); node.update_properties(properties);
} }
pub fn update_pad_properties(
&self,
node_id: u32,
port_id: u32,
properties: &HashMap<String, String>,
) {
let port = self.port(node_id, port_id);
port.update_properties(properties);
}
pub fn element_property(&self, node_id: u32, property_name: &str) -> Option<String> { pub fn element_property(&self, node_id: u32, property_name: &str) -> Option<String> {
let node = self.graphview.borrow().node(node_id).unwrap(); let node = self.node(node_id);
PropertyExt::property(&node, property_name) PropertyExt::property(&node, property_name)
} }
pub fn pad_properties(&self, node_id: u32, port_id: u32) -> HashMap<String, String> {
let port = self.port(node_id, port_id);
let mut properties: HashMap<String, String> = HashMap::new();
for (name, value) in port.properties().iter() {
if !port.hidden_property(name) {
properties.insert(name.to_string(), value.to_string());
}
}
properties
}
fn create_port_with_caps(
&self,
node_id: u32,
direction: GM::PortDirection,
presence: GM::PortPresence,
caps: String,
) {
let node = self.node(node_id);
let ports = node.all_ports(direction);
let port_name = match direction {
GM::PortDirection::Input => String::from("sink_"),
GM::PortDirection::Output => String::from("src_"),
_ => String::from("?"),
};
let graphview = self.graphview.borrow();
let port_name = format!("{}{}", port_name, ports.len());
let port = graphview.create_port(&port_name, direction, presence);
let properties: HashMap<String, String> = HashMap::from([("_caps".to_string(), caps)]);
port.update_properties(&properties);
if let Some(mut node) = graphview.node(node_id) {
graphview.add_port_to_node(&mut node, port);
}
}
fn clear_graph(&self) { fn clear_graph(&self) {
let graph_view = self.graphview.borrow(); let graph_view = self.graphview.borrow();
graph_view.clear(); graph_view.clear();

View file

@ -284,11 +284,20 @@ impl Pipeline {
let unique_name = node.unique_name(); let unique_name = node.unique_name();
description.push_str(&format!("{} name={} ", node.name(), unique_name)); description.push_str(&format!("{} name={} ", node.name(), unique_name));
elements.insert(unique_name.clone(), unique_name.clone()); elements.insert(unique_name.clone(), unique_name.clone());
// Node properties
for (name, value) in node.properties().iter() { for (name, value) in node.properties().iter() {
//This allow to have an index in front of a property such as an enum. //This allow to have an index in front of a property such as an enum.
let value = value.split_once(':').unwrap_or((value, value));
if !node.hidden_property(name) { if !node.hidden_property(name) {
description.push_str(&format!("{}={} ", name, value.1)); description.push_str(&format!("{}={} ", name, value));
}
}
//Port properties
let ports = node.all_ports(PortDirection::All);
for port in ports {
for (name, value) in port.properties().iter() {
if !port.hidden_property(name) {
description.push_str(&format!("{}::{}={} ", port.name(), name, value));
}
} }
} }

View file

@ -35,6 +35,10 @@
</menu> </menu>
<menu id="port_menu"> <menu id="port_menu">
<section> <section>
<item>
<attribute name="label" translatable="yes" comments="port menu entry properties">_Properties</attribute>
<attribute name="action">app.port.properties</attribute>
</item>
<item> <item>
<attribute name="label" translatable="yes" comments="port menu entry delete the link">_Delete</attribute> <attribute name="label" translatable="yes" comments="port menu entry delete the link">_Delete</attribute>
<attribute name="action">app.port.delete</attribute> <attribute name="action">app.port.delete</attribute>
@ -77,7 +81,7 @@
</item> </item>
</submenu> </submenu>
<item> <item>
<attribute name="label" translatable="yes" comments="Node menu entry request pad">_Properties</attribute> <attribute name="label" translatable="yes" comments="Node menu entry properties">_Properties</attribute>
<attribute name="action">app.node.properties</attribute> <attribute name="action">app.node.properties</attribute>
<attribute name="accel">&lt;primary&gt;n</attribute> <attribute name="accel">&lt;primary&gt;n</attribute>
</item> </item>

View file

@ -134,7 +134,7 @@ pub fn property_to_widget<F: Fn(String, String) + 'static>(
let flags = param.flags_class(); let flags = param.flags_class();
for value in flags.values() { for value in flags.values() {
combo.append_text(&format!( combo.append_text(&format!(
"{}:{}: {}", "{}:{}:{}",
value.value(), value.value(),
value.nick(), value.nick(),
value.name() value.name()
@ -142,9 +142,8 @@ pub fn property_to_widget<F: Fn(String, String) + 'static>(
} }
} }
if let Some(value) = app.element_property(node_id, property_name) { if let Some(value) = app.element_property(node_id, property_name) {
let value = value.split_once(':').unwrap_or(("0", ""));
//Retrieve the first value (index) from the property //Retrieve the first value (index) from the property
combo.set_active(Some(value.0.parse::<u32>().unwrap_or(0))); combo.set_active(Some(value.parse::<u32>().unwrap_or(0)));
} else if (param.flags() & glib::ParamFlags::READABLE) == glib::ParamFlags::READABLE } else if (param.flags() & glib::ParamFlags::READABLE) == glib::ParamFlags::READABLE
|| (param.flags() & glib::ParamFlags::READWRITE) == glib::ParamFlags::READWRITE || (param.flags() & glib::ParamFlags::READWRITE) == glib::ParamFlags::READWRITE
{ {
@ -155,12 +154,7 @@ pub fn property_to_widget<F: Fn(String, String) + 'static>(
combo.connect_changed(move |c| { combo.connect_changed(move |c| {
if let Some(text) = c.active_text() { if let Some(text) = c.active_text() {
let text = text.to_string(); f(c.widget_name().to_string(), text.to_string())
let fields: Vec<&str> = text.split(':').collect();
f(
c.widget_name().to_string(),
format!("{}:{}", fields[0], fields[1]),
)
} }
}); });
Some(combo.upcast::<gtk::Widget>()) Some(combo.upcast::<gtk::Widget>())
@ -249,3 +243,104 @@ pub fn display_plugin_properties(app: &GPSApp, element_name: &str, node_id: u32)
dialog.show(); dialog.show();
} }
pub fn display_pad_properties(
app: &GPSApp,
element_name: &str,
port_name: &str,
node_id: u32,
port_id: u32,
) {
let dialog = gtk::Dialog::with_buttons(
Some(&format!("{} properties from {}", port_name, element_name,)),
Some(&app.window),
gtk::DialogFlags::MODAL,
&[("Close", gtk::ResponseType::Close)],
);
dialog.set_default_size(640, 480);
dialog.set_modal(true);
let update_properties: Rc<RefCell<HashMap<String, String>>> =
Rc::new(RefCell::new(HashMap::new()));
let grid = gtk::Grid::new();
grid.set_column_spacing(4);
grid.set_row_spacing(4);
grid.set_margin_bottom(12);
let mut i = 0;
let properties = app.pad_properties(node_id, port_id);
for (name, value) in properties {
let property_name = gtk::Label::new(Some(&name));
property_name.set_hexpand(true);
property_name.set_halign(gtk::Align::Start);
property_name.set_margin_start(4);
let property_value = gtk::Entry::new();
property_value.set_width_request(150);
property_value.set_text(&value);
property_value.connect_changed(
glib::clone!(@weak property_name, @weak property_value, @strong update_properties=> move |_| {
update_properties.borrow_mut().insert(property_name.text().to_string(), property_value.text().to_string());
}),
);
grid.attach(&property_name, 0, i, 1, 1);
grid.attach(&property_value, 1, i, 1, 1);
i += 1;
}
// Add a new property allowing to set pads property.
let label = gtk::Label::new(Some("Add a new Property"));
label.set_hexpand(true);
label.set_halign(gtk::Align::Start);
label.set_margin_start(4);
let property_name = gtk::Entry::new();
property_name.set_width_request(150);
let property_value = gtk::Entry::new();
property_value.set_width_request(150);
property_name.connect_changed(
glib::clone!(@weak property_name, @weak property_value, @strong update_properties=> move |_| {
update_properties.borrow_mut().insert(property_name.text().to_string(), property_value.text().to_string());
}),
);
property_value.connect_changed(
glib::clone!(@weak property_name, @weak property_value, @strong update_properties=> move |_| {
update_properties.borrow_mut().insert(property_name.text().to_string(), property_value.text().to_string());
}),
);
grid.attach(&label, 0, i, 1, 1);
grid.attach(&property_name, 1, i, 1, 1);
grid.attach(&property_value, 2, i, 1, 1);
// Add all specific properties from the given element
let scrolledwindow = gtk::ScrolledWindow::builder()
.hexpand(true)
.vexpand(true)
.build();
scrolledwindow.set_child(Some(&grid));
let content_area = dialog.content_area();
content_area.append(&scrolledwindow);
content_area.set_vexpand(true);
content_area.set_margin_start(10);
content_area.set_margin_end(10);
content_area.set_margin_top(10);
content_area.set_margin_bottom(10);
let app_weak = app.downgrade();
dialog.connect_response(
glib::clone!(@strong update_properties, @weak dialog => move |_,_| {
let app = upgrade_weak!(app_weak);
for p in update_properties.borrow().values() {
GPS_INFO!("updated properties {}", p);
}
app.update_pad_properties(node_id, port_id, &update_properties.borrow());
dialog.close();
}),
);
dialog.show();
}