Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/olpcgames
diff options
context:
space:
mode:
authorMorgan Collett <morgan.collett@gmail.com>2008-01-12 13:29:34 (GMT)
committer Morgan Collett <morgan.collett@gmail.com>2008-01-12 13:29:34 (GMT)
commit003a22744f3d330cd4240753749d84d7799646a1 (patch)
treee76d4bd3c9dfc776fb214d63e78b44bab7ac12cf /olpcgames
parent1480838b59eada15406799ebc1946fbfb6a68c8c (diff)
Update to upstream OLPCGames 1.4
Diffstat (limited to 'olpcgames')
-rw-r--r--olpcgames/__init__.py4
-rw-r--r--olpcgames/_cairoimage.py58
-rw-r--r--olpcgames/activity.py4
-rw-r--r--olpcgames/camera.py6
-rw-r--r--olpcgames/canvas.py27
-rw-r--r--olpcgames/data/__init__.py36
-rw-r--r--olpcgames/data/sleeping_svg.py501
-rw-r--r--olpcgames/eventwrap.py50
-rw-r--r--olpcgames/gtkEvent.py34
-rw-r--r--olpcgames/pangofont.py126
-rw-r--r--olpcgames/pausescreen.py89
-rw-r--r--olpcgames/svgsprite.py69
-rw-r--r--olpcgames/video.py117
13 files changed, 972 insertions, 149 deletions
diff --git a/olpcgames/__init__.py b/olpcgames/__init__.py
index 78c56f4..5fd28b7 100644
--- a/olpcgames/__init__.py
+++ b/olpcgames/__init__.py
@@ -19,7 +19,7 @@ Attributes of Note:
ACTIVITY -- if not None, then the activity instance which represents
this activity at the Sugar shell level.
- widget -- PygameCanvas instance, a GTK widget with an embedded
+ WIDGET -- PygameCanvas instance, a GTK widget with an embedded
socket object which is a proxy for the SDL window Pygame to which
pygame renders.
"""
@@ -39,4 +39,4 @@ from olpcgames import pangofont
from olpcgames import mesh
ACTIVITY = None
-widget = None
+widget = WIDGET = None
diff --git a/olpcgames/_cairoimage.py b/olpcgames/_cairoimage.py
new file mode 100644
index 0000000..302b916
--- /dev/null
+++ b/olpcgames/_cairoimage.py
@@ -0,0 +1,58 @@
+"""Utility functions for cairo-specific operations"""
+import cairo, pygame, struct
+big_endian = struct.pack( '=i', 1 ) == struct.pack( '>i', 1 )
+
+def newContext( width, height ):
+ """Create a new render-to-image context
+
+ width, height -- pixel dimensions to be rendered
+
+ returns surface, context for rendering
+ """
+ csrf = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+ return csrf, cairo.Context (csrf)
+
+def mangle_color(color):
+ """Mange a colour depending on endian-ness, and swap-necessity
+
+ This implementation has only been tested on an AMD64
+ machine with a get_data implementation (rather than
+ a get_data_as_rgba implementation).
+ """
+ r,g,b = color[:3]
+ if len(color) > 3:
+ a = color[3]
+ else:
+ a = 255.0
+ return map(_fixColorBase, (r,g,b,a) )
+
+def _fixColorBase( v ):
+ """Return a properly clamped colour in floating-point space"""
+ return max((0,min((v,255.0))))/255.0
+
+def asImage( csrf ):
+ """Get the pixels in csrf as a Pygame image"""
+ # Create and return a new Pygame Image derived from the Cairo Surface
+ format = 'ARGB'
+ if hasattr(csrf,'get_data'):
+ # more recent API, native-format, but have to (potentially) convert the format...
+ data = csrf.get_data()
+ if not big_endian:
+ import numpy
+ data = numpy.frombuffer( data, 'I' ).astype( '>I4' ).tostring()
+ else:
+ data = str(data) # there's one copy
+ else:
+ # older api, not native, but we know what it is...
+ data = csrf.get_data_as_rgba()
+ data = str(data) # there's one copy
+ width, height = csrf.get_width(),csrf.get_height()
+ try:
+ return pygame.image.fromstring(
+ data,
+ (width,height),
+ format
+ ) # there's the next
+ except ValueError, err:
+ err.args += (len(data), (width,height), width*height*4,format )
+ raise
diff --git a/olpcgames/activity.py b/olpcgames/activity.py
index f159b50..45a6a69 100644
--- a/olpcgames/activity.py
+++ b/olpcgames/activity.py
@@ -1,8 +1,8 @@
"""Embeds the Canvas widget into a Sugar-specific Activity environment"""
import logging
logging.root.setLevel( logging.WARN )
-log = logging.getLogger( 'activity' )
-log.setLevel( logging.INFO )
+log = logging.getLogger( 'olpcgames.activity' )
+#log.setLevel( logging.INFO )
import pygtk
pygtk.require('2.0')
diff --git a/olpcgames/camera.py b/olpcgames/camera.py
index dfc969a..b51a394 100644
--- a/olpcgames/camera.py
+++ b/olpcgames/camera.py
@@ -12,7 +12,7 @@ import pygame
import gst
from olpcgames.util import get_activity_root
-log = logging.getLogger( 'camera' )
+log = logging.getLogger( 'olpcgames.camera' )
#log.setLevel( logging.DEBUG )
CAMERA_LOAD = 9917
@@ -22,8 +22,8 @@ class CameraSprite(object):
"""Create gstreamer surface for the camera."""
def __init__(self, x, y):
import olpcgames
- if olpcgames.widget:
- self._init_video(olpcgames.widget, x, y)
+ if olpcgames.WIDGET:
+ self._init_video(olpcgames.WIDGET, x, y)
def _init_video(self, widget, x, y):
from olpcgames import video
diff --git a/olpcgames/canvas.py b/olpcgames/canvas.py
index eda64a2..0874d2d 100644
--- a/olpcgames/canvas.py
+++ b/olpcgames/canvas.py
@@ -1,6 +1,9 @@
"""Implements bridge connection between Sugar/GTK and PyGame"""
import os
import sys
+import logging
+log = logging.getLogger( 'olpcgames.canvas' )
+#log.setLevel( logging.DEBUG )
import threading
from pprint import pprint
@@ -10,11 +13,11 @@ import gtk
import gobject
import pygame
-from olpcgames import gtkEvent, video
+from olpcgames import gtkEvent, util
__all__ = ['PyGameCanvas']
-class PyGameCanvas(gtk.EventBox):
+class PyGameCanvas(gtk.Layout):
"""Canvas providing bridge methods to run PyGame in GTK
The PyGameCanvas creates a secondary thread in which the Pygame instance will
@@ -54,7 +57,7 @@ class PyGameCanvas(gtk.EventBox):
self._align.show()
- self.add(self._align)
+ self.put(self._align, 0,0)
# Construct a gtkEvent.Translator
self._translator = gtkEvent.Translator(self, self._inner_evb)
@@ -96,16 +99,26 @@ class PyGameCanvas(gtk.EventBox):
def _start(self, fn):
"""The method that actually runs in the background thread"""
import olpcgames
- olpcgames.widget = self
+ olpcgames.widget = olpcgames.WIDGET = self
try:
import sugar.activity.activity,os
except ImportError, err:
log.info( """Running outside Sugar""" )
else:
- os.chdir(sugar.activity.activity.get_bundle_path())
+ try:
+ os.chdir(sugar.activity.activity.get_bundle_path())
+ except KeyError, err:
+ pass
try:
- fn()
+ try:
+ log.info( '''Running mainloop: %s''', fn )
+ fn()
+ except Exception, err:
+ log.error(
+ """Uncaught top-level exception: %s""",
+ util.get_traceback( err ),
+ )
+ raise
finally:
gtk.main_quit()
-
diff --git a/olpcgames/data/__init__.py b/olpcgames/data/__init__.py
new file mode 100644
index 0000000..8510186
--- /dev/null
+++ b/olpcgames/data/__init__.py
@@ -0,0 +1,36 @@
+"""Design-time __init__.py for resourcepackage
+
+This is the scanning version of __init__.py for your
+resource modules. You replace it with a blank or doc-only
+init when ready to release.
+"""
+try:
+ __file__
+except NameError:
+ pass
+else:
+ import os
+ if os.path.splitext(os.path.basename( __file__ ))[0] == "__init__":
+ try:
+ from resourcepackage import package, defaultgenerators
+ generators = defaultgenerators.generators.copy()
+
+ ### CUSTOMISATION POINT
+ ## import specialised generators here, such as for wxPython
+ #from resourcepackage import wxgenerators
+ #generators.update( wxgenerators.generators )
+ except ImportError:
+ pass
+ else:
+ package = package.Package(
+ packageName = __name__,
+ directory = os.path.dirname( os.path.abspath(__file__) ),
+ generators = generators,
+ )
+ package.scan(
+ ### CUSTOMISATION POINT
+ ## force true -> always re-loads from external files, otherwise
+ ## only reloads if the file is newer than the generated .py file.
+ # force = 1,
+ )
+
diff --git a/olpcgames/data/sleeping_svg.py b/olpcgames/data/sleeping_svg.py
new file mode 100644
index 0000000..fa67eee
--- /dev/null
+++ b/olpcgames/data/sleeping_svg.py
@@ -0,0 +1,501 @@
+# -*- coding: ISO-8859-1 -*-
+"""Resource sleeping_svg (from file sleeping.svg)"""
+# written by resourcepackage: (1, 0, 1)
+source = 'sleeping.svg'
+package = 'olpcgames.data'
+data = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\012<!-- \
+Created with Inkscape (http://www.inkscape.org/) -->\012<svg\012 \
+ xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\012 xmlns:cc=\"ht\
+tp://web.resource.org/cc/\"\012 xmlns:rdf=\"http://www.w3.org/1\
+999/02/22-rdf-syntax-ns#\"\012 xmlns:svg=\"http://www.w3.org/20\
+00/svg\"\012 xmlns=\"http://www.w3.org/2000/svg\"\012 xmlns:xlink\
+=\"http://www.w3.org/1999/xlink\"\012 xmlns:sodipodi=\"http://so\
+dipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\012 xmlns:inkscape\
+=\"http://www.inkscape.org/namespaces/inkscape\"\012 width=\"736\
+.60107\"\012 height=\"923.09717\"\012 id=\"svg2\"\012 sodipodi:versi\
+on=\"0.32\"\012 inkscape:version=\"0.45.1\"\012 sodipodi:docbase=\"\
+/home/mcfletch/olpc/code/games-misc/olpcgames-src/olpcgames/\
+data\"\012 sodipodi:docname=\"sleeping.svg\"\012 inkscape:output_\
+extension=\"org.inkscape.output.svg.inkscape\"\012 version=\"1.0\
+\">\012 <defs\012 id=\"defs4\">\012 <linearGradient\012 id=\"l\
+inearGradient3152\">\012 <stop\012 style=\"stop-color:#\
+b8ffb4;stop-opacity:1;\"\012 offset=\"0\"\012 id=\"sto\
+p3154\" />\012 <stop\012 id=\"stop3214\"\012 offset\
+=\"0.5\"\012 style=\"stop-color:#2eff22;stop-opacity:0.498\
+03922;\" />\012 <stop\012 style=\"stop-color:#ffffff;st\
+op-opacity:0;\"\012 offset=\"1\"\012 id=\"stop3156\" />\
+\012 </linearGradient>\012 <radialGradient\012 inkscape:c\
+ollect=\"always\"\012 xlink:href=\"#linearGradient3152\"\012 \
+ id=\"radialGradient3158\"\012 cx=\"260.12256\"\012 cy=\"\
+235.24702\"\012 fx=\"260.12256\"\012 fy=\"235.24702\"\012 \
+ r=\"259.29678\"\012 gradientTransform=\"matrix(1,0,0,1.253\
+1846,0,-59.560934)\"\012 gradientUnits=\"userSpaceOnUse\" />\
+\012 </defs>\012 <sodipodi:namedview\012 id=\"base\"\012 pagecol\
+or=\"#ffffff\"\012 bordercolor=\"#666666\"\012 borderopacity=\"\
+1.0\"\012 gridtolerance=\"10000\"\012 guidetolerance=\"10\"\012 \
+ objecttolerance=\"10\"\012 inkscape:pageopacity=\"0.0\"\012 \
+inkscape:pageshadow=\"2\"\012 inkscape:zoom=\"1.2109676\"\012 \
+inkscape:cx=\"382.85714\"\012 inkscape:cy=\"461.2069\"\012 ink\
+scape:document-units=\"px\"\012 inkscape:current-layer=\"layer\
+1\"\012 inkscape:window-width=\"1600\"\012 inkscape:window-he\
+ight=\"1127\"\012 inkscape:window-x=\"0\"\012 inkscape:window-\
+y=\"0\" />\012 <metadata\012 id=\"metadata7\">\012 <rdf:RDF>\012 \
+ <cc:Work\012 rdf:about=\"\">\012 <dc:format>image/s\
+vg+xml</dc:format>\012 <dc:type\012 rdf:resource=\
+\"http://purl.org/dc/dcmitype/StillImage\" />\012 </cc:Work>\
+\012 </rdf:RDF>\012 </metadata>\012 <g\012 inkscape:label=\"Laye\
+r 1\"\012 inkscape:groupmode=\"layer\"\012 id=\"layer1\"\012 t\
+ransform=\"translate(-3.6769901,-73.051161)\">\012 <path\012 \
+ sodipodi:type=\"arc\"\012 style=\"opacity:1;color:#000000;\
+fill:url(#radialGradient3158);fill-opacity:1;fill-rule:eveno\
+dd;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-l\
+inejoin:miter;marker:none;marker-start:none;marker-mid:none;\
+marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;st\
+roke-dashoffset:0;stroke-opacity:1;visibility:visible;displa\
+y:inline;overflow:visible\"\012 id=\"path2178\"\012 sodip\
+odi:cx=\"260.12256\"\012 sodipodi:cy=\"235.24702\"\012 sod\
+ipodi:rx=\"259.29678\"\012 sodipodi:ry=\"324.94675\"\012 d\
+=\"M 519.41934 235.24702 A 259.29678 324.94675 0 1 1 0.82577\
+515,235.24702 A 259.29678 324.94675 0 1 1 519.41934 235.247\
+02 z\"\012 transform=\"matrix(1.4203822,0,0,1.4203822,2.504\
+0738,200.45905)\" />\012 <path\012 style=\"fill:#000000;fil\
+l-opacity:0.75;fill-rule:nonzero;stroke:none;stroke-width:1p\
+t;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\
+\"\012 id=\"path2160\"\012 d=\"M 420.07983,366.13071 C 420\
+.35487,366.47717 420.72076,366.7246 421.0413,367.02162 C 421\
+.54375,367.47276 422.06281,367.90429 422.57382,368.34583 C 4\
+23.28729,368.97986 424.02228,369.58903 424.74649,370.2106 C \
+425.62503,370.96294 426.49869,371.72131 427.37129,372.48063 \
+C 428.38549,373.33736 429.37161,374.22678 430.36963,375.1020\
+2 C 431.51957,376.11144 432.66227,377.12909 433.8068,378.144\
+7 C 435.10375,379.28207 436.39638,380.42416 437.68916,381.56\
+629 C 439.07238,382.75868 440.43413,383.9754 441.79974,385.1\
+8789 C 443.20004,386.42238 444.62683,387.62616 446.04562,388\
+.8391 C 447.49676,390.05005 448.96429,391.24028 450.43445,39\
+2.42792 C 451.96417,393.65117 453.55907,394.78949 455.13698,\
+395.94898 C 456.83948,397.17768 458.60045,398.31988 460.3532\
+5,399.47417 C 462.27994,400.72959 464.31105,401.80854 466.32\
+055,402.92156 C 468.55661,404.14536 470.8622,405.23086 473.1\
+6967,406.31074 C 475.67184,407.45821 478.22515,408.48722 480\
+.77405,409.52454 C 483.51937,410.62204 486.31152,411.59223 4\
+89.10452,412.55924 C 492.05602,413.59241 495.06998,414.42774\
+ 498.07923,415.2716 C 501.23779,416.16616 504.44361,416.8708\
+8 507.64836,417.5745 C 510.92868,418.27561 514.24385,418.790\
+77 517.55871,419.29543 C 520.86716,419.83295 524.19756,420.1\
+9662 527.5309,420.53139 C 530.86062,420.85145 534.19927,421.\
+03598 537.53901,421.20717 C 540.87406,421.39592 544.2147,421\
+.33746 547.55212,421.28446 C 550.92768,421.21773 554.29512,4\
+20.98306 557.66012,420.72502 C 561.0209,420.45787 564.3698,4\
+20.06437 567.71901,419.68331 C 570.96499,419.33121 574.18795\
+,418.8046 577.41097,418.29085 C 580.55689,417.7694 583.67686\
+,417.11029 586.79515,416.44738 C 589.93249,415.74608 593.044\
+28,414.93908 596.15094,414.1143 C 599.21068,413.29028 602.23\
+59,412.3538 605.25231,411.38586 C 608.26457,410.38752 611.22\
+46,409.24314 614.18464,408.1019 C 617.09398,406.98339 619.95\
+45,405.75011 622.80697,404.49587 C 625.61411,403.24034 628.3\
+8046,401.89814 631.14782,400.55819 C 633.83692,399.24273 636\
+.49752,397.87128 639.15408,396.49166 C 641.69701,395.16459 6\
+44.21761,393.79564 646.73927,392.4287 C 649.226,391.07864 65\
+1.69596,389.6984 654.16621,388.31856 C 664.28369,382.47714 6\
+35.39954,399.24448 647.39096,392.20906 C 649.71362,390.83128\
+ 652.01714,389.42151 654.32347,388.01666 C 656.58074,386.649\
+11 658.81401,385.24283 661.04492,383.83292 C 663.187,382.479\
+81 665.31986,381.11219 667.45597,379.74972 L 682.67421,373.8\
+2852 C 680.53333,375.19377 678.39504,376.56299 676.25306,377\
+.92652 C 674.02228,379.3423 671.79047,380.75695 669.53525,38\
+2.13372 C 667.22445,383.53974 664.91761,384.95222 662.60433,\
+386.35423 C 655.61128,390.50089 648.56215,394.55382 641.4868\
+8,398.55869 C 639.01339,399.93149 636.53782,401.30047 634.04\
+976,402.64675 C 631.52675,404.00642 629.00428,405.36735 626.\
+45516,406.67776 C 623.79203,408.04539 621.12639,409.40838 61\
+8.42657,410.70277 C 615.65387,412.03449 612.87794,413.36009 \
+610.05858,414.59127 C 607.18935,415.82018 604.3116,417.02842\
+ 601.39097,418.13174 C 598.41438,419.25931 595.43663,420.387\
+92 592.40026,421.34741 C 589.36654,422.28426 586.3267,423.20\
+206 583.25307,424.00155 C 580.12921,424.80704 577.00369,425.\
+61049 573.84621,426.27614 C 570.71325,426.91875 567.57887,42\
+7.5585 564.41815,428.0531 C 561.18267,428.54536 557.94654,42\
+9.03847 554.69048,429.37858 C 551.33145,429.74649 547.97234,\
+430.1215 544.60158,430.36782 C 541.21644,430.5953 537.82951,\
+430.81131 534.43558,430.8518 C 531.07392,430.87518 527.71049\
+,430.89848 524.35301,430.68741 C 520.99953,430.49414 517.647\
+13,430.28301 514.30415,429.94706 C 510.95344,429.57661 507.6\
+051,429.18426 504.27719,428.63828 C 500.94305,428.10693 497.\
+60828,427.56958 494.31089,426.83677 C 491.08361,426.10923 48\
+7.85646,425.37704 484.67505,424.46407 C 481.64095,423.59885 \
+478.60428,422.73682 475.62985,421.67916 C 472.81539,420.6957\
+9 470.00238,419.70689 467.23755,418.58909 C 464.66531,417.53\
+539 462.08915,416.48836 459.56863,415.31414 C 457.23636,414.\
+21006 454.9071,413.09837 452.64473,411.85467 C 450.60324,410\
+.7133 448.53944,409.60683 446.58754,408.31323 C 444.81432,40\
+7.13778 443.02862,405.98003 441.31079,404.72322 C 439.71016,\
+403.54798 438.09384,402.39203 436.55288,401.13812 C 435.0762\
+1,399.94004 433.59657,398.74568 432.14156,397.52114 C 430.71\
+41,396.29841 429.28064,395.08245 427.873,393.83679 C 426.503\
+83,392.62682 425.13537,391.41618 423.75477,390.21924 C 422.4\
+5847,389.08225 421.16119,387.9464 419.86302,386.81152 C 418.\
+70791,385.79925 417.55469,384.78482 416.40007,383.772 C 415.\
+40028,382.90611 414.40456,382.03536 413.39731,381.17806 C 41\
+2.52422,380.4317 411.656,379.67945 410.77279,378.9451 C 410.\
+03818,378.32256 409.30237,377.70143 408.56894,377.07747 C 40\
+8.05171,376.64287 407.52411,376.22075 407.01733,375.77379 C \
+406.66439,375.42865 406.27154,375.12044 405.95609,374.736 L \
+420.07983,366.13071 z \" />\012 <path\012 d=\"M 322.28988,3\
+66.13071 C 322.01483,366.47717 321.64895,366.7246 321.32841,\
+367.02162 C 320.82597,367.47276 320.3069,367.90429 319.79589\
+,368.34583 C 319.08241,368.97986 318.34743,369.58903 317.623\
+22,370.2106 C 316.74468,370.96294 315.87102,371.72131 314.99\
+842,372.48063 C 313.98423,373.33736 312.9981,374.22678 312.0\
+001,375.10202 C 310.85015,376.11144 309.70744,377.12909 308.\
+56293,378.1447 C 307.26598,379.28207 305.97336,380.42416 304\
+.68058,381.56629 C 303.29734,382.75868 301.93559,383.9754 30\
+0.57,385.18789 C 299.1697,386.42238 297.74291,387.62616 296.\
+32412,388.8391 C 294.873,390.05005 293.40545,391.24028 291.9\
+3531,392.42792 C 290.40559,393.65117 288.81068,394.78949 287\
+.23278,395.94898 C 285.53028,397.17768 283.7693,398.31988 28\
+2.01651,399.47417 C 280.08982,400.72959 278.0587,401.80854 2\
+76.0492,402.92156 C 273.81315,404.14536 271.50756,405.23086 \
+269.20009,406.31074 C 266.69792,407.45821 264.14461,408.4872\
+2 261.59571,409.52454 C 258.85039,410.62204 256.05823,411.59\
+223 253.26523,412.55924 C 250.31374,413.59241 247.29977,414.\
+42774 244.29052,415.2716 C 241.13196,416.16616 237.92614,416\
+.87088 234.72139,417.5745 C 231.44108,418.27561 228.12591,41\
+8.79077 224.81105,419.29543 C 221.50259,419.83295 218.17219,\
+420.19662 214.83886,420.53139 C 211.50914,420.85145 208.1704\
+9,421.03598 204.83074,421.20717 C 201.4957,421.39592 198.155\
+06,421.33746 194.81763,421.28446 C 191.44208,421.21773 188.0\
+7464,420.98306 184.70964,420.72502 C 181.34886,420.45787 177\
+.99995,420.06437 174.65075,419.68331 C 171.40476,419.33121 1\
+68.1818,418.8046 164.95878,418.29085 C 161.81286,417.7694 15\
+8.69291,417.11029 155.57462,416.44738 C 152.43728,415.74608 \
+149.3255,414.93908 146.21884,414.1143 C 143.1591,413.29028 1\
+40.13389,412.3538 137.1175,411.38586 C 134.10524,410.38752 1\
+31.14523,409.24314 128.1852,408.1019 C 125.27586,406.98339 1\
+22.41534,405.75011 119.56288,404.49587 C 116.75575,403.24034\
+ 113.9894,401.89814 111.22207,400.55819 C 108.53297,399.2427\
+3 105.87237,397.87128 103.21581,396.49166 C 100.67287,395.16\
+459 98.152294,393.79564 95.630638,392.4287 C 93.14389,391.07\
+864 90.673951,389.6984 88.203707,388.31856 C 78.086243,382.4\
+7714 106.97036,399.24448 94.978939,392.20906 C 92.656273,390\
+.83128 90.352774,389.42151 88.046448,388.01666 C 85.789177,3\
+86.64911 83.555916,385.24283 81.324993,383.83292 C 79.182934\
+,382.47981 77.050074,381.11219 74.913953,379.74972 L 59.6957\
+31,373.82852 C 61.836611,375.19377 63.974911,376.56299 66.11\
+6884,377.92652 C 68.34766,379.3423 70.579478,380.75695 72.83\
+467,382.13372 C 75.145475,383.53974 77.452326,384.95222 79.7\
+65589,386.35423 C 86.758645,390.50089 93.807748,394.55382 10\
+0.883,398.55869 C 103.3565,399.93149 105.83208,401.30047 108\
+.32013,402.64675 C 110.84314,404.00642 113.36559,405.36735 1\
+15.9147,406.67776 C 118.57783,408.04539 121.24346,409.40838 \
+123.94327,410.70277 C 126.71597,412.03449 129.49189,413.3600\
+9 132.31123,414.59127 C 135.18046,415.82018 138.0582,417.028\
+42 140.97881,418.13174 C 143.95541,419.25931 146.93315,420.3\
+8792 149.96952,421.34741 C 153.00323,422.28426 156.04307,423\
+.20206 159.1167,424.00155 C 162.24054,424.80704 165.36606,42\
+5.61049 168.52355,426.27614 C 171.65651,426.91875 174.79088,\
+427.5585 177.9516,428.0531 C 181.18709,428.54536 184.42322,4\
+29.03847 187.67927,429.37858 C 191.03831,429.74649 194.39741\
+,430.1215 197.76818,430.36782 C 201.15332,430.5953 204.54025\
+,430.81131 207.93418,430.8518 C 211.29584,430.87518 214.6592\
+6,430.89848 218.01675,430.68741 C 221.37023,430.49414 224.72\
+263,430.28301 228.06561,429.94706 C 231.41632,429.57661 234.\
+76466,429.18426 238.09257,428.63828 C 241.4267,428.10693 244\
+.76148,427.56958 248.05887,426.83677 C 251.28615,426.10923 2\
+54.5133,425.37704 257.69471,424.46407 C 260.7288,423.59885 2\
+63.76548,422.73682 266.7399,421.67916 C 269.55436,420.69579 \
+272.36737,419.70689 275.1322,418.58909 C 277.70444,417.53539\
+ 280.2806,416.48836 282.80113,415.31414 C 285.1334,414.21006\
+ 287.46265,413.09837 289.72502,411.85467 C 291.7665,410.7133\
+ 293.83031,409.60683 295.78222,408.31323 C 297.55542,407.137\
+78 299.34112,405.98003 301.05894,404.72322 C 302.65958,403.5\
+4798 304.27589,402.39203 305.81685,401.13812 C 307.29352,399\
+.94004 308.77316,398.74568 310.22816,397.52114 C 311.65561,3\
+96.29841 313.08907,395.08245 314.49672,393.83679 C 315.86588\
+,392.62682 317.23435,391.41618 318.61494,390.21924 C 319.911\
+24,389.08225 321.20852,387.9464 322.50669,386.81152 C 323.66\
+18,385.79925 324.81503,384.78482 325.96963,383.772 C 326.969\
+42,382.90611 327.96513,382.03536 328.97238,381.17806 C 329.8\
+4548,380.4317 330.71369,379.67945 331.59691,378.9451 C 332.3\
+3152,378.32256 333.06732,377.70143 333.80075,377.07747 C 334\
+.31799,376.64287 334.84558,376.22075 335.35236,375.77379 C 3\
+35.70529,375.42865 336.09814,375.12044 336.4136,374.736 L 32\
+2.28988,366.13071 z \"\012 id=\"path2162\"\012 style=\"fil\
+l:#000000;fill-opacity:0.75;fill-rule:nonzero;stroke:none;st\
+roke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;str\
+oke-opacity:1\" />\012 <path\012 style=\"fill:#000000;fill-\
+opacity:0.75;fill-rule:nonzero;stroke:none;stroke-width:1pt;\
+stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\012\
+ id=\"path2174\"\012 d=\"M 363.56451,383.66406 C 363.2\
+9789,384.11947 363.11097,384.61437 362.88438,385.08913 C 362\
+.56503,385.71349 362.28415,386.35637 361.98417,386.98968 C 3\
+61.59883,387.80682 361.31001,388.66309 360.97303,389.49955 C\
+ 360.58158,390.48782 360.2446,391.49591 359.88304,392.49501 \
+C 359.47472,393.65559 359.09862,394.82693 358.71289,395.9950\
+8 C 358.28054,397.30269 357.91308,398.63001 357.52373,399.95\
+051 C 357.10226,401.42131 356.77445,402.91584 356.41772,404.\
+40288 C 356.03758,406.05957 355.67624,407.72044 355.31143,40\
+9.38051 C 354.93639,411.10586 354.62209,412.8432 354.29778,4\
+14.57846 C 353.95914,416.41072 353.68547,418.25378 353.39986\
+,420.09471 C 353.09767,422.01995 352.87618,423.95563 352.643\
+78,425.88995 C 352.40586,427.8967 352.24593,429.91073 352.07\
+562,431.92382 C 351.91629,433.95529 351.78304,435.98864 351.\
+64542,438.02165 C 351.5051,440.1096 351.38765,442.19895 351.\
+26622,444.28805 C 351.13491,446.44906 350.9941,448.60949 350\
+.85664,450.77013 C 350.72765,452.93795 350.56813,455.10378 3\
+50.41467,457.26996 C 350.25248,459.46881 350.07615,461.66658\
+ 349.90426,463.86466 C 349.72711,466.05242 349.50047,468.235\
+71 349.28474,470.41986 C 349.06933,472.63327 348.80288,474.8\
+409 348.54333,477.04935 C 348.27687,479.24544 347.9552,481.4\
+3401 347.6439,483.62388 C 347.3292,485.821 346.94529,488.006\
+52 346.56931,490.19356 C 346.18304,492.38223 345.7145,494.55\
+499 345.2634,496.73079 C 344.80304,498.88744 344.25754,501.0\
+2401 343.72541,503.16357 C 343.19873,505.27872 342.60709,507\
+.37642 342.02636,509.477 C 341.45242,511.5036 340.81692,513.\
+51179 340.19303,515.52327 C 339.579,517.48655 338.89351,519.\
+4259 338.22066,521.3693 C 337.52576,523.32558 336.75445,525.\
+25314 335.99664,527.18551 C 335.25621,529.09523 334.4656,530\
+.98465 333.68412,532.87762 C 332.89153,534.72375 332.09494,5\
+36.56812 331.29879,538.4127 C 330.52012,540.19102 329.72848,\
+541.9636 328.94044,543.73774 C 328.17627,545.48552 327.37923\
+,547.21844 326.58698,548.95351 C 325.79159,550.70985 324.963\
+38,552.45063 324.13807,554.19294 C 323.29657,555.94061 322.4\
+3736,557.67961 321.58006,559.41955 C 320.71339,561.15716 319\
+.85494,562.89885 318.99475,564.63967 C 318.12909,566.38264 3\
+17.29007,568.13858 316.44572,569.8919 C 315.57499,571.66105 \
+314.78167,573.46556 313.97771,575.26527 C 313.19325,577.0957\
+7 312.47033,578.95167 311.73461,580.80204 C 310.99762,582.66\
+364 310.33451,584.55312 309.65608,586.43649 C 308.96316,588.\
+34295 308.36923,590.28231 307.75868,592.21589 C 307.15712,59\
+4.14403 306.62912,596.09342 306.0891,598.03922 C 305.56263,5\
+99.9412 305.15523,601.87189 304.72869,603.79759 C 304.30073,\
+605.67457 304.06586,607.58362 303.80201,609.48748 C 303.5324\
+9,611.35505 303.50387,613.23908 303.43969,615.12014 C 303.37\
+464,616.94922 303.54021,618.77033 303.66927,620.59176 C 303.\
+79296,622.3199 304.08519,624.02622 304.35157,625.73538 C 304\
+.61502,627.39034 305.10873,628.99125 305.56074,630.60013 C 3\
+06.00752,632.15988 306.58838,633.67514 307.12864,635.20312 C\
+ 307.6775,636.69384 308.43059,638.09344 309.11955,639.52034 \
+C 309.81034,640.91074 310.62616,642.2312 311.40271,643.57325\
+ C 312.16936,644.91811 313.11662,646.14135 314.00418,647.403\
+93 C 314.99219,648.72656 316.15747,649.89632 317.28843,651.0\
+9288 C 318.46185,652.30686 319.74291,653.40671 321.00019,654\
+.53049 C 322.2966,655.6648 323.68994,656.67667 325.06765,657\
+.70741 C 326.47942,658.75983 327.95117,659.72705 329.40559,6\
+60.71847 C 330.83949,661.67678 332.34116,662.52443 333.83093\
+,663.39053 C 335.29556,664.25037 336.83732,664.96109 338.365\
+67,665.69625 C 339.90883,666.42997 341.52771,666.97576 343.1\
+3097,667.55664 C 344.73218,668.10981 346.35529,668.58875 347\
+.97795,669.07256 C 349.65491,669.51863 351.38306,669.68065 3\
+53.09946,669.88963 C 354.84867,670.06333 356.60545,670.12506\
+ 358.36018,670.20906 C 360.07756,670.2966 361.79638,670.2728\
+7 363.51489,670.26883 C 365.20531,670.27174 366.89234,670.15\
+027 368.57919,670.0587 C 370.24527,669.9842 371.90054,669.78\
+813 373.55711,669.60806 C 375.19642,669.43166 376.82701,669.\
+1875 378.45965,668.9609 C 380.05633,668.73502 381.639,668.42\
+532 383.22608,668.14241 C 384.79034,667.88127 386.33919,667.\
+53818 387.89293,667.22433 C 389.43429,666.90277 390.96344,66\
+6.52725 392.49528,666.16451 C 394.03056,665.81731 395.5471,6\
+65.39645 397.06849,664.99483 C 398.64264,664.56434 400.22202\
+,664.15336 401.79852,663.73164 C 403.36426,663.26119 404.935\
+2,662.80866 406.50541,662.3535 C 408.05433,661.88535 409.586\
+83,661.36613 411.1234,660.86012 C 412.66775,660.35111 414.18\
+526,659.76629 415.71252,659.20982 C 417.23752,658.65947 418.\
+74032,658.0508 420.25157,657.4645 C 421.78841,656.85547 423.\
+2868,656.15704 424.79163,655.47466 C 426.29961,654.81287 427\
+.76918,654.06794 429.24814,653.34475 C 430.6928,652.6429 432\
+.0654,651.81007 433.46052,651.01822 C 409.43233,665.22265 41\
+8.13774,659.96775 423.38798,656.71194 C 424.6585,655.8887 42\
+5.88948,655.00695 427.13279,654.14384 C 428.32441,653.29299 \
+429.45698,652.3653 430.60682,651.46022 C 431.47422,650.77115\
+ 432.34875,650.09101 433.22174,649.40909 L 448.5228,643.3551\
+8 C 447.63804,644.01509 446.72472,644.64308 445.86728,645.34\
+265 C 444.71845,646.26217 443.57512,647.18953 442.40365,648.\
+08019 C 441.17228,648.9734 439.95693,649.89058 438.68912,650\
+.73413 C 432.83662,654.52282 427.0541,658.31426 420.69402,66\
+1.34738 C 419.27728,662.11016 417.8829,662.91763 416.41627,6\
+63.58508 C 414.92691,664.29306 413.44902,665.02549 411.93432\
+,665.67932 C 410.41153,666.3424 408.89415,667.01896 407.3392\
+1,667.60508 C 405.82142,668.184 404.30728,668.77253 402.7802\
+3,669.32688 C 401.24293,669.87049 399.71138,670.43093 398.15\
+957,670.93266 C 396.61026,671.42265 395.06745,671.93429 393.\
+5035,672.37678 C 391.92791,672.83163 390.35562,673.29957 388\
+.77032,673.71957 C 387.19381,674.14305 385.61788,674.56863 3\
+84.04086,674.99015 C 382.50743,675.37425 380.97868,675.77697\
+ 379.43716,676.12841 C 377.89624,676.47487 376.35896,676.837\
+7 374.81053,677.15004 C 373.24643,677.44935 371.68464,677.76\
+125 370.11446,678.02797 C 368.51685,678.29656 366.9236,678.5\
+9385 365.31562,678.79756 C 363.67262,679.0061 362.03203,679.\
+23485 360.38388,679.40114 C 358.70992,679.54982 357.03695,67\
+9.70997 355.35705,679.78096 C 353.653,679.85299 351.94917,67\
+9.93986 350.24276,679.91999 C 348.51003,679.89948 346.77686,\
+679.89135 345.046,679.79257 C 343.26754,679.68408 341.48595,\
+679.6006 339.71726,679.37303 C 337.94225,679.10105 336.15156\
+,678.88936 334.43306,678.33765 C 332.79598,677.8244 331.1544\
+,677.3242 329.53893,676.74424 C 327.90173,676.11886 326.2496\
+3,675.52578 324.67627,674.74596 C 323.1254,673.97225 321.562\
+17,673.22067 320.07267,672.33029 C 318.56132,671.43198 317.0\
+3713,670.55306 315.58562,669.55826 C 314.11604,668.54878 312\
+.63482,667.55487 311.20896,666.48351 C 309.80579,665.41766 3\
+08.38349,664.37439 307.0683,663.19816 C 305.78429,662.03802 \
+304.47767,660.90001 303.28216,659.64604 C 302.11242,658.3914\
+3 300.9084,657.16342 299.88424,655.78196 C 298.96626,654.474\
+88 297.98646,653.20835 297.19409,651.81588 C 296.39988,650.4\
+375 295.56515,649.0813 294.85536,647.65537 C 294.13919,646.1\
+7664 293.36012,644.72494 292.78129,643.18325 C 292.22278,641\
+.62181 291.61949,640.07435 291.16208,638.47811 C 290.68499,6\
+36.81415 290.1599,635.15907 289.86919,633.44829 C 289.57968,\
+631.69328 289.25735,629.942 289.12427,628.16477 C 288.97373,\
+626.29499 288.78192,624.42493 288.82889,622.5457 C 288.86416\
+,620.6118 288.86309,618.67496 289.1145,616.75238 C 289.35851\
+,614.80657 289.56627,612.85449 289.98378,610.93512 C 290.396\
+86,608.98011 290.79545,607.02179 291.3074,605.08916 C 291.83\
+86,603.12616 292.35898,601.16001 292.95529,599.21532 C 293.5\
+5531,597.26108 294.13954,595.30137 294.82052,593.37312 C 295\
+.49687,591.47567 296.15668,589.57191 296.87156,587.68842 C 2\
+97.60792,585.82579 298.33182,583.95803 299.09663,582.10678 C\
+ 299.88215,580.28367 300.65555,578.45551 301.52849,576.67149\
+ C 302.37027,574.91155 303.21063,573.15093 304.0723,571.4006\
+ C 304.92867,569.65917 305.77955,567.91493 306.65382,566.182\
+38 C 307.51229,564.44638 308.37352,562.71183 309.21869,560.9\
+6929 C 310.05554,559.23843 310.89164,557.50748 311.67649,555\
+.75215 C 312.47234,554.02453 313.28387,552.30409 314.03792,5\
+50.55739 C 314.82916,548.78481 315.62848,547.01578 316.40577\
+,545.23701 C 317.2127,543.40023 318.01405,541.56117 318.8030\
+7,539.71654 C 319.59553,537.83852 320.40019,535.96609 321.14\
+196,534.06683 C 321.89793,532.14643 322.66854,530.2315 323.3\
+8361,528.29533 C 324.06665,526.36841 324.76378,524.44612 325\
+.38216,522.4969 C 326.01357,520.50014 326.65767,518.50728 32\
+7.24477,516.49664 C 327.83761,514.40974 328.44098,512.32573 \
+328.96655,510.2204 C 329.50731,508.0994 330.05662,505.98047 \
+330.53336,503.84375 C 330.99109,501.68477 331.46412,499.5286\
+4 331.86906,497.35878 C 332.25347,495.1853 332.64721,493.013\
+59 332.95502,490.8274 C 333.27834,488.65205 333.61051,486.47\
+836 333.87985,484.29519 C 334.14635,482.09722 334.42445,479.\
+90067 334.63252,477.69603 C 334.85115,475.52144 335.08185,47\
+3.34776 335.26753,471.17003 C 335.44247,468.97902 335.61987,\
+466.78814 335.7857,464.59636 C 335.9374,462.43353 336.09908,\
+460.27127 336.2325,458.10726 C 336.36861,455.95054 336.50471\
+,453.79383 336.64346,451.63726 C 336.75954,449.54451 336.871\
+8,447.45154 337.00837,445.36 C 337.14218,443.32145 337.27141\
+,441.28256 337.42819,439.24561 C 337.58804,437.21771 337.738\
+7,435.18901 337.96899,433.16744 C 338.18602,431.21577 338.39\
+223,429.26293 338.69246,427.3216 C 338.96648,425.46725 339.2\
+2994,423.61113 339.55622,421.76492 C 339.87123,420.01556 340\
+.1748,418.26393 340.54188,416.52441 C 340.89585,414.85685 34\
+1.25483,413.1906 341.62509,411.52661 C 341.96789,410.02221 3\
+42.29031,408.5126 342.68484,407.02054 C 343.05884,405.68159 \
+343.40898,404.33587 343.82991,403.01022 C 344.20476,401.8347\
+4 344.56584,400.65438 344.97285,399.48945 C 345.31926,398.47\
+686 345.63507,397.45329 346.02625,396.45637 C 346.34746,395.\
+60134 346.62749,394.73113 346.98966,393.89195 C 347.27371,39\
+3.23878 347.49217,392.5551 347.8422,391.93148 C 348.06066,39\
+1.44853 348.29399,390.96969 348.49861,390.48035 L 363.56451,\
+383.66406 z \" />\012 <path\012 style=\"fill:#000000;fill-o\
+pacity:0.75;fill-rule:nonzero;stroke:none;stroke-width:1pt;s\
+troke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\012 \
+ id=\"path2176\"\012 d=\"M 206.26655,735.18853 C 206.83\
+428,735.13263 207.3974,735.24282 207.96264,735.26997 C 208.7\
+4945,735.38766 209.54574,735.41257 210.337,735.48383 C 211.4\
+0487,735.57658 212.4743,735.65567 213.54253,735.74595 C 214.\
+85506,735.85864 216.16829,735.96544 217.48119,736.07504 C 21\
+9.09858,736.19868 220.71821,736.28835 222.33737,736.38462 C \
+224.22785,736.49412 226.11976,736.57498 228.01139,736.66113 \
+C 230.21087,736.77385 232.40938,736.90196 234.6081,737.0278 \
+C 237.0714,737.16983 239.53507,737.30307 241.99787,737.45342\
+ C 244.67148,737.62094 247.34414,737.8036 250.01759,737.9742\
+6 C 252.83872,738.14605 255.65783,738.34915 258.47629,738.55\
+974 C 261.33166,738.75949 264.18381,739.00073 267.03608,739.\
+23951 C 269.88729,739.49322 272.74001,739.72881 275.59292,73\
+9.96221 C 278.4075,740.17784 281.21951,740.42472 284.0323,74\
+0.66212 C 286.81296,740.89496 289.59172,741.14985 292.37152,\
+741.39286 C 295.06522,741.63657 297.75949,741.87322 300.4530\
+1,742.11926 C 303.13613,742.35628 305.82004,742.58296 308.50\
+255,742.82687 C 311.19656,743.07346 313.89254,743.29738 316.\
+58863,743.51984 C 319.25058,743.73995 321.91436,743.93665 32\
+4.57819,744.1323 C 327.24092,744.32619 329.90506,744.49944 3\
+32.56926,744.6716 C 335.22359,744.84166 337.8814,744.9515 34\
+0.53834,745.07164 C 343.22564,745.19118 345.91516,745.25311 \
+348.60401,745.32616 C 351.31696,745.39874 354.03014,745.4615\
+8 356.7433,745.52498 C 359.44136,745.58758 362.13954,745.644\
+81 364.83774,745.70053 C 367.57326,745.73256 370.30893,745.7\
+4706 373.04456,745.76403 C 375.74646,745.78149 378.4484,745.\
+79575 381.15034,745.81059 C 383.82002,745.82382 386.48979,74\
+5.79548 389.15942,745.77758 C 391.8574,745.75953 394.55539,7\
+45.74216 397.25338,745.7246 C 399.91742,745.69135 402.58082,\
+745.63331 405.24395,745.55765 C 407.87129,745.50812 410.4949\
+8,745.36564 413.11893,745.23177 C 415.73845,745.09297 418.35\
+327,744.88722 420.96717,744.66993 C 423.51009,744.47596 426.\
+03684,744.14066 428.56376,743.80513 C 431.09356,743.45034 43\
+3.61486,743.042 436.1332,742.61487 C 438.63924,742.2061 441.\
+1236,741.68002 443.60982,741.16769 C 446.05806,740.633 448.5\
+0068,740.07365 450.9482,739.5357 C 453.40114,739.00595 455.8\
+4213,738.42516 458.28253,737.84124 C 460.69422,737.27756 463\
+.08874,736.64498 465.48757,736.02949 C 467.86795,735.42847 4\
+70.23683,734.78314 472.6091,734.1515 C 474.96773,733.51309 4\
+77.3144,732.83138 479.66421,732.16211 C 482.02051,731.48263 \
+484.35755,730.73855 486.69943,730.01148 C 488.98277,729.2684\
+1 491.25255,728.48635 493.5211,727.69967 C 495.74694,726.936\
+98 497.95792,726.13263 500.17079,725.33341 C 502.40879,724.5\
+2209 504.6282,723.66124 506.85109,722.80971 C 509.07688,721.\
+93485 511.30134,721.05647 513.52615,720.17909 C 515.67658,71\
+9.35468 517.79651,718.45525 519.92,717.56489 C 521.99762,716\
+.70152 524.05115,715.78147 526.11272,714.88069 C 528.11898,7\
+14.02833 530.1048,713.13028 532.09212,712.2351 C 534.05859,7\
+11.36195 536.02997,710.50006 538.00085,709.63697 C 539.90815\
+,708.77989 541.81101,707.91315 543.71275,707.04382 C 545.595\
+86,706.14929 547.48078,705.25855 549.36482,704.36601 C 550.2\
+541,703.91604 551.18227,703.55198 552.09107,703.14493 L 539.\
+24675,713.31982 C 538.34968,713.73375 537.44287,714.12701 53\
+6.55531,714.56169 C 534.67153,715.45623 532.79173,716.35952 \
+530.89422,717.22476 C 528.98861,718.0878 527.08548,718.95654\
+ 525.16954,719.79655 C 523.20122,720.65889 521.23139,721.517\
+91 519.27311,722.40296 C 517.28095,723.28623 515.28912,724.1\
+7001 513.28789,725.03273 C 511.22562,725.93162 509.1655,726.\
+83555 507.08618,727.6946 C 504.95435,728.56704 502.82537,729\
+.44643 500.67673,730.27721 C 498.45095,731.151 496.22608,732\
+.02716 493.99544,732.8885 C 491.76535,733.73663 489.53765,73\
+4.59119 487.29042,735.39333 C 485.07262,736.18412 482.85606,\
+736.9783 480.62694,737.73693 C 478.35074,738.51017 476.07912\
+,739.2981 473.7808,740.00435 C 471.43416,740.72754 469.09091\
+,741.46253 466.72735,742.12936 C 464.37161,742.79347 462.017\
+78,743.46469 459.65348,744.09791 C 457.27768,744.72254 454.9\
+0331,745.3528 452.52239,745.95783 C 450.11973,746.56848 447.\
+71825,747.18361 445.30364,747.74595 C 442.85614,748.31887 44\
+0.40672,748.88318 437.95004,749.41578 C 435.50275,749.96341 \
+433.05776,750.52223 430.60157,751.02901 C 428.10469,751.5294\
+5 425.60682,752.02583 423.09172,752.42808 C 420.56033,752.83\
+41 418.02848,753.23913 415.4862,753.57247 C 412.94418,753.88\
+674 410.40025,754.18248 407.84474,754.36767 C 405.22137,754.\
+56722 402.5975,754.76255 399.96919,754.88716 C 397.33809,755\
+.01363 394.70672,755.12897 392.07288,755.18189 C 389.40449,7\
+55.24329 386.7359,755.29941 384.06678,755.31801 C 381.36875,\
+755.33501 378.67073,755.35242 375.97272,755.37191 C 373.2990\
+3,755.38931 370.62523,755.41374 367.95151,755.38874 C 365.25\
+018,755.37285 362.54886,755.35643 359.84754,755.339 C 357.10\
+766,755.31917 354.36761,755.30541 351.62803,755.2566 C 348.9\
+2819,755.2002 346.22832,755.14489 343.52869,755.07854 C 340.\
+81464,755.01316 338.1006,754.94719 335.38672,754.87448 C 332\
+.69076,754.79861 329.99438,754.7288 327.30034,754.59865 C 32\
+4.63702,754.47443 321.97325,754.355 319.3131,754.17258 C 316\
+.64644,753.99677 313.97981,753.81979 311.31469,753.62143 C 3\
+08.64815,753.42194 305.98167,753.22127 303.31717,752.99564 C\
+ 300.61972,752.76816 297.92242,752.539 295.22668,752.29197 C\
+ 292.54232,752.05594 289.85729,751.82776 287.17355,751.58489\
+ C 284.48325,751.34013 281.79236,751.10214 279.10203,750.857\
+82 C 276.32458,750.61156 273.54785,750.3567 270.76879,750.12\
+897 C 267.95809,749.88986 265.14741,749.65067 262.3352,749.4\
+2984 C 259.48229,749.192 256.62979,748.94948 253.77775,748.7\
+0157 C 250.92829,748.46986 248.07881,748.23864 245.22702,748\
+.03704 C 242.40911,747.83606 239.59086,747.63932 236.77071,7\
+47.47191 C 234.09337,747.30158 231.41656,747.12239 228.73827\
+,746.96768 C 226.269,746.82962 223.79932,746.69923 221.33017\
+,746.55878 C 219.12742,746.44441 216.92494,746.32277 214.721\
+13,746.22959 C 212.81711,746.14391 210.91276,746.06422 209.0\
+1003,745.95189 C 207.37594,745.85328 205.74134,745.76175 204\
+.10919,745.63339 C 202.78951,745.52596 201.47005,745.4154 20\
+0.14929,745.32195 C 199.07382,745.24115 197.99943,745.14624 \
+196.92282,745.0813 C 196.13428,745.02941 195.34766,744.93008\
+ 194.55682,744.92561 C 194.04688,744.97798 193.52122,744.934\
+4 193.02027,745.08341 L 206.26655,735.18853 z \" />\012 </g>\012</\
+svg>\012"
+### end
diff --git a/olpcgames/eventwrap.py b/olpcgames/eventwrap.py
index c9e9752..92fbabb 100644
--- a/olpcgames/eventwrap.py
+++ b/olpcgames/eventwrap.py
@@ -3,6 +3,11 @@
Provides methods which will be substituted into Pygame in order to
provide the synthetic events that we will feed into the Pygame queue.
These methods are registered by the "install" method.
+
+Extension:
+
+ last_event_time() -- returns period since the last event was produced
+ in seconds. This can be used to create "pausing" effects for games.
"""
import pygame
import gtk
@@ -10,12 +15,18 @@ import Queue
import thread
import logging
-log = logging.getLogger( 'eventwrap' )
+log = logging.getLogger( 'olpcgames.eventwrap' )
# This module reuses Pygame's Event, but
# reimplements the event queue.
from pygame.event import Event, event_name, pump as pygame_pump, get as pygame_get
+class Event(object):
+ """Mock pygame events"""
+ def __init__(self, type, **named):
+ self.type = type
+ self.__dict__.update( named )
+
#print "Initializing own event.py"
# Install myself on top of pygame.event
@@ -62,22 +73,49 @@ def get():
if pygameEvents:
log.info( 'Raw Pygame events: %s', pygameEvents)
eventlist.extend( pygameEvents )
-
+ if eventlist:
+ _set_last_event_time()
return eventlist
+_LAST_EVENT_TIME = 0
+
+def _set_last_event_time( time=None ):
+ """Set this as the last event time"""
+ global _LAST_EVENT_TIME
+ if time is None:
+ time = pygame.time.get_ticks()
+ _LAST_EVENT_TIME = time
+ return time
+
+def last_event_time( ):
+ """Return the last event type for pausing operations in seconds"""
+ global _LAST_EVENT_TIME
+ return (pygame.time.get_ticks() - _LAST_EVENT_TIME)/1000.
+
def poll():
"""Get the next pending event if exists. Otherwise, return pygame.NOEVENT."""
pump()
try:
- return g_events.get(block=False)
+ result = g_events.get(block=False)
+ _set_last_event_time()
+ return result
except Queue.Empty:
return Event(pygame.NOEVENT)
-def wait():
- """Get the next pending event, waiting if none."""
+def wait( timeout = None):
+ """Get the next pending event, wait up to timeout if none
+
+ timeout -- if present, only wait up to timeout seconds, if we
+ do not find an event before then, return None
+ """
pump()
- return g_events.get(block=True)
+ try:
+ result = g_events.get(block=True, timeout=timeout)
+ _set_last_event_time()
+ return result
+ except Queue.Empty, err:
+ return None
def peek(types=None):
"""True if there is any pending event. (Unlike pygame, there's no option to
diff --git a/olpcgames/gtkEvent.py b/olpcgames/gtkEvent.py
index 0583a7d..ce4f9eb 100644
--- a/olpcgames/gtkEvent.py
+++ b/olpcgames/gtkEvent.py
@@ -4,16 +4,13 @@ pygtk.require('2.0')
import gtk
import gobject
import pygame
-import pygame.event as Pevent
-#PCevent = Pevent
-from olpcgames import eventwrap as PCevent
+from olpcgames import eventwrap
import logging
-log = logging.getLogger( 'gtkevent' )
-log.setLevel( logging.DEBUG )
+log = logging.getLogger( 'olpcgames.gtkevent' )
+#log.setLevel( logging.DEBUG )
-class MockEvent(object):
- """Used to inject key-repeat events."""
-
+class _MockEvent(object):
+ """Used to inject key-repeat events on the gtk side."""
def __init__(self, keyval):
self.keyval = keyval
@@ -101,7 +98,13 @@ class Translator(object):
self.__tick_id = None
#print "translator initialized"
-
+ mainwindow.connect( 'expose-event', self.do_expose_event )
+ def do_expose_event(self, event, widget):
+ """Handle exposure event (trigger redraw by gst)"""
+ log.info( 'Expose event: %s', event )
+ from olpcgames import eventwrap
+ eventwrap.post( eventwrap.Event( eventwrap.pygame.VIDEOEXPOSE ))
+ return True
def hook_pygame(self):
"""Hook the various Pygame features so that we implement the event APIs"""
# Pygame should be initialized. Hijack their key and mouse methods
@@ -114,7 +117,7 @@ class Translator(object):
def _quit(self, data=None):
self.__stopped = True
- PCevent.post(Pevent.Event(pygame.QUIT))
+ eventwrap.post(eventwrap.Event(pygame.QUIT))
def _keydown(self, widget, event):
key = event.keyval
@@ -173,7 +176,8 @@ class Translator(object):
ukey = unichr(gtk.gdk.keyval_to_unicode(event.keyval))
if ukey == '\000':
ukey = ''
- evt = Pevent.Event(type, key=keycode, unicode=ukey, mod=mod)
+ evt = eventwrap.Event(type, key=keycode, unicode=ukey, mod=mod)
+ assert evt.key, evt
self._post(evt)
return True
@@ -195,7 +199,7 @@ class Translator(object):
def _mouseevent(self, widget, event, type):
- evt = Pevent.Event(type,
+ evt = eventwrap.Event(type,
button=event.button,
pos=(event.x, event.y))
self._post(evt)
@@ -222,7 +226,7 @@ class Translator(object):
state & gtk.gdk.BUTTON3_MASK and 1 or 0,
]
- evt = Pevent.Event(pygame.MOUSEMOTION,
+ evt = eventwrap.Event(pygame.MOUSEMOTION,
pos=self.__mouse_pos,
rel=rel,
buttons=self.__button_state)
@@ -239,7 +243,7 @@ class Translator(object):
self.__held_time_left[key] -= delta
if self.__held_time_left[key] <= 0:
self.__held_time_left[key] = self.__repeat[1]
- self._keyevent(None, MockEvent(key), pygame.KEYDOWN)
+ self._keyevent(None, _MockEvent(key), pygame.KEYDOWN)
return True
@@ -257,7 +261,7 @@ class Translator(object):
def _post(self, evt):
try:
- PCevent.post(evt)
+ eventwrap.post(evt)
except pygame.error, e:
if str(e) == 'Event queue full':
print "Event queue full!"
diff --git a/olpcgames/pangofont.py b/olpcgames/pangofont.py
index a72550d..81a2d7c 100644
--- a/olpcgames/pangofont.py
+++ b/olpcgames/pangofont.py
@@ -15,8 +15,9 @@ import pygame.rect, pygame.image
import gtk
import struct
from pygame import surface
+from olpcgames import _cairoimage
-log = logging.getLogger( 'pangofont' )
+log = logging.getLogger( 'olpcgames.pangofont' )
#log.setLevel( logging.DEBUG )
# Install myself on top of pygame.font
@@ -49,7 +50,7 @@ class PangoFont(object):
STYLE_NORMAL = pango.STYLE_NORMAL
STYLE_ITALIC = pango.STYLE_ITALIC
STYLE_OBLIQUE = pango.STYLE_OBLIQUE
- def __init__(self, family=None, size=None, bold=False, italic=False, fd=None):
+ def __init__(self, family=None, size=None, bold=False, italic=False, underline=False, fd=None):
"""If you know what pango.FontDescription (fd) you want, pass it in as
'fd'. Otherwise, specify any number of family, size, bold, or italic,
and we will try to match something up for you."""
@@ -65,6 +66,7 @@ class PangoFont(object):
self.fd = fd
self.set_bold( bold )
self.set_italic( italic )
+ self.set_underline( underline )
def render(self, text, antialias=True, color=(255,255,255), background=None ):
"""Render the font onto a new Surface and return it.
@@ -84,6 +86,12 @@ class PangoFont(object):
# create layout
layout = pango.Layout(gtk.gdk.pango_context_get())
layout.set_font_description(self.fd)
+ if self.underline:
+ attrs = layout.get_attributes()
+ if not attrs:
+ attrs = pango.AttrList()
+ attrs.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, 0, 32767))
+ layout.set_attributes( attrs )
layout.set_text(text)
# determine pixel size
@@ -91,44 +99,23 @@ class PangoFont(object):
ink = pygame.rect.Rect(ink)
# Create a new Cairo ImageSurface
- csrf = cairo.ImageSurface(cairo.FORMAT_ARGB32, ink.w, ink.h)
- cctx = pangocairo.CairoContext(cairo.Context(csrf))
+ csrf,cctx = _cairoimage.newContext( ink.w, ink.h )
+ cctx = pangocairo.CairoContext(cctx)
# Mangle the colors on little-endian machines. The reason for this
# is that Cairo writes native-endian 32-bit ARGB values whereas
# Pygame expects endian-independent values in whatever format. So we
# tell our users not to expect transparency here (avoiding the A issue)
# and we swizzle all the colors around.
- big_endian = struct.pack( '=i', 1 ) == struct.pack( '>i', 1 )
- if hasattr(csrf,'get_data'):
- swap = True
- else:
- swap = False
- log.debug( 'big_endian: %s swap: %s', big_endian, swap )
- def mangle_color(color):
- """Mange a colour depending on endian-ness, and swap-necessity
-
- This implementation has only been tested on an AMD64
- machine with a get_data implementation (rather than
- a get_data_as_rgba implementation).
- """
- r,g,b = color[:3]
- if len(color) > 3:
- a = color[3]
- else:
- a = 255.0
- if swap and not big_endian:
- return map(_fixColorBase, (b,g,r,a) )
- return map(_fixColorBase, (r,g,b,a) )
# render onto it
if background is not None:
- background = mangle_color( background )
+ background = _cairoimage.mangle_color( background )
cctx.set_source_rgba(*background)
cctx.paint()
log.debug( 'incoming color: %s', color )
- color = mangle_color( color )
+ color = _cairoimage.mangle_color( color )
log.debug( ' translated color: %s', color )
cctx.new_path()
@@ -137,25 +124,7 @@ class PangoFont(object):
cctx.fill()
# Create and return a new Pygame Image derived from the Cairo Surface
- if big_endian:
- # You see, in big-endian-world, we can just use the RGB values
- format = "ARGB"
- else:
- # But with little endian, we've already swapped R and B in
- # mangle_color, so now just move the A
- format = "RGBA"
- if hasattr(csrf,'get_data'):
- data = csrf.get_data()
- else:
- # XXX little-endian here, check on a big-endian machine
- data = csrf.get_data_as_rgba()
- format = 'RGBA' # XXX wrong, what's with all the silly swapping!
- try:
- data = str(data)
- return pygame.image.fromstring(data, (ink.w,ink.h), format)
- except ValueError, err:
- err.args += (len(data), ink.w*ink.h*4,format )
- raise
+ return _cairoimage.asImage( csrf )
def set_bold( self, bold=True):
"""Set our font description's weight to "bold" or "normal"
@@ -193,6 +162,12 @@ class PangoFont(object):
def get_italic( self ):
"""Return whether we are currently italicised"""
return self.fd.get_style() == self.STYLE_ITALIC # what about oblique?
+
+ def set_underline( self, underline=True ):
+ """Set our current underlining properly"""
+ self.underline = underline
+ def get_underline( self ):
+ return self.underline
class SysFont(PangoFont):
"""Construct a PangoFont from a font description (name), size in pixels,
@@ -302,62 +277,3 @@ def stdcolor(color):
def _fixColorBase( v ):
"""Return a properly clamped colour in floating-point space"""
return max((0,min((v,255.0))))/255.0
-
-if __name__ == "__main__":
- # Simple testing code...
- logging.basicConfig()
- log.setLevel( logging.INFO )
- from pygame import image,display, event, sprite
- import pygame
- import pygame.event
- def main():
- display.init()
- maxX,maxY = display.list_modes()[0]
- screen = display.set_mode( (maxX/2, maxY/2 ) )
- background = pygame.Surface(screen.get_size())
- background = background.convert()
- background.fill((255, 255,255))
-
- screen.blit(background, (0, 0))
- display.flip()
-
- clock = pygame.time.Clock()
-
- font = PangoFont( size=30, family='monospace' )
- texts = [
- ( 'red', False,(255,0,0) , (255,255,255,0), (20,20) ),
- ( 'green',False,(0,255,0) , (20,80)),
- ( 'blue',False, (0,0,255) , (20,140)),
- ( 'blue-trans',False, (0,0,255,128) , (200,20)),
- ( 'cyan-trans',False, (0,255,255,128) , (200,80)),
- ]
- def rerender():
- return [
- (font.render( *(t[:-1]) ),t[-1]) for t in texts
- ]
- images = rerender()
- running = True
- while running:
- clock.tick( 60 )
-
- for event in pygame.event.get():
- log.debug( 'event: %s', event )
- if event.type == pygame.QUIT:
- running = False
- elif event.type == pygame.KEYDOWN:
- if event.key == pygame.K_b:
- w = font.get_bold()
- font.set_bold( not font.get_bold())
- log.info( 'bold weight: %s %s->%s', font.get_weight(), w, font.get_bold())
- images = rerender()
- elif event.key == pygame.K_i:
- font.set_italic( not font.get_italic())
- images = rerender()
- elif event.key == pygame.K_ESCAPE:
- running = False
- screen.fill( (255,255,255))
- for img,pos in images:
- screen.blit( img, pos )
- display.flip()
- main()
-
diff --git a/olpcgames/pausescreen.py b/olpcgames/pausescreen.py
new file mode 100644
index 0000000..1c1d6c3
--- /dev/null
+++ b/olpcgames/pausescreen.py
@@ -0,0 +1,89 @@
+"""Display a "paused" version of the currently-displayed screen
+
+This code is largely cribbed from the Pippy activity's display code,
+but we try to be a little more generally usable than they are, as
+we have more involved activities using the code.
+
+We use svgsprite to render a graphic which is stored in the
+olpcgames data directory over a dimmed version of the current
+screen contents.
+"""
+import logging
+log = logging.getLogger( 'olpcgames.pausescreen' )
+import pygame
+from pygame import sprite
+
+def get_events( sleep_timeout = 10, pause=None, **args ):
+ """Retrieve the set of pending events or sleep
+
+ sleep_timeout -- dormant period before we invoke pause_screen
+ pause -- callable to produce visual notification of pausing, normally
+ by taking the current screen and modifying it in some way. Defaults
+ to pauseScreen in this module. If you return nothing from this
+ function then no restoration or display-flipping will occur
+ *args -- if present, passed to pause to configuration operation (e.g.
+ to specify a different overlaySVG file)
+
+ returns set of pending events (potentially empty)
+ """
+ if not pause:
+ pause = pauseScreen
+ events = pygame.event.get( )
+ if not events:
+ log.info( 'No events in queue' )
+ old_screen = None
+ if hasattr(pygame.event, 'last_event_time') and pygame.event.last_event_time() > sleep_timeout:
+ # we've been waiting long enough, go to sleep visually
+ log.warn( 'Pausing activity after %s with function %s', sleep_timeout, pause )
+ old_screen = pause( )
+ if old_screen:
+ pygame.display.flip()
+ # now we wait until there *are* some events (efficiently)
+ # and retrieve any extra events that are waiting...
+ events = [ pygame.event.wait() ] + pygame.event.get()
+ log.warn( 'Activity restarted')
+ if old_screen:
+ restoreScreen( old_screen )
+ else:
+ log.info( 'Not running under OLPCGames' )
+ return events
+
+def pauseScreen( overlaySVG=None ):
+ """Display a "Paused" screen and suspend
+
+ This default implementation will not do anything to shut down your
+ simulation or other code running in other threads. It will merely block
+ this thread (the pygame thread) until an event shows up in the
+ eventwrap queue.
+
+ Returns a surface to pass to restoreScreen to continue...
+ """
+ from olpcgames import svgsprite
+ if not overlaySVG:
+ from olpcgames.data import sleeping_svg
+ overlaySVG = sleeping_svg.data
+ screen = pygame.display.get_surface()
+ old_screen = screen.copy() # save this for later.
+ pause_sprite = svgsprite.SVGSprite(
+ overlaySVG,
+ )
+ pause_sprite.rect.center = screen.get_rect().center
+ group = sprite.RenderUpdates( )
+ group.add( pause_sprite )
+
+ # dim the screen and display the 'paused' message in the center.
+ BLACK = (0,0,0)
+ WHITE = (255,255,255)
+ dimmed = screen.copy()
+ dimmed.set_alpha(128)
+ screen.fill(BLACK)
+ screen.blit(dimmed, (0,0))
+
+ group.draw( screen )
+ return old_screen
+
+def restoreScreen( old_screen ):
+ """Restore the original screen and return"""
+ screen = pygame.display.get_surface()
+ screen.blit(old_screen, (0,0))
+ return old_screen
diff --git a/olpcgames/svgsprite.py b/olpcgames/svgsprite.py
new file mode 100644
index 0000000..2c53178
--- /dev/null
+++ b/olpcgames/svgsprite.py
@@ -0,0 +1,69 @@
+"""RSVG/Cairo-based rendering of SVG into Pygame Images"""
+from pygame import sprite
+from olpcgames import _cairoimage
+import cairo, rsvg
+
+class SVGSprite( sprite.Sprite ):
+ """Sprite class which renders SVG source-code as a Pygame image"""
+ rect = image = None
+ resolution = None
+ def __init__(
+ self, svg=None, size=None, *args
+ ):
+ """Initialise the svg sprite
+
+ svg -- svg source text (i.e. content of an svg file)
+ size -- optional, to constrain size, (width,height), leaving one
+ as None or 0 causes proportional scaling, leaving both
+ as None or 0 causes natural scaling (screen resolution)
+ args -- if present, groups to which to automatically add
+ """
+ self.size = size
+ super( SVGSprite, self ).__init__( *args )
+ if svg:
+ self.setSVG( svg )
+ def setSVG( self, svg ):
+ """Set our SVG source"""
+ self.svg = svg
+ # XXX could delay this until actually asked to display...
+ if self.size:
+ width,height = self.size
+ else:
+ width,height = None,None
+ self.image = self._render( width,height )
+ rect = self.image.get_rect()
+ if self.rect:
+ rect.move( self.rect ) # should let something higher-level do that...
+ self.rect = rect
+
+ def _render( self, width, height ):
+ """Render our SVG to a Pygame image"""
+ handle = rsvg.Handle( data = self.svg )
+ originalSize = (width,height)
+ scale = 1.0
+ hw,hh = handle.get_dimension_data()[:2]
+ if hw and hh:
+ if not width:
+ if not height:
+ width,height = hw,hh
+ else:
+ scale = float(height)/hh
+ width = hh/float(hw) * height
+ elif not height:
+ scale = float(width)/hw
+ height = hw/float(hh) * width
+ else:
+ # scale only, only rendering as large as it is...
+ if width/height > hw/hh:
+ # want it taller than it is...
+ width = hh/float(hw) * height
+ else:
+ height = hw/float(hh) * width
+ scale = float(height)/hh
+
+ csrf, ctx = _cairoimage.newContext( int(width), int(height) )
+ ctx.scale( scale, scale )
+ handle.render_cairo( ctx )
+ return _cairoimage.asImage( csrf )
+ return None
+
diff --git a/olpcgames/video.py b/olpcgames/video.py
index 2c3a842..0cf9ac9 100644
--- a/olpcgames/video.py
+++ b/olpcgames/video.py
@@ -1,8 +1,11 @@
"""Video widget for displaying a gstreamer pipe"""
import logging
log = logging.getLogger( 'olpcgames.video' )
+#log.setLevel( logging.INFO )
import os
import signal
+import pygame
+import olpcgames
import pygtk
pygtk.require('2.0')
@@ -10,15 +13,47 @@ import gtk
import gst
class VideoWidget(gtk.DrawingArea):
- """A custom widget to render GStreamer video."""
+ """Widget to render GStreamer video over our Pygame Canvas
- def __init__(self, x=160, y=120):
+ The VideoWidget is a simple GTK window which is
+ held by the PygameCanvas, just as is the Pygame
+ window we normally use. As such this approach
+ *cannot* work without the GTK wrapper.
+
+ It *should* be possible to use raw X11 operations
+ to create a child window of the Pygame/SDL window
+ and use that for the same purpose, but that would
+ require some pretty low-level ctypes hacking.
+
+ Attributes of Note:
+
+ rect -- Pygame rectangle which tells us where to
+ display ourselves, setting the rect changes the
+ position and size of the window.
+ """
+ _imagesink = None
+ _renderedRect = None
+ def __init__(self, rect=None, force_aspect_ratio=True):
super(VideoWidget, self).__init__()
- self._imagesink = None
self.unset_flags(gtk.DOUBLE_BUFFERED)
- self.set_size_request(x,y)
+ if rect is None:
+ rect = pygame.Rect( (0,0), (160,120))
+ self.rect = rect
+ self.force_aspect_ratio = force_aspect_ratio
+ self.set_size_request(rect.width,rect.height)
+ olpcgames.WIDGET.put( self, rect.left,rect.top)
+ self._renderedRect = rect
+ self.show()
+
+ def set_rect( self, rect ):
+ """Set our rectangle (area of the screen)"""
+ log.debug( 'Set rectangle: %s', rect )
+ self.set_size_request(rect.width,rect.height)
+ olpcgames.WIDGET.move( self, rect.left,rect.top)
+ self.rect = rect
def do_expose_event(self, event):
+ """Handle exposure event (trigger redraw by gst)"""
if self._imagesink:
self._imagesink.expose()
return False
@@ -26,14 +61,36 @@ class VideoWidget(gtk.DrawingArea):
return True
def set_sink(self, sink):
+ """Set our window-sink for output"""
assert self.window.xid
self._imagesink = sink
self._imagesink.set_xwindow_id(self.window.xid)
+ self._imagesink.set_property('force-aspect-ratio', self.force_aspect_ratio)
+
+class PygameWidget( object ):
+ """Render "full-screen" video to the entire Pygame screen
+
+ Not particularly useful unless this happens to be exactly what you need.
+ """
+ def __init__( self ):
+ try:
+ window_id = pygame.display.get_wm_info()['window']
+ except KeyError, err: # pygame-ctypes...
+ window_id = int(os.environ['SDL_WINDOWID'])
+ self.window_id = window_id
+ self._imagesink = None
+ def set_sink( self, sink ):
+ """Set up our gst sink"""
+ log.info( 'Setting sink: %s', sink )
+ self._imagesink = sink
+ sink.set_xwindow_id( self.window_id )
#pipe_desc = 'v4l2src ! video/x-raw-yuv,width=160,height=120 ! ffmpegcolorspace ! xvimagesink'
-pipe_desc = 'v4l2src ! ffmpegcolorspace ! video/x-raw-yuv ! xvimagesink'
class Player(object):
- def __init__(self, videowidget):
+ pipe_desc = 'v4l2src ! ffmpegcolorspace ! video/x-raw-yuv ! xvimagesink'
+ test_pipe_desc = 'videotestsrc ! ffmpegcolorspace ! video/x-raw-yuv ! xvimagesink'
+ _synchronized = False
+ def __init__(self, videowidget, pipe_desc=pipe_desc):
self._playing = False
self._videowidget = videowidget
@@ -46,26 +103,68 @@ class Player(object):
bus.connect('message', self.on_message)
def play(self):
+ log.info( 'Play' )
if self._playing == False:
self._pipeline.set_state(gst.STATE_PLAYING)
self._playing = True
def pause(self):
+ log.info( 'Pause' )
if self._playing == True:
- self._pipeline.set_state(gst.STATE_PAUSED)
+ if self._synchronized:
+ log.debug( ' pause already sync\'d' )
+ self._pipeline.set_state(gst.STATE_PAUSED)
self._playing = False
+ def stop( self ):
+ """Stop all playback"""
+ self._pipeline.set_state( gst.STATE_NULL )
def on_sync_message(self, bus, message):
+ log.info( 'Sync: %s', message )
if message.structure is None:
return
if message.structure.get_name() == 'prepare-xwindow-id':
+ self._synchronized = True
self._videowidget.set_sink(message.src)
def on_message(self, bus, message):
+ log.info( 'Message: %s', message )
t = message.type
if t == gst.MESSAGE_ERROR:
err, debug = message.parse_error()
- log.debug("Video error: (%s) %s" ,err, debug)
+ log.warn("Video error: (%s) %s" ,err, debug)
self._playing = False
- gtk.main_quit()
+if __name__ == "__main__":
+ # Simple testing code...
+ logging.basicConfig()
+ log.setLevel( logging.DEBUG )
+ from pygame import image,display, event
+ import pygame
+ def main():
+ display.init()
+ maxX,maxY = display.list_modes()[0]
+ screen = display.set_mode( (maxX/3, maxY/3 ) )
+
+ display.flip()
+
+ pgw = PygameWidget( )
+ p = Player( pgw )
+ p.play()
+
+ clock = pygame.time.Clock()
+
+ running = True
+ while running:
+ clock.tick( 60 )
+ for evt in [pygame.event.wait()] + pygame.event.get():
+ if evt.type == pygame.KEYDOWN:
+ if p._playing:
+ p.pause()
+ else:
+ p.play()
+ elif evt.type == pygame.QUIT:
+ p.stop()
+ running = False
+ #display.flip()
+ main()