1import logging; logger = logging.getLogger("morse." + __name__)
2import datetime
3from ctypes import *
4from morse.middleware import AbstractDatastream
5from morse.core.datastream import *
6
7try:
8    P = CDLL("libposterLib.so")
9except OSError:
10    import morse.core.blenderapi
11    if not morse.core.blenderapi.fake:
12        logger.error('Cannot find libposterLib.so : check your LD_LIBRARY_PATH')
13        raise
14
15
16class PosterNotFound(Exception):
17    def __init__(self, value):
18        self.value = value
19    def __str__(self):
20        return repr(self.value)
21
22class InvalidRead(Exception):
23    def __init__(self, value):
24        self.value = value
25    def __str__(self):
26        return repr(self.value)
27
28def poster_name(component_name, mw_data):
29    # Check if the name of the poster has been given in mw_data
30    poster_name = ''
31    if 'poster' in mw_data:
32        poster_name = mw_data['poster']
33    else:
34        # Compose the name of the poster, based on the parent and module names
35        poster_name = component_name
36
37    return poster_name
38
39class DummyPoster:
40    def __init__(self, name):
41        self.poster_id = c_void_p()
42        c_name = create_string_buffer(bytes(name, 'utf-8'))
43        P.posterCreate(c_name, 8, byref(self.poster_id))
44
45    def __del__(self):
46        P.posterDelete(self.poster_id)
47        self.poster_id = None
48
49class PocolibsDataStreamOutput(AbstractDatastream):
50
51    def initialize(self, kind):
52        self.poster_id = c_void_p()
53        o = kind()
54        self.name = poster_name(self.component_name, self.kwargs)
55        c_name = create_string_buffer(bytes(self.name, 'utf-8'))
56        logger.info("Create poster %s of size %d" % (self.name, sizeof(o)))
57        r = P.posterCreate(c_name, sizeof(o), byref(self.poster_id))
58        if r != 0:
59            P.posterFind(c_name, byref(self.poster_id))
60
61    def write(self, obj):
62        r = P.posterWrite(self.poster_id, 0, byref(obj), sizeof(obj))
63        if r != sizeof(obj):
64            raise "too bad : write failed"
65
66    def finalize(self):
67        logger.info("Releaase poster %s" % self.name)
68        P.posterDelete(self.poster_id)
69        self.poster_id = None
70
71class PocolibsDataStreamInput(AbstractDatastream):
72    def initialize(self, kind):
73        self.poster_id = c_void_p()
74        name = poster_name(self.component_name, self.kwargs)
75        delay = self.kwargs.get('delay', True)
76        self.name = name
77        self.c_name = create_string_buffer(bytes(name, 'utf-8'))
78
79        self.o = kind()
80        self.found = False
81        self._find()
82        if not self.found and not delay:
83            raise PosterNotFound(self.name)
84
85    def _find(self):
86        logger.debug("Searching to read %s" % self.name)
87        r = P.posterFind(self.c_name, byref(self.poster_id))
88        if r == 0:
89            self.found = True
90
91    def read(self):
92        if not self.found:
93            self._find()
94
95        if self.found:
96            r = P.posterRead(self.poster_id, 0, byref(self.o), sizeof(self.o))
97            if r != sizeof(self.o):
98                raise InvalidRead(self.name)
99            return self.o
100        else:
101            return None
102
103    def finalize(self):
104        if self.found:
105            P.posterForget(self.poster_id)
106
107class PocolibsDatastreamManager(DatastreamManager):
108    """ Handle communication between Blender and Pocolibs."""
109
110    def compute_date():
111        """ Compute the current time
112
113        ( we only require that the date
114        increases using a constant step so real time is ok)
115        """
116        t = datetime.datetime.now()
117        date = int(t.hour * 3600* 1000 + t.minute * 60 * 1000 +
118                t.second * 1000 + t.microsecond / 1000)
119
120        return date, t
121