Example #1
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        self.mime = 'video/x-ms-asf'
        self.type = 'asf format'
        self._languages = []
        self._extinfo = {}

        h = file.read(30)
        if len(h) < 30:
            raise core.ParseError()

        (guidstr, objsize, objnum, reserved1, \
         reserved2) = struct.unpack('<16sQIBB',h)
        guid = self._parseguid(guidstr)

        if (guid != GUIDS['ASF_Header_Object']):
            raise core.ParseError()
        if reserved1 != 0x01 or reserved2 != 0x02:
            raise core.ParseError()

        log.debug("asf header size: %d / %d objects" % (objsize, objnum))
        header = file.read(objsize - 30)
        for i in range(0, objnum):
            h = self._getnextheader(header)
            header = header[h[1]:]

        del self._languages
        del self._extinfo
Example #2
0
    def parseDisc(self, device):
        type = None
        if self.is_disc(device) != 2:
            raise core.ParseError()

        f = open(device)
        try:
            # read CD-XA001 at byte 1024 in sector 16
            f.seek(2048 * 16 + 1024, 0)
            if f.read(8) != 'CD-XA001':
                raise core.ParseError()
            # read VIDEO_CD at sector 150
            f.seek(2048 * 150, 0)
            typebuffer = f.read(8)
            if typebuffer != 'VIDEO_CD' and typebuffer != 'SUPERVCD':
                raise core.ParseError()
            # Read some bytes of the ISO9660 part to better guess VCD or SVCD.
            # Maybe this code is not needed and VIDEO_CD and SUPERVCD are enough.
            f.seek(2048 * 16, 0)
            iso9660 = f.read(2048 * 16)
            if typebuffer == 'VIDEO_CD' and iso9660.find('MPEGAV') > 0:
                type = 'VCD'
            elif typebuffer == 'SUPERVCD' and \
                 (iso9660.find('SVCD') > 0 or iso9660.find('MPEG2') > 0):
                type = 'SVCD'
            else:
                raise core.ParseError()
        finally:
            f.close()

        # read the tracks to generate the title list
        device = open(device)
        (first, last) = cdrom.audiocd_toc_header(device)

        lmin = 0
        lsec = 0

        num = 0
        for i in range(first, last + 2):
            if i == last + 1:
                min, sec, frames = cdrom.audiocd_leadout(device)
            else:
                min, sec, frames = cdrom.audiocd_toc_entry(device, i)
            if num:
                vi = core.VideoStream()
                # XXX add more static information here, it's also possible
                # XXX to scan for more informations like fps
                # XXX Settings to MPEG1/2 is a wild guess, maybe the track
                # XXX isn't playable at all (e.g. the menu)
                if type == 'VCD':
                    vi.codec = 'MPEG1'
                else:
                    vi.codec = 'MPEG2'
                vi.length = (min - lmin) * 60 + (sec - lsec)
                self.tracks.append(vi)
            num += 1
            lmin, lsec = min, sec
        device.close()
Example #3
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        self.sequence_header_offset = 0
        self.mpeg_version = 2

        # detect TS (fast scan)
        if not self.isTS(file):
            # detect system mpeg (many infos)
            if not self.isMPEG(file):
                # detect PES
                if not self.isPES(file):
                    # Maybe it's MPEG-ES
                    if self.isES(file):
                        # If isES() succeeds, we needn't do anything further.
                        return
                    if file.name.lower().endswith('mpeg') or \
                             file.name.lower().endswith('mpg'):
                        # This has to be an mpeg file. It could be a bad
                        # recording from an ivtv based hardware encoder with
                        # same bytes missing at the beginning.
                        # Do some more digging...
                        if not self.isMPEG(file, force=True) or \
                           not self.video or not self.audio:
                            # does not look like an mpeg at all
                            raise core.ParseError()
                    else:
                        # no mpeg at all
                        raise core.ParseError()

        self.mime = 'video/mpeg'
        if not self.video:
            self.video.append(core.VideoStream())

        if self.sequence_header_offset <= 0:
            return

        self.progressive(file)

        for vi in self.video:
            vi.width, vi.height = self.dxy(file)
            vi.fps, vi.aspect = self.framerate_aspect(file)
            vi.bitrate = self.bitrate(file)
            if self.length:
                vi.length = self.length

        if not self.type:
            self.type = 'MPEG Video'

        # set fourcc codec for video and audio
        vc, ac = 'MP2V', 'MP2A'
        if self.mpeg_version == 1:
            vc, ac = 'MPEG', 0x0050
        for v in self.video:
            v.codec = vc
        for a in self.audio:
            if not a.codec:
                a.codec = ac
Example #4
0
 def __init__(self,file):
     core.Music.__init__(self)
     t = self._what(file)
     if not t:
         raise core.ParseError()
     (self.type, self.samplerate, self.channels, self.bitrate, \
      self.samplebits) = t
     if self.bitrate == -1:
         # doesn't look right
         raise core.ParseError()
     self.mime = "audio/%s" % self.type
Example #5
0
 def _parse(self, device):
     if not _ifoparser:
         log.debug("kaa.metadata not compiled with DVD support")
         raise core.ParseError()
     info = _ifoparser.parse(device)
     if not info:
         raise core.ParseError()
     for pos, title in enumerate(info):
         ti = DVDTitle(title)
         ti.trackno = pos + 1
         ti.trackof = len(info)
         self.tracks.append(ti)
Example #6
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        self._references = []

        self.mime = 'video/quicktime'
        self.type = 'Quicktime Video'
        h = file.read(8)
        try:
            (size, type) = struct.unpack('>I4s', h)
        except struct.error:
            # EOF.
            raise core.ParseError()

        if type == 'ftyp':
            # file type information
            if size >= 12:
                # this should always happen
                if file.read(4) != 'qt  ':
                    # not a quicktime movie, it is a mpeg4 container
                    self.mime = 'video/mp4'
                    self.type = 'MPEG-4 Video'
                size -= 4
            file.seek(size - 8, 1)
            h = file.read(8)
            (size, type) = struct.unpack('>I4s', h)

        while type in ('mdat', 'skip'):
            # movie data at the beginning, skip
            file.seek(size - 8, 1)
            h = file.read(8)
            (size, type) = struct.unpack('>I4s', h)

        if not type in ('moov', 'wide', 'free'):
            log.debug('invalid header: %r' % type)
            raise core.ParseError()

        # Extended size
        if size == 1:
            size = struct.unpack('>Q', file.read(8))

        # Back over the atom header we just read, since _readatom expects the
        # file position to be at the start of an atom.
        file.seek(-8, 1)
        while self._readatom(file):
            pass

        if self._references:
            self._set('references', self._references)
Example #7
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        # read the header
        h = file.read(12)
        if h[:4] != "RIFF" and h[:4] != 'SDSS':
            raise core.ParseError()

        self.has_idx = False
        self.header = {}
        self.junkStart = None
        self.infoStart = None
        self.type = h[8:12]
        if self.type == 'AVI ':
            self.mime = 'video/avi'
        elif self.type == 'WAVE':
            self.mime = 'audio/wav'
        try:
            while self._parseRIFFChunk(file):
                pass
        except IOError:
            log.exception('error in file, stop parsing')

        self._find_subtitles(file.name)

        if not self.has_idx and self.media == core.MEDIA_AV:
            log.debug('WARNING: avi has no index')
            self._set('corrupt', True)
Example #8
0
    def __init__(self, file):
        core.Image.__init__(self)
        self.mime = 'image/bmp'
        self.type = 'windows bitmap image'

        try:
            (bfType, bfSize, bfZero, bfOffset, biSize, self.width,
             self.height) = struct.unpack('<2sIIIIII', file.read(26))
        except struct.error:
            raise core.ParseError()

        # seek to the end to test length
        file.seek(0, 2)

        if bfType != 'BM' or bfSize != file.tell():
            raise core.ParseError()
Example #9
0
    def __init__(self,file):
        core.Image.__init__(self)
        self.mime = 'image/gif'

        try:
            header = struct.unpack('<6sHH', file.read(10))
        except struct.error:
            # EOF.
            raise core.ParseError()

        gifType, self.width, self.height = header

        if not gifType.startswith('GIF'):
            raise core.ParseError()

        self.type = gifType.lower()
Example #10
0
    def __init__(self, file):
        core.Image.__init__(self)
        self.iptc = None
        self.mime = 'image/tiff'
        self.type = 'TIFF image'
        self.intel = 0
        iptc = {}
        header = file.read(8)

        if header[:4] == MOTOROLASIGNATURE:
            self.intel = 0
            (offset, ) = struct.unpack(">I", header[4:8])
            file.seek(offset)
            (len, ) = struct.unpack(">H", file.read(2))
            app = file.read(len * 12)
            for i in range(len):
                (tag, type, length, value, offset) = \
                      struct.unpack('>HHIHH', app[i*12:i*12+12])
                if tag == 0x8649:
                    file.seek(offset, 0)
                    iptc = IPTC.parseiptc(file.read(1000))
                elif tag == 0x0100:
                    if value != 0:
                        self.width = value
                    else:
                        self.width = offset
                elif tag == 0x0101:
                    if value != 0:
                        self.height = value
                    else:
                        self.height = offset

        elif header[:4] == INTELSIGNATURE:
            self.intel = 1
            (offset, ) = struct.unpack("<I", header[4:8])
            file.seek(offset, 0)
            (len, ) = struct.unpack("<H", file.read(2))
            app = file.read(len * 12)
            for i in range(len):
                (tag, type, length, offset, value) = \
                      struct.unpack('<HHIHH', app[i*12:i*12+12])
                if tag == 0x8649:
                    file.seek(offset)
                    iptc = IPTC.parseiptc(file.read(1000))
                elif tag == 0x0100:
                    if value != 0:
                        self.width = value
                    else:
                        self.width = offset
                elif tag == 0x0101:
                    if value != 0:
                        self.height = value
                    else:
                        self.height = offset
        else:
            raise core.ParseError()

        if iptc:
            self._appendtable('IPTC', iptc)
Example #11
0
 def __init__(self, device):
     core.Disc.__init__(self)
     if self.is_disc(device) != 2:
         raise core.ParseError()
     self.offset = 0
     self.mime = 'unknown/unknown'
     self.type = 'CD'
     self.subtype = 'data'
Example #12
0
    def __init__(self, file):
        core.Game.__init__(self)

        # Determine if the ROM is a Gameboy Advance ROM.
        # Compare the Logo Code. All GBA Roms have this code.
        file.seek(4)
        if file.read(156) != GBA_LOGOCODE:

            # Determine if the ROM is a Standard Gameboy ROM
            # Compare the Logo Code. All GB Roms have this code.
            file.seek(260)
            if file.read(len(GB_LOGOCODE)) != GB_LOGOCODE:
                raise core.ParseError()

            # Retrieve the ROM Title
            game_title = file.read(15)
            self.title = game_title

            # Retrieve the Rom Type (GB Colour or GB)j
            if file.read(1) == '\x80':
                self.mime = 'games/gbc'
                self.type = 'GameBoyColour game'
            else:
                self.mime = 'games/gb'
                self.type = 'GameBoy game'

        else:

            self.mime = 'games/gba'
            self.type = 'GameBoyAdvance game'

            # Retrieve the ROM Title
            game_title = file.read(12)
            self.title = game_title

            # Retrieve the Game Code
            game_code = file.read(4)

            # Retrieve the  Manufacturer Code
            maker_code = file.read(2)
            log.debug("MAKER CODE: %s" % maker_code)

            # Check that the Fized Value is 0x96, if not then error.
            if file.read(1) != '\x96':
                raise core.ParseError()
Example #13
0
    def parseDVDiso(self, f):
        # brute force reading of the device to find out if it is a DVD
        f.seek(32768, 0)
        buffer = f.read(60000)

        if buffer.find('UDF') == -1:
            raise core.ParseError()

        # seems to be a DVD, read a little bit more
        buffer += f.read(550000)

        if buffer.find('VIDEO_TS') == -1 and \
               buffer.find('VIDEO_TS.IFO') == -1 and \
               buffer.find('OSTA UDF Compliant') == -1:
            raise core.ParseError()

        # OK, try libdvdread
        self._parse(f.name)
