Update of /cvsroot/freevo/freevo/src/mediadb
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31083
Modified Files:
__init__.py audio_parser.py db.py debug.py generic.py item.py
listing.py parser.py video_parser.py
Added Files:
globals.py watcher.py
Log Message:
background checking, do not split the db over directories
Index: debug.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/debug.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** debug.py 10 Apr 2005 11:20:50 -0000 1.3
--- debug.py 1 May 2005 17:34:54 -0000 1.4
***************
*** 32,40 ****
--- 32,47 ----
import sys
import cPickle
+ import notifier
from mediadb import *
+ from mediadb.globals import *
+
+ # init the notifier
+ notifier.init( notifier.GENERIC )
def print_data(data, space=' '):
for key, info in data.items():
+ if key.startswith('_'):
+ continue
if isinstance(info, (list, tuple)):
print '%s%s: [' % (space, key)
***************
*** 47,55 ****
print '%s ]' % (space)
! elif not key in ( 'mminfo', 'fxd' ):
print '%s%s: %s' % (space, key, info)
! if not data.has_key('mminfo'):
return
! mminfo = cPickle.loads(data['mminfo'])
print_data(mminfo, ' ')
print
--- 54,62 ----
print '%s ]' % (space)
! else:
print '%s%s: %s' % (space, key, info)
! if not data.has_key(MMINFO):
return
! mminfo = cPickle.loads(data[MMINFO])
print_data(mminfo, ' ')
print
***************
*** 57,68 ****
l = Listing(sys.argv[1])
if l.num_changes:
! l.update()
print
print 'Listing for %s' % l.cache.dirname
for key in l.cache.data:
! if not key in ('overlay', 'items'):
print ' %s: %s' % (key, l.cache.data[key])
print
! for file, info in l.cache.items.items():
print ' %s' % file
print_data(info)
--- 64,77 ----
l = Listing(sys.argv[1])
if l.num_changes:
! print 'update listing', l.num_changes
! l.update(fast=False)
!
print
print 'Listing for %s' % l.cache.dirname
for key in l.cache.data:
! if not key.startswith('_'):
print ' %s: %s' % (key, l.cache.data[key])
print
! for file, info in l.cache.files.items():
print ' %s' % file
print_data(info)
--- NEW FILE: globals.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# globals - Global variables used by the mediadb
# -----------------------------------------------------------------------------
# $Id: globals.py,v 1.1 2005/05/01 17:34:54 dischi Exp $
#
# -----------------------------------------------------------------------------
# Freevo - A Home Theater PC framework
# Copyright (C) 2002-2004 Krister Lagerstrom, Dirk Meyer, et al.
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file freevo/Docs/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
#
# -----------------------------------------------------------------------------
DATA_VERSION = '_V'
ITEMS = '_I'
ITEMS_MTIME = '_IM'
OVERLAY_ITEMS = '_O'
OVERLAY_MTIME = '_OM'
NEW_FILE = '_NF'
NEEDS_UPDATE = '_NU'
EXTENTION = '_E'
ISDIR = '_D'
MMINFO = '_M'
MTIME = '_T'
MTIME_DEP = '_TD'
TITLE = 'title'
FILETITLE = 'filetitle'
COVER = 'cover'
EXTRA_COVER = 'extra_cover'
TYPE = 'type'
URL = 'url'
FXD = 'fxd'
COVER_EXT = ('png', 'jpg', 'gif')
--- NEW FILE: watcher.py ---
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------------
# watcher - Watch/Scan directories and notify on changes
# -----------------------------------------------------------------------------
# $Id: watcher.py,v 1.1 2005/05/01 17:34:54 dischi Exp $
#
# FIXME: stop everything when dir is not shown
#
# -----------------------------------------------------------------------------
# Freevo - A Home Theater PC framework
# Copyright (C) 2002-2004 Krister Lagerstrom, Dirk Meyer, et al.
#
# First Edition: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
#
# Please see the file freevo/Docs/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 stat
import logging
import notifier
# get logging object
log = logging.getLogger('mediadb')
# mediadb imports
from globals import *
class Watcher:
def __init__(self):
self.listing = ''
self.notifier_scan = None
self.notifier_check = None
self.callback = None
def cwd(self, listing, callback=None):
self.callback = callback
self.listing = listing
if not listing:
if self.notifier_scan:
log.info('remove scanner')
notifier.removeTimer(self.notifier_scan)
self.notifier_scan = None
if self.notifier_check:
notifier.removeTimer(self.notifier_check)
return
num_changes = listing.cache.num_changes()
if num_changes:
log.info('%s changes in dir' % num_changes)
if not num_changes:
if self.notifier_scan:
log.info('remove scanner')
notifier.removeTimer(self.notifier_scan)
self.notifier_scan = None
else:
if not self.notifier_scan:
log.info('add scanner')
self.notifier_scan = notifier.addTimer(0, self.scan)
if not self.notifier_check:
self.notifier_check = notifier.addTimer(1000, self.check)
def scan(self):
if self.listing.cache.parse_next():
return True
log.info('remove scanner')
self.listing.cache.save()
self.notifier_scan = None
if self.callback:
self.callback()
return False
def check(self):
# check dir modification time
cache = self.listing.cache
if os.stat(cache.dirname)[stat.ST_MTIME] != \
cache.data[ITEMS_MTIME]:
if self.callback:
log.info('directory changed')
self.callback()
return True
try:
if os.stat(cache.overlay_dir)[stat.ST_MTIME] != \
cache.data[OVERLAY_MTIME]:
if self.callback:
log.info('overlay changed')
self.callback()
return True
except OSError:
# no ovrlay
pass
if self.notifier_scan:
# scanning in progress, do not check changes
return True
# FIXME: now check all items modification time
# or maybe only fxd files
return True
Index: db.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/db.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** db.py 17 Apr 2005 14:57:58 -0000 1.7
--- db.py 1 May 2005 17:34:54 -0000 1.8
***************
*** 5,8 ****
--- 5,10 ----
# $Id$
#
+ # TODO: check for images of files
+ #
#
-----------------------------------------------------------------------------
# Freevo - A Home Theater PC framework
***************
*** 35,43 ****
import time
import os
- import stat
import re
import logging
# freevo imports
import util.vfs as vfs
import util.cache as cache
--- 37,47 ----
import time
import os
import re
+ import md5
import logging
+ from stat import *
# freevo imports
+ import sysconfig
import util.vfs as vfs
import util.cache as cache
***************
*** 46,49 ****
--- 50,54 ----
# mediadb imports
import parser
+ from globals import *
# get logging object
***************
*** 53,56 ****
--- 58,67 ----
VERSION = 0.1
+ # cache dir for metadata
+ CACHE_DIR = sysconfig.VFS_DIR + '/metadata'
+
+ if not os.path.isdir(CACHE_DIR):
+ os.makedirs(CACHE_DIR)
+
class CacheList:
"""
***************
*** 66,70 ****
if dirname in self.caches:
cache = self.caches[dirname]
! mtime = os.stat(cache.file)[stat.ST_MTIME]
if mtime == cache.mtime:
return cache
--- 77,81 ----
if dirname in self.caches:
cache = self.caches[dirname]
! mtime = os.stat(cache.cachefile)[ST_MTIME]
if mtime == cache.mtime:
return cache
***************
*** 94,132 ****
dirname = os.path.normpath(os.path.abspath(dirname))
# remove softlinks from path
! dirname = os.path.realpath(dirname) + '/'
self.dirname = dirname
! self.overlay_file = vfs.getoverlay(dirname)
! self.file = self.overlay_file + '/freevo.db'
self.data = None
self.changed = False
self.check_time = 0
! if os.path.isfile(self.file):
# load cache file
! self.data = cache.load(self.file, VERSION)
! self.mtime = os.stat(self.file)[stat.ST_MTIME]
! elif not os.path.isdir(os.path.dirname(self.overlay_file)):
! # create vfs overlay dir; we will need it anyway for
! # storing the db file
! os.makedirs(os.path.dirname(self.overlay_file))
if not self.data:
# create a new cache data dict
! self.data = {'items_mtime': 0,
! 'items': {},
! 'overlay_mtime': {},
! 'overlay': {},
! 'cover': '',
! 'audiocover': '',
}
# save file to make sure the file itself exist in the future
! # process and to avoid directory changes just because the cache
! # is saved to a new file.
self.changed = True
self.save()
# 'normal' files
! self.items = self.data['items']
# files in the overlay dir
! self.overlay = self.data['overlay']
# internal stuff about changes
- self.__added = []
self.__changed = []
self.__check_global = False
--- 105,151 ----
dirname = os.path.normpath(os.path.abspath(dirname))
# remove softlinks from path
! dirname = os.path.realpath(dirname)
! if not dirname.endswith('/'):
! dirname = dirname + '/'
self.dirname = dirname
!
! for mp in vfs.mountpoints:
! if dirname.startswith(mp.mountdir):
! self.overlay_dir = mp.get_overlay(dirname)
! digest = md5.md5(mp.get_relative_path(dirname)).hexdigest()
! self.cachefile = mp.mediadb + '/' + digest + '.db'
! break
! else:
! self.overlay_dir = sysconfig.VFS_DIR + dirname
! digest = md5.md5(dirname).hexdigest()
! self.cachefile = CACHE_DIR + '/' + digest + '.db'
!
self.data = None
self.changed = False
self.check_time = 0
! if os.path.isfile(self.cachefile):
# load cache file
! self.data = cache.load(self.cachefile, VERSION)
! self.mtime = os.stat(self.cachefile)[ST_MTIME]
!
if not self.data:
# create a new cache data dict
! self.data = { DATA_VERSION: parser.VERSION,
! ITEMS_MTIME: 0,
! ITEMS: {},
! OVERLAY_MTIME: {},
! OVERLAY_ITEMS: {},
! COVER: '',
! EXTRA_COVER: '',
}
# save file to make sure the file itself exist in the future
! # process.
self.changed = True
self.save()
# 'normal' files
! self.files = self.data[ITEMS]
# files in the overlay dir
! self.overlay = self.data[OVERLAY_ITEMS]
# internal stuff about changes
self.__changed = []
self.__check_global = False
***************
*** 142,146 ****
! def check(self, overlay = False):
"""
Check the directory for changes.
--- 161,165 ----
! def check(self, overlay = False, complete_check = False):
"""
Check the directory for changes.
***************
*** 148,164 ****
if overlay:
# handling the overlay dir
! dirname = self.overlay_file
listing = self.overlay
! mtime = 'overlay_mtime'
else:
# handling the 'normal' dir
dirname = self.dirname
! listing = self.items
! mtime = 'items_mtime'
deleted = []
! # get mtime (may be 0 for devices)
! data_mtime = os.stat(dirname)[stat.ST_MTIME]
! if data_mtime != self.data[mtime] or not data_mtime:
log.debug('check %s' % dirname)
# mtime differs, check directory for added and deleted files
--- 167,193 ----
if overlay:
# handling the overlay dir
! dirname = self.overlay_dir
listing = self.overlay
! mtime = OVERLAY_MTIME
else:
# handling the 'normal' dir
dirname = self.dirname
! listing = self.files
! mtime = ITEMS_MTIME
deleted = []
! added = []
! try:
! # get mtime (may be 0 for devices)
! data_mtime = os.stat(dirname)[ST_MTIME]
! except OSError:
! # no overlay dir
! self.check_time = time.time()
! if self.changed:
! call_later(self.save)
! return
!
! if data_mtime != self.data[mtime] or not data_mtime or complete_check:
! complete_check = True
log.debug('check %s' % dirname)
# mtime differs, check directory for added and deleted files
***************
*** 189,226 ****
# ignore such files
continue
! if overlay and (f == 'freevo.db' or f.find('.thumb.') > 0 or \
! f.endswith('.raw') or f.endswith('.cache')):
# ignore such files in overlay
continue
! fullname = dirname + '/' + f
! if overlay and os.path.isdir(fullname):
# ignore directories in overlay
continue
! # add as added
! self.__added.append((f, fullname))
- for basename, info in listing.items():
- # check all files for changes (compare mtime)
- if self.reduce_files and not basename in self.reduce_files:
- continue
- filename = dirname + '/' + basename
- mtime = os.stat(filename)[stat.ST_MTIME]
- if mtime != info['mtime']:
- # changed
- info['mtime'] = mtime
- self.__changed.append((basename, filename, info))
- elif info.has_key('isdir'):
- # For directories also check the overlay directory. A change
- # in the overlay will change the directory, too
- overlay = vfs.getoverlay(filename)
- if os.path.isdir(overlay):
- mtime = os.stat(overlay)[stat.ST_MTIME]
- if mtime != info['overlay_mtime']:
- info['overlay_mtime'] = mtime
- self.__changed.append((basename, filename, info))
! if deleted and len(self.__added):
self.__check_global = True
self.changed = True
if overlay:
self.check_time = time.time()
--- 218,285 ----
# ignore such files
continue
! if overlay and f.endswith('.raw'):
# ignore such files in overlay
continue
! filename = dirname + f
! stat = os.stat(filename)
! isdir = S_ISDIR(stat[ST_MODE])
! if overlay and isdir:
# ignore directories in overlay
continue
! # add file
! ext = f[f.rfind('.')+1:].lower()
! title = parser.getname(f, isdir)
! info = { EXTENTION : ext,
! MTIME : stat[ST_MTIME],
! MTIME_DEP : [],
! TITLE : title,
! FILETITLE : title,
! NEW_FILE : True
! }
! if isdir:
! info[ISDIR] = True
! added.append((f, info))
! self.__changed.append((f, filename, info))
! try:
! for basename, info in listing.items():
! # check all files for changes (compare mtime)
! if self.reduce_files and not basename in self.reduce_files:
! continue
! filename = dirname + basename
! if info.has_key(NEEDS_UPDATE):
! self.__changed.append((basename, filename, info))
! continue
! mtime = os.stat(filename)[ST_MTIME]
! if mtime != info[MTIME]:
! # changed
! info[MTIME] = mtime
! self.__changed.append((basename, filename, info))
! elif info.has_key(ISDIR):
! # For directories also check the overlay directory. A
! # change in the overlay will change the directory, too
! overlay_dir = vfs.getoverlay(filename)
! if os.path.isdir(overlay_dir):
! mtime = os.stat(overlay_dir)[ST_MTIME]
! if mtime != info[OVERLAY_MTIME]:
! info[OVERLAY_MTIME] = mtime
! self.__changed.append((basename, filename, info))
! except OSError, e:
! # that shouldn't mappen, but it does on fat partitions when
! # an item is removed and nothing new is added. So if this is the
! # case, we start everything again.
! if complete_check:
! # Oops, no, that's expected at all, raise the error again
! log.exception('strange OSError, please report')
! raise e
! return self.check(overlay, True)
!
! if deleted or added:
self.__check_global = True
self.changed = True
+ if added:
+ for filename, info in added:
+ listing[filename] = info
if overlay:
self.check_time = time.time()
***************
*** 237,323 ****
if not self.changed:
return
! log.debug('save %s' % self.file)
! cache.save(self.file, self.data, VERSION)
! self.mtime = os.stat(self.file)[stat.ST_MTIME]
self.changed = False
! def parse(self, callback):
"""
Parse added and changed files. If callback is not None, the callback
will be called after each file.
"""
! if not self.__added and not self.__changed and \
! not self.__check_global:
return
self.changed = True
! for basename, filename in self.__added:
! # check new files
! log.debug('new: %s' % basename)
! ext = basename[basename.rfind('.')+1:].lower()
! if ext == basename:
! ext = ''
! info = { 'ext' : ext,
! 'mtime' : os.stat(filename)[stat.ST_MTIME],
! 'mtime_dep': []
! }
! parser.parse(basename, filename, info)
!
! prefix = basename[:-len(ext)]
! if ext in ('png', 'jpg', 'gif'):
! # the new item is an image, search all items for a similar
! # name to add the file as cover
! for i_basename, i_info in self.items.items():
! if i_basename[:-len(i_info['ext'])] == prefix:
! i_info['cover'] = filename
! else:
! # search the items in the list for covers matching the
! # basename of the new item
! for ext in ('png', 'jpg', 'gif'):
! if prefix + ext in self.items:
! info['cover'] = self.dirname + '/' + prefix + ext
! if prefix + ext in self.overlay:
! info['cover'] = self.overlay_file + '/' + prefix + ext
! if vfs.isoverlay(filename):
! self.overlay[basename] = info
! else:
! self.items[basename] = info
! if callback:
! callback()
! for basename, filename, info in self.__changed:
! # check changed files
! log.debug('changed: %s' % filename)
! parser.parse(basename, filename, info)
! log.debug(info['mtime_dep'])
! for key in info['mtime_dep']:
! del info[key]
! info['mtime_dep'] = []
! if callback:
! callback()
if self.__check_global:
# check global data when files are added or deleted
for cover in ('cover.png', 'cover.jpg', 'cover.gif'):
! if self.items.has_key(cover):
# directory cover image
! self.data['cover'] = self.dirname + '/' + cover
! self.data['audiocover'] = self.data['cover']
break
if self.overlay.has_key(cover):
# cover in overlay
! self.data['cover'] = self.overlay_file + '/' + cover
! self.data['audiocover'] = self.data['cover']
break
else:
# no cover, try to find at least some image that can be used
# as cover for audio items
! self.data['cover'] = ''
! self.data['audiocover'] = ''
cover = []
! for f, i in self.items.items():
! if i['ext'] in ('png', 'jpg', 'gif'):
cover.append(f)
if len(cover) > 10:
--- 296,384 ----
if not self.changed:
return
! log.debug('save %s' % self.cachefile)
! cache.save(self.cachefile, self.data, VERSION)
! self.mtime = os.stat(self.cachefile)[ST_MTIME]
self.changed = False
! def parse_next(self):
! """
! Parse the next item in the changed list. Return True if more
! items are in the list, otherwise return False. This function
! should be called from the notifier to parse all items in the
! background.
! """
! if not self.__changed:
! return False
! basename, filename, info = self.__changed.pop()
! log.debug('parse_next: %s' % basename)
! parser.parse(basename, filename, info, self, self.items())
! self.changed = True
! if not self.__changed:
! return False
! return True
!
!
! def parse_item(self, item):
! """
! Parse the info for the given file if it is in the changed list.
! """
! for c in self.__changed:
! if c[2] == item.attr:
! basename, filename, info = c
! log.debug('parse_item: %s' % basename)
! parser.parse(basename, filename, info, self, self.items())
! self.changed = True
! self.__changed.remove(c)
! return True
! return False
!
!
! def parse(self, callback, fast_scan=False):
"""
Parse added and changed files. If callback is not None, the callback
will be called after each file.
"""
! if not self.__changed and not self.__check_global:
return
self.changed = True
! items = self.items()
!
! if fast_scan:
! for basename, filename, info in self.__changed:
! info[NEEDS_UPDATE] = True
! else:
! for basename, filename, info in self.__changed:
! # check changed files
! log.debug('changed: %s' % filename)
! parser.parse(basename, filename, info, self, items)
! if callback:
! callback()
! self.__changed = []
if self.__check_global:
# check global data when files are added or deleted
for cover in ('cover.png', 'cover.jpg', 'cover.gif'):
! if self.files.has_key(cover):
# directory cover image
! self.data[COVER] = self.dirname + '/' + cover
! self.data[EXTRA_COVER] = self.data[COVER]
break
if self.overlay.has_key(cover):
# cover in overlay
! self.data[COVER] = self.overlay_dir + '/' + cover
! self.data[EXTRA_COVER] = self.data[COVER]
break
else:
# no cover, try to find at least some image that can be used
# as cover for audio items
! self.data[COVER] = ''
! self.data[EXTRA_COVER] = ''
cover = []
! for f, i in self.files.items():
! if i[EXTENTION] in ('png', 'jpg', 'gif'):
cover.append(f)
if len(cover) > 10:
***************
*** 325,333 ****
break
if len(cover) == 1:
! self.data['audiocover'] = cover[0]
else:
cover = filter(parser.cover_filter, cover)
if cover:
! self.data['audiocover'] = cover[0]
if callback:
--- 386,394 ----
break
if len(cover) == 1:
! self.data[EXTRA_COVER] = cover[0]
else:
cover = filter(parser.cover_filter, cover)
if cover:
! self.data[EXTRA_COVER] = cover[0]
if callback:
***************
*** 335,374 ****
self.save()
- self.__added = []
- self.__changed = []
self.__check_global = False
self.reduce_files = []
! def add_missing(self):
"""
! Add the new files still missing in the databse with
! basic attributes.
"""
! if not self.__added:
! return
!
! for basename, filename in self.__added:
! ext = basename[basename.rfind('.')+1:].lower()
! if ext == basename:
! ext = ''
! info = { 'ext' : ext,
! 'mtime' : 1,
! 'mtime_dep': []
! }
! parser.parse(basename, filename, info, True)
! if vfs.isoverlay(filename):
! self.overlay[basename] = info
! else:
! self.items[basename] = info
! def list(self):
"""
! Return all items.
"""
! return self.items.items() + self.overlay.items()
def num_changes(self):
"""
--- 396,428 ----
self.save()
self.__check_global = False
self.reduce_files = []
! def items(self):
"""
! Return all items.
"""
! return self.files.items() + self.overlay.items()
! def keys(self):
"""
! Return all keys.
"""
! return self.files.keys() + self.overlay.keys()
+ def filename(self, basename):
+ """
+ Return full filename of the basename (handles overlay).
+ """
+ if basename in self.files:
+ return self.dirname + basename
+ if basename in self.overlay:
+ return self.overlay_dir + basename
+ raise OSError('No key "%s" in cache' % basename)
+
+
def num_changes(self):
"""
***************
*** 378,382 ****
if self.reduce_files or self.check_time + 2 < time.time():
self.check()
! changes = len(self.__added) + len(self.__changed)
if self.__check_global:
return changes + 1
--- 432,436 ----
if self.reduce_files or self.check_time + 2 < time.time():
self.check()
! changes = len(self.__changed)
if self.__check_global:
return changes + 1
***************
*** 398,414 ****
"""
def __init__(self, filename, db):
! self.file = db
self.data = None
! if os.path.isfile(self.file):
# load cache file
! self.data = cache.load(self.file, VERSION)
! self.mtime = os.stat(self.file)[stat.ST_MTIME]
if not self.data:
# create a new cache data dict
! self.data = { 'ext': '',
! 'cover': '',
! 'audiocover': '',
! 'mtime' : os.stat(filename)[stat.ST_MTIME],
! 'mtime_dep': []
}
# save file to make sure the file itself exist in the future
--- 452,469 ----
"""
def __init__(self, filename, db):
! self.cachefile = db
self.data = None
! if os.path.isfile(self.cachefile):
# load cache file
! self.data = cache.load(self.cachefile, VERSION)
! self.mtime = os.stat(self.cachefile)[ST_MTIME]
if not self.data:
# create a new cache data dict
! self.data = { DATA_VERSION: parser.VERSION,
! EXTENTION : '',
! COVER : '',
! EXTRA_COVER : '',
! MTIME : os.stat(filename)[ST_MTIME],
! MTIME_DEP : []
}
# save file to make sure the file itself exist in the future
***************
*** 417,421 ****
self.changed = True
basename = filename[filename.rfind('/'):]
! parser.parse(basename, filename, self.data)
self.save()
--- 472,476 ----
self.changed = True
basename = filename[filename.rfind('/'):]
! parser.parse(basename, filename, self.data, self, [])
self.save()
***************
*** 427,433 ****
if not self.changed:
return
! log.info('save %s' % self.file)
! cache.save(self.file, self.data, VERSION)
! self.mtime = os.stat(self.file)[stat.ST_MTIME]
self.changed = False
--- 482,488 ----
if not self.changed:
return
! log.debug('save %s' % self.cachefile)
! cache.save(self.cachefile, self.data, VERSION)
! self.mtime = os.stat(self.cachefile)[ST_MTIME]
self.changed = False
Index: audio_parser.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/audio_parser.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** audio_parser.py 10 Apr 2005 11:20:50 -0000 1.5
--- audio_parser.py 1 May 2005 17:34:54 -0000 1.6
***************
*** 43,46 ****
--- 43,49 ----
#
+ # internal version of the file
+ VERSION = 0.1
+
def cache(listing):
"""
***************
*** 184,197 ****
except:
continue
! myname = vfs.getoverlay(os.path.join(path, 'cover.jpg'))
if id3.tag:
images = id3.tag.getImages();
for img in images:
! if vfs.isfile(myname) and (get_md5(vfs.open(myname,'rb')) == \
! get_md5(img.imageData)):
# Image already there and has identical md5, skip
pass
! elif not vfs.isfile(myname):
! f = vfs.open(myname, "wb")
f.write(img.imageData)
f.flush()
--- 187,201 ----
except:
continue
! myname = vfs.getoverlay(os.path.join(item.dirname, 'cover.jpg'))
if id3.tag:
images = id3.tag.getImages();
for img in images:
! if os.path.isfile(myname) and \
! (get_md5(vfs.open(myname,'rb')) == \
! get_md5(img.imageData)):
# Image already there and has identical md5, skip
pass
! elif not os.path.isfile(myname):
! f = open(myname, "wb")
f.write(img.imageData)
f.flush()
***************
*** 201,206 ****
# cover
iname = os.path.splitext(os.path.basename(i))[0]+'.jpg'
! myname = vfs.getoverlay(os.path.join(path, iname))
! f = vfs.open(myname, "wb")
f.write(img.imageData)
f.flush()
--- 205,210 ----
# cover
iname = os.path.splitext(os.path.basename(i))[0]+'.jpg'
! myname = vfs.getoverlay(os.path.join(item.dirname, iname))
! f = open(myname, "wb")
f.write(img.imageData)
f.flush()
Index: listing.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/listing.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** listing.py 10 Apr 2005 11:20:50 -0000 1.5
--- listing.py 1 May 2005 17:34:54 -0000 1.6
***************
*** 39,42 ****
--- 39,44 ----
from db import Cache, FileCache
from item import ItemInfo
+ import parser
+ from globals import *
log = logging.getLogger('mediadb')
***************
*** 63,67 ****
self.visible = []
return
! for basename, item in self.cache.list():
self.data.append(ItemInfo(basename, dirname, item, self.cache))
self.visible = self.data
--- 65,69 ----
self.visible = []
return
! for basename, item in self.cache.items():
self.data.append(ItemInfo(basename, dirname, item, self.cache))
self.visible = self.data
***************
*** 77,91 ****
if self.num_changes == 0:
return
! if fast:
! self.cache.add_missing()
! else:
! self.cache.parse(callback)
dirname = self.dirname
cache = self.cache
! for basename, item in self.cache.list():
self.data.append(ItemInfo(basename, dirname, item, cache))
self.num_changes = 0
self.visible = self.data
!
def get_dir(self):
--- 79,90 ----
if self.num_changes == 0:
return
! self.cache.parse(callback, fast)
dirname = self.dirname
cache = self.cache
! for basename, item in self.cache.items():
self.data.append(ItemInfo(basename, dirname, item, cache))
self.num_changes = 0
self.visible = self.data
!
def get_dir(self):
***************
*** 93,98 ****
Return all directory items.
"""
! ret = filter(lambda x: x.attr.has_key('isdir'), self.visible)
! self.visible = filter(lambda x: not x.attr.has_key('isdir'),
self.visible)
return ret
--- 92,97 ----
Return all directory items.
"""
! ret = filter(lambda x: x.attr.has_key(ISDIR), self.visible)
! self.visible = filter(lambda x: not x.attr.has_key(ISDIR),
self.visible)
return ret
***************
*** 132,136 ****
ret = []
for v in visible:
! if v.attr['ext'] in suffix_list: ret.append(v)
else: self.visible.append(v)
return ret
--- 131,135 ----
ret = []
for v in visible:
! if v.attr[EXTENTION] in suffix_list: ret.append(v)
else: self.visible.append(v)
return ret
***************
*** 147,152 ****
ret = []
for v in visible:
! if v.attr.has_key('type') and \
! v.attr['type'].lower() == type.lower():
ret.append(v)
else:
--- 146,151 ----
ret = []
for v in visible:
! if v.attr.has_key(TYPE) and \
! v.attr[TYPE].lower() == type.lower():
ret.append(v)
else:
***************
*** 208,212 ****
for dirname, ( cache, all_files ) in self.caches.items():
! for basename, item in cache.list():
if basename in all_files:
self.data.append(ItemInfo(basename, dirname, item, cache))
--- 207,211 ----
for dirname, ( cache, all_files ) in self.caches.items():
! for basename, item in cache.items():
if basename in all_files:
self.data.append(ItemInfo(basename, dirname, item, cache))
***************
*** 220,224 ****
for dirname, ( cache, all_files ) in self.caches.items():
cache.parse(callback)
! for basename, item in cache.list():
if basename in all_files:
self.data.append(ItemInfo(basename, dirname, item, cache))
--- 219,223 ----
for dirname, ( cache, all_files ) in self.caches.items():
cache.parse(callback)
! for basename, item in cache.items():
if basename in all_files:
self.data.append(ItemInfo(basename, dirname, item, cache))
Index: __init__.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/__init__.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** __init__.py 10 Apr 2005 11:20:41 -0000 1.4
--- __init__.py 1 May 2005 17:34:54 -0000 1.5
***************
*** 42,46 ****
--- 42,53 ----
from parser import cache, init
from generic import get
+ from watcher import Watcher as _Watcher
+ from globals import *
+
+ watcher = _Watcher()
# init parsing module
init()
+
+ def item():
+ return ItemInfo('', '', {})
Index: parser.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/parser.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** parser.py 17 Apr 2005 16:40:23 -0000 1.6
--- parser.py 1 May 2005 17:34:54 -0000 1.7
***************
*** 33,36 ****
--- 33,37 ----
import os
import stat
+ import time
import mmpython
import pickle
***************
*** 40,60 ****
# freevo imports
import config
- import util.fxdparser
import util.vfs as vfs
# mediadb imports
import db
# list of external parser
_parser = []
def init():
"""
Init the parser module
"""
for f in os.listdir(os.path.dirname(__file__)):
if f.endswith('_parser.py'):
exec('import %s' % f[:-3])
_parser.append(eval(f[:-3]))
--- 41,68 ----
# freevo imports
import config
import util.vfs as vfs
+ import util
# mediadb imports
import db
+ from globals import *
# list of external parser
_parser = []
+ # internal version of the file
+ VERSION = 0.1
+
def init():
"""
Init the parser module
"""
+ global VERSION
+ VERSION += mmpython.version.CHANGED
for f in os.listdir(os.path.dirname(__file__)):
if f.endswith('_parser.py'):
exec('import %s' % f[:-3])
_parser.append(eval(f[:-3]))
+ VERSION += eval(f[:-3]).VERSION
***************
*** 67,71 ****
ret = {}
for k in object.keys:
! if not k in [ 'thumbnail', 'url' ] and getattr(object,k) != None:
value = getattr(object,k)
if isstring(value):
--- 75,79 ----
ret = {}
for k in object.keys:
! if not k in [ 'thumbnail', URL ] and getattr(object,k) != None:
value = getattr(object,k)
if isstring(value):
***************
*** 146,224 ****
! def parse(basename, filename, object, fast_scan=False):
"""
Add additional informations to filename, object.
"""
! if object.has_key('type'):
! del object['url']
! del object['type']
mminfo = None
! if not fast_scan and not object['ext'] in [ 'xml', 'fxd' ]:
mminfo = mmpython.parse(filename)
is_dir = os.path.isdir(filename)
title = getname(filename, is_dir)
! object['title:filename'] = title
if mminfo:
# store mmpython data as pickle for faster loading
! object['mminfo'] = cPickle.dumps(simplify(mminfo),
pickle.HIGHEST_PROTOCOL)
! if mminfo.title:
! object['title'] = mminfo.title.replace('\0', '').strip()
else:
! object['title'] = title
! elif object.has_key('mminfo'):
! del object['mminfo']
! object['title'] = title
else:
! object['title'] = title
if is_dir:
! object['isdir'] = True
if vfs.abspath(filename + '/' + basename + '.fxd'):
# directory is covering a fxd file
! object['type'] = 'fxd'
! if not fast_scan:
! # Create a simple (fast) cache of subdirs to get some basic idea
! # about the files inside the directory
! c = db.Cache(filename)
! if c.num_changes():
! c.add_missing()
! listing = vfs.listdir(filename, include_overlay=True)
! # get directory cover
! for l in listing:
! if l.endswith('/cover.png') or l.endswith('/cover.jpg') or \
! l.endswith('/cover.gif'):
! object['cover'] = l
! break
! else:
! if object.has_key('cover'):
! del object['cover']
! if object.has_key('audiocover'):
! del object['audiocover']
! files = util.find_matches(listing, ('jpg', 'gif', 'png' ))
! if len(files) == 1:
! object['audiocover'] = files[0]
! elif len(files) > 1 and len(files) < 10:
! files = filter(cover_filter, files)
! if files:
! object['audiocover'] = files[0]
! # check for fxd files in the directory
! fxd = vfs.abspath(filename + '/folder.fxd')
! if fxd:
! object['fxd'] = fxd
! elif object.has_key('fxd'):
! del object['fxd']
! # save directory overlay mtime
! overlay = vfs.getoverlay(filename)
! if os.path.isdir(overlay):
! mtime = os.stat(overlay)[stat.ST_MTIME]
! object['overlay_mtime'] = mtime
! else:
! object['overlay_mtime'] = 0
else:
! if object.has_key('isdir'):
! del object['isdir']
# call external parser
--- 154,267 ----
! def parse(basename, filename, object, cache, listing):
"""
Add additional informations to filename, object.
"""
! for key in object[MTIME_DEP]:
! del object[key]
! object[MTIME_DEP] = []
!
! for key in [ URL, TYPE, NEEDS_UPDATE ]:
! if object.has_key(key):
! del object[key]
!
! if object.has_key(NEW_FILE):
! added = True
! del object[NEW_FILE]
! else:
! added = False
!
mminfo = None
! ext = object[EXTENTION]
! if not ext in [ 'xml', 'fxd' ]:
mminfo = mmpython.parse(filename)
is_dir = os.path.isdir(filename)
title = getname(filename, is_dir)
! object[FILETITLE] = title
!
if mminfo:
# store mmpython data as pickle for faster loading
! object[MMINFO] = cPickle.dumps(simplify(mminfo),
pickle.HIGHEST_PROTOCOL)
! if hasattr(mminfo, TITLE) and mminfo.title:
! object[TITLE] = mminfo.title.replace('\0', '').strip()
else:
! object[TITLE] = title
! elif object.has_key(MMINFO):
! del object[MMINFO]
! object[TITLE] = title
else:
! object[TITLE] = title
if is_dir:
! object[ISDIR] = True
if vfs.abspath(filename + '/' + basename + '.fxd'):
# directory is covering a fxd file
! object[TYPE] = 'fxd'
! # Create a simple (fast) cache of subdirs to get some basic idea
! # about the files inside the directory
! c = db.Cache(filename)
! if c.num_changes():
! c.parse(None, True)
!
! listing = c.keys()
!
! # get directory cover
! for fname in listing:
! if fname in ( 'cover.png', 'cover.jpg', 'cover.gif'):
! object[COVER] = c.filename(fname)
! object[EXTRA_COVER] = c.filename(fname)
! break
! else:
! if object.has_key(COVER):
! del object[COVER]
! if object.has_key(EXTRA_COVER):
! del object[EXTRA_COVER]
! files = util.find_matches(listing, COVER_EXT)
! if len(files) == 1:
! object[EXTRA_COVER] = files[0]
! elif len(files) > 1 and len(files) < 10:
! files = filter(cover_filter, files)
! if files:
! object[EXTRA_COVER] = files[0]
!
! # get folder fxd
! for fname in listing:
! if fname == 'folder.fxd':
! object[FXD] = c.filename(fname)
! break
! else:
! if object.has_key(FXD):
! del object[FXD]
!
! # save directory overlay mtime
! overlay = vfs.getoverlay(filename)
! if os.path.isdir(overlay):
! mtime = os.stat(overlay)[stat.ST_MTIME]
! object[OVERLAY_MTIME] = mtime
! else:
! object[OVERLAY_MTIME] = 0
else:
! if object.has_key(ISDIR):
! del object[ISDIR]
!
! if ext in COVER_EXT:
! # find items that could have this file as cover
! splitext = basename[:-len(ext)]
! for key, value in listing:
! if key.startswith(splitext) and \
! not value[EXTENTION] in COVER_EXT:
! value[COVER] = filename
! else:
! # search for a cover for this file
! if object.has_key(COVER):
! del object[COVER]
! splitext = basename[:-len(ext)]
! for key, value in listing:
! if key.startswith(splitext) and value[EXTENTION] in COVER_EXT:
! object[COVER] = cache.filename(key)
!
# call external parser
Index: video_parser.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/video_parser.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** video_parser.py 10 Apr 2005 11:20:50 -0000 1.4
--- video_parser.py 1 May 2005 17:34:54 -0000 1.5
***************
*** 30,33 ****
--- 30,38 ----
#
-----------------------------------------------------------------------------
+ # internal version of the file
+ VERSION = 0.1
+
+ from globals import *
+
def parse(filename, object, mminfo):
"""
***************
*** 35,40 ****
"""
if mminfo and mminfo.type == 'DVD':
! object['url'] = 'dvd://' + filename
! object['type'] = 'dvd'
--- 40,45 ----
"""
if mminfo and mminfo.type == 'DVD':
! object[URL] = 'dvd://' + filename
! object[TYPE] = 'dvd'
Index: item.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/item.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** item.py 10 Apr 2005 11:20:50 -0000 1.4
--- item.py 1 May 2005 17:34:54 -0000 1.5
***************
*** 40,43 ****
--- 40,46 ----
from util.callback import *
+ # mediadb globals
+ from globals import *
+
# get logging object
log = logging.getLogger('mediadb')
***************
*** 53,57 ****
attr = {}
if basename:
! attr['ext'] = basename[basename.rfind('.')+1:].lower()
# attr is the dict that will be stored in the mediadb
self.attr = attr
--- 56,60 ----
attr = {}
if basename:
! attr[EXTENTION] = basename[basename.rfind('.')+1:].lower()
# attr is the dict that will be stored in the mediadb
self.attr = attr
***************
*** 68,73 ****
# cache this item belongs to (needed for saving)
self.cache = cache
! if self.attr.has_key('url'):
! self.url = self.attr['url']
else:
self.url = 'file://' + self.filename
--- 71,76 ----
# cache this item belongs to (needed for saving)
self.cache = cache
! if self.attr.has_key(URL):
! self.url = self.attr[URL]
else:
self.url = 'file://' + self.filename
***************
*** 85,89 ****
Get the itnformation 'key' from the item.
"""
! if key in ('cover', 'audiocover'):
if self.attr.has_key(key):
return self.attr[key]
--- 88,92 ----
Get the itnformation 'key' from the item.
"""
! if key in (COVER, EXTRA_COVER):
if self.attr.has_key(key):
return self.attr[key]
***************
*** 96,107 ****
if self.attr.has_key(key):
return self.attr[key]
if self.hidden_variables.has_key(key):
return self.hidden_variables[key]
if self.mminfo == None:
# unpickle mmpython data
! if not self.attr.has_key('mminfo'):
return None
log.debug('unpickle %s' % self.basename)
! self.mminfo = cPickle.loads(self.attr['mminfo'])
log.debug('mmget %s (%s)' % (self.basename, key))
if self.mminfo.has_key(key):
--- 99,112 ----
if self.attr.has_key(key):
return self.attr[key]
+ elif key == TITLE and self.attr.has_key(FILETITLE):
+ return self.attr[FILETITLE]
if self.hidden_variables.has_key(key):
return self.hidden_variables[key]
if self.mminfo == None:
# unpickle mmpython data
! if not self.attr.has_key(MMINFO):
return None
log.debug('unpickle %s' % self.basename)
! self.mminfo = cPickle.loads(self.attr[MMINFO])
log.debug('mmget %s (%s)' % (self.basename, key))
if self.mminfo.has_key(key):
***************
*** 129,133 ****
Check if 'key' is in the item somewhere.
"""
! if key in ('cover', 'audiocover'):
return True
if self.tmp.has_key(key):
--- 134,138 ----
Check if 'key' is in the item somewhere.
"""
! if key in (COVER, EXTRA_COVER):
return True
if self.tmp.has_key(key):
***************
*** 139,146 ****
if self.mminfo == None:
# unpickle mmpython data
! if not self.attr.has_key('mminfo'):
return False
log.debug('unpickle %s' % self.basename)
! self.mminfo = cPickle.loads(self.attr['mminfo'])
log.debug('mmget %s (%s)' % (self.basename, key))
if self.mminfo.has_key(key):
--- 144,151 ----
if self.mminfo == None:
# unpickle mmpython data
! if not self.attr.has_key(MMINFO):
return False
log.debug('unpickle %s' % self.basename)
! self.mminfo = cPickle.loads(self.attr[MMINFO])
log.debug('mmget %s (%s)' % (self.basename, key))
if self.mminfo.has_key(key):
***************
*** 149,170 ****
- def keys(self):
- """
- Return a list of valid keys.
- """
- ret = [ 'cover', 'audiocover' ]
- if self.mminfo == None:
- if self.attr.has_key('mminfo'):
- log.debug('unpickle %s' % self.basename)
- self.mminfo = cPickle.loads(self.attr['mminfo'])
- else:
- self.mminfo = {}
- for vardict in self.tmp, self.attr, self.hidden_variables,
self.mminfo:
- for key in vardict:
- if not key in ret:
- ret.append(key)
- return ret
-
-
def store(self, key, value):
"""
--- 154,157 ----
***************
*** 188,193 ****
self.cache.changed = True
call_later(self.cache.save)
! if not key in self.attr['mtime_dep']:
! self.attr['mtime_dep'].append(key)
return True
--- 175,180 ----
self.cache.changed = True
call_later(self.cache.save)
! if not key in self.attr[MTIME_DEP]:
! self.attr[MTIME_DEP].append(key)
return True
Index: generic.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/mediadb/generic.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** generic.py 10 Apr 2005 11:20:50 -0000 1.1
--- generic.py 1 May 2005 17:34:54 -0000 1.2
***************
*** 43,47 ****
# freevo imports
import sysconfig
- import util
# mediadb imports
--- 43,46 ----
***************
*** 70,74 ****
# Disc is data of some sort. Mount it to get the file info
! util.mount(media.mountdir, force=True)
if os.path.isdir(os.path.join(media.mountdir, 'VIDEO_TS')) or \
os.path.isdir(os.path.join(media.mountdir, 'video_ts')):
--- 69,73 ----
# Disc is data of some sort. Mount it to get the file info
! media.mount()
if os.path.isdir(os.path.join(media.mountdir, 'VIDEO_TS')) or \
os.path.isdir(os.path.join(media.mountdir, 'video_ts')):
***************
*** 79,87 ****
info.filename = info['mime'][6:] + '://'
if info['mime'] in ('video/vcd', 'video/dvd'):
! util.umount(media.mountdir)
return info
# save directory listing in item
info['listing'] = os.listdir(media.mountdir)
! util.umount(media.mountdir)
# set correct dirname / filename
info.dirname = media.mountdir
--- 78,86 ----
info.filename = info['mime'][6:] + '://'
if info['mime'] in ('video/vcd', 'video/dvd'):
! media.umount()
return info
# save directory listing in item
info['listing'] = os.listdir(media.mountdir)
! media.umount()
# set correct dirname / filename
info.dirname = media.mountdir
-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog