示例#1
0
class Frame(object):
    """Basic frame object, all other frametypes extend from this."""
    _buffer = None
    length = None

    @property
    def view(self):
        """view() -> memoryview
        
        Returns a memoryview of the frame's data.
        """
        return self._buffer.view()
    
    def bytes(self):
        """bytes() -> bytearray()
        
        Returns a copy of the frame's data.
        """
        return self._buffer.bytes()

    def __eq__(self, other):
        if isinstance(other, Frame):
            return self._buffer == other._buffer
        else:
            return self._buffer == other

    def _frame_assembled(self):
        """Implement this method if you need to do sth. as soon
        as the frames buffer is available."""
        pass

    def append(self, buf):
        """append(buf) -> nothing
        
        Append data from buf to this frame, up to the frame's
        length. Expects a ZeroCopyBuffer as input.
        """
        self._buffer = ZeroCopyBuffer(self.length)
        buf.delete(self._buffer.extend(buf))
        
        if (len(self._buffer) < self.length):
            assert(len(buf) == 0)
            self._buffer.fill(buf._fileobj, completely=True)
        
        assert(len(self._buffer) == self.length)
        self._frame_assembled()
示例#2
0
 def append(self, buf):
     """append(buf) -> nothing
     
     Append data from buf to this frame, up to the frame's
     length. Expects a ZeroCopyBuffer as input.
     """
     self._buffer = ZeroCopyBuffer(self.length)
     buf.delete(self._buffer.extend(buf))
     
     if (len(self._buffer) < self.length):
         assert(len(buf) == 0)
         self._buffer.fill(buf._fileobj, completely=True)
     
     assert(len(self._buffer) == self.length)
     self._frame_assembled()
示例#3
0
    def frames(self, skip_invalid_data = True, emit_meta_frames = True, \
        emit_riff_frames = True, emit_id3_frames = True, emit_ape_frames = True):
        """frames(skip_invalid_data = True, emit_meta_frames = True, \
            emit_riff_frames = True, emit_id3_frames = True, emit_ape_frames = True) -> frame data
        
        Reads frames one-by-one, according to the method's arguments.
        Raises an MP3Error if invalid data is encountered and ingore_invalid_data
        is False.
        """
        in_sync = True

        try:
            buf = ZeroCopyBuffer(self._buffer_size, self._inobj)
            buf.fill()

            while len(buf) > 4: # We need at least 4 bytes for our shortest header
                # Try to parse a frame
                frame = None
                for frame_class in self._FRAME_TYPES:
                    try:
                        frame = frame_class(buf, self, strict=not in_sync)
                        break
                    except _InvalidFrame:
                        pass

                if frame and not in_sync:
                    # Recover from lost sync
                    try:
                        buf.fill(at_least = frame.length + 12)

                        # See if there is a consequent valid frame
                        for frame_class in self._FRAME_TYPES:
                            try:
                                frame_class(buf, self, offset=frame.length, strict=True)
                                in_sync = True
                                break
                            except _InvalidFrame:
                                pass
    
                        frame = in_sync and frame or None
                    except EOFError:
                        # Not enough data left to check the next frame, accept it anyways
                        pass

                if frame:
                    # Consumed data is removed from the buffer in Frame.append()
                    frame.append(buf)

                    if (isinstance(frame, ID3Frame) and (emit_meta_frames or emit_id3_frames)) or \
                        (isinstance(frame, APEFrame) and (emit_meta_frames or emit_ape_frames)) or \
                        (isinstance(frame, RIFFFrame) and emit_riff_frames) or \
                        isinstance(frame, MPEGFrame):
                        yield frame
                else:
                    in_sync = False

                    if not skip_invalid_data:
                        raise MP3Error('encountered invalid data')

                    buf.delete(1)

                if len(buf) < 12:
                    buf.fill(self._inobj)
        except EOFError:
            if not skip_invalid_data:
                raise MP3Error('encountered invalid data')
        finally:
            del buf