source: trunk/src/testing/bin/fileServer/misc/mmpython/audio/ogginfo.py @ 4

Revision 4, 6.3 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1#if 0
2# -----------------------------------------------------------------------
3# $Id: ogginfo.py,v 1.16 2004/05/18 21:56:18 dischi Exp $
4# -----------------------------------------------------------------------
5# $Log: ogginfo.py,v $
6# Revision 1.16  2004/05/18 21:56:18  dischi
7# do not pare the whole file to get the length
8#
9# Revision 1.15  2003/09/22 16:21:20  the_krow
10# o ogg parsing should basically work
11# o utf-8 for vorbis comments
12#
13# Revision 1.14  2003/06/30 13:17:18  the_krow
14# o Refactored mediainfo into factory, synchronizedobject
15# o Parsers now register directly at mmpython not at mmpython.mediainfo
16# o use mmpython.Factory() instead of mmpython.mediainfo.get_singleton()
17# o Bugfix in PNG parser
18# o Renamed disc.AudioInfo into disc.AudioDiscInfo
19# o Renamed disc.DataInfo into disc.DataDiscInfo
20#
21# Revision 1.13  2003/06/29 12:03:15  dischi
22# make some debug silent
23#
24# Revision 1.12  2003/06/20 19:17:22  dischi
25# remove filename again and use file.name
26#
27# Revision 1.11  2003/06/10 11:17:39  the_krow
28# - OGG Fixes
29# - changed one DiscInfo reference in vcdinfo I missed before
30#
31# Revision 1.10  2003/06/08 19:53:38  dischi
32# also give the filename to init for additional data tests
33#
34# Revision 1.9  2003/06/08 13:44:56  dischi
35# Changed all imports to use the complete mmpython path for mediainfo
36#
37# Revision 1.8  2003/06/08 13:11:25  dischi
38# removed print at the end and moved it into register
39#
40# Revision 1.7  2003/06/07 23:32:11  the_krow
41# changed names to new format
42# debug messages
43#
44# Revision 1.6  2003/05/13 15:23:59  the_krow
45# IPTC
46#
47# Revision 1.5  2003/05/13 12:31:43  the_krow
48# + Copyright Notice
49#
50# -----------------------------------------------------------------------
51# MMPython - Media Metadata for Python
52# Copyright (C) 2003 Thomas Schueppel
53#
54# This program is free software; you can redistribute it and/or modify
55# it under the terms of the GNU General Public License as published by
56# the Free Software Foundation; either version 2 of the License, or
57# (at your option) any later version.
58#
59# This program is distributed in the hope that it will be useful, but
60# WITHOUT ANY WARRANTY; without even the implied warranty of MER-
61# CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
62# Public License for more details.
63#
64# You should have received a copy of the GNU General Public License along
65# with this program; if not, write to the Free Software Foundation, Inc.,
66# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
67#
68# -----------------------------------------------------------------------
69#endif
70
71import re
72import os, stat
73import struct
74
75from mmpython import mediainfo
76import mmpython
77
78VORBIS_PACKET_INFO = '\01vorbis'
79VORBIS_PACKET_HEADER = '\03vorbis'
80VORBIS_PACKET_SETUP = '\05vorbis'
81
82_print = mediainfo._debug
83
84class OggInfo(mediainfo.MusicInfo):
85    def __init__(self,file):
86        mediainfo.MusicInfo.__init__(self)
87        h = file.read(4+1+1+20+1)
88        if h[:5] != "OggS\00":
89            _print("Invalid header")
90            self.valid = 0
91            return
92        if ord(h[5]) != 2:
93            _print("Invalid header type flag (trying to go ahead anyway)")
94        self.pageSegCount = ord(h[-1])
95        # Skip the PageSegCount
96        file.seek(self.pageSegCount,1)
97        h = file.read(7)
98        if h != VORBIS_PACKET_INFO:
99            _print("Wrong vorbis header type, giving up.")
100            self.valid = 0
101            return
102        self.valid = 1
103        self.mime = 'application/ogg'
104        header = {}
105        info = file.read(23)
106        self.version, self.channels, self.samplerate, bitrate_max, self.bitrate, bitrate_min, blocksize, framing = struct.unpack('<IBIiiiBB',info[:23])
107        # INFO Header, read Oggs and skip 10 bytes
108        h = file.read(4+10+13)       
109        if h[:4] == 'OggS':
110            (serial, pagesequence, checksum, numEntries) = struct.unpack( '<14xIIIB', h )
111            # skip past numEntries
112            file.seek(numEntries,1)
113            h = file.read(7)
114            if h != VORBIS_PACKET_HEADER:
115                # Not a corrent info header
116                return                       
117            self.encoder = self._extractHeaderString(file)
118            numItems = struct.unpack('<I',file.read(4))[0]
119            for i in range(numItems):
120                s = self._extractHeaderString(file)
121                a = re.split('=',s)
122                header[(a[0]).upper()]=a[1]
123            # Put Header fields into info fields
124            if header.has_key('TITLE'):
125                self.title = header['TITLE']
126            if header.has_key('ALBUM'):
127                self.album = header['ALBUM']
128            if header.has_key('ARTIST'):
129                self.artist = header['ARTIST']           
130            if header.has_key('COMMENT'):
131                self.comment = header['COMMENT']
132            if header.has_key('DATE'):
133                self.date = header['DATE']
134            if header.has_key('ENCODER'):
135                self.encoder = header['ENCODER']
136            if header.has_key('TRACKNUMBER'):
137                self.trackno = header['TRACKNUMBER']
138            self.type = 'OGG Vorbis'
139            self.subtype = ''
140            self.length = self._calculateTrackLength(file)
141            self.appendtable('VORBISCOMMENT',header)
142                                           
143    def _extractHeaderString(self,f):
144        len = struct.unpack( '<I', f.read(4) )[0]
145        return unicode(f.read(len), 'utf-8')
146   
147
148    def _calculateTrackLength(self,f):
149        # seek to the end of the stream, to avoid scanning the whole file
150        if (os.stat(f.name)[stat.ST_SIZE] > 20000):
151            f.seek(os.stat(f.name)[stat.ST_SIZE]-10000)
152
153        # read the rest of the file into a buffer
154        h = f.read()
155        granule_position = 0
156        # search for each 'OggS' in h       
157        if len(h):
158            idx = h.rfind('OggS')
159            if idx < 0:
160                return 0
161            pageSize = 0
162            h = h[idx+4:]
163            (check, type, granule_position, absPos, serial, pageN, crc, segs) = struct.unpack( '<BBIIIIIB', h[:23] )           
164            if check != 0:
165                _print(h[:10])
166                return
167            _print("granule = %d / %d" % (granule_position, absPos))
168        # the last one is the one we are interested in
169        return (granule_position / self.samplerate)
170
171mmpython.registertype( 'application/ogg', ('ogg',), mediainfo.TYPE_MUSIC, OggInfo )
Note: See TracBrowser for help on using the repository browser.