Esempio n. 1
0
 def testIsTrue(self):
     self.failUnless(common.strToBool('True'))
     self.failUnless(common.strToBool('true'))
     self.failUnless(common.strToBool('1'))
     self.failUnless(common.strToBool('yes'))
     self.failIf(common.strToBool('False'))
     self.failIf(common.strToBool('false'))
     self.failIf(common.strToBool('0'))
     self.failIf(common.strToBool('no'))
     self.failIf(common.strToBool('I am a monkey'))
Esempio n. 2
0
 def testIsTrue(self):
     self.failUnless(common.strToBool('True'))
     self.failUnless(common.strToBool('true'))
     self.failUnless(common.strToBool('1'))
     self.failUnless(common.strToBool('yes'))
     self.failIf(common.strToBool('False'))
     self.failIf(common.strToBool('false'))
     self.failIf(common.strToBool('0'))
     self.failIf(common.strToBool('no'))
     self.failIf(common.strToBool('I am a monkey'))
Esempio n. 3
0
    def parseFeederports(self, node):
        """
        Returns a list of feeder ports to use (possibly empty),
        and whether or not to use random feeder ports.

        @rtype: (list, bool)
        """
        # returns a list of allowed port numbers
        # port := int
        # port-range := port "-" port
        # port-term := port | port-range
        # port-list := "" | port-term | port-term "," port-list
        # <feederports>port-list</feederports>
        random = False
        if node.hasAttribute('random'):
            random = common.strToBool(node.getAttribute('random'))
        ports = []
        if not node.firstChild:
            return (ports, random)
        terms = str(node.firstChild.nodeValue).split(',')
        for term in terms:
            if '-' in term:
                (lower, upper) = [int(x) for x in term.split('-')]
                for port in range(lower, upper+1):
                    if port not in ports:
                        ports.append(port)
            else:
                port = int(term)
                if port not in ports:
                    ports.append(port)
        return (ports, random)
Esempio n. 4
0
    def _parseNode(self, node):

        recordingChunk = {}
        try:
            for name in self.ELEMENTS:
                # Raises and IndexError if the element is missing
                element = node.getElementsByTagName(name)[0]
                # Get all the child nodes for the element,
                # theoretically only one containing the value we need
                childNodes = [x for x in element.childNodes\
                    if x.nodeType == Node.TEXT_NODE]
                if  name in ['start', 'stop']:
                    # the time must be represented in iso 8601 format,
                    # with a second-precision and in utc (,000+0000) and
                    # we transform it in a unix timestamp
                    recordingChunk[name] = time.mktime(time.strptime(
                        str(childNodes[0].nodeValue),
                        '%Y-%m-%dT%H:%M:%S,000+0000'))
                elif  name in ['record', 'complete']:
                    recordingChunk[name] = strToBool(childNodes[0].nodeValue)
                else:
                    recordingChunk[name] = childNodes[0].nodeValue
        except IndexError:
            self.warning("The mandatory element '%s' is missing.", name)
            return None
        except ValueError:
            self.warning("Could not parse element '%s'.", name)
            return None
        return recordingChunk
Esempio n. 5
0
    def parseFeederports(self, node):
        """
        Returns a list of feeder ports to use (possibly empty),
        and whether or not to use random feeder ports.

        @rtype: (list, bool)
        """
        # returns a list of allowed port numbers
        # port := int
        # port-range := port "-" port
        # port-term := port | port-range
        # port-list := "" | port-term | port-term "," port-list
        # <feederports>port-list</feederports>
        random = False
        if node.hasAttribute('random'):
            random = common.strToBool(node.getAttribute('random'))
        ports = []
        if not node.firstChild:
            return (ports, random)
        terms = str(node.firstChild.nodeValue).split(',')
        for term in terms:
            if '-' in term:
                (lower, upper) = [int(x) for x in term.split('-')]
                if lower > upper:
                    raise ConfigError("<feederports> has an invalid range: "
                            "%s > %s " % (lower, upper))
                for port in range(lower, upper+1):
                    if port not in ports:
                        ports.append(port)
            else:
                port = int(term)
                if port not in ports:
                    ports.append(port)
        return (ports, random)
Esempio n. 6
0
 def boolean(v):
     if isinstance(v, bool):
         return v
     return common.strToBool(v)
