> Just tell me. It is easy to add new functions to the parsing and
> caching routine.
it's late right now (for me[NL])...
but out the top of my head:
-ape-tag parsing in mmpython --> I must send in a patch but
apev2tag.py has changed recently,i have to make a new good patch
again.
-all possible mp3 tags (including user defined) like album_artist
(foobar2000) should be in the meta database.
-data like like rating and play_counter should be written to mp3 tags-tags
The meta database should be a cache of the real data , and may never
contain any new data (right now play_counter and rating are in the
sqlite-db but not in the tags)
-when bug #1170064 is fixed (just rename audio/plugins/playlist.py to
something else) is fixed i will make a freevo CVS compatible version
of audio_album_tree.
-I did some test in comparing an unindexed sqlite database to a python
list of dicts(or objects) and the speed(after loading into memory) of
a python pickle/marshall is higher than unindexed sqlite db.
but unindexed sqlite is still fast enough.
Prototype of a user-(pre)defined sqlite database with custom tags
using a "hacked" mmpython:
"""
concept for a dynamic meta database for freevo.
assumes everyone uses different mp3-tags
fields is a tuple/list that contains the tags to be added to the meta-database.
includes automatic schema updates if "fields" changes
NOTE: REQUIRES A HACKED VERSION OF MMPYTHON(because i want my ape-tags.)
"""
import mmpython
import sqlite
import sys
import os
try:
import psyco
psyco.full()
print 'PSYCO!'
except:
print 'no spyco.'
enc = sys.getdefaultencoding()
mmpython.audio.mp3taginfo.READ_ORDER = ('apev2','id3v1') #id3v2 is
evil ;) , i do not use or support it.
mmpython.audio.mp3taginfo.READ_ALL = False
#problem tags:
#lastplayed is used by freevo as a timestamp,
#,timestamps are not readable in a tag, i would prefer ape format
(TODO:search link)
#same for lastplayed.
#my preferred way of storing datetime:
#http://wiki.hydrogenaudio.org/index.php?title=Foobar2000_Encouraged_Tag_Standards#LAST_PLAYED
#http://www.hydrogenaudio.org/musepack/klemm/www.personal.uni-jena.de/~pfk/mpp/sv8/time.html
#
class Tag(object):
"""
name=name in database
type=python-type (allowed are int,str,float)
"""
type=str
#data class
def __init__(self,name,tagname=None):
self.name = name
if tagname:
self.tagname = tagname
else:
self.tagname = name
def tag2db(self,value):
return unicode(value)
class TagInt(Tag):
type=int
class TagFloat(Tag):
type=float
class TagRg(TagFloat):
"""
replaygain tag must be cleaned up on reading
tag contains -1.111 DB , must return -1.111
"""
def tag2db(self,value):
if value:
return unicode(value.split[0])
class TagYYYYMMDD(Tag):
def tag2db(self,value):
if value:
return unicode(value[0:4]+'-'+value[4:6]+'-'+value[6:8])
systemfields = [TagInt('id'),Tag('dirtitle'), Tag('path'), Tag('filename')]
#, Tag('start_time'), Tag('end_time'),
fields = [
Tag('artist'),Tag('album'),TagInt('track',tagname='trackno'),Tag('title')
, TagInt('year',tagname='date')
,Tag('comment'),Tag('genre'),TagInt('length')
, TagInt('track_total',tagname='trackof')
, TagInt('bpm')
,TagInt('bitrate')
,TagRg('replaygain_album_gain'),TagRg('replaygain_track_gain')
,Tag('album_artist')
#,TagFloat('replaygain_track_peak')
,Tag('origin'),TagYYYYMMDD('date_add'),Tag('last_played')
#, Tag('type')
,TagInt('play_count',tagname='play_counter')
,TagInt('rating')
]
allfields = systemfields + fields
dbschema = """CREATE TABLE music (id INTEGER PRIMARY KEY
, dirtitle VARCHAR(255), path VARCHAR(255), filename VARCHAR(255) """
for field in fields:
if field.type == str:
dbschema += '\n,%s VARCHAR(255)' % field.name
elif field.type == int:
dbschema += '\n,%s INTEGER' % field.name
elif field.type == float:
dbschema += '\n,%s NUMERIC' % field.name
dbschema+=')'
db = sqlite.Connection('./musicdb_test.sqlite',encoding='utf-8')
cursor = db.cursor()
#table versioning by exact same create string.
#update schema if needed.
cursor.execute("SELECT sql FROM sqlite_master where name = 'music'")
if not cursor.rowcount:
print 'CREATING music TABLE'
cursor.execute(dbschema)
db.commit()
else:
currentschema = cursor.fetchone()[0]
if currentschema <> dbschema:
print 'DB SHEMA WAS MODIFIED:DROPPING music TABLE'
cursor.execute('DROP TABLE music')
cursor.execute(dbschema)
db.commit()
def update_or_create(musicfile,info):
"""
update meta-database
"""
id = None
cursor.execute('select id from music where path=%s and
filename=%s',os.path.dirname(musicfile),os.path.basename(musicfile))
result = cursor.fetchone()
if result:
id = result.id
print 'update:',id
dbdict = {}
else:
dbdict =
{'filename':os.path.basename(musicfile),'path':os.path.dirname(musicfile)}
for field in fields:
#print field.name, field,dir(field)
if field.tagname in info.keys: #tag found:copy tag do
dbdict(TODO:SET enc to iso???? instead of ascii)
try:
dbdict[field.name] = unicode(info[field.tagname],enc)
except:
dbdict[field.name] = 'unicode-error'
else: #no tag:set default value in dbdict
#rint 'no-tag:',field.name
if field.type in (int,float):
dbdict[field.name] = 0
else:
dbdict[field.name] = None
if id == None:
#insert into music (comment,title,dirname,artist) values (%s,%s,%s,%s)
dbquery = 'insert into music (%s) values (%s)' %(
','.join(dbdict.keys())
,','.join(['%s']*len(dbdict.keys())))
#2 args to cursor.execute:let pysqlite figure out quoting etc.
cursor.execute(dbquery,dbdict.values())
else:
dbquery = 'update music set '
#comment=%s ,album=%s ,title=%s etc..
dbquery += ','.join([key+'=%s ' for key in dbdict.keys()])
dbquery += 'where id=%s' % id
#2 args to cursor.execute:let pysqlite figure out quoting etc.
cursor.execute(dbquery,dbdict.values())
#testing,fill some data intomthe database
for (dirpath, dirnames, filenames) in os.walk('/mnt/hdc2/data/mp3'):
for filename in filenames:
#print filename
if not filename.lower().endswith('mp3'):
continue
musicfile = os.path.join(dirpath,filename)
try:
temp = unicode(musicfile,enc)
except:
print 'unicode-error! on',musicfile
continue
print 'parsing..',musicfile
info = mmpython.parse(musicfile)
#for k in info.keys:
# print k,'=',info[k]
#sys.exit(0)
if not info:
continue #no tag->not in database
update_or_create(musicfile,info)
print 'commit...'
db.commit()
print 'END'
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Freevo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-devel