Example #14
0
    def __init__(self, url):
        core.Music.__init__(self)
        tup = urlparse.urlsplit(url)
        scheme, location, path, query, fragment = tup
        if scheme != 'http':
            raise core.ParseError()

        # Open an URL Connection
        fi = urllib.urlopen(url)

        # grab the statusline
        self.statusline = fi.readline()
        try:
            statuslist = string.split(self.statusline)
        except ValueError:
            # assume it is okay since so many servers are badly configured
            statuslist = ["ICY", "200"]

        if statuslist[1] != "200":
            if fi:
                fi.close()
            raise core.ParseError()

        self.type = 'audio'
        self.subtype = 'mp3'
        # grab any headers for a max of 10 lines
        linecnt = 0
        tab = {}
        lines = fi.readlines(512)
        for linecnt in range(0, 11):
            icyline = lines[linecnt]
            icyline = icyline.rstrip('\r\n')
            if len(icyline) < 4:
                break
            cidx = icyline.find(':')
            if cidx != -1:
                # break on short line (ie. really should be a blank line)
                # strip leading and trailing whitespace
                tab[icyline[:cidx].strip()] = icyline[cidx + 2:].strip()
        if fi:
            fi.close()
        self._appendtable('ICY', tab)
Example #15
0
    def __init__(self,device):
        core.Disc.__init__(self)
        self.offset = 0
        # check disc
        if self.is_disc(device) != 1:
            raise core.ParseError()

        self.query(device)
        self.mime = 'audio/cd'
        self.type = 'CD'
        self.subtype = 'audio'
Example #16
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        self.samplerate = 1

        self.file = file
        # Read enough that we're likely to get the full seekhead (FIXME: kludge)
        buffer = file.read(2000)
        if len(buffer) == 0:
            # Regular File end
            raise core.ParseError()

        # Check the Matroska header
        header = EbmlEntity(buffer)
        if header.get_id() != MATROSKA_HEADER_ID:
            raise core.ParseError()

        log.debug("HEADER ID found %08X" % header.get_id())
        self.mime = 'application/mkv'
        self.type = 'Matroska'
        self.has_idx = False
        self.objects_by_uid = {}

        # Now get the segment
        self.segment = segment = EbmlEntity(buffer[header.get_total_len():])
        # Record file offset of segment data for seekheads
        self.segment.offset = header.get_total_len() + segment.get_header_len()
        if segment.get_id() != MATROSKA_SEGMENT_ID:
            log.debug("SEGMENT ID not found %08X" % segment.get_id())
            return

        log.debug("SEGMENT ID found %08X" % segment.get_id())
        try:
            for elem in self.process_one_level(segment):
                if elem.get_id() == MATROSKA_SEEKHEAD_ID:
                    self.process_elem(elem)
        except core.ParseError:
            pass

        if not self.has_idx:
            log.debug('WARNING: file has no index')
            self._set('corrupt', True)
Example #17
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        self.mime = 'video/real'
        self.type = 'Real Video'
        h = file.read(10)
        try:
            (object_id, object_size,
             object_version) = struct.unpack('>4sIH', h)
        except struct.error:
            # EOF.
            raise core.ParseError()

        if not object_id == '.RMF':
            raise core.ParseError()

        file_version, num_headers = struct.unpack('>II', file.read(8))
        log.debug("size: %d, ver: %d, headers: %d" % \
                  (object_size, file_version,num_headers))
        for i in range(0, num_headers):
            try:
                oi = struct.unpack('>4sIH', file.read(10))
            except (struct.error, IOError):
                # Header data we expected wasn't there.  File may be
                # only partially complete.
                break

            if object_id == 'DATA' and oi[0] != 'INDX':
                log.debug(
                    'INDX chunk expected after DATA but not found -- file corrupt'
                )
                break

            (object_id, object_size, object_version) = oi
            if object_id == 'DATA':
                # Seek over the data chunk rather than reading it in.
                file.seek(object_size - 10, 1)
            else:
                self._read_header(object_id, file.read(object_size - 10))
            log.debug("%s [%d]" % (object_id, object_size - 10))
