Merge branch 'guistart' of git://git.lumiera.org/lumiera/ichthyo into gui
This commit is contained in:
commit
51f05ebb3e
31 changed files with 1815 additions and 150 deletions
|
|
@ -257,7 +257,7 @@ def configurePlatform(env):
|
|||
if not conf.CheckPkgConfig('glibmm-2.4', '2.16'):
|
||||
problems.append('Unable to configure Lib glib--, exiting.')
|
||||
|
||||
if not conf.CheckPkgConfig('gthread-2.0', '2.16'):
|
||||
if not conf.CheckPkgConfig('gthread-2.0', '2.12.4'):
|
||||
problems.append('Need gthread support lib for glib-- based thread handling.')
|
||||
|
||||
if not conf.CheckPkgConfig('cairomm-1.0', 0.6):
|
||||
|
|
|
|||
|
|
@ -141,8 +141,12 @@ PKG_CHECK_MODULES(LUMIERA_COMMON_LIBS, [sigc++-2.0 >= 2.0.17])
|
|||
# gtk+-2.0 >= 2.12 gtkmm-2.4 >= 2.12 for Debian Lenny compatibility
|
||||
|
||||
PKG_CHECK_MODULES(LUMIERA_GUI, [
|
||||
gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 gdl-1.0 >= 0.6.1
|
||||
cairomm-1.0 >= 0.6.0 gavl >= 0.2.5 librsvg-2.0 >= 2.18.1
|
||||
gtk+-2.0 >= 2.8
|
||||
gtkmm-2.4 >= 2.8
|
||||
cairomm-1.0 >= 0.6.0
|
||||
librsvg-2.0 >= 2.18.1
|
||||
gdl-1.0 >= 0.6.1
|
||||
gavl >= 0.2.5
|
||||
gthread-2.0 >= 2.12.4])
|
||||
|
||||
# END Gtk Dependancies
|
||||
|
|
|
|||
468
doc/devel/draw/PlayerArch-1.svg
Normal file
468
doc/devel/draw/PlayerArch-1.svg
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="800"
|
||||
height="600"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45.1"
|
||||
sodipodi:docbase="/mnt/Lager/heim/devel/lumi/doc/devel/draw"
|
||||
sodipodi:docname="PlayerArch-1.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.0">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2"
|
||||
inkscape:cx="346.20838"
|
||||
inkscape:cy="304.01881"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:window-width="1668"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
width="800px"
|
||||
height="600px"
|
||||
showgrid="true"
|
||||
gridspacingx="2px"
|
||||
gridspacingy="2px"
|
||||
gridanglex="30px"
|
||||
gridanglez="30px"
|
||||
grid_units="px"
|
||||
inkscape:grid-points="true"
|
||||
inkscape:grid-bbox="false"
|
||||
gridcolor="#4b4bf4"
|
||||
gridopacity="0.09019608"
|
||||
showguides="true"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:object-nodes="true"
|
||||
gridtolerance="10000"
|
||||
inkscape:guide-points="true"
|
||||
guidetolerance="5" />
|
||||
<defs
|
||||
id="globals">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3262"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleInL"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleInL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3342"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
|
||||
transform="scale(-0.8)" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
orient="auto"
|
||||
id="ArrowHIV1end"
|
||||
refY="0"
|
||||
inkscape:stockid="ArrowHIV1end"
|
||||
refX="0">
|
||||
<path
|
||||
style="fill:#40c0ab;stroke:#01ffff;stroke-width:0.1;stroke-linecap:butt;stroke-miterlimit:6.5"
|
||||
d="M -8,0 L -10,1.2 L -2,1.2 L 5,0 L -2,-1.2 L -10,-1.2 L -8,0 z "
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="pathPfeil1" />
|
||||
</marker>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/2.5/" />
|
||||
<dc:title>AllocationCluster</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Ichthyostega</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:description>design sketch: Structure of the AllocationCluster mem manager</dc:description>
|
||||
<dc:date>2008</dc:date>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/2.5/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Drawing"
|
||||
id="lay1"
|
||||
inkscape:groupmode="layer" />
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#6c6c6c;stroke-width:1.50000012;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect4196"
|
||||
width="180.16087"
|
||||
height="80"
|
||||
x="190.12445"
|
||||
y="130" />
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect4200"
|
||||
width="130.423"
|
||||
height="70.324265"
|
||||
x="340"
|
||||
y="260" />
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect4206"
|
||||
width="110.59406"
|
||||
height="30.243902"
|
||||
x="249.40594"
|
||||
y="169.7561" />
|
||||
<rect
|
||||
y="399.51221"
|
||||
x="230"
|
||||
height="40.487804"
|
||||
width="90.396042"
|
||||
id="rect4208"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="260"
|
||||
y="180"
|
||||
id="text4216"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4218"
|
||||
x="260"
|
||||
y="180"
|
||||
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">play thread</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="450"
|
||||
y="190"
|
||||
id="text4224"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4226"
|
||||
x="450"
|
||||
y="190"
|
||||
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">put(Frame&)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="193.62445"
|
||||
y="143.5"
|
||||
id="text4235"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2265"
|
||||
x="193.62445"
|
||||
y="143.5">PlaybackController</tspan></text>
|
||||
<path
|
||||
style="fill:#55cbb9;fill-opacity:1;fill-rule:evenodd;stroke:#55cbb9;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#ArrowHIV1end);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 770,160 L 860,180 L 860,180"
|
||||
id="path4263" />
|
||||
<rect
|
||||
y="250"
|
||||
x="60"
|
||||
height="80"
|
||||
width="130.09683"
|
||||
id="rect2226"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#6c6c6c;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2236"
|
||||
y="290"
|
||||
x="70"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2263"
|
||||
x="70"
|
||||
y="290"
|
||||
style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">start(...)</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2244"
|
||||
y="410"
|
||||
x="240"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
sodipodi:role="line"
|
||||
x="240"
|
||||
y="410"
|
||||
style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
id="tspan2218">PlayProcess</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2248"
|
||||
y="263.5"
|
||||
x="63.5"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2252"
|
||||
x="63.5"
|
||||
y="263.5">Player (interface)</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2267"
|
||||
y="160"
|
||||
x="200"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
y="160"
|
||||
x="200"
|
||||
id="tspan2269"
|
||||
sodipodi:role="line">start_playback_thread()</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInL);stroke-opacity:1"
|
||||
d="M 630,300 L 630,250 L 660,210"
|
||||
id="path2271"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
|
||||
d="M 520,380 L 580,380 L 580,380"
|
||||
id="path3449" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:7px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="220"
|
||||
y="290"
|
||||
id="text3453"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3455"
|
||||
x="220"
|
||||
y="290"
|
||||
style="font-size:7px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;font-family:Bitstream Vera Sans">yields</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text3457"
|
||||
y="90"
|
||||
x="320"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#008080;fill-opacity:1;fill-rule:evenodd;stroke:#008080;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="90"
|
||||
x="320"
|
||||
id="tspan3459"
|
||||
sodipodi:role="line">GUI (Plugin)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#008080;fill-opacity:1;fill-rule:evenodd;stroke:#008080;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="60"
|
||||
y="370"
|
||||
id="text3461"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3463"
|
||||
x="60"
|
||||
y="370">Proc (or Backend?)</tspan></text>
|
||||
<rect
|
||||
y="300.12677"
|
||||
x="389.802"
|
||||
height="20"
|
||||
width="70.198021"
|
||||
id="rect3465"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text3467"
|
||||
y="312.62677"
|
||||
x="391.50003"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
y="312.62677"
|
||||
x="391.50003"
|
||||
id="tspan3469"
|
||||
sodipodi:role="line">Displayer (Proxy)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="345.00003"
|
||||
y="273.12677"
|
||||
id="text3471"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3473"
|
||||
x="345.00003"
|
||||
y="273.12677"
|
||||
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">PlayerFacade (Proxy)</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
|
||||
d="M 110,290 L 210,290 L 270,390"
|
||||
id="path3481"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
|
||||
d="M 540,270 L 540,110"
|
||||
id="path3483" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text3485"
|
||||
y="229.80247"
|
||||
x="460.00003"
|
||||
style="font-size:7px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
||||
y="229.80247"
|
||||
x="460.00003"
|
||||
id="tspan3487"
|
||||
sodipodi:role="line">actually</tspan><tspan
|
||||
style="font-size:7px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
||||
y="236.80247"
|
||||
x="460.00003"
|
||||
sodipodi:role="line"
|
||||
id="tspan3489">talks to...</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#008080;fill-opacity:1;fill-rule:evenodd;stroke:#008080;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="480.00003"
|
||||
y="280.12677"
|
||||
id="text3493"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3495"
|
||||
x="480.00003"
|
||||
y="280.12677">libCommon</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#6c6c6c;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2222"
|
||||
width="130.09683"
|
||||
height="110.27864"
|
||||
x="60"
|
||||
y="400" />
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2224"
|
||||
width="70.181519"
|
||||
height="20"
|
||||
x="109.90098"
|
||||
y="450" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="114.5"
|
||||
y="460"
|
||||
id="text2230"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
id="tspan2232"
|
||||
style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
y="460"
|
||||
x="114.5"
|
||||
sodipodi:role="line">PlayContext</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="63.5"
|
||||
y="413.5"
|
||||
id="text2234"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
y="413.5"
|
||||
x="63.5"
|
||||
id="tspan2236"
|
||||
sodipodi:role="line">PlayerService</tspan></text>
|
||||
<rect
|
||||
y="430"
|
||||
x="109.81848"
|
||||
height="20"
|
||||
width="70.181519"
|
||||
id="rect2239"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
y="470"
|
||||
x="109.81848"
|
||||
height="20"
|
||||
width="70.181519"
|
||||
id="rect2241"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2243"
|
||||
width="70.181519"
|
||||
height="20"
|
||||
x="109.81848"
|
||||
y="490" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2245"
|
||||
y="440"
|
||||
x="114.5"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
sodipodi:role="line"
|
||||
x="114.5"
|
||||
y="440"
|
||||
style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
id="tspan2247">PlayContext</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
x="114.5"
|
||||
y="480"
|
||||
id="text2249"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
id="tspan2251"
|
||||
style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
y="480"
|
||||
x="114.5"
|
||||
sodipodi:role="line">PlayContext</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2253"
|
||||
y="500"
|
||||
x="114.5"
|
||||
style="font-size:14px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
sodipodi:role="line"
|
||||
x="114.5"
|
||||
y="500"
|
||||
style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans"
|
||||
id="tspan2255">PlayContext</tspan></text>
|
||||
<path
|
||||
id="path2257"
|
||||
d="M 240,420 L 170,440"
|
||||
style="fill:#55cbb9;fill-opacity:1;fill-rule:evenodd;stroke:#55cbb9;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#ArrowHIV1end);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 30 KiB |
|
|
@ -42,8 +42,89 @@ namespace lib {
|
|||
using std::tr1::function;
|
||||
using lumiera::Literal;
|
||||
|
||||
typedef struct nobug_flag* NoBugFlag;
|
||||
|
||||
class Thread;
|
||||
|
||||
/**
|
||||
* Brainstorming-in-code: how I would like to shape the API for joining threads.
|
||||
* Intended use: This non-copyable handle has to be created within the thread which
|
||||
* wants to wait-blocking on the termination of another thread. You then pass it
|
||||
* into the ctor of the Thread starting wrapper class (see below), which causes
|
||||
* the embedded lock/condition var to be used to sync on the end of the newly
|
||||
* created thread. Note, after ending the execution, the newly created thread
|
||||
* will be on hold until either the #join() function is called or this handle
|
||||
* goes out of scope altogether. Explanation: this is implemented by locking
|
||||
* the embedded monitor immediately in the ctor. Thus, unless entering the
|
||||
* wait state, the contained mutex remains locked and prevents the thread
|
||||
* manager from invoking the broadcast() on the condition var.
|
||||
*
|
||||
* @note this is a draft. It doesn't even work, because Cehteh is still planning
|
||||
* details of the thread handling and didn't implement the waiting feature.
|
||||
*/
|
||||
class JoinHandle
|
||||
: public Sync<NonrecursiveLock_Waitable>
|
||||
, Sync<NonrecursiveLock_Waitable>::Lock
|
||||
{
|
||||
typedef Sync<NonrecursiveLock_Waitable> SyncBase;
|
||||
|
||||
bool isWaiting_;
|
||||
volatile bool armed_;
|
||||
|
||||
friend class Thread;
|
||||
|
||||
LumieraCondition
|
||||
accessLockedCondition()
|
||||
{
|
||||
ASSERT (!armed_, "Lifecycle error, JoinHandle used for several threads.");
|
||||
armed_ = true;
|
||||
return accessMonitor().accessCond();
|
||||
}
|
||||
|
||||
bool
|
||||
wakeupCheck()
|
||||
{
|
||||
if (!armed_)
|
||||
throw lumiera::error::Logic ("no thread created blocking on this JoinHandle");
|
||||
|
||||
if (!isWaiting_)
|
||||
{
|
||||
isWaiting_ = true;
|
||||
return false; // causes entering the blocking wait
|
||||
}
|
||||
TODO ("any possibility to detect spurious wakeups? can they happen?");
|
||||
return true; // causes end of the blocking wait
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/** Create a promise, that the current thread will or may
|
||||
* wait-blocking on another not-yet existing thread to terminate.
|
||||
* When passed in on creation of the other thread, as long as this
|
||||
* handle lives, the other thread will be on hold after termination.
|
||||
*/
|
||||
JoinHandle()
|
||||
: SyncBase::Lock(this)
|
||||
, isWaiting_(false)
|
||||
, armed_(false)
|
||||
{ }
|
||||
|
||||
/** put the current thread into a blocking wait until another thread
|
||||
* has terminated. This other thread needs to be created by the Thread
|
||||
* wrapper, passing this JoinHandle as ctor parameter.
|
||||
* @throws error::Logic if no thread has been registered to block on this
|
||||
*/
|
||||
void
|
||||
join()
|
||||
{
|
||||
accessMonitor().wait (*this, &JoinHandle::wakeupCheck);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* A thin convenience wrapper for dealing with threads,
|
||||
* as implemented by the backend (on top of pthread).
|
||||
* Using this wrapper...
|
||||
|
|
@ -63,8 +144,8 @@ namespace lib {
|
|||
* is superfluous in the final application. Re-evaluate this!
|
||||
*/
|
||||
class Thread
|
||||
: public Sync<NonrecursiveLock_Waitable>,
|
||||
boost::noncopyable
|
||||
: public Sync<NonrecursiveLock_Waitable>
|
||||
, boost::noncopyable
|
||||
{
|
||||
volatile bool started_;
|
||||
|
||||
|
|
@ -87,17 +168,15 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
public:
|
||||
Thread (Literal& purpose, Operation const& operation, struct nobug_flag *logging_flag = &NOBUG_FLAG(operate))
|
||||
: started_(false),
|
||||
operation_(operation)
|
||||
void
|
||||
start_thread (lumiera_thread_class kind, Literal& purpose, NoBugFlag logging_flag, LumieraCondition joinCond=0)
|
||||
{
|
||||
Lock sync(this);
|
||||
LumieraThread res =
|
||||
lumiera_thread_run ( LUMIERA_THREAD_INTERACTIVE
|
||||
lumiera_thread_run ( kind
|
||||
, &run // invoking the run helper and..
|
||||
, this // passing this start context as parameter
|
||||
, 0 // no condition variable provided (for now...)
|
||||
, joinCond // maybe wait-blocking for the thread to terminate
|
||||
, purpose.c_str()
|
||||
, logging_flag
|
||||
);
|
||||
|
|
@ -109,6 +188,40 @@ namespace lib {
|
|||
// prior to leaving and thereby possibly destroying this local context
|
||||
sync.wait (started_);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Create a new thread to execute the given operation.
|
||||
* The new thread starts up synchronously, i.e. when the ctor returns, the new thread
|
||||
* has started running and taken over (copied) the operation functor passed in. The
|
||||
* thread will be created by lumiera_thread_run (declared in threads.h), it can't
|
||||
* be cancelled and it can't be joined.
|
||||
* @param purpose fixed char string used to denote the thread for diagnostics
|
||||
* @param logging_flag NoBug flag to receive diagnostics regarding the new thread
|
||||
* @param operation defining what to execute within the new thread. Any functor
|
||||
* which can be bound to function<void(void)>. Note this functor will be
|
||||
* copied onto the stack of the new thread, thus it can be transient.
|
||||
*
|
||||
*/
|
||||
Thread (Literal& purpose, Operation const& operation, NoBugFlag logging_flag = &NOBUG_FLAG(operate)) ///TODO: define a dedicated flag for threads
|
||||
: started_(false),
|
||||
operation_(operation)
|
||||
{
|
||||
start_thread (LUMIERA_THREAD_INTERACTIVE, purpose, logging_flag);
|
||||
}
|
||||
|
||||
/** Variant of the standard case, used to register a JoinHandle in addition to starting a thread.
|
||||
* @param join ref to a JoinHandle, which needs to be created in the thread which plans
|
||||
* to wait-blocking on the termination of this newly created thread
|
||||
*
|
||||
*/
|
||||
Thread (Literal& purpose, Operation const& operation,
|
||||
JoinHandle& join, NoBugFlag logging_flag = &NOBUG_FLAG(operate)) ///TODO: define a dedicated flag for threads
|
||||
: started_(false),
|
||||
operation_(operation)
|
||||
{
|
||||
start_thread (LUMIERA_THREAD_INTERACTIVE, purpose, logging_flag,
|
||||
join.accessLockedCondition());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,18 +60,18 @@ namespace gui {
|
|||
: theGUI_("lumieraorg_Gui", 1, 1, "lumieraorg_GuiStarterPlugin") // load GuiStarterPlugin
|
||||
{
|
||||
ASSERT (theGUI_);
|
||||
this->kickOff (terminationHandle);
|
||||
bool res = this->kickOff (terminationHandle);
|
||||
|
||||
if (lumiera_error_peek())
|
||||
if (!res || lumiera_error_peek())
|
||||
throw lumiera::error::Fatal("failed to bring up GUI",lumiera_error());
|
||||
}
|
||||
|
||||
~GuiRunner () { }
|
||||
|
||||
|
||||
void kickOff (Subsys::SigTerm& terminationHandle)
|
||||
bool kickOff (Subsys::SigTerm& terminationHandle)
|
||||
{
|
||||
theGUI_->kickOff (reinterpret_cast<void*> (&terminationHandle));
|
||||
return theGUI_->kickOff (reinterpret_cast<void*> (&terminationHandle));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,17 @@ namespace gui {
|
|||
|
||||
|
||||
|
||||
#include "include/dummy-player-facade.h"
|
||||
|
||||
namespace proc {
|
||||
|
||||
/** storage for the DummyPlayer facade proxy factory... */
|
||||
lumiera::facade::Accessor<DummyPlayer> DummyPlayer::facade;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace facade {
|
||||
|
|
@ -107,7 +118,9 @@ namespace lumiera {
|
|||
|
||||
|
||||
|
||||
typedef InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 1)
|
||||
/* ==================== GuiNotification =================================== */
|
||||
|
||||
typedef InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 0)
|
||||
, gui::GuiNotification
|
||||
> Handle_GuiNotification;
|
||||
|
||||
|
|
@ -127,12 +140,55 @@ namespace lumiera {
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template void openProxy<Handle_GuiNotification> (Handle_GuiNotification const&);
|
||||
template void closeProxy<Handle_GuiNotification> (void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==================== DummyPlayer ======================================= */
|
||||
|
||||
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0)
|
||||
, proc::DummyPlayer
|
||||
> Handle_DummyPlayer;
|
||||
|
||||
|
||||
template<>
|
||||
class Proxy<Handle_DummyPlayer>
|
||||
: public Holder<Handle_DummyPlayer>
|
||||
{
|
||||
//----Proxy-Implementation-of-DummyPlayer--------
|
||||
typedef proc::DummyPlayer::Process Process;
|
||||
|
||||
/** @note as an optimisation we hand out a direct reference
|
||||
* to the implementing process object. While this ref could
|
||||
* still be passed as handle to the C Language interface, using
|
||||
* it directly within the client (=GUI) retains only on level
|
||||
* of indirection, irrespective which interface is used. */
|
||||
Process& start()
|
||||
{
|
||||
Process* pP = static_cast<Process*> (_i_.startPlay());
|
||||
|
||||
if (!pP || lumiera_error_peek())
|
||||
throw lumiera::error::State("failed to start DummyPlayer", lumiera_error());
|
||||
|
||||
return *pP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Proxy (IHandle const& iha) : THolder(iha) {}
|
||||
};
|
||||
|
||||
|
||||
template void openProxy<Handle_DummyPlayer> (Handle_DummyPlayer const&);
|
||||
template void closeProxy<Handle_DummyPlayer> (void);
|
||||
|
||||
|
||||
} // namespace facade
|
||||
|
||||
} // namespace lumiera
|
||||
|
|
|
|||
|
|
@ -23,11 +23,12 @@
|
|||
** This file contains the definition of the controller object
|
||||
*/
|
||||
|
||||
#include "playback-controller.hpp"
|
||||
|
||||
#ifndef CONTROLLER_HPP
|
||||
#define CONTROLLER_HPP
|
||||
|
||||
#include "playback-controller.hpp"
|
||||
|
||||
|
||||
namespace gui {
|
||||
|
||||
namespace model {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
timeline-track.cpp - Implementation of the timeline track object
|
||||
playback-controller.cpp - Implementation of the playback controller object
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
|
|
@ -20,52 +20,79 @@
|
|||
|
||||
* *****************************************************/
|
||||
|
||||
#include "playback-controller.hpp"
|
||||
#include "../gtk-lumiera.hpp"
|
||||
#include "gui/controller/playback-controller.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include <nobug.h>
|
||||
|
||||
namespace gui {
|
||||
namespace controller {
|
||||
|
||||
PlaybackController::PlaybackController() :
|
||||
thread(0),
|
||||
finish_playback_thread(false),
|
||||
playing(false)
|
||||
{
|
||||
start_playback_thread();
|
||||
}
|
||||
playing(false),
|
||||
playHandle(0)
|
||||
{ }
|
||||
|
||||
|
||||
PlaybackController::~PlaybackController()
|
||||
{
|
||||
mutex.lock();
|
||||
finish_playback_thread = true;
|
||||
mutex.unlock();
|
||||
thread->join();
|
||||
end_playback_thread();
|
||||
}
|
||||
|
||||
void
|
||||
PlaybackController::play()
|
||||
{
|
||||
Glib::Mutex::Lock lock(mutex);
|
||||
playing = true;
|
||||
if (playing && thread && playHandle)
|
||||
{
|
||||
playHandle->pause(false);
|
||||
return;
|
||||
}
|
||||
if (thread)
|
||||
end_playback_thread();
|
||||
|
||||
{
|
||||
Lock sync(this);
|
||||
try
|
||||
{
|
||||
playHandle = & (proc::DummyPlayer::facade().start());
|
||||
start_playback_thread();
|
||||
playing = true;
|
||||
}
|
||||
catch (lumiera::error::State& err)
|
||||
{
|
||||
WARN (operate, "failed to start playback: %s" ,err.what());
|
||||
lumiera_error();
|
||||
playing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlaybackController::pause()
|
||||
{
|
||||
Glib::Mutex::Lock lock(mutex);
|
||||
Lock sync(this);
|
||||
playing = false;
|
||||
if (playHandle)
|
||||
playHandle->pause(true);
|
||||
}
|
||||
|
||||
void
|
||||
PlaybackController::stop()
|
||||
{
|
||||
Glib::Mutex::Lock lock(mutex);
|
||||
playing = false;
|
||||
{
|
||||
Lock sync(this);
|
||||
playing = false;
|
||||
playHandle = 0;
|
||||
// TODO: stop player somehow?
|
||||
}
|
||||
end_playback_thread();
|
||||
}
|
||||
|
||||
bool
|
||||
PlaybackController::is_playing()
|
||||
{
|
||||
Glib::Mutex::Lock lock(mutex);
|
||||
Lock sync(this);
|
||||
return playing;
|
||||
}
|
||||
|
||||
|
|
@ -73,10 +100,25 @@ void
|
|||
PlaybackController::start_playback_thread()
|
||||
{
|
||||
dispatcher.connect(sigc::mem_fun(this, &PlaybackController::on_frame));
|
||||
finish_playback_thread = false;
|
||||
thread = Glib::Thread::create (sigc::mem_fun(
|
||||
this, &PlaybackController::playback_thread), true);
|
||||
}
|
||||
|
||||
void
|
||||
PlaybackController::end_playback_thread()
|
||||
{
|
||||
{
|
||||
Lock sync(this);
|
||||
finish_playback_thread = true;
|
||||
playing = false;
|
||||
}
|
||||
if (thread)
|
||||
thread->join();
|
||||
thread = 0;
|
||||
finish_playback_thread = false;
|
||||
}
|
||||
|
||||
void
|
||||
PlaybackController::attach_viewer(
|
||||
const sigc::slot<void, void*>& on_frame)
|
||||
|
|
@ -90,115 +132,43 @@ PlaybackController::playback_thread()
|
|||
for(;;)
|
||||
{
|
||||
{
|
||||
Glib::Mutex::Lock lock(mutex);
|
||||
Lock sync(this);
|
||||
if(finish_playback_thread)
|
||||
return;
|
||||
}
|
||||
|
||||
if(is_playing())
|
||||
pull_frame();
|
||||
|
||||
Glib::Thread::yield();
|
||||
|
||||
usleep(40000); // ca 25 frames pre second
|
||||
}
|
||||
}
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
inline int
|
||||
clamp(const int &val, const int &maxval, const int &minval)
|
||||
{
|
||||
if(val > maxval) return maxval;
|
||||
if(val < minval) return minval;
|
||||
return val;
|
||||
}
|
||||
|
||||
inline void
|
||||
rgb_to_yuv(int r, int g, int b, byte &y, byte &u, byte &v)
|
||||
{
|
||||
// This code isn't great, but it does the job
|
||||
y = (byte)clamp((299 * r + 587 * g + 114 * b) / 1000, 235, 16);
|
||||
v = (byte)clamp((500 * r - 419 * g - 81 * b) / 1000 + 127, 255, 0);
|
||||
u = (byte)clamp((-169 * r - 331 * g + 500 * b) / 1000 + 127, 255, 0);
|
||||
}
|
||||
|
||||
void rgb_buffer_to_yuy2(unsigned char *in, unsigned char *out)
|
||||
{
|
||||
for(int i = 0; i < 320*240*2; i+=4)
|
||||
{
|
||||
byte y0, u0, v0;
|
||||
const byte r0 = *(in++);
|
||||
const byte g0 = *(in++);
|
||||
const byte b0 = *(in++);
|
||||
rgb_to_yuv(r0, g0, b0, y0, u0, v0);
|
||||
|
||||
byte y1, u1, v1;
|
||||
const byte r1 = *(in++);
|
||||
const byte g1 = *(in++);
|
||||
const byte b1 = *(in++);
|
||||
rgb_to_yuv(r1, g1, b1, y1, u1, v1);
|
||||
|
||||
out[i] = y0;
|
||||
out[i + 1] = u0;
|
||||
out[i + 2] = y1;
|
||||
out[i + 3] = v0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlaybackController::pull_frame()
|
||||
{
|
||||
static int frame = 0;
|
||||
unsigned char in[320 * 240 * 3];
|
||||
REQUIRE (is_playing());
|
||||
REQUIRE (playHandle);
|
||||
|
||||
frame--;
|
||||
unsigned char * newBuffer = reinterpret_cast<unsigned char*> (playHandle->getFrame());
|
||||
|
||||
if(frame <= 0)
|
||||
frame = 200;
|
||||
|
||||
if(frame > 150)
|
||||
{
|
||||
for(int i = 0; i < 320*240*3; i+=3)
|
||||
{
|
||||
byte value = (byte)rand();
|
||||
in[i] = value;
|
||||
in[i+1] = value;
|
||||
in[i+2] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char row[320 * 3];
|
||||
|
||||
for(int x = 0; x < 320; x++)
|
||||
{
|
||||
byte &r = row[x*3];
|
||||
byte &g = row[x*3+1];
|
||||
byte &b = row[x*3+2];
|
||||
|
||||
if(x < 1*320/7) r = 0xC0, g = 0xC0, b = 0xC0;
|
||||
else if(x < 2*320/7) r = 0xC0, g = 0xC0, b = 0x00;
|
||||
else if(x < 3*320/7) r = 0x00, g = 0xC0, b = 0xC0;
|
||||
else if(x < 4*320/7) r = 0x00, g = 0xC0, b = 0x00;
|
||||
else if(x < 5*320/7) r = 0xC0, g = 0x00, b = 0xC0;
|
||||
else if(x < 6*320/7) r = 0xC0, g = 0x00, b = 0x00;
|
||||
else r = 0x00, g = 0x00, b = 0xC0;
|
||||
}
|
||||
|
||||
for(int y = 0; y < 240; y++)
|
||||
if (newBuffer != currentBuffer)
|
||||
{
|
||||
memcpy(in + y*320*3, row, sizeof(row));
|
||||
currentBuffer = newBuffer;
|
||||
dispatcher.emit();
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE (render, "frame dropped?");
|
||||
}
|
||||
}
|
||||
|
||||
rgb_buffer_to_yuy2(in, buffer);
|
||||
|
||||
dispatcher.emit();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaybackController::on_frame()
|
||||
{
|
||||
frame_signal.emit(buffer);
|
||||
frame_signal.emit(currentBuffer);
|
||||
}
|
||||
|
||||
} // namespace controller
|
||||
|
|
|
|||
|
|
@ -23,16 +23,26 @@
|
|||
** This file contains the definition of the playback controller object
|
||||
*/
|
||||
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <glibmm.h>
|
||||
|
||||
#ifndef PLAYBACK_CONTROLLER_HPP
|
||||
#define PLAYBACK_CONTROLLER_HPP
|
||||
|
||||
#include "include/dummy-player-facade.h"
|
||||
#include "lib/sync.hpp"
|
||||
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <glibmm.h>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace gui {
|
||||
namespace controller {
|
||||
namespace controller {
|
||||
|
||||
using lib::Sync;
|
||||
using lib::RecursiveLock_NoWait;
|
||||
|
||||
|
||||
class PlaybackController
|
||||
: boost::noncopyable,
|
||||
public Sync<RecursiveLock_NoWait>
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -54,6 +64,8 @@ private:
|
|||
|
||||
void start_playback_thread();
|
||||
|
||||
void end_playback_thread();
|
||||
|
||||
void playback_thread();
|
||||
|
||||
void pull_frame();
|
||||
|
|
@ -64,15 +76,15 @@ private:
|
|||
|
||||
Glib::Thread *thread;
|
||||
|
||||
Glib::StaticMutex mutex;
|
||||
|
||||
Glib::Dispatcher dispatcher;
|
||||
|
||||
volatile bool finish_playback_thread;
|
||||
|
||||
volatile bool playing;
|
||||
|
||||
unsigned char buffer[320 * 240 * 4];
|
||||
proc::DummyPlayer::Process *playHandle;
|
||||
|
||||
unsigned char * currentBuffer;
|
||||
|
||||
sigc::signal<void, void*> frame_signal;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ extern "C" {
|
|||
#include "common/interface.h"
|
||||
}
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
|
||||
namespace gui {
|
||||
|
||||
|
|
@ -69,6 +71,7 @@ namespace gui {
|
|||
*
|
||||
*/
|
||||
class GuiFacade
|
||||
: boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -91,7 +94,7 @@ namespace gui {
|
|||
* @internal this function is invoked automatically during the GUI
|
||||
* loading and startup process. Don't call it manually.
|
||||
*/
|
||||
virtual void kickOff (lumiera::Subsys::SigTerm&) =0;
|
||||
virtual bool kickOff (lumiera::Subsys::SigTerm&) =0;
|
||||
|
||||
|
||||
protected:
|
||||
|
|
@ -100,7 +103,7 @@ namespace gui {
|
|||
|
||||
/** interface of the GuiStarterPlugin */
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_Gui, 1,
|
||||
LUMIERA_INTERFACE_SLOT (void, kickOff, (void*))
|
||||
LUMIERA_INTERFACE_SLOT (bool, kickOff, (void*))
|
||||
);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ using std::string;
|
|||
using lib::Thread;
|
||||
using std::tr1::bind;
|
||||
using lumiera::Subsys;
|
||||
using lumiera::error::LUMIERA_ERROR_STATE;
|
||||
using gui::LUMIERA_INTERFACE_INAME(lumieraorg_Gui, 1);
|
||||
|
||||
|
||||
|
|
@ -77,7 +78,7 @@ namespace gui {
|
|||
|
||||
namespace { // implementation details
|
||||
|
||||
/**
|
||||
/******************************************************************************
|
||||
* Implement the necessary steps for actually making the Lumiera Gui available.
|
||||
* Open the business interface(s) and start up the GTK GUI main event loop.
|
||||
*/
|
||||
|
|
@ -133,10 +134,22 @@ namespace gui {
|
|||
} // (End) impl details
|
||||
|
||||
|
||||
void
|
||||
|
||||
|
||||
bool
|
||||
kickOff (Subsys::SigTerm& terminationHandle)
|
||||
{
|
||||
Thread ("GUI-Main", bind (&runGUI, terminationHandle));
|
||||
try
|
||||
{
|
||||
Thread ("GUI-Main", bind (&runGUI, terminationHandle));
|
||||
return true; // if we reach this line...
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
if (!lumiera_error_peek())
|
||||
LUMIERA_ERROR_SET (gui, STATE, "unexpected error when starting the GUI thread");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
|
@ -226,9 +239,9 @@ extern "C" { /* ================== define an lumieraorg_Gui instance ===========
|
|||
, NULL /* on open */
|
||||
, NULL /* on close */
|
||||
, LUMIERA_INTERFACE_INLINE (kickOff, "\255\142\006\244\057\170\152\312\301\372\220\323\230\026\200\065",
|
||||
void, (void* termSig),
|
||||
bool, (void* termSig),
|
||||
{
|
||||
gui::kickOff (*reinterpret_cast<Subsys::SigTerm *> (termSig));
|
||||
return gui::kickOff (*reinterpret_cast<Subsys::SigTerm *> (termSig));
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace gui {
|
|||
|
||||
|
||||
|
||||
LUMIERA_INTERFACE_INSTANCE (lumieraorg_GuiNotification, 1
|
||||
LUMIERA_INTERFACE_INSTANCE (lumieraorg_GuiNotification, 0
|
||||
,lumieraorg_GuiNotificationFacade
|
||||
, LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_GuiNotificationFacade_descriptor)
|
||||
, NULL /* on open */
|
||||
|
|
@ -171,7 +171,7 @@ namespace gui {
|
|||
|
||||
NotificationService::NotificationService ()
|
||||
: implInstance_(this,_instance),
|
||||
serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_GuiNotification, 1,lumieraorg_GuiNotificationFacade))
|
||||
serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_GuiNotification, 0,lumieraorg_GuiNotificationFacade))
|
||||
{
|
||||
INFO (operate, "GuiNotification Facade opened.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ namespace gui {
|
|||
|
||||
/* === Interface Lifecycle === */
|
||||
|
||||
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 1)
|
||||
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 0)
|
||||
, GuiNotification
|
||||
> ServiceInstanceHandle;
|
||||
|
||||
|
|
|
|||
122
src/include/dummy-player-facade.h
Normal file
122
src/include/dummy-player-facade.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
DUMMY-PLAYER-FACADE.hpp - access point to a dummy test player
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PROC_INTERFACE_DUMMYPLAYER_H
|
||||
#define PROC_INTERFACE_DUMMYPLAYER_H
|
||||
|
||||
|
||||
|
||||
struct lumiera_playprocess_struct { };
|
||||
typedef struct lumiera_playprocess_struct lumiera_playprocess;
|
||||
typedef lumiera_playprocess* LumieraPlayProcess;
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus /* ============== C++ Interface ================= */
|
||||
|
||||
#include "common/subsys.hpp"
|
||||
#include "include/interfaceproxy.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
|
||||
|
||||
namespace proc {
|
||||
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* Interface Proc-Layer (or maybe the backend?):
|
||||
* Global access point for starting a dummy playback, generating
|
||||
* some test image data for the GUI to display in a viewer window.
|
||||
*
|
||||
* This is a mockup service we created 1/2009 to collect some
|
||||
* experiences regarding integration of the application layers.
|
||||
* Lumiera is not yet able actually to deliver rendered video data.
|
||||
*
|
||||
*/
|
||||
class DummyPlayer
|
||||
{
|
||||
public:
|
||||
/** provide a descriptor for lumiera::AppState,
|
||||
* wired accordingly to allow main to deal with
|
||||
* the dummy player as independent subsystem. */
|
||||
static lumiera::Subsys& getDescriptor();
|
||||
|
||||
/** get an implementation instance of this service */
|
||||
static lumiera::facade::Accessor<DummyPlayer> facade;
|
||||
|
||||
|
||||
/**
|
||||
* Continuous playback process, which has been started with a specific
|
||||
* output size, format and framerate. It is a handle to a calculation process,
|
||||
* which is about to produce a stream of frames to be retrieved by calling
|
||||
* the #getFrame function on this handle.
|
||||
*
|
||||
* @todo solve the lifecycle and ownership!
|
||||
*/
|
||||
class Process
|
||||
: public lumiera_playprocess
|
||||
, boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual void pause(bool) =0;
|
||||
virtual void* const getFrame() =0;
|
||||
|
||||
virtual ~Process();
|
||||
};
|
||||
|
||||
|
||||
//////////////////TODO: define some dummy negotiation about size and framerate....
|
||||
|
||||
virtual Process& start() =0;
|
||||
|
||||
virtual ~DummyPlayer();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace proc
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
#endif /* =========================== CL Interface ===================== */
|
||||
|
||||
|
||||
#include "common/interface.h"
|
||||
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_DummyPlayer, 0
|
||||
, LUMIERA_INTERFACE_SLOT (LumieraPlayProcess, startPlay,(void) )
|
||||
, LUMIERA_INTERFACE_SLOT (void, pausePlay,(LumieraPlayProcess, bool))
|
||||
, LUMIERA_INTERFACE_SLOT (void, terminate,(LumieraPlayProcess) )
|
||||
, LUMIERA_INTERFACE_SLOT (void *, getFrame, (LumieraPlayProcess) )
|
||||
);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -85,7 +85,7 @@ extern "C" {
|
|||
|
||||
#include "common/interface.h"
|
||||
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_GuiNotification, 1,
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_GuiNotification, 0,
|
||||
LUMIERA_INTERFACE_SLOT (void, displayInfo, (const char*)),
|
||||
LUMIERA_INTERFACE_SLOT (void, triggerGuiShutdown, (const char*)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -83,15 +83,19 @@ namespace lumiera {
|
|||
/* declare flags used throughout the code base */
|
||||
NOBUG_DECLARE_FLAG (all);
|
||||
NOBUG_DECLARE_FLAG (lumiera_all);
|
||||
NOBUG_DECLARE_FLAG (lib_all);
|
||||
NOBUG_DECLARE_FLAG (lumiera); ///< master log, informative console output
|
||||
NOBUG_DECLARE_FLAG (operate); ///< logging channel reporting what the application does
|
||||
NOBUG_DECLARE_FLAG (render); ///< logging channel focusing on the render engine's workings
|
||||
NOBUG_DECLARE_FLAG (config); ///< logging channel covering application and session configuration
|
||||
NOBUG_DECLARE_FLAG (memory); ///< logging channel covering memory management issues
|
||||
NOBUG_DECLARE_FLAG (sync); ///< especially for tracing synchronisation
|
||||
NOBUG_DECLARE_FLAG (test);
|
||||
|
||||
|
||||
/* further flags which don't fit into any specific translation unit */
|
||||
NOBUG_DECLARE_FLAG (sync); ///< especially for tracing synchronisation
|
||||
|
||||
|
||||
#endif /*NOBUGCFG_H ======= (End) Part 1: DECLARATIONS ======== */
|
||||
|
||||
|
||||
|
|
@ -105,15 +109,18 @@ namespace lumiera {
|
|||
/* flags used throughout the code base... */
|
||||
NOBUG_CPP_DEFINE_FLAG (all);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT (lumiera_all, all);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT (lib_all, all);
|
||||
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT (lumiera, lumiera_all);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT (config, lumiera);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT (operate, lumiera);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (render, lumiera, LOG_WARNING);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (memory, lumiera, LOG_WARNING);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (sync, memory, LOG_WARNING);
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (test, all, LOG_ERR);
|
||||
|
||||
|
||||
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (sync, lib_all, LOG_WARNING);
|
||||
|
||||
|
||||
|
||||
#endif /*NOBUG_INIT_DEFS_ ==== (End) Part 2: DEFINITIONS ========= */
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace lumiera {
|
|||
desc_ (description),
|
||||
cause_ ("")
|
||||
{
|
||||
lumiera_error_set (this->id_, description.c_str ());
|
||||
lumiera_error_set (this->id_, description.c_str ());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
typedef void* _ThisType::*unspecified_bool_type;
|
||||
typedef TY* _ThisType::*unspecified_bool_type;
|
||||
|
||||
/** implicit conversion to "bool" */
|
||||
operator unspecified_bool_type() const // never throws
|
||||
|
|
|
|||
|
|
@ -331,6 +331,8 @@ namespace lib {
|
|||
|
||||
void setTimeout(ulong relative) {timeout_.setOffset(relative);}
|
||||
bool isTimedWait() {return (timeout_);}
|
||||
|
||||
LumieraCondition accessCond() {return static_cast<LumieraCondition> (this);}
|
||||
};
|
||||
|
||||
typedef Mutex<Wrapped_LumieraExcMutex> NonrecursiveLock_NoWait;
|
||||
|
|
@ -419,6 +421,11 @@ namespace lib {
|
|||
/** for creating a ClassLock */
|
||||
Lock(Monitor& m) : mon_(m)
|
||||
{ mon_.acquireLock(); }
|
||||
|
||||
/** for controlled access to the
|
||||
* underlying sync primitives */
|
||||
Monitor&
|
||||
accessMonitor() { return mon_; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "backend/enginefacade.hpp"
|
||||
#include "backend/netnodefacade.hpp"
|
||||
#include "backend/scriptrunnerfacade.hpp"
|
||||
#include "include/dummy-player-facade.h"
|
||||
#include "proc/facade.hpp"
|
||||
#include "gui/guifacade.hpp"
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ namespace {
|
|||
Subsys& engine = backend::EngineFacade::getDescriptor();
|
||||
Subsys& netNode = backend::NetNodeFacade::getDescriptor();
|
||||
Subsys& script = backend::ScriptRunnerFacade::getDescriptor();
|
||||
Subsys& player = proc::DummyPlayer::getDescriptor();
|
||||
Subsys& builder = proc::Facade::getBuilderDescriptor();
|
||||
Subsys& session = proc::Facade::getSessionDescriptor();
|
||||
Subsys& lumigui = gui::GuiFacade::getDescriptor();
|
||||
|
|
@ -66,6 +68,7 @@ main (int argc, const char* argv[])
|
|||
netNode.depends (engine);
|
||||
// lumigui.depends (session); //////TODO commented out in order to be able to start up a dummy GuiStarterPlugin
|
||||
// lumigui.depends (engine);
|
||||
lumigui.depends (player);
|
||||
script.depends (session);
|
||||
script.depends (engine);
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,18 @@ liblumiproccontrol_la_SOURCES = \
|
|||
$(liblumiproccontrol_la_srcdir)/stypemanager.cpp
|
||||
|
||||
|
||||
liblumiprocplay_la_srcdir = $(top_srcdir)/src/proc/play
|
||||
noinst_LTLIBRARIES += liblumiprocplay.la
|
||||
|
||||
liblumiprocplay_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror
|
||||
liblumiprocplay_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra
|
||||
|
||||
liblumiprocplay_la_SOURCES = \
|
||||
$(liblumiprocplay_la_srcdir)/dummy-player-service.cpp \
|
||||
$(liblumiprocplay_la_srcdir)/dummy-image-generator.cpp
|
||||
|
||||
|
||||
|
||||
liblumiprocmobjectsession_la_srcdir = $(top_srcdir)/src/proc/mobject/session
|
||||
noinst_LTLIBRARIES += liblumiprocmobjectsession.la
|
||||
|
||||
|
|
@ -193,6 +205,8 @@ noinst_HEADERS += \
|
|||
$(liblumiproc_la_srcdir)/mobject/builderfacade.hpp \
|
||||
$(liblumiproc_la_srcdir)/control/pathmanager.hpp \
|
||||
$(liblumiproc_la_srcdir)/control/renderstate.hpp \
|
||||
$(liblumiproc_la_srcdir)/play/dummy-player-service.cpp \
|
||||
$(liblumiproc_la_srcdir)/play/dummy-image-generator.hpp \
|
||||
$(liblumiproc_la_srcdir)/mobject/interpolator.hpp \
|
||||
$(liblumiproc_la_srcdir)/mobject/parameter.hpp \
|
||||
$(liblumiproc_la_srcdir)/mobject/paramprovider.hpp \
|
||||
|
|
@ -243,5 +257,6 @@ liblumieraproc_la_LIBADD = \
|
|||
liblumiprocmobject.la \
|
||||
liblumiprocmobjectbuilder.la \
|
||||
liblumiproccontrol.la \
|
||||
liblumiprocplay.la \
|
||||
liblumiprocmobjectsession.la
|
||||
|
||||
|
|
|
|||
170
src/proc/play/dummy-image-generator.cpp
Normal file
170
src/proc/play/dummy-image-generator.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
DummyImageGenerator - creating test output frames for simulated playback
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Joel Holdsworth <joel@airwebreathe.org.uk>,
|
||||
Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "proc/play/dummy-image-generator.hpp"
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace play {
|
||||
|
||||
|
||||
|
||||
namespace { // implementation details
|
||||
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
inline int
|
||||
clamp (const int &val, const int &maxval, const int &minval)
|
||||
{
|
||||
if(val > maxval) return maxval;
|
||||
if(val < minval) return minval;
|
||||
return val;
|
||||
}
|
||||
|
||||
inline void
|
||||
rgb_to_yuv (int r, int g, int b, byte &y, byte &u, byte &v)
|
||||
{
|
||||
// This code isn't great, but it does the job
|
||||
y = (byte)clamp((299 * r + 587 * g + 114 * b) / 1000, 235, 16);
|
||||
v = (byte)clamp((500 * r - 419 * g - 81 * b) / 1000 + 127, 255, 0);
|
||||
u = (byte)clamp((-169 * r - 331 * g + 500 * b) / 1000 + 127, 255, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rgb_buffer_to_yuy2 (unsigned char *in, unsigned char *out)
|
||||
{
|
||||
for (uint i = 0; i < 320*240*2; i+=4)
|
||||
{
|
||||
byte y0, u0, v0;
|
||||
const byte r0 = *(in++);
|
||||
const byte g0 = *(in++);
|
||||
const byte b0 = *(in++);
|
||||
rgb_to_yuv(r0, g0, b0, y0, u0, v0);
|
||||
|
||||
byte y1, u1, v1;
|
||||
const byte r1 = *(in++);
|
||||
const byte g1 = *(in++);
|
||||
const byte b1 = *(in++);
|
||||
rgb_to_yuv(r1, g1, b1, y1, u1, v1);
|
||||
|
||||
out[i] = y0;
|
||||
out[i + 1] = u0;
|
||||
out[i + 2] = y1;
|
||||
out[i + 3] = v0;
|
||||
} }
|
||||
|
||||
|
||||
} // (End) implementation details
|
||||
|
||||
|
||||
|
||||
|
||||
DummyImageGenerator::DummyImageGenerator(uint fps)
|
||||
: current_(0)
|
||||
, frame_(0)
|
||||
, fps_(fps)
|
||||
{ }
|
||||
|
||||
|
||||
void * const
|
||||
DummyImageGenerator::next()
|
||||
{
|
||||
|
||||
++frame_;
|
||||
if(frame_ > 2 * fps_)
|
||||
frame_ = 0;
|
||||
|
||||
if(frame_ < 1 * fps_)
|
||||
{
|
||||
// create random snow...
|
||||
for(int i = 0; i < 320*240*3; i+=3)
|
||||
{
|
||||
byte value ( rand() );
|
||||
buf_[i] = value;
|
||||
buf_[i+1] = value;
|
||||
buf_[i+2] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // create a colour strip pattern
|
||||
typedef unsigned char Row[320 * 3];
|
||||
|
||||
unsigned char * row = buf_;
|
||||
|
||||
// create a colour strip pattern in the first row...
|
||||
for(int x = 0; x < 320; ++x)
|
||||
{
|
||||
byte &r = row[x*3];
|
||||
byte &g = row[x*3+1];
|
||||
byte &b = row[x*3+2];
|
||||
|
||||
if (x < 1*320/7) r = 0xC0, g = 0xC0, b = 0xC0;
|
||||
else if(x < 2*320/7) r = 0xC0, g = 0xC0, b = 0x00;
|
||||
else if(x < 3*320/7) r = 0x00, g = 0xC0, b = 0xC0;
|
||||
else if(x < 4*320/7) r = 0x00, g = 0xC0, b = 0x00;
|
||||
else if(x < 5*320/7) r = 0xC0, g = 0x00, b = 0xC0;
|
||||
else if(x < 6*320/7) r = 0xC0, g = 0x00, b = 0x00;
|
||||
else r = 0x00, g = 0x00, b = 0xC0;
|
||||
}
|
||||
|
||||
// fill remaining rows of the frame with the same pattern
|
||||
for(int y = 1; y < 240; ++y)
|
||||
memcpy(buf_ + y*sizeof(Row), row, sizeof(Row));
|
||||
|
||||
}
|
||||
|
||||
// select output buffer to return
|
||||
unsigned char * outBuff;
|
||||
|
||||
if (!current_)
|
||||
{
|
||||
outBuff = outFrame_A_;
|
||||
current_= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
outBuff = outFrame_B_;
|
||||
current_= 0;
|
||||
}
|
||||
|
||||
rgb_buffer_to_yuy2(buf_, outBuff);
|
||||
return outBuff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void * const
|
||||
DummyImageGenerator::current()
|
||||
{
|
||||
if (!current_) return outFrame_A_;
|
||||
else return outFrame_B_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace play
|
||||
|
||||
} // namespace proc
|
||||
89
src/proc/play/dummy-image-generator.hpp
Normal file
89
src/proc/play/dummy-image-generator.hpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
DUMMY-IMAGE-GENERATOR.hpp - creating test output frames for simulated playback
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Joel Holdsworth <joel@airwebreathe.org.uk>,
|
||||
Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/** @file dummy-image-generator.hpp
|
||||
** Generator for test dummy video frames to simulate playback of rendered output.
|
||||
** As of 1/2009 the render engine and source reading functions are not ready yet.
|
||||
** So, in order to learn how to build up the GUI/Playback interfaces, we use
|
||||
** this dummy image generator to create visible output. First implemented
|
||||
** by Joel within PlaybackController, then factored out into a separate
|
||||
** dummy playback service.
|
||||
**
|
||||
** @see gui::controller::PlaybackController
|
||||
** @see proc::play::DummyPlayerService
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PROC_PLAY_DUMMY_IMAGE_GENERATOR_H
|
||||
#define PROC_PLAY_DUMMY_IMAGE_GENERATOR_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace play {
|
||||
|
||||
|
||||
class DummyImageGenerator
|
||||
{
|
||||
|
||||
unsigned char buf_[320 * 240 * 3]; ///< working buffer for next frame
|
||||
|
||||
unsigned char outFrame_A_[320 * 240 * 4]; ///< output frame 1
|
||||
unsigned char outFrame_B_[320 * 240 * 4]; ///< output frame 2
|
||||
|
||||
uint current_;
|
||||
uint frame_;
|
||||
uint fps_;
|
||||
|
||||
|
||||
public:
|
||||
DummyImageGenerator(uint fps);
|
||||
|
||||
~DummyImageGenerator() { }
|
||||
|
||||
/** generate the next frame and
|
||||
* occupy the alternate buffer.
|
||||
* @return the buffer containing the new frame
|
||||
*/
|
||||
void * const next();
|
||||
|
||||
/** just re-return a pointer to the current frame
|
||||
* without generating any new image data */
|
||||
void * const current();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace play
|
||||
|
||||
} // namespace proc
|
||||
#endif // PROC_PLAY_DUMMY_IMAGE_GENERATOR_H
|
||||
|
||||
325
src/proc/play/dummy-player-service.cpp
Normal file
325
src/proc/play/dummy-player-service.cpp
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
DummyPlayerService - access point and service implementing a dummy test player
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "proc/play/dummy-player-service.hpp"
|
||||
#include "proc/play/dummy-image-generator.hpp"
|
||||
#include "lib/singleton.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "common/interfacedescriptor.h"
|
||||
}
|
||||
|
||||
#include <string>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace play{
|
||||
|
||||
using std::string;
|
||||
using lumiera::Subsys;
|
||||
using boost::scoped_ptr;
|
||||
|
||||
|
||||
namespace { // hidden local details of the service implementation....
|
||||
|
||||
/** details of how the DummyPlayer service can be started
|
||||
* and used as independent "subsystem" within main() */
|
||||
class DummyPlayerSubsysDescriptor
|
||||
: public Subsys
|
||||
{
|
||||
operator string () const { return "Dummy-Player"; }
|
||||
|
||||
|
||||
bool
|
||||
shouldStart (lumiera::Option&)
|
||||
{
|
||||
return false; // for now the DummyPlayerService only comes "up" as dependency,
|
||||
} // but doesn't start as a subsystem on it's own.
|
||||
|
||||
bool
|
||||
start (lumiera::Option&, Subsys::SigTerm terminationHandle)
|
||||
{
|
||||
ASSERT (!thePlayer_);
|
||||
|
||||
thePlayer_.reset (new DummyPlayerService (terminationHandle));
|
||||
return true;
|
||||
}
|
||||
|
||||
/** manages the actual (single) instance of the player service impl */
|
||||
scoped_ptr<DummyPlayerService> thePlayer_;
|
||||
|
||||
|
||||
void
|
||||
triggerShutdown () throw()
|
||||
{
|
||||
TODO ("implement waiting for any playback processes to terminate gracefully");
|
||||
//..... but this would require us to use a separate thread, so I skip it for now.
|
||||
// Probably it's better design to manage the processes in a separate thread anyway...
|
||||
|
||||
thePlayer_.reset(0);
|
||||
}
|
||||
|
||||
bool
|
||||
checkRunningState () throw()
|
||||
{
|
||||
//note: not locking here...
|
||||
return (thePlayer_);
|
||||
}
|
||||
};
|
||||
|
||||
lumiera::Singleton<DummyPlayerSubsysDescriptor> theDescriptor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ================== define an lumieraorg_GuiNotification instance ======================= */
|
||||
|
||||
LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0
|
||||
,lumieraorg_DummyPlayerFacade_descriptor
|
||||
, NULL, NULL, NULL
|
||||
, LUMIERA_INTERFACE_INLINE (name, "\305\162\202\240\075\316\146\100\314\152\075\343\372\065\226\307",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{ (void)ifa; return "DummyPlayer"; }
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (brief, "\317\045\366\076\064\072\156\274\220\346\262\207\062\367\057\232",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{ (void)ifa; return "Proc Interface: dummy player to test integration with the GUI"; }
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (homepage, "\136\225\033\362\161\251\300\256\117\072\171\102\235\004\235\200",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{ (void)ifa; return "http://www.lumiera.org/develompent.html" ;}
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (version, "\212\146\344\127\124\116\101\205\211\174\322\241\162\122\023\165",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{ (void)ifa; return "0.1~pre"; }
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (author, "\064\226\072\300\054\345\042\357\337\226\155\025\306\051\117\105",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{ (void)ifa; return "Hermann Vosseler"; }
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (email, "\041\075\220\112\246\304\261\135\003\135\060\202\230\327\303\206",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{ (void)ifa; return "Ichthyostega@web.de"; }
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (copyright, "\232\305\163\271\174\025\270\075\012\201\331\256\327\375\066\210",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{
|
||||
(void)ifa;
|
||||
return
|
||||
"Copyright (C) Lumiera.org\n"
|
||||
" 2009 Hermann Vosseler <Ichthyostega@web.de>";
|
||||
}
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (license, "\136\136\073\173\145\357\151\062\040\013\323\272\051\352\305\060",
|
||||
const char*, (LumieraInterface ifa),
|
||||
{
|
||||
(void)ifa;
|
||||
return
|
||||
"This program is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License as published by\n"
|
||||
"the Free Software Foundation; either version 2 of the License, or\n"
|
||||
"(at your option) any later version.\n"
|
||||
"\n"
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
"GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU General Public License\n"
|
||||
"along with this program; if not, write to the Free Software\n"
|
||||
"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA";
|
||||
}
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (state, "\224\251\004\001\165\140\116\246\126\311\115\234\023\026\331\350",
|
||||
int, (LumieraInterface ifa),
|
||||
{(void)ifa; return LUMIERA_INTERFACE_EXPERIMENTAL; }
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (versioncmp, "\267\155\303\046\353\222\323\014\145\027\043\100\370\311\257\126",
|
||||
int, (const char* a, const char* b),
|
||||
{return 0;} ////////////////////////////////////////////TODO define version ordering
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using lumiera::facade::LUMIERA_ERROR_FACADE_LIFECYCLE;
|
||||
typedef lib::SingletonRef<DummyPlayer>::Accessor InstanceRef;
|
||||
|
||||
InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual DummyPlayer implementation...
|
||||
|
||||
typedef DummyPlayer::Process* ProcP;
|
||||
|
||||
|
||||
LUMIERA_INTERFACE_INSTANCE (lumieraorg_DummyPlayer, 0
|
||||
,lumieraorg_DummyPlayerFacade
|
||||
, LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_DummyPlayerFacade_descriptor)
|
||||
, NULL /* on open */
|
||||
, NULL /* on close */
|
||||
, LUMIERA_INTERFACE_INLINE (startPlay, "\143\323\102\155\051\006\235\004\037\310\354\121\176\142\342\210",
|
||||
LumieraPlayProcess, (void),
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return static_cast<LumieraPlayProcess> (& (_instance->start()));
|
||||
}
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (pausePlay, "\275\157\316\220\210\053\226\134\057\016\273\265\240\053\112\307",
|
||||
void, (LumieraPlayProcess handle, bool doPlay),
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
REQUIRE (handle);
|
||||
ProcP proc = static_cast<ProcP> (handle);
|
||||
|
||||
proc->pause(doPlay);
|
||||
}
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (terminate, "\005\265\115\021\076\143\010\215\373\252\370\174\235\136\340\004",
|
||||
void, (LumieraPlayProcess handle),
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
REQUIRE (handle);
|
||||
ProcP proc = static_cast<ProcP> (handle);
|
||||
|
||||
UNIMPLEMENTED ("terminate a running playback process");
|
||||
}
|
||||
)
|
||||
, LUMIERA_INTERFACE_INLINE (getFrame, "\230\130\101\300\047\065\170\052\226\164\026\112\150\166\074\134",
|
||||
void *, (LumieraPlayProcess handle),
|
||||
{
|
||||
//skipping full checks for performance reasons
|
||||
REQUIRE (_instance && !lumiera_error_peek());
|
||||
|
||||
REQUIRE (handle);
|
||||
ProcP proc = static_cast<ProcP> (handle);
|
||||
|
||||
return const_cast<void*> (proc->getFrame());
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
} // (End) hidden service impl details
|
||||
|
||||
|
||||
|
||||
|
||||
DummyPlayerService::DummyPlayerService (Subsys::SigTerm terminationHandle)
|
||||
: error_("")
|
||||
, notifyTermination_(terminationHandle)
|
||||
, implInstance_(this,_instance)
|
||||
, serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_DummyPlayer, 0, lumieraorg_DummyPlayerFacade))
|
||||
{
|
||||
INFO (operate, "DummyPlayer Facade opened.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DummyPlayer::Process&
|
||||
DummyPlayerService::start()
|
||||
{
|
||||
// REQUIRE (!theProcess_.isActive()); //////////////TODO: reactivate this check when we have really independent processes which can be stopped!
|
||||
theProcess_.setRate(25);
|
||||
|
||||
return theProcess_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ProcessImpl::setRate (uint fps)
|
||||
{
|
||||
// REQUIRE (fps==0 || fps_==0 ); //////////////TODO: reactivate this check when we have really independent processes which can be stopped!
|
||||
// REQUIRE (fps==0 || !play_ ); //////////////TODO: reactivate this check when we have really independent processes which can be stopped!
|
||||
|
||||
fps_ = fps;
|
||||
play_ = (fps != 0);
|
||||
|
||||
if (play_)
|
||||
imageGen_.reset(new DummyImageGenerator(fps));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ProcessImpl::pause(bool doPause)
|
||||
{
|
||||
REQUIRE (isActive());
|
||||
play_ = !doPause;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* const
|
||||
ProcessImpl::getFrame()
|
||||
{
|
||||
REQUIRE (isActive());
|
||||
ASSERT (imageGen_);
|
||||
|
||||
if (play_)
|
||||
return imageGen_->next();
|
||||
else
|
||||
return imageGen_->current();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace play
|
||||
|
||||
|
||||
|
||||
/** @internal intended for use by main(). */
|
||||
lumiera::Subsys&
|
||||
DummyPlayer::getDescriptor()
|
||||
{
|
||||
return play::theDescriptor();
|
||||
}
|
||||
|
||||
// emit the vtable here into this translation unit within liblumieraproc.so ...
|
||||
DummyPlayer::~DummyPlayer() { }
|
||||
DummyPlayer::Process::~Process() { }
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace proc
|
||||
140
src/proc/play/dummy-player-service.hpp
Normal file
140
src/proc/play/dummy-player-service.hpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
DUMMY-PLAYER-SERVICE.hpp - service implementing a dummy test player
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/** @file notification-service.hpp
|
||||
** A public service provided by the GUI, implementing the gui::GuiNotification facade interface.
|
||||
** The purpose of this service is to push state update and notification of events from the lower
|
||||
** layers into the Lumiera GUI. Typically, this happens asynchronously and triggered by events
|
||||
** within the lower layers.
|
||||
**
|
||||
** This service is the implementation of a layer separation facade interface. Clients should use
|
||||
** gui::GuiNotification#facade to access this service. This header defines the interface used
|
||||
** to \em provide this service, not to access it.
|
||||
**
|
||||
** @see gui::GuiFacade
|
||||
** @see guifacade.cpp starting this service
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PROC_DUMMYPLAYER_SERVICE_H
|
||||
#define PROC_DUMMYPLAYER_SERVICE_H
|
||||
|
||||
|
||||
#include "include/dummy-player-facade.h"
|
||||
#include "common/instancehandle.hpp"
|
||||
#include "lib/singleton-ref.hpp"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace play {
|
||||
|
||||
using std::string;
|
||||
using lumiera::Subsys;
|
||||
|
||||
|
||||
class DummyImageGenerator;
|
||||
|
||||
|
||||
class ProcessImpl
|
||||
: public DummyPlayer::Process
|
||||
{
|
||||
void pause(bool doPause);
|
||||
void* const getFrame();
|
||||
|
||||
uint fps_;
|
||||
bool play_;
|
||||
|
||||
boost::scoped_ptr<DummyImageGenerator> imageGen_;
|
||||
|
||||
|
||||
public:
|
||||
ProcessImpl() : fps_(0), play_(false), imageGen_(0) {}
|
||||
|
||||
/* Implementation-level API to be used By DummyPlayerService */
|
||||
|
||||
/** activate a playback process
|
||||
* with given specification */
|
||||
void setRate (uint fps);
|
||||
|
||||
bool isActive () { return fps_ != 0; }
|
||||
bool isPlaying() { return play_; }
|
||||
};
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Actual implementation of the GuiNotification service
|
||||
* within the Lumiera GTK GUI. Creating an instance of
|
||||
* this class automatically registers the interface
|
||||
* with the Lumiera Interface/Plugin system and creates
|
||||
* a forwarding proxy within the application core to
|
||||
* route calls through this interface.
|
||||
*
|
||||
* @todo the ctor of this class should take references
|
||||
* to any internal service providers within the
|
||||
* GUI which are needed to implement the service.
|
||||
*/
|
||||
class DummyPlayerService
|
||||
: public DummyPlayer
|
||||
{
|
||||
|
||||
/* === Implementation of the Facade Interface === */
|
||||
|
||||
Process& start();
|
||||
|
||||
|
||||
/** for now we use an single inline Process...
|
||||
* @todo actually implement multiple independent Playback processes!
|
||||
* @todo I am aware holding this object inline may cause a segfault at shutdown!
|
||||
*/
|
||||
ProcessImpl theProcess_;
|
||||
|
||||
string error_;
|
||||
Subsys::SigTerm notifyTermination_;
|
||||
|
||||
|
||||
|
||||
/* === Interface Lifecycle === */
|
||||
|
||||
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0)
|
||||
, DummyPlayer
|
||||
> ServiceInstanceHandle;
|
||||
|
||||
lib::SingletonRef<DummyPlayer> implInstance_;
|
||||
ServiceInstanceHandle serviceInstance_;
|
||||
|
||||
public:
|
||||
DummyPlayerService(Subsys::SigTerm terminationHandle);
|
||||
|
||||
~DummyPlayerService() { notifyTermination_(&error_); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace play
|
||||
|
||||
} // namespace proc
|
||||
#endif
|
||||
|
|
@ -337,6 +337,10 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
PLANNED "Waiting on Thread termination" ThreadWrapperJoin_test <<END
|
||||
END
|
||||
|
||||
|
||||
TEST "Starting and stopping subsystems" SubsystemRunner_test <<END
|
||||
out: -----singleSubsys_complete_cycle-----
|
||||
out: -----singleSubsys_start_failure-----
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ test_lib_SOURCES = \
|
|||
$(testlib_srcdir)/sync-locking-test.cpp \
|
||||
$(testlib_srcdir)/sync-waiting-test.cpp \
|
||||
$(testlib_srcdir)/thread-wrapper-test.cpp \
|
||||
$(testlib_srcdir)/thread-wrapper-join-test.cpp \
|
||||
$(testlib_srcdir)/test/cmdlinewrappertest.cpp \
|
||||
$(testlib_srcdir)/test/testoptiontest.cpp \
|
||||
$(testlib_srcdir)/vectortransfertest.cpp \
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ namespace lumiera
|
|||
<< string (t1) << "\n";
|
||||
|
||||
#ifdef DEBUG
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////TODO: better way of detecting debug builds
|
||||
verify_error_detection ();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
141
tests/lib/thread-wrapper-join-test.cpp
Normal file
141
tests/lib/thread-wrapper-join-test.cpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
ThreadWrapperJoin(Test) - wait blocking on termination of a thread
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
|
||||
#include "include/symbol.hpp"
|
||||
#include "backend/thread-wrapper.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/sync.hpp"
|
||||
|
||||
#include <tr1/functional>
|
||||
|
||||
using std::tr1::bind;
|
||||
using test::Test;
|
||||
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace test {
|
||||
|
||||
/**************************************************************************
|
||||
* @test use the Lumiera backend to create some new threads, additionally
|
||||
* passing an condition variable for waiting on thread termination.
|
||||
* Actually this is implemented as creating and passing a JoinHandle.
|
||||
*
|
||||
* @see lib::Thread
|
||||
* @see threads.h
|
||||
*/
|
||||
class ThreadWrapperJoin_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
simpleUse ();
|
||||
wrongUse ();
|
||||
}
|
||||
|
||||
|
||||
volatile int aValue_; ///< state to be modified by the other thread
|
||||
|
||||
void
|
||||
theAction (int secretValue) ///< to be run in a new thread...
|
||||
{
|
||||
sleep(1);
|
||||
aValue_ = secretValue+42;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
simpleUse ()
|
||||
{
|
||||
aValue_=0;
|
||||
int mySecret = (rand() % 1000) - 500;
|
||||
|
||||
JoinHandle waitingHandle;
|
||||
|
||||
Thread("test Thread joining",
|
||||
bind (&ThreadWrapperJoin_test::theAction, this, mySecret),
|
||||
waitingHandle);
|
||||
// note binding and thread wrapper already destroyed
|
||||
|
||||
waitingHandle.join(); // blocks until theAction() is done
|
||||
|
||||
ASSERT (aValue_ == mySecret+42);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wrongUse ()
|
||||
{
|
||||
JoinHandle waitingHandle;
|
||||
|
||||
Thread("test Thread joining-1",
|
||||
bind (&ThreadWrapperJoin_test::theAction, this, 111));
|
||||
// note we "forget" to pass the JoinHandle
|
||||
try
|
||||
{
|
||||
waitingHandle.join(); // protocol error: handle wasn't passed for starting a Thread;
|
||||
NOTREACHED;
|
||||
}
|
||||
catch (lumiera::error::Logic& logo)
|
||||
{ lumiera_error(); }
|
||||
|
||||
|
||||
Thread("test Thread joining-2",
|
||||
bind (&ThreadWrapperJoin_test::theAction, this, 222),
|
||||
waitingHandle); // this time we pass it....
|
||||
|
||||
#ifdef DEBUG
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////TODO: better way of detecting debug builds
|
||||
try
|
||||
{
|
||||
Thread("test Thread joining-3",
|
||||
bind (&ThreadWrapperJoin_test::theAction, this, 333),
|
||||
waitingHandle); // but then pass it again for another thread....
|
||||
NOTREACHED;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ASSERT (lumiera_error() == lumiera::error::LUMIERA_ERROR_ASSERTION);
|
||||
}
|
||||
#endif
|
||||
|
||||
// note: the waitingHandle goes out of scope here,
|
||||
// which unblocks the second thread. The first thread wasn't blocked,
|
||||
// while the third thread wasn't created at all.
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (ThreadWrapperJoin_test, "function common");
|
||||
|
||||
|
||||
|
||||
} // namespace test
|
||||
|
||||
} // namespace lib
|
||||
|
|
@ -747,7 +747,7 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
|
|||
}
|
||||
//}}}</pre>
|
||||
</div>
|
||||
<div title="BuildDependencies" modifier="Ichthyostega" modified="200808190851" created="200803261326" changecount="15">
|
||||
<div title="BuildDependencies" modifier="Ichthyostega" modified="200901182029" created="200803261326" changecount="16">
|
||||
<pre>! Programming Languages
|
||||
* C
|
||||
** a C99 compatible compiler, some GCC extensions are used, most are optional.
|
||||
|
|
@ -787,7 +787,7 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
|
|||
** libcairomm-1.0-dev (>=0.6.0)
|
||||
** libgdl-1-dev (>=0.6.1)
|
||||
*** libbonoboui2-dev (>=2.14.0)
|
||||
** libglibmm-2.4-dev (>=2.16), requiring glib2.0 (>=2.16)
|
||||
** libglibmm-2.4-dev (>=2.16), requiring glib2.0 (>=2.16) and gthread-2.0 (>=2.12.4)
|
||||
** libxv-dev ~~(1.0.2 is known to work)~~
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -780,7 +780,7 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
|
|||
}
|
||||
//}}}</pre>
|
||||
</div>
|
||||
<div title="BuildDependenceis" modifier="Ichthyostega" modified="200808190850" created="200708120103" tags="organization buildsys" changecount="18">
|
||||
<div title="BuildDependenceis" modifier="Ichthyostega" modified="200901182029" created="200708120103" tags="organization buildsys" changecount="19">
|
||||
<pre>for __Building__
|
||||
* gcc (4.1), glibc6 (2.3), libstdc++6 (4.1)
|
||||
* [[build system|BuildSystem]] dependencies: SCons (0.96.90), Python (2.4), pkg-config
|
||||
|
|
@ -799,7 +799,7 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
|
|||
** libcairomm-1.0-dev (>=0.6.0)
|
||||
** libgdl-1-dev (>=0.6.1)
|
||||
*** libbonoboui2-dev (>=2.14.0)
|
||||
** libglibmm-2.4-dev (>=2.16), requiring glib2.0 (>=2.16)
|
||||
** libglibmm-2.4-dev (>=2.16), requiring glib2.0 (>=2.16) and gthread-2.0 (>=2.12.4)
|
||||
** libxv-dev (>=1.0.2)
|
||||
//usually, newer versions are OK//
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue