Merge branch 'guistart' of git://git.lumiera.org/lumiera/ichthyo into gui

This commit is contained in:
Joel Holdsworth 2009-01-24 21:28:45 +00:00
commit 51f05ebb3e
31 changed files with 1815 additions and 150 deletions

View file

@ -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):

View file

@ -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

View 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&amp;)</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

View file

@ -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());
}
};

View file

@ -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));
}
};

View file

@ -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

View file

@ -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 {

View file

@ -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

View file

@ -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;
};

View file

@ -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*))
);

View file

@ -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));
}
)
)

View file

@ -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.");
}

View file

@ -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;

View 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

View file

@ -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*)),
);

View file

@ -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 ========= */

View file

@ -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 ());
}

View file

@ -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

View file

@ -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_; }
};

View file

@ -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);

View file

@ -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

View 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

View 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

View 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

View 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

View file

@ -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-----

View file

@ -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 \

View file

@ -121,6 +121,7 @@ namespace lumiera
<< string (t1) << "\n";
#ifdef DEBUG
/////////////////////////////////////////////////////////////////////////////////////////////TODO: better way of detecting debug builds
verify_error_detection ();
#endif
}

View 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

View file

@ -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 (&gt;=0.6.0)
** libgdl-1-dev (&gt;=0.6.1)
*** libbonoboui2-dev (&gt;=2.14.0)
** libglibmm-2.4-dev (&gt;=2.16), requiring glib2.0 (&gt;=2.16)
** libglibmm-2.4-dev (&gt;=2.16), requiring glib2.0 (&gt;=2.16) and gthread-2.0 (&gt;=2.12.4)
** libxv-dev ~~(1.0.2 is known to work)~~

View file

@ -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 (&gt;=0.6.0)
** libgdl-1-dev (&gt;=0.6.1)
*** libbonoboui2-dev (&gt;=2.14.0)
** libglibmm-2.4-dev (&gt;=2.16), requiring glib2.0 (&gt;=2.16)
** libglibmm-2.4-dev (&gt;=2.16), requiring glib2.0 (&gt;=2.16) and gthread-2.0 (&gt;=2.12.4)
** libxv-dev (&gt;=1.0.2)
//usually, newer versions are OK//