Example #18
0
 def __init__(self, inbuf):
     # Compute the EBML id
     # Set the CRC len to zero
     self.crc_len = 0
     # Now loop until we find an entity without CRC
     try:
         self.build_entity(inbuf)
     except IndexError:
         raise core.ParseError()
     while self.get_id() == MATROSKA_CRC32_ID:
         self.crc_len += self.get_total_len()
         inbuf = inbuf[self.get_total_len():]
         self.build_entity(inbuf)
Example #19
0
    def parseDVDdir(self, dirname):
        def iglob(path, ifile):
            # Case insensitive glob to find video_ts dir/file.  Python 2.5 has
            # glob.iglob but this doesn't exist in 2.4.
            file_glob = ''.join(['[%s%s]' % (c, c.upper()) for c in ifile])
            return glob.glob(os.path.join(path, file_glob))

        if True not in [ os.path.isdir(x) for x in iglob(dirname, 'video_ts') ] + \
                       [ os.path.isfile(x) for x in iglob(dirname, 'video_ts.vob') ]:
            raise core.ParseError()

        # OK, try libdvdread
        self._parse(dirname)
        return 1
Example #20
0
    def _parseAVIH(self, t):
        retval = {}
        v = struct.unpack('<IIIIIIIIIIIIII', t[0:56])
        (retval['dwMicroSecPerFrame'], retval['dwMaxBytesPerSec'],
         retval['dwPaddingGranularity'], retval['dwFlags'],
         retval['dwTotalFrames'], retval['dwInitialFrames'],
         retval['dwStreams'], retval['dwSuggestedBufferSize'],
         retval['dwWidth'], retval['dwHeight'], retval['dwScale'],
         retval['dwRate'], retval['dwStart'], retval['dwLength']) = v
        if retval['dwMicroSecPerFrame'] == 0:
            log.warning("ERROR: Corrupt AVI")
            raise core.ParseError()

        return retval
Example #21
0
    def execute(cls, uri, http_verb, extra_headers=None, batch=False, **kw):
        """
        if batch == False, execute a command with the given parameters and
        return the response JSON.
        If batch == True, return the dictionary that would be used in a batch
        command.
        """
        if batch:
            ret = {"method": http_verb, "path": uri.split("parse.com")[1]}
            if kw:
                ret["body"] = kw
            return ret

        if not ('app_id' in ACCESS_KEYS and 'rest_key' in ACCESS_KEYS):
            raise core.ParseError('Missing connection credentials')

        app_id = ACCESS_KEYS.get('app_id')
        rest_key = ACCESS_KEYS.get('rest_key')
        master_key = ACCESS_KEYS.get('master_key')

        headers = extra_headers or {}
        url = uri if uri.startswith(API_ROOT) else cls.ENDPOINT_ROOT + uri
        data = kw and json.dumps(kw) or "{}"
        if http_verb == 'GET' and data:
            url += '?%s' % urlencode(kw)
            data = None

        request = Request(url, data, headers)
        request.add_header('Content-type', 'application/json')
        request.add_header('X-Parse-Application-Id', app_id)
        request.add_header('X-Parse-REST-API-Key', rest_key)

        if master_key and 'X-Parse-Session-Token' not in headers.keys():
            request.add_header('X-Parse-Master-Key', master_key)

        request.get_method = lambda: http_verb

        try:
            response = urlopen(request)
        except HTTPError as e:
            exc = {
                400: core.ResourceRequestBadRequest,
                401: core.ResourceRequestLoginRequired,
                403: core.ResourceRequestForbidden,
                404: core.ResourceRequestNotFound
            }.get(e.code, core.ParseError)
            raise exc(e.read())

        return json.loads(response.read())
