Update of /cvsroot/freevo/kaa/metadata/src/disc
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14035/src/disc
Added Files:
.cvsignore CDDB.py DiscID.py __init__.py audioinfo.py
cdrommodule.c datainfo.py discinfo.py dvdinfo.py ifomodule.c
lsdvd.py vcdinfo.py
Log Message:
move current mmpython cvs to kaa.metadata
--- NEW FILE: vcdinfo.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# vcdinfo.py - parse vcd track informations
# -----------------------------------------------------------------------------
# $Id: vcdinfo.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
#
# -----------------------------------------------------------------------------
# kaa-Metadata - Media Metadata for Python
# Copyright (C) 2003-2005 Thomas Schueppel, Dirk Meyer
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file doc/CREDITS for a complete list of authors.
#
# 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
#
# -----------------------------------------------------------------------------
# kaa imports
from kaa.metadata import factory
from kaa.metadata import mediainfo
from discinfo import DiscInfo
import cdrom
class VCDInfo(DiscInfo):
def __init__(self,device):
DiscInfo.__init__(self)
self.context = 'video'
self.offset = 0
self.mime = 'video/vcd'
self.type = 'CD'
self.subtype = 'video'
# parse disc
self.parseDisc(device)
def parseDisc(self, device):
type = None
if DiscInfo.isDisc(self, device) != 2:
raise mediainfo.KaaMetadataParseError()
# brute force reading of the device to find out if it is a VCD
f = open(device,'rb')
f.seek(32768, 0)
buffer = f.read(60000)
f.close()
if buffer.find('SVCD') > 0 and buffer.find('TRACKS.SVD') > 0 and \
buffer.find('ENTRIES.SVD') > 0:
type = 'SVCD'
elif buffer.find('INFO.VCD') > 0 and buffer.find('ENTRIES.VCD') > 0:
type = 'VCD'
else:
raise mediainfo.KaaMetadataParseError()
# read the tracks to generate the title list
device = open(device)
(first, last) = cdrom.toc_header(device)
lmin = 0
lsec = 0
num = 0
for i in range(first, last + 2):
if i == last + 1:
min, sec, frames = cdrom.leadout(device)
else:
min, sec, frames = cdrom.toc_entry(device, i)
if num:
vi = mediainfo.VideoInfo()
# 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()
factory.register( 'video/vcd', mediainfo.EXTENSION_DEVICE,
mediainfo.TYPE_AV, VCDInfo )
--- NEW FILE: .cvsignore ---
*.pyc *.pyo
--- NEW FILE: dvdinfo.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# dvdinfo.py - parse dvd title structure
# -----------------------------------------------------------------------------
# $Id: dvdinfo.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
#
# TODO: update the ifomodule and remove the lsdvd parser
#
# -----------------------------------------------------------------------------
# kaa-Metadata - Media Metadata for Python
# Copyright (C) 2003-2005 Thomas Schueppel, Dirk Meyer
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file doc/CREDITS for a complete list of authors.
#
# 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
#
# -----------------------------------------------------------------------------
# python imports
import os
import logging
# kaa imports
import ifoparser
from kaa.metadata import mediainfo
from kaa.metadata import factory
from discinfo import DiscInfo
# get logging object
log = logging.getLogger('metadata')
class DVDAudio(mediainfo.AudioInfo):
def __init__(self, title, number):
mediainfo.AudioInfo.__init__(self)
self.number = number
self.title = title
self.id, self.language, self.codec, self.channels, self.samplerate = \
ifoparser.audio(title, number)
class DVDTitle(mediainfo.AVInfo):
def __init__(self, number):
mediainfo.AVInfo.__init__(self)
self.number = number
self.chapters, self.angles, self.length, audio_num, \
subtitles_num = ifoparser.title(number)
self.keys.append('chapters')
self.keys.append('subtitles')
self.mime = 'video/mpeg'
for a in range(1, audio_num+1):
self.audio.append(DVDAudio(number, a))
for s in range(1, subtitles_num+1):
self.subtitles.append(ifoparser.subtitle(number, s)[0])
class DVDInfo(DiscInfo):
def __init__(self, device):
DiscInfo.__init__(self)
self.context = 'video'
self.offset = 0
log.info('trying buggy dvd detection')
if isinstance(device, file):
self.parseDVDiso(device)
elif os.path.isdir(device):
self.parseDVDdir(device)
else:
self.parseDisc(device)
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
self.mime = 'video/dvd'
self.type = 'DVD'
self.subtype = 'video'
def parseDVDdir(self, dirname):
if not (os.path.isdir(dirname+'/VIDEO_TS') or \
os.path.isdir(dirname+'/video_ts') or \
os.path.isdir(dirname+'/Video_ts')):
raise mediainfo.KaaMetadataParseError()
# OK, try libdvdread
title_num = ifoparser.open(dirname)
if not title_num:
raise mediainfo.KaaMetadataParseError()
for title in range(1, title_num+1):
ti = DVDTitle(title)
ti.trackno = title
ti.trackof = title_num
self.appendtrack(ti)
ifoparser.close()
return 1
def parseDisc(self, device):
if DiscInfo.isDisc(self, device) != 2:
raise mediainfo.KaaMetadataParseError()
# 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 mediainfo.KaaMetadataParseError()
# 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 mediainfo.KaaMetadataParseError()
# OK, try libdvdread
title_num = ifoparser.open(device)
if not title_num:
raise mediainfo.KaaMetadataParseError()
for title in range(1, title_num+1):
ti = DVDTitle(title)
ti.trackno = title
ti.trackof = title_num
self.appendtrack(ti)
ifoparser.close()
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 mediainfo.KaaMetadataParseError()
# 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 mediainfo.KaaMetadataParseError()
# OK, try libdvdread
title_num = ifoparser.open(f.name)
if not title_num:
raise mediainfo.KaaMetadataParseError()
for title in range(1, title_num+1):
ti = DVDTitle(title)
ti.trackno = title
ti.trackof = title_num
self.appendtrack(ti)
ifoparser.close()
if not factory.gettype('video/dvd', mediainfo.EXTENSION_DEVICE):
factory.register( 'video/dvd', mediainfo.EXTENSION_DEVICE,
mediainfo.TYPE_AV, DVDInfo )
if not factory.gettype('video/dvd', mediainfo.EXTENSION_DIRECTORY):
factory.register('video/dvd', mediainfo.EXTENSION_DIRECTORY,
mediainfo.TYPE_AV, DVDInfo)
factory.register('video/dvd', ['iso'], mediainfo.TYPE_AV, DVDInfo)
--- NEW FILE: cdrommodule.c ---
/*
* cdrommodule.c
* Python extension module for reading in audio CD-ROM data
*
* Please port me to other OSes besides Linux, Solaris, OpenBSD,
* and FreeBSD!
*
* See the README for info.
*
* Written 17 Nov 1999 by Ben Gertzfield <[EMAIL PROTECTED]>
* This work is released under the GNU GPL, version 2 or later.
*
* FreeBSD support by Michael Yoon <[EMAIL PROTECTED]>
* OpenBSD support added by Alexander Guy <[EMAIL PROTECTED]>
*
* Thanks to Viktor Fougstedt <[EMAIL PROTECTED]> for info
* on the <sys/cdio.h> include file to make this work on Solaris!
*
* Release version 1.2
*
*
*
* changes for kaa.metadata:
*
* Fixed bug in the cdrommodule that the file was not closed after usage.
* The result was a drive you can't eject while the program (e.g. Freevo)
* is running.
*
*
* CVS ID: $Id: cdrommodule.c,v 1.1 2005/07/02 16:33:11 dischi Exp $
*/
#include "Python.h"
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <linux/cdrom.h>
#endif
#if defined(sun) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/cdio.h>
#endif
/*
* Since FreeBSD has identical support but different names for lots
* of these structs and constants, we'll just #define CDDB_WHATEVER
* so that we don't have to repeat the code.
*/
#ifdef __FreeBSD__
#define CDDB_TOC_HEADER_STRUCT ioc_toc_header
#define CDDB_STARTING_TRACK_FIELD starting_track
#define CDDB_ENDING_TRACK_FIELD ending_track
#define CDDB_READ_TOC_HEADER_FLAG CDIOREADTOCHEADER
#define CDDB_TOC_ENTRY_STRUCT ioc_read_toc_single_entry
#define CDDB_TRACK_FIELD track
#define CDDB_FORMAT_FIELD address_format
#define CDDB_MSF_FORMAT CD_MSF_FORMAT
#define CDDB_ADDR_FIELD entry.addr
#define CDDB_READ_TOC_ENTRY_FLAG CDIOREADTOCENTRY
#define CDDB_CDROM_LEADOUT 0xaa
#define CDDB_DEFAULT_CDROM_DEVICE "/dev/cdrom"
#define CDDB_DEFAULT_CDROM_FLAGS 0
#elif defined(__OpenBSD__)
#define CDDB_TOC_HEADER_STRUCT ioc_toc_header
#define CDDB_STARTING_TRACK_FIELD starting_track
#define CDDB_ENDING_TRACK_FIELD ending_track
#define CDDB_READ_TOC_HEADER_FLAG CDIOREADTOCHEADER
#define CDDB_TOC_ENTRY_STRUCT ioc_read_toc_entry
#define CDDB_TRACK_FIELD starting_track
#define CDDB_FORMAT_FIELD address_format
#define CDDB_MSF_FORMAT CD_MSF_FORMAT
#define CDDB_ADDR_FIELD data->addr
#define CDDB_READ_TOC_ENTRY_FLAG CDIOREADTOCENTRIES
#define CDDB_CDROM_LEADOUT 0xaa
#define CDDB_DEFAULT_CDROM_DEVICE "/dev/cdrom"
#define CDDB_DEFAULT_CDROM_FLAGS 0
#else /* Linux and Solaris */
#define CDDB_TOC_HEADER_STRUCT cdrom_tochdr
#define CDDB_STARTING_TRACK_FIELD cdth_trk0
#define CDDB_ENDING_TRACK_FIELD cdth_trk1
#define CDDB_READ_TOC_HEADER_FLAG CDROMREADTOCHDR
#define CDDB_TOC_ENTRY_STRUCT cdrom_tocentry
#define CDDB_TRACK_FIELD cdte_track
#define CDDB_FORMAT_FIELD cdte_format
#define CDDB_MSF_FORMAT CDROM_MSF
#define CDDB_ADDR_FIELD cdte_addr
#define CDDB_READ_TOC_ENTRY_FLAG CDROMREADTOCENTRY
#define CDDB_CDROM_LEADOUT CDROM_LEADOUT
#ifdef sun
#define CDDB_DEFAULT_CDROM_DEVICE "/dev/vol/alias/cdrom0"
#else
#define CDDB_DEFAULT_CDROM_DEVICE "/dev/cdrom"
#endif /* sun */
#define CDDB_DEFAULT_CDROM_FLAGS O_RDONLY | O_NONBLOCK
#endif /* __FreeBSD__ */
static PyObject *cdrom_error;
static PyObject *cdrom_toc_header(PyObject *self, PyObject *args)
{
struct CDDB_TOC_HEADER_STRUCT hdr;
PyObject *cdrom_fileobj;
int cdrom_fd;
if (!PyArg_ParseTuple(args, "O!", &PyFile_Type, &cdrom_fileobj))
return NULL;
cdrom_fd = fileno(PyFile_AsFile(cdrom_fileobj));
if (ioctl(cdrom_fd, CDDB_READ_TOC_HEADER_FLAG, &hdr) < 0) {
PyErr_SetFromErrno(cdrom_error);
return NULL;
}
return Py_BuildValue("bb", hdr.CDDB_STARTING_TRACK_FIELD,
hdr.CDDB_ENDING_TRACK_FIELD);
}
static PyObject *cdrom_toc_entry(PyObject *self, PyObject *args)
{
struct CDDB_TOC_ENTRY_STRUCT entry;
PyObject *cdrom_fileobj;
int cdrom_fd;
unsigned char track;
#if defined(__OpenBSD__)
struct cd_toc_entry data;
#endif
if (!PyArg_ParseTuple(args, "O!b", &PyFile_Type, &cdrom_fileobj, &track))
return NULL;
cdrom_fd = fileno(PyFile_AsFile(cdrom_fileobj));
entry.CDDB_TRACK_FIELD = track;
entry.CDDB_FORMAT_FIELD = CDDB_MSF_FORMAT;
#if defined(__OpenBSD__)
entry.data = &data;
entry.data_len = sizeof(data);
#endif
if (ioctl(cdrom_fd, CDDB_READ_TOC_ENTRY_FLAG, &entry) < 0) {
PyErr_SetFromErrno(cdrom_error);
return NULL;
}
return Py_BuildValue("bbb", entry.CDDB_ADDR_FIELD.msf.minute,
entry.CDDB_ADDR_FIELD.msf.second,
entry.CDDB_ADDR_FIELD.msf.frame);
}
static PyObject *cdrom_leadout(PyObject *self, PyObject *args)
{
struct CDDB_TOC_ENTRY_STRUCT entry;
PyObject *cdrom_fileobj;
int cdrom_fd;
#if defined(__OpenBSD__)
struct cd_toc_entry data;
#endif
if (!PyArg_ParseTuple(args, "O!", &PyFile_Type, &cdrom_fileobj))
return NULL;
cdrom_fd = fileno(PyFile_AsFile(cdrom_fileobj));
entry.CDDB_TRACK_FIELD = CDDB_CDROM_LEADOUT;
entry.CDDB_FORMAT_FIELD = CDDB_MSF_FORMAT;
#if defined(__OpenBSD__)
entry.data = &data;
entry.data_len = sizeof(data);
#endif
if (ioctl(cdrom_fd, CDDB_READ_TOC_ENTRY_FLAG, &entry) < 0) {
PyErr_SetFromErrno(cdrom_error);
return NULL;
}
return Py_BuildValue("bbb", entry.CDDB_ADDR_FIELD.msf.minute,
entry.CDDB_ADDR_FIELD.msf.second,
entry.CDDB_ADDR_FIELD.msf.frame);
}
int cdrom_close(FILE *cdrom_file)
{
return 0;
}
static PyObject *cdrom_really_close(PyObject *self, PyObject *args)
{
PyObject *cdrom_fileobj;
int cdrom_fd;
#if defined(__OpenBSD__)
struct cd_toc_entry data;
#endif
if (!PyArg_ParseTuple(args, "O!", &PyFile_Type, &cdrom_fileobj))
return NULL;
cdrom_fd = fileno(PyFile_AsFile(cdrom_fileobj));
close(cdrom_fd);
return Py_BuildValue("b", 1);
}
static PyObject* cdrom_open(PyObject *self, PyObject *args)
{
int cdrom_fd;
FILE *cdrom_file;
char *cdrom_device = CDDB_DEFAULT_CDROM_DEVICE;
int cdrom_open_flags = CDDB_DEFAULT_CDROM_FLAGS;
PyObject *cdrom_file_object;
if (!PyArg_ParseTuple(args, "|si", &cdrom_device, &cdrom_open_flags))
return NULL;
cdrom_fd = open(cdrom_device, cdrom_open_flags);
if (cdrom_fd == -1) {
PyErr_SetFromErrno(cdrom_error);
return NULL;
}
cdrom_file = fdopen(cdrom_fd, "r");
if (cdrom_file == NULL) {
PyErr_SetFromErrno(cdrom_error);
return NULL;
}
cdrom_file_object = PyFile_FromFile(cdrom_file, cdrom_device, "r",
cdrom_close);
if (cdrom_file_object == NULL) {
PyErr_SetString(cdrom_error, "Internal conversion from file pointer to
Python object failed");
fclose(cdrom_file);
return NULL;
}
return Py_BuildValue("O", cdrom_file_object);
}
static PyMethodDef cdrom_methods[] = {
{ "toc_header", cdrom_toc_header, METH_VARARGS },
{ "toc_entry", cdrom_toc_entry, METH_VARARGS },
{ "leadout", cdrom_leadout, METH_VARARGS},
{ "open", cdrom_open, METH_VARARGS},
{ "close", cdrom_really_close, METH_VARARGS},
{ NULL, NULL }
};
void initcdrom(void)
{
PyObject *module, *dict;
module = Py_InitModule("cdrom", cdrom_methods);
dict = PyModule_GetDict(module);
cdrom_error = PyErr_NewException("cdrom.error", NULL, NULL);
PyDict_SetItemString(dict, "error", cdrom_error);
}
--- NEW FILE: __init__.py ---
--- NEW FILE: discinfo.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# discinfo.py - basic class for any discs containing collections of media.
# -----------------------------------------------------------------------------
# $Id: discinfo.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
#
# -----------------------------------------------------------------------------
# kaa-Metadata - Media Metadata for Python
# Copyright (C) 2003-2005 Thomas Schueppel, Dirk Meyer
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file doc/CREDITS for a complete list of authors.
#
# 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
#
# -----------------------------------------------------------------------------
# freevo imports
import os
import re
import time
import array
import md5
from struct import *
import logging
# kaa imports
from kaa.metadata import mediainfo
# get logging object
log = logging.getLogger('metadata')
CREATE_MD5_ID = 0
try:
from fcntl import ioctl
import DiscID
except:
log.warning('WARNING: failed to import ioctl, discinfo won\'t work')
def cdrom_disc_status(device, handle_mix = 0):
"""
check the current disc in device
return: no disc (0), audio cd (1), data cd (2), blank cd (3)
"""
CDROM_DRIVE_STATUS=0x5326
CDSL_CURRENT=( (int ) ( ~ 0 >> 1 ) )
CDROM_DISC_STATUS=0x5327
CDS_AUDIO=100
CDS_MIXED=105
CDS_DISC_OK=4
# FreeBSD ioctls - there is no CDROM.py
# XXX 0xc0086305 below creates a warning, but 0xc0086305L
# doesn't work. Suppress that warning for Linux users,
# until a better solution can be found.
if os.uname()[0] == 'FreeBSD':
CDIOREADTOCENTRYS = 0xc0086305L
CD_MSF_FORMAT = 2
try:
fd = os.open(device, os.O_RDONLY | os.O_NONBLOCK)
if os.uname()[0] == 'FreeBSD':
try:
cd_toc_entry = array.array('c', '\000'*4096)
(address, length) = cd_toc_entry.buffer_info()
buf = pack('BBHP', CD_MSF_FORMAT, 0, length, address)
s = ioctl(fd, CDIOREADTOCENTRYS, buf)
s = CDS_DISC_OK
except:
s = CDS_NO_DISC
else:
s = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)
except:
log.error('ERROR: no permission to read %s' % device)
log.error('Media detection not possible, set drive to \'empty\'')
# maybe we need to close the fd if ioctl fails, maybe
# open fails and there is no fd, maye we aren't running
# linux and don't have ioctl
try:
os.close(fd)
except:
pass
return 0
if not s == CDS_DISC_OK:
# no disc, error, whatever
try:
os.close(fd)
except:
pass
return 0
if os.uname()[0] == 'FreeBSD':
s = 0
# We already have the TOC from above
for i in range(0, 4096, 8):
control = unpack('B', cd_toc_entry[i+1])[0] & 4
track = unpack('B', cd_toc_entry[i+2])[0]
if track == 0:
break
if control == 0 and s != CDS_MIXED:
s = CDS_AUDIO
elif control != 0:
if s == CDS_AUDIO:
s = CDS_MIXED
else:
s = 100 + control # ugly, but encodes Linux ioctl returns
elif control == 5:
s = CDS_MIXED
else:
s = ioctl(fd, CDROM_DISC_STATUS)
os.close(fd)
if s == CDS_MIXED and handle_mix:
return 4
if s == CDS_AUDIO or s == CDS_MIXED:
return 1
try:
fd = open(device, 'rb')
# try to read from the disc to get information if the disc
# is a rw medium not written yet
fd.seek(32768) # 2048 multiple boundary for FreeBSD
# FreeBSD doesn't return IOError unless we try and read:
fd.read(1)
except IOError:
# not readable
fd.close()
return 3
# disc ok
fd.close()
return 2
id_cache = {}
def cdrom_disc_id(device, handle_mix=0):
"""
return the disc id of the device or None if no disc is there
"""
global id_cache
try:
if id_cache[device][0] + 0.9 > time.time():
return id_cache[device][1:]
except:
pass
disc_type = cdrom_disc_status(device, handle_mix=handle_mix)
if disc_type == 0 or disc_type == 3:
return 0, None
elif disc_type == 1 or disc_type == 4:
disc_id = DiscID.disc_id(device)
id = '%08lx_%d' % (disc_id[0], disc_id[1])
else:
f = open(device,'rb')
if os.uname()[0] == 'FreeBSD':
# FreeBSD can only seek to 2048 multiple boundaries.
# Below works on Linux and FreeBSD:
f.seek(32768)
id = f.read(829)
label = id[40:72]
id = id[813:829]
else:
f.seek(0x0000832d)
id = f.read(16)
f.seek(32808, 0)
label = f.read(32)
if CREATE_MD5_ID:
id_md5 = md5.new()
id_md5.update(f.read(51200))
id = id_md5.hexdigest()
f.close()
m = re.match("^(.*[^ ]) *$", label)
if m:
id = '%s%s' % (id, m.group(1))
id = re.compile('[^a-zA-Z0-9()_-]').sub('_', id)
id_cache[device] = time.time(), disc_type, id
id = id.replace('/','_')
return disc_type, id
class DiscInfo(mediainfo.CollectionInfo):
def isDisc(self, device):
(type, self.id) = cdrom_disc_id(device, handle_mix=1)
if type != 2:
if type == 4:
self.keys.append('mixed')
self.mixed = 1
type = 1
return type
if CREATE_MD5_ID:
if len(self.id) == 32:
self.label = ''
else:
self.label = self.id[32:]
else:
if len(self.id) == 16:
self.label = ''
else:
self.label = self.id[16:]
self.keys.append('label')
return type
--- NEW FILE: ifomodule.c ---
//based on http://arnfast.net/projects/ifoinfo.php by Jens Arnfast
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <dvdread/dvd_reader.h>
#include <dvdread/ifo_types.h>
#include <dvdread/ifo_read.h>
static PyObject *ifoinfo_open(PyObject *self, PyObject *args);
static PyObject *ifoinfo_close(PyObject *self, PyObject *args);
static PyObject *ifoinfo_read_title(PyObject *self, PyObject *args);
static PyObject *ifoinfo_get_audio_tracks(PyObject *self, PyObject *args);
static PyObject *ifoinfo_get_subtitle_tracks(PyObject *self, PyObject *args);
static PyMethodDef IfoMethods[] = {
{"open", ifoinfo_open, METH_VARARGS},
{"close", ifoinfo_close, METH_VARARGS},
{"title", ifoinfo_read_title, METH_VARARGS},
{"audio", ifoinfo_get_audio_tracks, METH_VARARGS},
{"subtitle", ifoinfo_get_subtitle_tracks, METH_VARARGS},
{NULL, NULL}
};
void initifoparser() {
(void) Py_InitModule("ifoparser", IfoMethods);
}
dvd_reader_t *dvd;
ifo_handle_t *ifofile;
static PyObject *ifoinfo_open(PyObject *self, PyObject *args) {
tt_srpt_t *tt_srpt;
int i, ch, gotopt = -1, dochapters = -1;
char *dvddevice;
if (!PyArg_ParseTuple(args, "s", &dvddevice))
return Py_BuildValue("i", 0);
dvd = DVDOpen(dvddevice);
if (!dvd)
return Py_BuildValue("i", 0);
ifofile = ifoOpen(dvd, 0);
if (!ifofile) {
DVDClose(dvd);
return Py_BuildValue("i", 0);
}
tt_srpt = ifofile->tt_srpt;
return Py_BuildValue("i", tt_srpt->nr_of_srpts);
}
static PyObject *ifoinfo_close(PyObject *self, PyObject *args) {
ifoClose(ifofile);
DVDClose(dvd);
return Py_BuildValue("i", 0);
}
static PyObject *ifoinfo_read_title(PyObject *self, PyObject *args) {
int i;
tt_srpt_t *tt_srpt;
ifo_handle_t *vtsfile;
int vtsnum, ttnnum, j;
long playtime;
if (!PyArg_ParseTuple(args, "i", &i))
return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0);
i--;
tt_srpt = ifofile->tt_srpt;
vtsnum = tt_srpt->title[i].title_set_nr;
ttnnum = tt_srpt->title[i].vts_ttn;
vtsfile = ifoOpen(dvd, vtsnum);
if (!vtsfile)
return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0);
playtime = 0;
if (vtsfile->vts_pgcit) {
dvd_time_t *ttime;
ttime = &vtsfile->vts_pgcit->pgci_srp[0].pgc->playback_time;
playtime = ((ttime->hour * 60) + ttime->minute) * 60 + ttime->second;
}
// Number of Chapters, Number of Angles, Playback time, Num Audio tracks,
// Num subtitles
return Py_BuildValue("(iiiii)", tt_srpt->title[i].nr_of_ptts,
tt_srpt->title[i].nr_of_angles, playtime,
vtsfile->vtsi_mat->nr_of_vts_audio_streams,
vtsfile->vtsi_mat->nr_of_vts_subp_streams);
}
static PyObject * ifoinfo_get_subtitle_tracks(PyObject *self, PyObject *args) {
char language[5];
int trackno;
tt_srpt_t *tt_srpt;
int vtsnum, ttnnum;
ifo_handle_t *vtsfile;
int i;
subp_attr_t *attr;
if (!PyArg_ParseTuple(args, "ii", &i, &trackno))
return Py_BuildValue("(s)", "N/A");
i--;
trackno--;
tt_srpt = ifofile->tt_srpt;
vtsnum = tt_srpt->title[i].title_set_nr;
ttnnum = tt_srpt->title[i].vts_ttn;
vtsfile = ifoOpen(dvd, vtsnum);
if (vtsfile->vts_pgcit) {
attr = &vtsfile->vtsi_mat->vts_subp_attr[trackno];
if ( attr->type == 0
&& attr->lang_code == 0
&& attr->zero1 == 0
&& attr->zero2 == 0
&& attr->lang_extension == 0 ) {
return Py_BuildValue("(s)", "N/A");
}
/* language code */
if (isalpha((int)(attr->lang_code >> 8)) && isalpha((int)(attr->lang_code &
0xff))) {
snprintf(language, 5, "%c%c", attr->lang_code >> 8, attr->lang_code &
0xff);
} else {
snprintf(language, 5, "%02x%02x", 0xff & (unsigned)(attr->lang_code >>
8),
0xff & (unsigned)(attr->lang_code & 0xff));
}
return Py_BuildValue("(s)", language);
}
}
static PyObject * ifoinfo_get_audio_tracks(PyObject *self, PyObject *args) {
char audioformat[10];
char audiolang[5];
int audiochannels;
int audioid;
int audiofreq;
audio_attr_t *attr;
int i;
int trackno;
tt_srpt_t *tt_srpt;
int vtsnum, ttnnum;
ifo_handle_t *vtsfile;
if (!PyArg_ParseTuple(args, "ii", &i, &trackno))
return Py_BuildValue("i", 0);
i--;
trackno--;
tt_srpt = ifofile->tt_srpt;
vtsnum = tt_srpt->title[i].title_set_nr;
ttnnum = tt_srpt->title[i].vts_ttn;
vtsfile = ifoOpen(dvd, vtsnum);
if (vtsfile->vts_pgcit && vtsfile->vtsi_mat) {
attr = &vtsfile->vtsi_mat->vts_audio_attr[trackno];
audioid = trackno + 128;
if ( attr->audio_format == 0
&& attr->multichannel_extension == 0
&& attr->lang_type == 0
&& attr->application_mode == 0
&& attr->quantization == 0
&& attr->sample_frequency == 0
&& attr->channels == 0
&& attr->lang_extension == 0
&& attr->unknown1 == 0
&& attr->unknown1 == 0) {
snprintf(audioformat, 10, "Unknown");
return Py_BuildValue("i", 0);
}
/* audio format */
switch (attr->audio_format) {
case 0:
snprintf(audioformat, 10, "ac3");
break;
case 1:
snprintf(audioformat, 10, "N/A");
break;
case 2:
snprintf(audioformat, 10, "mpeg1");
break;
case 3:
snprintf(audioformat, 10, "mpeg2ext");
break;
case 4:
snprintf(audioformat, 10, "lpcm");
break;
case 5:
snprintf(audioformat, 10, "N/A");
break;
case 6:
snprintf(audioformat, 10, "dts");
break;
default:
snprintf(audioformat, 10, "N/A");
}
switch (attr->lang_type) {
case 0:
assert(attr->lang_code == 0 || attr->lang_code == 0xffff);
snprintf(audiolang, 5, "N/A");
break;
case 1:
snprintf(audiolang, 5, "%c%c", attr->lang_code>>8, attr->lang_code &
0xff);
break;
default:
snprintf(audiolang, 5, "N/A");
}
switch(attr->sample_frequency) {
case 0:
audiofreq = 48;
break;
case 1:
audiofreq = -1;
break;
default:
audiofreq = -1;
}
audiochannels = attr->channels + 1;
//AUDIOTRACK: ID=%i; LANG=%s; FORMAT=%s; CHANNELS=%i; FREQ=%ikHz
return Py_BuildValue("(issii)", audioid, audiolang, audioformat,
audiochannels,
audiofreq);
}
return NULL;
}
--- NEW FILE: lsdvd.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# lsdvdinfo.py - parse dvd title structure using lsdvd
# -----------------------------------------------------------------------------
# $Id: lsdvd.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
#
# TODO: update the ifomodule and remove the lsdvd parser
#
# -----------------------------------------------------------------------------
# kaa-Metadata - Media Metadata for Python
# Copyright (C) 2003-2005 Thomas Schueppel, Dirk Meyer
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file doc/CREDITS for a complete list of authors.
#
# 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
#
# -----------------------------------------------------------------------------
# python imports
import os
import popen2
import logging
import re
# kaa imports
from kaa.metadata import mediainfo
from kaa.metadata import factory
from discinfo import DiscInfo
# get logging object
log = logging.getLogger('metadata')
LSDVD_EXE='lsdvd'
class DVDAudio(mediainfo.AudioInfo):
def __init__(self, data):
mediainfo.AudioInfo.__init__(self)
self.number = int(data[1])
if data[3] != 'xx':
self.language = data[3]
try:
# some DVDs have a very bad language setting
self.language.encode()
except UnicodeError:
self.language = ''
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 DVDVideo(mediainfo.VideoInfo):
def __init__(self, data):
mediainfo.VideoInfo.__init__(self)
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.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
log.info('trying lsdvd for scanning the disc')
if os.path.isdir(device):
self.parseDVDdir(device)
else:
self.parseDisc(device)
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
log.info('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
"""
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 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(data[3])
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')
child.wait()
child.fromchild.close()
child.childerr.close()
child.tochild.close()
if len(self.tracks) == 0:
raise mediainfo.KaaMetadataParseError()
for ti in self.tracks:
ti.trackof = len(self.tracks)
def parseDVDdir(self, dirname):
if os.path.isdir(dirname+'/VIDEO_TS') or \
os.path.isdir(dirname+'/video_ts') or \
os.path.isdir(dirname+'/Video_ts'):
self.lsdvd(dirname)
return
raise mediainfo.KaaMetadataParseError()
def parseDisc(self, device):
if DiscInfo.isDisc(self, device) != 2:
raise mediainfo.KaaMetadataParseError()
# 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 mediainfo.KaaMetadataParseError()
# 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 mediainfo.KaaMetadataParseError()
try:
self.lsdvd(device)
except mediainfo.KaaMetadataParseError:
# we are very sure this is a DVD, maybe the drive was not
# ready, let's try again
self.lsdvd(device)
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:
log.info('ImportError: lsdvd not found')
raise ImportError
factory.register( 'video/dvd', mediainfo.EXTENSION_DEVICE,
mediainfo.TYPE_AV, DVDInfo )
factory.register( 'video/dvd', mediainfo.EXTENSION_DIRECTORY,
mediainfo.TYPE_AV, DVDInfo )
--- NEW FILE: CDDB.py ---
#!/usr/bin/env python
# Module for retrieving CDDB v1 data from CDDB servers via HTTP
# Written 17 Nov 1999 by Ben Gertzfield <[EMAIL PROTECTED]>
# This work is released under the GNU GPL, version 2 or later.
# Release version 1.3
# CVS ID: $Id: CDDB.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
import urllib, string, socket, os, struct, re
name = 'CDDB.py'
version = 1.3
if os.environ.has_key('EMAIL'):
(default_user, hostname) = string.split(os.environ['EMAIL'], '@')
else:
try:
default_user = os.geteuid() or os.environ['USER'] or 'user'
except:
default_user = 'user'
hostname = socket.gethostname() or 'host'
proto = 4
default_server = 'http://freedb.freedb.org/~cddb/cddb.cgi'
def query(track_info, server_url=default_server,
user=default_user, host=hostname, client_name=name,
client_version=version, trying=0):
disc_id = track_info[0]
num_tracks = track_info[1]
query_str = (('%08lx %d ') % (long(disc_id), num_tracks))
for i in track_info[2:]:
query_str = query_str + ('%d ' % i)
query_str = urllib.quote_plus(string.rstrip(query_str))
url = "%s?cmd=cddb+query+%s&hello=%s+%s+%s+%s&proto=%i" % \
(server_url, query_str, user, host, client_name,
client_version, proto)
response = urllib.urlopen(url)
# Four elements in header: status, category, disc-id, title
header = string.split(string.rstrip(response.readline()), ' ', 3)
try:
header[0] = string.atoi(header[0])
except:
if trying > 10:
return [ 900, None ]
return query(track_info, default_server,
default_user, hostname, name, version, trying+1)
if header[0] == 200: # OK
result = { 'category': header[1], 'disc_id': header[2], 'title':
header[3] }
return [ header[0], result ]
elif header[0] == 211 or header[0] == 210: # multiple matches
result = []
for line in response.readlines():
line = string.rstrip(line)
if line == '.': # end of matches
break
# otherwise:
# split into 3 pieces, not 4
# (thanks to bgp for the fix!)
match = string.split(line, ' ', 2)
result.append({ 'category': match[0], 'disc_id': match[1], 'title':
match[2] })
return [ header[0], result ]
else:
return [ header[0], None ]
def read(category, disc_id, server_url=default_server,
user=default_user, host=hostname, client_name=name,
client_version=version, trying=0):
url = "%s?cmd=cddb+read+%s+%s&hello=%s+%s+%s+%s&proto=%i" % \
(server_url, category, disc_id, user, host, client_name,
client_version, proto)
response = urllib.urlopen(url)
header = string.split(string.rstrip(response.readline()), ' ', 3)
try:
header[0] = string.atoi(header[0])
except:
if trying > 10:
return [ 900, None ]
return read(category, disc_id, default_server,
user, host, client_name, client_version, trying+1)
if header[0] == 210 or header[0] == 417: # success or access denied
reply = []
for line in response.readlines():
line = string.rstrip(line)
if line == '.':
break;
line = string.replace(line, r'\t', "\t")
line = string.replace(line, r'\n', "\n")
line = string.replace(line, r'\\', "\\")
reply.append(line)
if header[0] == 210: # success, parse the reply
return [ header[0], parse_read_reply(reply) ]
else: # access denied. :(
return [ header[0], reply ]
else:
return [ header[0], None ]
def parse_read_reply(comments):
len_re = re.compile(r'#\s*Disc length:\s*(\d+)\s*seconds')
revis_re = re.compile(r'#\s*Revision:\s*(\d+)')
submit_re = re.compile(r'#\s*Submitted via:\s*(.+)')
keyword_re = re.compile(r'([^=]+)=(.*)')
result = {}
for line in comments:
keyword_match = keyword_re.match(line)
if keyword_match:
(keyword, data) = keyword_match.groups()
if result.has_key(keyword):
result[keyword] = result[keyword] + data
else:
result[keyword] = data
continue
len_match = len_re.match(line)
if len_match:
result['disc_len'] = int(len_match.group(1))
continue
revis_match = revis_re.match(line)
if revis_match:
result['revision'] = int(revis_match.group(1))
continue
submit_match = submit_re.match(line)
if submit_match:
result['submitted_via'] = submit_match.group(1)
continue
return result
--- NEW FILE: datainfo.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# datainfo.py - info about a normal data disc
# -----------------------------------------------------------------------------
# $Id: datainfo.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
#
# -----------------------------------------------------------------------------
# kaa-Metadata - Media Metadata for Python
# Copyright (C) 2003-2005 Thomas Schueppel, Dirk Meyer
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file doc/CREDITS for a complete list of authors.
#
# 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
#
# -----------------------------------------------------------------------------
# kaa imports
from kaa.metadata import mediainfo
from kaa.metadata import factory
from discinfo import DiscInfo
class DataDiscInfo(DiscInfo):
def __init__(self,device):
DiscInfo.__init__(self)
if DiscInfo.isDisc(self, device) != 2:
raise mediainfo.KaaMetadataParseError()
self.context = 'unknown'
self.offset = 0
self.mime = 'unknown/unknown'
self.type = 'CD'
self.subtype = 'data'
factory.register( 'cd/unknown', mediainfo.EXTENSION_DEVICE,
mediainfo.TYPE_NONE, DataDiscInfo )
--- NEW FILE: audioinfo.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# audioinfo.py - support for audio cds
# -----------------------------------------------------------------------------
# $Id: audioinfo.py,v 1.1 2005/07/02 16:33:11 dischi Exp $
#
# -----------------------------------------------------------------------------
# kaa-Metadata - Media Metadata for Python
# Copyright (C) 2003-2005 Thomas Schueppel, Dirk Meyer
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file doc/CREDITS for a complete list of authors.
#
# 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
#
# -----------------------------------------------------------------------------
# python imports
import cdrom
import logging
# kaa imports
import kaa.metadata
from kaa.metadata import mediainfo
from kaa.metadata import factory
# disc imports
import discinfo
import DiscID
import CDDB
# get logging object
log = logging.getLogger('metadata')
class AudioDiscInfo(discinfo.DiscInfo):
def __init__(self,device):
discinfo.DiscInfo.__init__(self)
self.context = 'audio'
self.offset = 0
# check disc
if discinfo.DiscInfo.isDisc(self, device) != 1:
raise mediainfo.KaaMetadataParseError()
self.query(device)
self.mime = 'audio/cd'
self.type = 'CD'
self.subtype = 'audio'
def query(self, device):
disc_id = DiscID.disc_id(device)
if kaa.metadata.USE_NETWORK:
try:
(query_stat, query_info) = CDDB.query(disc_id)
except:
# Oops no connection
query_stat = 404
else:
query_stat = 404
if query_stat == 210 or query_stat == 211:
# set this to success
query_stat = 200
for i in query_info:
if i['title'] != i['title'].upper():
query_info = i
break
else:
query_info = query_info[0]
elif query_stat != 200:
log.error("failure getting disc info, status %i" % query_stat)
if query_stat == 200:
qi = query_info['title'].split('/')
self.artist = qi[0].strip()
self.title = qi[1].strip()
for type in ('title', 'artist'):
if getattr(self, type) and \
getattr(self, type)[0] in ('"', '\'') \
and getattr(self, type)[-1] in ('"', '\''):
setattr(self, type, getattr(self, type)[1:-1])
(read_stat, read_info) = CDDB.read(query_info['category'],
query_info['disc_id'])
# id = disc_id + number of tracks
#self.id = '%s_%s' % (query_info['disc_id'], disc_id[1])
if read_stat == 210:
for i in range(0, disc_id[1]):
mi = mediainfo.MusicInfo()
mi.title = read_info['TTITLE' + `i`]
mi.album = self.title
mi.artist = self.artist
mi.genre = query_info['category']
mi.codec = 'PCM'
mi.samplerate = 44.1
mi.trackno = i+1
mi.trackof = disc_id[1]
self.tracks.append(mi)
for type in ('title', 'album', 'artist', 'genre'):
if getattr(mi, type) and \
getattr(mi, type)[0] in ('"', '\'') \
and getattr(mi, type)[-1] in ('"', '\''):
setattr(mi, type, getattr(mi, type)[1:-1])
else:
log.error("failure getting track info, status: %i" % read_stat)
# set query_stat to somthing != 200
query_stat = 400
if query_stat != 200:
log.error("failure getting disc info, status %i" % query_stat)
self.no_caching = 1
for i in range(0, disc_id[1]):
mi = mediainfo.MusicInfo()
mi.title = 'Track %s' % (i+1)
mi.codec = 'PCM'
mi.samplerate = 44.1
mi.trackno = i+1
mi.trackof = disc_id[1]
self.tracks.append(mi)
# read the tracks to generate the title list
device = open(device)
(first, last) = cdrom.toc_header(device)
lmin = 0
lsec = 0
num = 0
for i in range(first, last + 2):
if i == last + 1:
min, sec, frames = cdrom.leadout(device)
else:
min, sec, frames = cdrom.toc_entry(device, i)
if num:
self.tracks[num-1].length = (min-lmin)*60 + (sec-lsec)
num += 1
lmin, lsec = min, sec
device.close()
# correct bad titles for the tracks, containing also the artist
for t in self.tracks:
if not self.artist or not t.title.startswith(self.artist):
break
else:
for t in self.tracks:
t.title = t.title[len(self.artist):].lstrip('/ \t-_')
# correct bad titles for the tracks, containing also the title
for t in self.tracks:
if not self.title or not t.title.startswith(self.title):
break
else:
for t in self.tracks:
t.title = t.title[len(self.title):].lstrip('/ \t-_')
factory.register( 'audio/cd', mediainfo.EXTENSION_DEVICE,
mediainfo.TYPE_AUDIO, AudioDiscInfo )
--- NEW FILE: DiscID.py ---
#!/usr/bin/env python
# Module for fetching information about an audio compact disc and
# returning it in a format friendly to CDDB.
# If called from the command line, will print out disc info in a
# format identical to Robert Woodcock's 'cd-discid' program.
# Written 17 Nov 1999 by Ben Gertzfield <[EMAIL PROTECTED]>
# This work is released under the GNU GPL, version 2 or later.
# Release version 1.3
# changes for kaa.metadata:
#
# Fixed bug in the cdrommodule that the file was not closed after usage.
# The result was a drive you can't eject while the program (e.g. Freevo)
# is running. Added cvs log for DiscID and cdrommodule to keep track of
# all changes we did for kaa.metadata.
#
try:
import cdrom, sys
except ImportError:
# Seems cdrom has either not been compiler or is not supported
# on this System
pass
def cddb_sum(n):
ret = 0
while n > 0:
ret = ret + (n % 10)
n = n / 10
return ret
def disc_id(device):
device = cdrom.open(device)
(first, last) = cdrom.toc_header(device)
track_frames = []
checksum = 0
for i in range(first, last + 1):
(min, sec, frame) = cdrom.toc_entry(device, i)
checksum = checksum + cddb_sum(min*60 + sec)
track_frames.append(min*60*75 + sec*75 + frame)
(min, sec, frame) = cdrom.leadout(device)
track_frames.append(min*60*75 + sec*75 + frame)
total_time = (track_frames[-1] / 75) - (track_frames[0] / 75)
discid = ((long(checksum) % 0xff) << 24 | total_time << 8 | last)
cdrom.close(device)
return [discid, last] + track_frames[:-1] + [ track_frames[-1] / 75 ]
if __name__ == '__main__':
dev_name = None
device = None
if len(sys.argv) >= 2:
dev_name = sys.argv[1]
if dev_name:
device = open(dev_name)
else:
device = open()
disc_info = disc_id(device)
print ('%08lx' % disc_info[0]),
for i in disc_info[1:]:
print ('%d' % i),
-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog