Changeset 34:3a90641eba91 in xplra


Ignore:
Timestamp:
02/09/13 12:29:31 (12 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

Implemented the multi-dataref getter in Python

Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • src/client/python/xplra.py

    r32 r34  
    127127        """Determine if we are connected to the simulator."""
    128128        return self._stream is not None
     129
     130    def createMultiGetter(self):
     131        """Create a new multi-dataref getter for this X-Plane object."""
     132        return MultiGetter(self)
    129133
    130134    def getInt(self, name):
     
    354358
    355359#-------------------------------------------------------------------------------
     360
     361class MultiBuffer(object):
     362    """Buffer for querying or setting multi-dataref values."""
     363    @staticmethod
     364    def _getDefault(type, length):
     365        """Get the default value for the given type."""
     366        if type==TYPE_INT:
     367            return 0
     368        elif type==TYPE_FLOAT:
     369            return float(0.0)
     370        elif type==TYPE_DOUBLE:
     371            return 0.0
     372        elif length<=0:
     373            return []
     374        elif type==TYPE_FLOAT_ARRAY:
     375            return [float(0.0)] * length
     376        elif type==TYPE_INT_ARRAY or type==TYPE_BYTE_ARRAY:
     377            return [0] * length
     378
     379    def __init__(self, xplane, registerCommand, unregisterCommand):
     380        """Construct the buffer for the given XPlane instance and with the
     381        given register/unregister command values."""
     382        self._xplane = xplane
     383        self._registerCommand = registerCommand
     384        self._unregisterCommand = unregisterCommand
     385
     386        self._dataRefs = []
     387        self._values = None
     388
     389        self._registeredID = None
     390
     391    def addInt(self, name):
     392        """Add an integer to the buffer with the given name
     393
     394        Returns an ID (or index) of the dataref."""
     395        return self._add(name, TYPE_INT)
     396
     397    def addFloat(self, name):
     398        """Add a float to the buffer with the given name
     399
     400        Returns an ID (or index) of the dataref."""
     401        return self._add(name, TYPE_FLOAT)
     402
     403    def addDouble(self, name):
     404        """Add a double to the buffer with the given name
     405
     406        Returns an ID (or index) of the dataref."""
     407        return self._add(name, TYPE_DOUBLE)
     408
     409    def addFloatArray(self, name, length = -1, offset = 0):
     410        """Add a floating point array to the buffer with the given name.
     411
     412        Returns an ID (or index) of the dataref."""
     413        return self._add(name, TYPE_FLOAT_ARRAY, length, offset)
     414
     415    def addIntArray(self, name, length = -1, offset = 0):
     416        """Add an integer array to the buffer with the given name.
     417
     418        Returns an ID (or index) of the dataref."""
     419        return self._add(name, TYPE_INT_ARRAY, length, offset)
     420
     421    def addByteArray(self, name, length = -1, offset = 0):
     422        """Add a byte array to the buffer with the given name.
     423
     424        Returns an ID (or index) of the dataref."""
     425        return self._add(name, TYPE_BYTE_ARRAY, length, offset)
     426
     427    def finalize(self):
     428        """Finalize the buffer, if not finalized yet.
     429
     430        It initializes the array of values with some defaults.
     431
     432        Returns whether there is any data in the buffer."""
     433        if self._values is None:
     434            self._values = [self._getDefault(type, length)
     435                            for (_, type, length, _) in self._dataRefs]
     436        return self._values!=[]
     437
     438    def register(self):
     439        """Register the buffer in X-Plane."""
     440        if self.finalize() and self._registeredID is None:
     441            self._writeSpec(self._registerCommand)
     442            self._registeredID = self._xplane._readU32()
     443
     444    def unregister(self):
     445        """Unregister the buffer from X-Plane."""
     446        if self._registeredID is not None:
     447            self._xplane._writeU8(self._unregisterCommand)
     448            self._xplane._writeU32(self._registeredID)
     449            self._xplane._flush()
     450            self._xplane._checkResult()
     451            self._registeredID = None
     452
     453    def execute(self):
     454        """Perform the querying or the setting of the values.
     455
     456        It first checks if the buffer is finalized. If not, it will be
     457        finalized. However, if it is not finalized but also registered, it will
     458        first be unregistered and the re-registered after finalizing."""
     459        if self._values is None and self._registeredID is not None:
     460            self.unregister()
     461            self.register()
     462        else:
     463            self.finalize()
     464
     465        if self._registeredID is None:
     466            self._executeUnregistered()
     467        else:
     468            self._executeRegistered()
     469
     470    def getString(self, id):
     471        """Get the value of the dataref with the given ID as a string.
     472
     473        The dataref should be of type byte array."""
     474        if self._dataRefs[id][1]!=TYPE_BYTE_ARRAY:
     475            raise TypeError("xplra.MultiBuffer.getString: only byte arrays can be converted to strings")
     476        if self._values is None:
     477            self.finalize()
     478        s = ""
     479        for c in self._values[id]:
     480            if c==0: break
     481            s += chr(c)
     482        return s
     483
     484    def _add(self, name, type, length = None, offset = None):
     485        """Add a scalar to the buffer with the given name and type"""
     486        index = len(self._dataRefs)
     487        self._values = None
     488        self._dataRefs.append( (name, type, length, offset) )
     489        return index
     490
     491    def _writeSpec(self, command):
     492        """Write the specification preceded by the given command and check for
     493        the result.
     494
     495        The specification is basically the list of the datarefs."""
     496        self._xplane._writeU8(command)
     497        self._xplane._writeU32(len(self._dataRefs))
     498
     499        for (name, type, length, offset) in self._dataRefs:
     500            self._xplane._writeString(name)
     501            self._xplane._writeU8(type)
     502            if length is not None and offset is not None:
     503                self._xplane._writeS32(length)
     504                self._xplane._writeS32(offset)
     505
     506        self._xplane._flush()
     507        self._xplane._checkResult()
     508
     509    def __len__(self):
     510        """Get the number of value items in the buffer."""
     511        if self._values is None:
     512            self.finalize()
     513        return len(self._values)
     514
     515    def __getitem__(self, id):
     516        """Get the item with the given ID."""
     517        if self._values is None:
     518            self.finalize()
     519        return self._values[id]
     520
     521    def __setitem__(self, id, value):
     522        """Set the item with the given ID."""
     523        if self._values is None:
     524            self.finalize()
     525        type = self._dataRefs[id][1]
     526        if type==TYPE_INT:
     527            self._values[id] = int(value)
     528        elif type==TYPE_FLOAT:
     529            self._values[id] = float(value)
     530        elif type==TYPE_DOUBLE:
     531            self._values[id] = double(value)
     532        elif type==TYPE_FLOAT_ARRAY:
     533            self._values[id] = [float(x) for x in value]
     534        elif type==TYPE_INT_ARRAY:
     535            self._values[id] = [int(x) for x in value]
     536        elif type==TYPE_BYTE_ARRAY:
     537            if instanceof(value, str):
     538                self._values[id] = [ord(x) for x in value]
     539            else:
     540                self._values[id] = [int(x) for x in value]
     541
     542    def __iter__(self):
     543        """Get an iterator over the values of this buffer."""
     544        if self._values is None:
     545            self.finalize()
     546        return iter(self._values)
     547
     548
     549#-------------------------------------------------------------------------------
     550
     551class MultiGetter(MultiBuffer):
     552    """Multi-dataref buffer for querying."""
     553    def __init__(self, xplane):
     554        """Construct the getter."""
     555        super(MultiGetter, self).__init__(xplane,
     556                                          COMMAND_REGISTER_GET_MULTI,
     557                                          COMMAND_UNREGISTER_GET_MULTI)
     558
     559    def _executeRegistered(self):
     560        """Execute the query if the buffer is registered."""
     561        self._xplane._writeU8(COMMAND_EXECUTE_GET_MULTI)
     562        self._xplane._writeU32(self._registeredID)
     563        self._xplane._flush()
     564
     565        self._xplane._checkResult()
     566
     567        self._readValues()
     568
     569    def _executeUnregistered(self):
     570        """Execute the query if the buffer is not registered."""
     571        self._writeSpec(COMMAND_GET_MULTI)
     572        self._readValues()
     573
     574    def _readValues(self):
     575        """Read the values into the values array."""
     576        for i in range(0, len(self._dataRefs)):
     577            self._values[i] = self._xplane._readValue(self._dataRefs[i][1])
     578
     579#-------------------------------------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.