Example #22
0
    def parseDisc(self, device):
        if self.is_disc(device) != 2:
            raise core.ParseError()

        # brute force reading of the device to find out if it is a DVD
        f = open(device, 'rb')
        f.seek(32768, 0)
        buffer = f.read(60000)

        if buffer.find('UDF') == -1:
            f.close()
            raise core.ParseError()

        # seems to be a DVD, read a little bit more
        buffer += f.read(550000)
        f.close()

        if buffer.find('VIDEO_TS') == -1 and \
               buffer.find('VIDEO_TS.IFO') == -1 and \
               buffer.find('OSTA UDF Compliant') == -1:
            raise core.ParseError()

        # OK, try libdvdread
        self._parse(device)
Example #23
0
    def __init__(self, file):
        core.Music.__init__(self)
        if file.name.endswith('.ac3'):
            # when the ending is ac3, force the detection. It may not be
            # necessary the the header is at the beginning but in the first
            # 2000 bytes
            check_length = 1000
        else:
            check_length = 1
        for i in range(check_length):
            if file.read(2) == '\x0b\x77':
                break
        else:
            raise core.ParseError()

        info = struct.unpack('<HBBBB', file.read(6))
        self.samplerate = FSCOD[info[1] >> 6]
        self.bitrate = FRMSIZCOD[(info[1] & 0x3F) >> 1] * 1000
        bsmod = info[2] & 0x7
        channels = ACMOD[info[3] >> 5]
        acmod = info[3] >> 5
        self.channels = ACMOD[acmod][1]
        bits = 0
        if acmod & 0x01 and not acmod == 0x01:
            bits += 2
        if acmod & 0x04:
            bits += 2
        if acmod == 0x02:
            bits += 2

        # info is now 5 bits of info[3] and all bits of info[4] ( == 13 bits)
        # 'bits' bits (0-6) bits are information we don't need, after that,
        # the bit we need is lfeon.
        info = (((info[3] & 0x1F) << 8) + info[4])

        # now we create the mask we need (based on 'bits')
        # the bit number 13 - 'bits' is what we want to read
        for i in range(13 - bits - 1):
            info = info >> 1
        if info & 1:
            # LFE channel
            self.channels += 1

        file.seek(-1, 2)
        size = file.tell()
        self.length = size * 8.0 / self.bitrate
        self.codec = 0x2000  # fourcc code of ac3
        self.mime = 'audio/ac3'
Example #24
0
    def _parseOGGS(self, file):
        h = file.read(27)
        if len(h) == 0:
            # Regular File end
            return None, None
        elif len(h) < 27:
            log.debug("%d Bytes of Garbage found after End." % len(h))
            return None, None
        if h[:4] != "OggS":
            log.debug("Invalid Ogg")
            raise core.ParseError()

        version = ord(h[4])
        if version != 0:
            log.debug("Unsupported OGG/OGM Version %d." % version)
            return None, None

        head = struct.unpack('<BQIIIB', h[5:])
        headertype, granulepos, serial, pageseqno, checksum, \
                    pageSegCount = head

        self.mime = 'application/ogm'
        self.type = 'OGG Media'
        tab = file.read(pageSegCount)
        nextlen = 0
        for i in range(len(tab)):
            nextlen += ord(tab[i])
        else:
            h = file.read(1)
            packettype = ord(h[0]) & PACKET_TYPE_BITS
            if packettype == PACKET_TYPE_HEADER:
                h += file.read(nextlen - 1)
                self._parseHeader(h, granulepos)
            elif packettype == PACKED_TYPE_METADATA:
                h += file.read(nextlen - 1)
                self._parseMeta(h)
            else:
                file.seek(nextlen - 1, 1)
        if len(self.all_streams) > serial:
            stream = self.all_streams[serial]
            if hasattr(stream, 'samplerate') and \
                   stream.samplerate:
                stream.length = granulepos / stream.samplerate
            elif hasattr(stream, 'bitrate') and \
                     stream.bitrate:
                stream.length = granulepos / stream.bitrate

        return granulepos, nextlen + 27 + pageSegCount
Example #25
0
    def __init__(self, file):
        core.Image.__init__(self)
        self.mime = 'image/png'
        self.type = 'PNG image'

        signature = file.read(8)
        if (signature != PNGSIGNATURE):
            raise core.ParseError()

        self.meta = {}
        while self._readChunk(file):
            pass
        if len(self.meta.keys()):
            self._appendtable('PNGMETA', self.meta)
        for key, value in self.meta.items():
            if key.startswith('Thumb:') or key == 'Software':
                self._set(key, value)
