# -----------------------------------------------------------------------
# lsdvdinfo.py - parse dvd title structure
# -----------------------------------------------------------------------
# $Id: lsdvd.py 1906 2006-09-26 13:18:52Z duncan $
#
# Use lsdvd to get dvd informations.
#
# -----------------------------------------------------------------------
# $Log: lsdvd.py,v $
# Revision 1.13.2.1 2005/06/30 17:28:24 dischi
# fix to new lsdvd
#
# Revision 1.13 2005/01/13 20:19:34 dischi
# detect video_ts in lower case
#
# Revision 1.12 2004/08/27 17:27:44 dischi
# do not import ifoparser
#
#
# -----------------------------------------------------------------------
# Copyright (C) 2003 Thomas Schueppel, Dirk Meyer
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MER-
# CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ----------------------------------------------------------------------- */
import os
import re
from mmpython import mediainfo
import mmpython
from discinfo import DiscInfo
LSDVD_EXE='lsdvd'
class DVDAudio(mediainfo.AudioInfo):
def __init__(self, data):
mediainfo.AudioInfo.__init__(self)
self.rawdata = data
self.number = int(data[1])
try:
self.id = int(data[20],0)
except:
self.id = self.number
if data[3] != 'xx':
self.language = data[3]
self.languagedesc = data[5]
try:
# some DVDs have a very bad language setting
self.language.encode()
except UnicodeError:
self.language = ''
try:
self.languagedesc.encode()
except UnicodeError:
self.languagedesc = ''
try:
self.codec = data[7]
try:
self.samplerate = int(data[9])
except ValueError, e:
if data[9].lower().find('khz') > 0:
pos = data[9].lower().find('khz')
self.samplerate = int(data[9][:pos]) * 1000
else:
raise e
self.channels = data[13]
except Exception, e:
# WTF, strange DVD, now try to find the bug (may not work)
self.codec = data[data.index('Format:') + 1]
try:
freq = data[data.index('Frequency:') + 1]
self.samplerate = int(freq)
except ValueError:
if freq.lower().find('khz') > 0:
self.samplerate = int(freq[:freq.lower().find('khz')])*1000
self.channels = int(data[data.index('Channels:') + 1])
class DVDSubtitle(mediainfo.SubtitleInfo):
def __init__(self, data):
mediainfo.SubtitleInfo.__init__(self)
self.rawdata = data
self.number = int(data[1])
try:
self.id = int(data[10],0)
except:
self.id = self.number
self.language = data[3]
try:
self.language.encode()
except UnicodeError:
self.language = ''
self.languagedesc = data[5]
try:
self.languagedesc.encode()
except UnicodeError:
self.languagedesc = ''
self.content = data[7]
try:
self.languagedesc.encode()
except UnicodeError:
self.languagedesc = ''
def __repr__(self):
if self.languagedesc != '':
return self.languagedesc
return self.language
class DVDVideo(mediainfo.VideoInfo):
def __init__(self, data):
mediainfo.VideoInfo.__init__(self)
self.rawdata = data
self.width = int(data[12])
self.height = int(data[14])
self.fps = float(data[5])
self.aspect = data[10]
class DVDTitle(mediainfo.AVInfo):
def __init__(self, data):
mediainfo.AVInfo.__init__(self)
self.rawdata = data
self.number = int(data[1])
self.keys.append('subtitles')
self.keys.append('chapters')
self.mime = 'video/mpeg'
l = re.split('[:.]', data[3])
self.length = (int(l[0])*60+int(l[1]))*60+int(l[2])
self.trackno = int(data[1])
self.chapters = int(data[5])
class DVDInfo(DiscInfo):
def __init__(self, device):
DiscInfo.__init__(self)
self.context = 'video'
self.offset = 0
if mediainfo.DEBUG > 1:
print 'trying lsdvd for scanning the disc'
if os.path.isdir(device):
self.valid = self.isDVDdir(device)
else:
self.valid = self.isDisc(device)
if self.valid and self.tracks:
self.keys.append('length')
self.length = 0
first = 0
for t in self.tracks:
self.length += t.length
if not first:
first = t.length
if self.length/len(self.tracks) == first:
# badly mastered dvd
self.length = first
if mediainfo.DEBUG > 1:
print 'lsdvd detection ok'
self.mime = 'video/dvd'
self.type = 'DVD'
self.subtype = 'video'
def lsdvd(self, path):
"""
use lsdvd to get informations about this disc
"""
import popen2
if mediainfo.DEBUG > 1:
print '%s -v -n -a -s "%s"' % (LSDVD_EXE, path)
child = popen2.Popen3('%s -v -n -a -s "%s"' % \
(LSDVD_EXE, path), 1, 100)
for line in child.fromchild.readlines():
data = line.replace(',', '').replace('\t', '').\
replace('\n', '').lstrip(' ').split(' ')
if mediainfo.DEBUG > 1:
print data
if len(data) > 2:
if data[0] == 'Title:':
ti = DVDTitle(data)
self.appendtrack(ti)
elif data[0] == 'Audio:':
self.tracks[-1].audio.append(DVDAudio(data))
elif data[0] == 'Subtitle:':
self.tracks[-1].subtitles.append(DVDSubtitle(data))
elif data[0] == 'VTS:':
self.tracks[-1].video.append(DVDVideo(data))
self.tracks[-1].video[-1].length = self.tracks[-1].length
elif data[:3] == ['Number', 'of', 'Angles:']:
self.tracks[-1].angles = int(data[3])
self.tracks[-1].keys.append('angles')
elif data[:2] == ['Longest', 'track:']:
self.tracks[-1].longesttrack = int(data[2])
self.tracks[-1].keys.append('longesttrack')
child.wait()
child.fromchild.close()
child.childerr.close()
child.tochild.close()
if len(self.tracks) > 0:
for ti in self.tracks:
ti.trackof = len(self.tracks)
return 1
return 0
def isDVDdir(self, dirname):
if os.path.isdir(dirname+'/VIDEO_TS') or \
os.path.isdir(dirname+'/video_ts') or \
os.path.isdir(dirname+'/Video_ts'):
return self.lsdvd(dirname)
return 0
def isDisc(self, device):
if DiscInfo.isDisc(self, device) != 2:
return 0
# 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()
return 0
# 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:
return 0
ret = self.lsdvd(device)
if not ret:
# we are very sure this is a DVD, maybe the drive was not
# ready, let's try again
return self.lsdvd(device)
return 1
if os.environ.has_key('LSDVD') and os.environ['LSDVD']:
LSDVD_EXE = os.environ['LSDVD']
else:
for path in os.environ['PATH'].split(':'):
if os.path.isfile(os.path.join(path, 'lsdvd')):
LSDVD_EXE = os.path.join(path, 'lsdvd')
break
else:
if mediainfo.DEBUG:
print 'ImportError: lsdvd not found'
raise ImportError
mmpython.registertype( 'video/dvd', mediainfo.EXTENSION_DEVICE,
mediainfo.TYPE_AV, DVDInfo )
mmpython.registertype( 'video/dvd', mediainfo.EXTENSION_DIRECTORY,
mediainfo.TYPE_AV, DVDInfo )
|