Esempio n. 7
0
class Index(log.Loggable):
    '''
    Creates an index of keyframes for a file, than can be used later for
    seeking in non indexed formats or whithout parsing the headers.

    The format of the index is very similar to the AVI Index, but it can also
    include information about the real time of each entry in UNIX time.
    (see 'man aviindex')

    If the index is for an indexed format, the offset of the first entry will
    not start from 0. This offset is the size of the headers.  '''

    # CHK:      Chunk number starting from 0
    # POS:      Absolute byte position of the chunk in the file
    # LEN:      Length in bytes of the chunk
    # TS:       Timestamp of the chunk (ns)
    # DUR:      Duration of the chunk (ns)
    # KF:       Whether it starts with a keyframe or not
    # TDT:      Time and date using a UNIX timestamp (s)
    # TDUR:     Duration of the chunk in UNIX time (s)
    INDEX_HEADER = "FLUIDX1 #Flumotion\n"
    INDEX_KEYS = ['CHK', 'POS', 'LEN', 'TS', 'DUR', 'KF', 'TDT', 'TDUR']
    INDEX_EXTENSION = 'index'

    logCategory = "index"

    def __init__(self, component=None, location=None):
        self._index = []
        self._headers_size = 0
        self.comp = component
        self.location = location

    ### Public methods ###

    def updateStart(self, timestamp):
        '''
        Remove entries in the index older than this timestamp
        '''
        self.debug("Removing entries older than %s", timestamp)
        self._index = self._filter_index(timestamp) or []

    def addEntry(self, offset, timestamp, keyframe, tdt=0, writeIndex=True):
        '''
        Add a new entry to the the index and writes it to disk if
        writeIndex is True
        '''
        if len(self._index) > 0:
            # Check that new entries have increasing timestamp, offset and tdt
            if not self._checkEntriesContinuity(offset, timestamp, tdt):
                return
            # And update the length and duration of the last entry
            self._updateLastEntry(offset, timestamp, tdt)
            # Then write the last updated index entry to disk
            if writeIndex and self.location:
                f = _openFile(self, self.comp, self.location, 'a+')
                if not f:
                    return
                off = self._index[0]['offset'] - self._headers_size
                self._write_index_entry(f, self._index[-1], off,
                                        len(self._index) - 1)

        self._index.append({
            'offset': offset,
            'length': -1,
            'timestamp': timestamp,
            'duration': -1,
            'keyframe': keyframe,
            'tdt': tdt,
            'tdt-duration': -1
        })

        self.debug(
            "Added new entry to the index: offset=%s timestamp=%s "
            "keyframe=%s tdt=%s", offset, timestamp, keyframe, tdt)

    def setLocation(self, location):
        self.location = location

    def setHeadersSize(self, size):
        '''
        Set the headers size in bytes. Multifdsink append the stream headers
        to each client. This size is then used to adjust the offset of the
        index entries
        '''
        self._headers_size = size

    def getHeaders(self):
        '''
        Return an index entry corresponding to the headers, which is a chunk
        with 'offset' 0 and 'length' equals to the headers size
        '''
        if self._headers_size == 0:
            return None
        return {
            'offset': 0,
            'length': self._headers_size,
            'timestamp': 0,
            'duration': -1,
            'keyframe': 0,
            'tdt': 0,
            'tdt-duration': -1
        }

    def getFirstTimestamp(self):
        if len(self._index) == 0:
            return -1
        return self._index[0]['timestamp']

    def getFirstTDT(self):
        if len(self._index) == 0:
            return -1
        return self._index[0]['tdt']

    def clipTimestamp(self, start, stop):
        '''
        Clip the current index to a start and stop time, returning all the
        entries matching the boundaries using the 'timestamp'
        '''
        return self._clip('timestamp', 'duration', start, stop)

    def clipTDT(self, start, stop):
        '''
        Clip the current index to a start and stop time, returning all the
        entries matching the boundaries using the 'tdt'
        '''
        return self._clip('tdt', 'tdt-duration', start, stop)

    def clear(self):
        '''
        Clears the index
        '''
        self._index = []

    def save(self, start=None, stop=None):
        '''
        Saves the index in a file, using the entries from 'start' to 'stop'
        '''
        if self.location is None:
            self.warning("Couldn't save the index, the location is not set.")
            return False
        f = _openFile(self, self.comp, self.location, 'w+')
        if not f:
            return False

        self._write_index_headers(f)
        if len(self._index) == 0:
            return True

        self._write_index_entries(f, self._filter_index(start, stop))
        self.info("Index saved successfully. start=%s stop=%s location=%s ",
                  start, stop, self.location)
        return True

    def loadIndexFile(self, location):
        '''
        Loads the entries of the index from an index file
        '''
        def invalidIndex(reason):
            self.warning("This file is not a valid index: %s", reason)
            return False

        if not location.endswith(self.INDEX_EXTENSION):
            return invalidIndex("the extension of this file is not '%s'" %
                                self.INDEX_EXTENSION)
        try:
            self.info("Loading index file %s", location)
            handle = open(location, 'r')
            indexString = handle.readlines()
            handle.close()
        except IOError, e:
            return invalidIndex("error reading index file (%r)" % e)
        # Check if the file is not empty
        if len(indexString) == 0:
            return invalidIndex("the file is empty")
        # Check headers
        if not indexString[0].startswith('FLUIDX1 #'):
            return invalidIndex('header is not FLUIDX1')
        # Check index keys declaration
        keysStr = ' '.join(self.INDEX_KEYS)
        if indexString[1].strip('\n') != keysStr:
            return invalidIndex('keys definition is not: %s' % keysStr)
        # Add entries
        setHeaders = True
        for entryLine in indexString[2:]:
            e = entryLine.split(' ')
            if len(e) < len(self.INDEX_KEYS):
                return invalidIndex("one of the entries doesn't have enough "
                                    "parameters (needed=%d, provided=%d)" %
                                    (len(self.INDEX_KEYS), len(e)))
            try:
                self.addEntry(int(e[1]), int(e[3]), common.strToBool(e[5]),
                              int(e[6]))
            except Exception, e:
                return invalidIndex("could not parse one of the entries: %r" %
                                    e)
            if setHeaders:
                self._headers_size = int(e[1])
                setHeaders = False
Esempio n. 8
0
 def boolean(v):
     if isinstance(v, bool):
         return v
     return common.strToBool(v)