Example #26
0
    def build_entity(self, inbuf):
        self.compute_id(inbuf)

        if self.id_len == 0:
            log.debug("EBML entity not found, bad file format")
            raise core.ParseError()

        self.entity_len, self.len_size = self.compute_len(inbuf[self.id_len:])
        self.entity_data = inbuf[self.get_header_len() : self.get_total_len()]
        self.ebml_length = self.entity_len
        self.entity_len = min(len(self.entity_data), self.entity_len)

        # if the data size is 8 or less, it could be a numeric value
        self.value = 0
        if self.entity_len <= 8:
            for pos, shift in zip(range(self.entity_len), range((self.entity_len-1)*8, -1, -8)):
                self.value |= ord(self.entity_data[pos]) << shift
Example #27
0
    def __init__(self, file):
        core.Music.__init__(self)
        tags = M4ATags(file)
        if tags.get('FileType') != 'M4A ':
            raise core.ParseError()

        self.valid = True
        self.mime = 'audio/mp4'
        self.filename = getattr(file, 'name', None)
        # Initialize core attributes from available tag values.
        self.title = tags.get('Title')
        self.artist = tags.get('Artist')
        self.album = tags.get('Album')
        self.trackno = tags.get('Track')
        self.year = tags.get('Year')
        self.encoder = tags.get('Tool')
        self.length = tags.get('Length')
        self.samplerate = tags.get('SampleRate')
Example #28
0
 def ret(obj, *args, **kw):
     conn = ACCESS_KEYS
     if not (conn and conn.get('master_key')):
         message = '%s requires the master key' % func.__name__
         raise core.ParseError(message)
     func(obj, *args, **kw)
Example #29
0
    def __init__(self, file):
        core.Music.__init__(self)
        h = file.read(4 + 1 + 1 + 20 + 1)
        if h[:5] != "OggS\00":
            log.info("Invalid header")
            raise core.ParseError()
        if ord(h[5]) != 2:
            log.info("Invalid header type flag (trying to go ahead anyway)")
        self.pageSegCount = ord(h[-1])
        # Skip the PageSegCount
        file.seek(self.pageSegCount, 1)
        h = file.read(7)
        if h != VORBIS_PACKET_INFO:
            log.info("Wrong vorbis header type, giving up.")
            raise core.ParseError()

        # http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions
        self.mime = 'audio/x-vorbis+ogg'
        header = {}
        info = file.read(23)
        self.version, self.channels, self.samplerate, bitrate_max, \
                      self.bitrate, bitrate_min, blocksize, \
                      framing = struct.unpack('<IBIiiiBB',info[:23])
        self.bitrate = self.bitrate / 1000
        # INFO Header, read Oggs and skip 10 bytes
        h = file.read(4 + 10 + 13)
        if h[:4] == 'OggS':
            (serial, pagesequence, checksum, numEntries) = \
                     struct.unpack( '<14xIIIB', h )
            # skip past numEntries
            file.seek(numEntries, 1)
            h = file.read(7)
            if h != VORBIS_PACKET_HEADER:
                # Not a corrent info header
                return
            self.encoder = self._extractHeaderString(file)
            numItems = struct.unpack('<I', file.read(4))[0]
            for i in range(numItems):
                s = self._extractHeaderString(file)
                a = re.split('=', s)
                header[(a[0]).upper()] = a[1]
            # Put Header fields into info fields
            if header.has_key('TITLE'):
                self.title = header['TITLE']
            if header.has_key('ALBUM'):
                self.album = header['ALBUM']
            if header.has_key('ARTIST'):
                self.artist = header['ARTIST']
            if header.has_key('COMMENT'):
                self.comment = header['COMMENT']
            if header.has_key('DATE'):
                # FIXME: try to convert to timestamp
                self.userdate = header['DATE']
            if header.has_key('ENCODER'):
                self.encoder = header['ENCODER']
            if header.has_key('TRACKNUMBER'):
                self.trackno = header['TRACKNUMBER']
            self.type = 'OGG Vorbis'
            self.subtype = ''
            self.length = self._calculateTrackLength(file)
            self._appendtable('VORBISCOMMENT', header)
Example #30
0
    def __init__(self, file):
        core.Image.__init__(self)
        self.mime = 'image/jpeg'
        self.type = 'jpeg image'

        if file.read(2) != '\xff\xd8':
            raise core.ParseError()

        file.seek(-2, 2)
        if file.read(2) != '\xff\xd9':
            # Normally an JPEG should end in ffd9. This does not however
            # we assume it's an jpeg for now
            log.info("Wrong encode found for jpeg")

        file.seek(2)
        app = file.read(4)
        self.meta = {}

        while (len(app) == 4):
            (ff, segtype, seglen) = struct.unpack(">BBH", app)
            if ff != 0xff: break
            if segtype == 0xd9:
                break

            elif SOF.has_key(segtype):
                data = file.read(seglen - 2)
                (precision,self.height,self.width,\
                 num_comp) = struct.unpack('>BHHB', data[:6])

            elif segtype == 0xe1:
                data = file.read(seglen - 2)
                type = data[:data.find('\0')]
                if type == 'Exif':
                    # create a fake file from the data we have to
                    # pass it to the EXIF parser
                    fakefile = cStringIO.StringIO()
                    fakefile.write('\xFF\xD8')
                    fakefile.write(app)
                    fakefile.write(data)
                    fakefile.seek(0)
                    exif = EXIF.process_file(fakefile)
                    fakefile.close()
                    if exif:
                        self.thumbnail = exif.get('JPEGThumbnail', None)
                        if self.thumbnail:
                            self.thumbnail = str(self.thumbnail)
                        self._appendtable('EXIF', exif)

                        if 'Image Orientation' in exif:
                            orientation = str(exif['Image Orientation'])
                            if orientation.find('90 CW') > 0:
                                self.rotation = 90
                            elif orientation.find('90') > 0:
                                self.rotation = 270
                            elif orientation.find('180') > 0:
                                self.rotation = 180
                        t = exif.get('Image DateTimeOriginal')
                        if not t:
                            # sometimes it is called this way
                            t = exif.get('EXIF DateTimeOriginal')
                        if not t:
                            t = exif.get('Image DateTime')
                        if t:
                            try:
                                t = time.strptime(str(t), '%Y:%m:%d %H:%M:%S')
                                self.timestamp = int(time.mktime(t))
                            except ValueError:
                                # Malformed time string.
                                pass
                elif type == 'http://ns.adobe.com/xap/1.0/':
                    # FIXME: parse XMP data (xml)
                    doc = data[data.find('\0') + 1:]
                else:
                    pass

            elif segtype == 0xed:
                iptc = IPTC.parseiptc(file.read(seglen - 2))
                if iptc:
                    self._appendtable('IPTC', iptc)

            elif segtype == 0xe7:
                # information created by libs like epeg
                data = file.read(seglen - 2)
                if data.count('\n') == 1:
                    key, value = data.split('\n')
                    self.meta[key] = value

            elif segtype == 0xfe:
                self.comment = file.read(seglen - 2)
                if self.comment.startswith('<?xml'):
                    # This could be a comment based on
                    # http://www.w3.org/TR/photo-rdf/
                    log.error('xml comment parser not integrated')
                    self.comment = ''
            else:
                # Huffman table marker (FFC4)
                # Start of Scan marker (FFDA)
                # Quantization table marker (FFDB)
                # Restart Interval (FFDD) ???
                if not segtype in (0xc4, 0xda, 0xdb, 0xdd):
                    log.info("SEGMENT: 0x%x%x, len=%d" % (ff, segtype, seglen))
                file.seek(seglen - 2, 1)
            app = file.read(4)

        if len(self.meta.keys()):
            self._appendtable('JPGMETA', self.meta)

        for key, value in self.meta.items():
            if key.startswith('Thumb:') or key == 'Software':
                self._set(key, value)