[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r151 - in gnue-cddb: . lib schema
From: |
johannes |
Subject: |
r151 - in gnue-cddb: . lib schema |
Date: |
Thu, 2 Dec 2004 08:36:54 -0600 (CST) |
Author: johannes
Date: 2004-12-02 08:36:52 -0600 (Thu, 02 Dec 2004)
New Revision: 151
Added:
gnue-cddb/cddb.gpd
gnue-cddb/disc.gfd
gnue-cddb/dlgArtist.gfd
gnue-cddb/dlgMatch.gfd
gnue-cddb/lib/cddbplib.py
gnue-cddb/schema/cddb-C.gld
Removed:
gnue-cddb/artist.gfd
gnue-cddb/cddb.gfd
gnue-cddb/schema/auth.gsd
gnue-cddb/schema/base.gsd
Modified:
gnue-cddb/
gnue-cddb/lib/helper.py
gnue-cddb/schema/cddb.gcd
gnue-cddb/schema/filedb.gcd
gnue-cddb/schema/gen.gsd
Log:
Heavy reworked to get up to date with GNUe tools ... (will create ogg files now)
Property changes on: gnue-cddb
___________________________________________________________________
Name: svn:ignore
- *.pyc
+ *.pyc
testing
Deleted: gnue-cddb/artist.gfd
===================================================================
--- gnue-cddb/artist.gfd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/artist.gfd 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="iso8859-1"?>
-
-<!-- GNUe-Designer (0.5.4.99)
- Saved on: 2004-06-11 19:56:44 -->
-
-<form title="GNUe CD Database / Artists">
- <options/>
- <datasource name="dts_artist" connection="appserver" table="cddb_artist"
- order_by="cddb_name"/>
-
- <logic>
-
- <block name="blk" datasource="dts_artist" rows="20">
- <field name="fldName" field="cddb_name" maxLength="30"/>
- </block>
-
- </logic>
-
- <layout xmlns:c="GNUe:Layout:Char" c:height="25" c:width="107" tabbed="top">
-
- <page name="Artists">
- <label c:height="1" c:width="12" c:x="1" c:y="0" text="Name"/>
- <entry c:height="1" c:width="30" c:x="1" c:y="1" block="blk"
- field="fldName" name="entName"/>
- </page>
-
- </layout>
-
-</form>
Deleted: gnue-cddb/cddb.gfd
===================================================================
--- gnue-cddb/cddb.gfd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/cddb.gfd 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,492 +0,0 @@
-<?xml version="1.0" encoding="iso8859-1"?>
-
-<!-- GNUe-Designer (0.5.4.99)
- Saved on: 2004-06-11 19:56:44 -->
-
-<form title="GNUe CD Database">
- <options/>
- <datasource name="dts_artist" connection="appserver" table="cddb_artist"
- order_by="cddb_name" prequery="Y"/>
- <datasource name="dts_category" connection="appserver" table="cddb_category"
- order_by="cddb_name" prequery="Y"/>
- <datasource name="dts_disc" connection="appserver" table="cddb_disc"/>
- <datasource name="dts_track" connection="appserver" detaillink="cddb_disc"
- master="dts_disc" masterlink="gnue_id" table="cddb_track"
- order_by="cddb_track"/>
- <datasource name="dts_options" connection="appserver" table="cddb_options"/>
-
- <trigger name="query_cd" type="NAMED"><![CDATA[
- import DiscID
- import CDDB
- import re
- from lib import helper
-
- CDDB.proto = 6
-
- setStatusText ('Retrieving disc information ...')
-
- dev = DiscID.open ()
- discInfo = DiscID.disc_id (dev)
-
- print "RESULT:", discInfo
-
- setStatusText ('Querying remote database at: %s' % CDDB.default_server)
- result = CDDB.query (discInfo)
- print "RESULT:", result
-
- if result [0] == 200:
- match = result [1]
- elif result [0] == 210:
- params = {'matches': result}
- activateDialog ('selectMatch', params, 1)
- if not params.has_key ('match'):
- return
- else:
- match = params ['match']
- else:
- match = {'disc_id' : "%08x" % discInfo [0],
- 'category': 'misc',
- 'title': 'Various / Unknown'}
-
- print "MATCH:", match
-
- setStatusText ('Downloading record ...')
- res = CDDB.read (match ['category'], match ['disc_id'])
- cdbdata = res [1]
- print "Download:", cdbdata.keys ()
- for (k, x) in cdbdata.items ():
- print "%s = %s" % (k, x)
-
- artistRec = helper.processArtists (cdbdata, discInfo, dts_artist)
-
- if len (artistRec ['new'].keys ()):
- params = {'artists': artistRec}
- activateDialog ('selectArtist', params, 1)
-
- print "PARAMS:", params
- if not params.has_key ('updartists'):
- return
-
- artistRec = params ['updartists']
- blk_disc.fldArtist.resetForeignKey ()
- blk_track.fldArtist.resetForeignKey ()
-
- helper.updateArtists (artistRec)
-
- discid = match ['disc_id']
- res = dts_disc.simpleQuery ({'cddb_discid': discid})
- if not res [0].has_key ('gnue_id'):
- blk_disc.newRecord ()
-
- res = dts_category.simpleQuery ({'cddb_matchcode': match ['category']})
- category_id = res [0].get ('gnue_id', None)
-
- blk_disc.fldTitle.set (artistRec ['title'])
- blk_disc.fldArtist.set (artistRec ['disc']['id'])
- blk_disc.fldCategory.set (category_id)
- blk_disc.fldDiscid.set (match ['disc_id'])
- if cdbdata.has_key ('DYEAR'):
- blk_disc.fldYear.set (cdbdata ['DYEAR'])
-
-
- tracks = artistRec ['tracks'].keys ()
- tracks.sort ()
-
- tracklens = discInfo [2:]
- tracklens [-1] = discInfo [-1] * 75
-
- blk_track.firstRecord ()
- needNext = False
- for tNum in tracks:
- needNext = not blk_track.isEmpty ()
- if not needNext:
- blk_track.newRecord ()
-
- blk_track.fldTrack.set (tNum+1)
- blk_track.fldTitle.set (unicode (cdbdata ['TTITLE%d' % tNum], 'utf-8'))
- blk_track.fldArtist.set (artistRec ['tracks'][tNum]['id'])
- blk_track.fldLength.set (round ((tracklens [tNum+1]-tracklens
[tNum])/75))
-
- if needNext:
- blk_track.nextRecord ()
-
-
- setStatusText ('')
- ]]>
- </trigger>
-
- <trigger name="rip_disc" type="NAMED">
- from lib import cdparanoia
- from lib import gogo
- from os import path, makedirs
- import mx.DateTime
-
- discPath = blk_disc.fldUrl.get ()
- print "DiscPath:", discPath
-
- dae = cdparanoia.cdparanoia ()
- enc = gogo.gogo ()
-
- blk_track.firstRecord ()
-
- while not blk_track.isEmpty ():
- if blk_track.fldUrl.isEmpty ():
- filename = 'Track%02d.wav' % blk_track.fldTrack.get ()
- mp3file = 'Track%02d.mp3' % blk_track.fldTrack.get ()
- fullpath = path.join (discPath, filename)
- try:
- makedirs (discPath)
- except:
- # TODO: handle errors !
- pass
-
- print "Extracting track %d to '%s' ..." % (blk_track.fldTrack.get (),
- fullpath)
- dae.runDAE (blk_track.fldTrack.get (), fullpath)
- print "Encoding to MPEG 1 Layer 3 ..."
- enc.runEncoding (fullpath, True)
-
- blk_track.fldUrl.set (path.join (discPath, mp3file))
- blk_track.fldRipdate.set (mx.DateTime.now ())
-
- blk_track.nextRecord ()
- </trigger>
-
- <trigger name="tag_files" type="NAMED">
- import ID3
- import os.path
-
- blk_track.firstRecord ()
-
- while not blk_track.isEmpty ():
- filename = blk_track.fldUrl.get ()
- artistId = blk_track.fldArtist.get ()
- artist = blk_track.fldArtist.allowedValues () [0][artistId] or
'unknown'
-
- dts_category.simpleQuery ({'gnue_id': blk_disc.fldCategory.get ()})
- genre = blk_category.fldId.get ()
-
- if os.path.exists (filename):
- itag = ID3.ID3 (filename)
- print "tag created"
- itag.album = blk_disc.fldTitle.get () or 'Unknown'
- title = blk_track.fldTitle.get () or 'Unknown'
- itag.title = title.encode ('latin-1')
- itag.artist = artist.encode ('latin-1')
- itag.genre = genre
- itag.year = "%s" % blk_disc.fldYear.get ()
- itag.comment= blk_track.fldComment.get ()
- itag.track = "%d" % blk_track.fldTrack.get ()
-
- itag.write ()
-
-
- blk_track.nextRecord ()
-
- print "BLK:", dir (blk_track)
- </trigger>
-
- <trigger name="import_files" type="NAMED">
- from lib import helper
-
- basepath = blk_disc.fldUrl.get ()
- helper.importFiles (blk_track, basepath)
- </trigger>
-
-
- <logic>
-
- <block name="blk_artist" datasource="dts_artist">
- <field name="fldName" field="cddb_name" maxLength="60"/>
- <trigger name="updateReferences" type="POST-COMMIT">
- <![CDATA[
- blk_disc.fldArtist.resetForeignKey ()
- blk_track.fldArtist.resetForeignKey ()
- ]]>
- </trigger>
- </block>
-
- <block name="blk_category" datasource="dts_category">
- <field name="fldId" field="cddb_id" maxLength="3" typecast="number"/>
- <field name="fldName" field="cddb_name" maxLength="30"/>
- <field name="fldMatchcode" field="cddb_matchcode" maxLength="30"/>
- <trigger name="updateReferences" type="POST-COMMIT">
- blk_disc.fldCategory.resetForeignKey ()
- </trigger>
- </block>
-
- <block name="blk_disc" datasource="dts_disc">
- <field name="fldTitle" field="cddb_title" maxLength="60"/>
- <field name="fldArtist" field="cddb_artist" fk_key="gnue_id"
- fk_description="cddb_name" fk_source="dts_artist"/>
- <field name="fldCategory" field="cddb_category" fk_key="gnue_id"
- fk_description="cddb_name" fk_source="dts_category"/>
- <field name="fldYear" field="cddb_year" maxLength="4" typecast="number"/>
- <field name="fldDiscid" field="cddb_discid" maxLength="8" readonly="Y"/>
- <field name="fldComment" field="cddb_comment" maxLength="70"/>
- <field name="fldUrl" field="filedb_url" readonly="Y"/>
- </block>
-
- <block name="blk_track" datasource="dts_track" rows="15">
- <field name="fldTrack" field="cddb_track" maxLength="2"
- typecast="number"/>
- <field name="fldTitle" field="cddb_title" maxLength="90"/>
- <field name="fldArtist" field="cddb_artist" fk_key="gnue_id"
- fk_description="cddb_name" fk_source="dts_artist"/>
- <field name="fldLength" field="cddb_length" maxLength="4"
- typecast="number"/>
- <field name="fldComment" field="cddb_comment" maxLength="28"/>
- <field name="fldUrl" field="filedb_url" maxLength="256"/>
- <field name="fldRipdate" field="filedb_ripdate" typecast="date"/>
- </block>
-
- <block name="blk_options" datasource="dts_options">
- <field name="fldBasepath" field="cddb_basepath" maxLength="250"/>
- </block>
-
- </logic>
-
- <layout xmlns:c="GNUe:Layout:Char" c:height="25" c:width="107" tabbed="top">
-
- <page name="Disc">
- <label c:height="1" c:width="11" c:x="1" c:y="1" text="Title :"/>
- <label c:height="1" c:width="12" c:x="1" c:y="2" text="Artist :"/>
- <label c:height="1" c:width="14" c:x="1" c:y="3" text="Category:"/>
- <label c:height="1" c:width="8" c:x="48" c:y="1" text="Year :"/>
- <label c:height="1" c:width="8" c:x="48" c:y="2" text="Discid :"/>
- <label c:height="1" c:width="8" c:x="48" c:y="3" text="Comment:"/>
-
- <button c:height="1" c:width="10" c:x="1" c:y="5" label="Query">
- <trigger src="query_cd" name="query_cd" type="ON-ACTION"/>
- </button>
- <button c:height="1" c:width="10" c:x="12" c:y="5" label="DAE">
- <trigger src="rip_disc" name="rip_disc" type="ON-ACTION"/>
- </button>
- <button c:height="1" c:width="10" c:x="23" c:y="5" label="Tag">
- <trigger src="tag_files" name="tag_files" type="ON-ACTION"/>
- </button>
- <button c:height="1" c:width="10" c:x="34" c:y="5" label="Import">
- <trigger src="import_files" name="import_files" type="ON-ACTION"/>
- </button>
-
- <entry name="entCddbTitle" c:height="1" c:width="30" c:x="16"
- c:y="1" block="blk_disc" field="fldTitle"/>
- <entry name="entCddbArtist" c:height="1" c:width="30" c:x="16"
- c:y="2" block="blk_disc" field="fldArtist" style="dropdown"/>
- <entry name="entCddbCategory" c:height="1" c:width="30"
- c:x="16" c:y="3" block="blk_disc" field="fldCategory"
style="dropdown"/>
- <entry name="entCddbYear" c:height="1" c:width="10" c:x="57"
- c:y="1" block="blk_disc" field="fldYear"/>
- <entry name="entCddbDiscid" c:height="1" c:width="10" c:x="57"
- c:y="2" block="blk_disc" field="fldDiscid"/>
- <entry name="entCddbComment" c:height="1" c:width="30" c:x="57"
- c:y="3" block="blk_disc" field="fldComment"/>
- <entry c:height="1" c:width="30" c:x="57" c:y="4" block="blk_disc"
- field="fldUrl"/>
-
- <!-- tracks -->
- <label c:height="1" c:width="2" c:x="1" c:y="6" text="Nr"/>
- <label c:height="1" c:width="12" c:x="5" c:y="6" text="Title"/>
- <label c:height="1" c:width="4" c:x="36" c:y="6" text="Secs"/>
- <label c:height="1" c:width="11" c:x="42" c:y="6" text="Artist"/>
- <label c:height="1" c:width="8" c:x="72" c:y="6" text="URL"/>
- <label c:height="1" c:width="8" c:x="99" c:y="6" text="Date"/>
-
- <entry c:height="1" c:width="3" c:x="1" c:y="7" name="entTrack"
- block="blk_track" field="fldTrack"/>
- <entry c:height="1" c:width="30" c:x="5" c:y="7" name="entTitle"
- block="blk_track" field="fldTitle"/>
- <entry c:height="1" c:width="5" c:x="36" c:y="7" name="entLength"
- block="blk_track" field="fldLength"/>
- <entry c:height="1" c:width="25" c:x="42" c:y="7" name="entArtist"
- block="blk_track" field="fldArtist" style="dropdown"/>
-
- <entry c:height="1" c:width="30" c:x="68" c:y="7" name="entURL"
- block="blk_track" field="fldUrl"/>
- <entry c:height="1" c:width="8" c:x="99" c:y="7" name="entComment"
- block="blk_track" field="fldComment"/>
- </page>
-
- <page name="Artists">
- <label name="lblCddbName" c:height="1" c:width="12" c:x="1"
- c:y="1" text="Artist Name:"/>
- <entry name="entCddbName" c:height="1" c:width="30" c:x="15"
- c:y="1" block="blk_artist" field="fldName" label=""/>
- </page>
-
- <page name="Category">
- <label c:height="1" c:width="10" c:x="1" c:y="1" text="ID3-Id :"/>
- <label c:height="1" c:width="10" c:x="1" c:y="2" text="Name :"/>
- <label c:height="1" c:width="10" c:x="1" c:y="3" text="Matchcode:"/>
- <entry c:height="1" c:width="5" c:x="12" c:y="1" name="entCddbId"
- block="blk_category" field="fldId"/>
- <entry c:height="1" c:width="30" c:x="12" c:y="2" name="entName"
- block="blk_category" field="fldName"/>
- <entry c:height="1" c:width="30" c:x="12" c:y="3" name="entMatchcode"
- block="blk_category" field="fldMatchcode"/>
- </page>
-
- <page name="Options">
- <label c:heigth="1" c:width="10" c:x="1" c:y="1" text="Basepath:"/>
- <entry c:height="1" c:width="70" c:x="12" c:y="1" name="entBasepath"
- block="blk_options" field="fldBasepath"/>
- </page>
- </layout>
-
- <!-- =================================================================== -->
- <!-- Dialog to select a remote database match -->
- <!-- =================================================================== -->
-
- <dialog xmlns:c="GNUe:Layout:Char" name="selectMatch">
- <trigger type="On-Startup">
- form.setFeature ('GUI:MENUBAR:SUPPRESS', True)
- form.setFeature ('GUI:TOOLBAR:SUPPRESS', True)
- form.setFeature ('GUI:STATUSBAR:SUPPRESS', True)
- </trigger>
-
- <trigger type="On-Activation">
- matches = getParameter ('matches')
- print "MATCHES:", matches
- rs = dts.createResultSet ()
- rec = None
-
- for match in matches [1]:
- if rec is None:
- rec = rs.firstRecord ()
- else:
- rec = rs.insertRecord ()
-
-
- blk.fldTitle.set (match ['title'])
- blk.fldCategory.set (match ['category'])
- blk.fldDiscid.set (match ['disc_id'])
-
- blk.firstRecord ()
- </trigger>
-
- <datasource name="dts" type="static">
- <staticset fields="title,category,discid">
- <staticsetrow>
- <staticsetfield name="title" value="Unknown / Unknown"/>
- <staticsetfield name="category" value="unknown"/>
- <staticsetfield name="discid" value=""/>
- </staticsetrow>
- </staticset>
- </datasource>
-
- <logic>
- <block name="blk" datasource="dts" rows="12">
- <field name="fldCategory" field="category" readonly="Y"/>
- <field name="fldTitle" field="title" readonly="Y"/>
- <field name="fldDiscid" field="discid" readonly="Y"/>
- </block>
- </logic>
-
- <layout xmlns:c="GNUe:Layout:Char" c:width="70" c:height="15">
- <page>
- <label c:x="0" c:y="0" c:width="7" c:height="1" text="Disc-Id"/>
- <label c:x="10" c:y="0" c:width="8" c:height="1" text="Category"/>
- <label c:x="31" c:y="0" c:width="9" c:height="1" text="Title"/>
-
- <entry c:x="0" c:y="1" c:width="9" block="blk" field="fldDiscid"/>
- <entry c:x="10" c:y="1" c:width="20" block="blk" field="fldCategory"/>
- <entry c:x="31" c:y="1" c:width="60" block="blk" field="fldTitle"/>
-
- <button c:x="0" c:y="14" c:width="10" c:height="1" label="Ok">
- <trigger name="Ok" type="On-Action"><![CDATA[
- res = {'category': blk.fldCategory.get (), \
- 'disc_id': blk.fldDiscid.get (), \
- 'title': blk.fldTitle.get ()}
- setParameter ('match', res)
- close ()
- ]]>
- </trigger>
- </button>
- <button c:x="11" c:y="14" c:width="10" c:height="1" label="Abbrechen">
- <trigger name="Cancel" type="On-Action">
- close ()
- </trigger>
- </button>
- </page>
- </layout>
- </dialog>
-
-
- <!-- =================================================================== -->
- <!-- Dialog to enter a new artist -->
- <!-- =================================================================== -->
-
- <dialog xmlns:c="GNUe:Layout:Char" name="selectArtist">
- <trigger type="On-Startup">
- form.setFeature ('GUI:MENUBAR:SUPPRESS', True)
- form.setFeature ('GUI:TOOLBAR:SUPPRESS', True)
- form.setFeature ('GUI:STATUSBAR:SUPPRESS', True)
- </trigger>
-
- <trigger type="On-Activation">
- artists = getParameter ('artists')
-
- for artist in artists ['new'].keys ():
- if not blk.isEmpty ():
- blk.newRecord ()
- org.newRecord ()
-
- blk.fldName.set (artist)
- org.artist.set (artist)
- </trigger>
-
- <datasource name="dts" connection="appserver" table="cddb_artist"
- order_by="cddb_name"/>
-
- <logic>
- <block name="org" rows="10">
- <field name="artist"/>
- </block>
- <block name="blk" datasource="dts" rows="10">
- <field name="id" field="gnue_id"/>
- <field name="fldName" field="cddb_name"/>
- </block>
- </logic>
-
- <layout xmlns:c="GNUe:Layout:Char" c:width="80" c:height="15">
- <page>
- <label c:x="0" c:y="0" c:width="10" c:height="1" text="Artist "/>
- <label c:x="35" c:y="0" c:width="10" c:height="1" text="Suggested"/>
-
- <entry c:x="0" c:y="1" c:width="30" name="entArtist" block="blk"
- field="fldName"/>
- <entry c:x="35" c:y="1" c:width="30" name="artist" block="org"
- field="artist" style="label"/>
-
- <button c:x="0" c:y="14" c:width="10" c:height="1" label="Ok">
- <trigger name="Ok" type="On-Action">
- if not blk.isSaved ():
- blk.commit ()
-
- artists = getParameter ('artists')
- newArtists = artists ['new']
-
- blk.firstRecord ()
- org.firstRecord ()
-
- while not blk.isEmpty ():
- newArtists [org.artist.get ()] = {'name': blk.fldName.get (),
- 'id' : blk.id.get ()}
- blk.nextRecord ()
- org.nextRecord ()
-
- setParameter ('updartists', artists)
- close ()
- </trigger>
- </button>
- <button c:x="11" c:y="14" c:width="10" c:height="1" label="Abbrechen">
- <trigger name="Cancel" type="On-Action">
- if not blk.isSaved ():
- blk.rollback ()
- close ()
- </trigger>
- </button>
- </page>
- </layout>
- </dialog>
-</form>
Added: gnue-cddb/cddb.gpd
===================================================================
--- gnue-cddb/cddb.gpd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/cddb.gpd 2004-12-02 14:36:52 UTC (rev 151)
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+
+<processes title="GNUe CD Database">
+ <process title="Base Data">
+ <step type="form" location="appserver://appserver/form/cddb_category"
+ title="Categories">
+ <description><![CDATA[
+ <html><head></head><body>
+ <h1>Categories</h1>
+ <p>The path pattern of a category superseeds the pattern given in the
+ options to define the directory where all ripped and encoded files of
+ a disc will be stored. Additionally one can use the following special
+ patterns to build a path:</p>
+ <table>
+ <tr><th>Pattern</th><th>Replacement</th></tr>
+ <tr><td>%c</td><td>Name of the category</td></tr>
+ <tr><td>%m</td><td>Matchcode of the category</td></tr>
+ <tr><td>%a</td><td>Full name of the Artist</td></tr>
+ <tr><td>%t</td><td>Title of the album (disc)</td></tr>
+ </table>
+ </body></html>]]>
+ </description>
+ </step>
+
+ <step type="form" location="appserver://appserver/form/cddb_artist"
+ title="Artists" >
+ <description><![CDATA[
+ <html><head></head><body>
+ <h1>Artists</h1>
+ <p>The full name of an artist is built as
+ "<last name> <middle name> <firstname>"</p>
+ </body></html>]]>
+ </description>
+ </step>
+
+ <step type="form" location="appserver://appserver/form/cddb_options"
+ title="Options">
+ <description><![CDATA[
+ <html><head></head><body>
+ <h1>Options</h1>
+ <p>The path pattern defines where all the ripped and encoded files of
+ a disc will be stored. Additionally one can use the following
+ special patterns to build a path:</p>
+ <table>
+ <tr><th>Pattern</th><th>Replacement</th></tr>
+ <tr><td>%c</td><td>Name of the category</td></tr>
+ <tr><td>%m</td><td>Matchcode of the category</td></tr>
+ <tr><td>%a</td><td>Full name of the Artist</td></tr>
+ <tr><td>%t</td><td>Title of the album (disc)</td></tr>
+ </table>
+ </body></html>]]>
+ </description>
+ </step>
+ </process>
+
+ <process title="Disc-Management">
+ <step type="form" location="./disc.gfd" title="Manage discs" />
+ </process>
+</processes>
+
Added: gnue-cddb/disc.gfd
===================================================================
--- gnue-cddb/disc.gfd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/disc.gfd 2004-12-02 14:36:52 UTC (rev 151)
@@ -0,0 +1,452 @@
+<?xml version="1.0" encoding="iso8859-1"?>
+
+<!-- CD Database main form
+
+ Copyright 2004 Free Software Foundation
+
+ This file is part of GNU Enterprise.
+
+ GNU Enterprise 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.
+
+ GNU Enterprise is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY 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 GNU Enterprise; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ $Id: $ -->
+
+<form title="GNUe CD Database">
+ <options>
+ </options>
+
+
+ <!-- =================================================================== -->
+ <!-- Datasources -->
+ <!-- =================================================================== -->
+
+ <datasource connection="appserver" name="dtsDArtist" table="cddb_artist"
+ order_by="cddb_name" prequery="True" cache="250" />
+
+ <datasource connection="appserver" name="dtsTArtist" table="cddb_artist"
+ order_by="cddb_name" prequery="True" cache="250" />
+
+ <datasource connection="appserver" name="dtsCategory" table="cddb_category"
+ order_by="cddb_name" prequery="True" cache="250" />
+
+ <datasource connection="appserver" name="dtsOptions" table="cddb_options"
+ prequery="True" />
+
+ <datasource connection="appserver" name="dtsDisc" table="cddb_disc" />
+ <datasource connection="appserver" name="dtsTrack" table="cddb_track"
+ master="dtsDisc" masterlink="gnue_id" detaillink="cddb_disc"
+ order_by="cddb_track" />
+
+
+ <!-- =================================================================== -->
+ <!-- Blocks -->
+ <!-- =================================================================== -->
+
+ <logic>
+ <block name="blkDisc" datasource="dtsDisc">
+ <field name="title" field="cddb_title" maxLength="60" />
+
+ <field name="artist" field="cddb_artist" fk_key="gnue_id"
+ fk_description="cddb_name" fk_source="dtsDArtist" />
+
+ <field name="category" field="cddb_category" fk_key="gnue_id"
+ fk_description="cddb_name" fk_source="dtsCategory" />
+
+ <field name="year" field="cddb_year" maxLength="4"
+ typecast="number"/>
+
+ <field name="discid" field="cddb_discid" maxLength="8" />
+ <field name="seconds" field="cddb_seconds" typecast="number" />
+ <field name="comment" field="cddb_comment" maxLength="70" />
+ <field name="url" field="filedb_url" readonly="True" />
+ <field name="length" field="cddb_length" typecast="date" />
+ </block>
+
+
+ <block name="blkTrack" datasource="dtsTrack" rows="15" >
+
+ <field name="track" field="cddb_track" maxLength="2"
+ typecast="number" />
+
+ <field name="title" field="cddb_title" maxLength="90" />
+ <field name="comment" field="cddb_comment" maxLength="70" />
+ <field name="length" field="cddb_length" typecast="date" />
+
+ <field name="artist" field="cddb_artist" fk_key="gnue_id"
+ fk_description="cddb_name" fk_source="dtsTArtist" />
+
+ <field name="ripped" field="filedb_ripdate" typecast="date" />
+ <field name="url" field="filedb_url" />
+ <field name="action" />
+
+ </block>
+
+ <block name="blkOptions" datasource="dtsOptions">
+ <field name="basepath" field="cddb_basepath" readonly="True" />
+ </block>
+
+ </logic>
+
+
+ <!-- =================================================================== -->
+ <!-- Layout (Main Form) -->
+ <!-- =================================================================== -->
+
+ <layout xmlns:c="GNUe:Layout:Char" c:height="23" c:width="100" tabbed="none">
+
+ <page name="pgDisc" caption="Disc">
+
+ <!-- ================================================================ -->
+ <!-- Master Record (Disc) -->
+ <!-- ================================================================ -->
+
+ <label c:x="1" c:y="1" c:width="9" text="Title:" />
+ <label c:x="1" c:y="2" c:width="9" text="Artist:" />
+ <label c:x="1" c:y="3" c:width="9" text="Category:" />
+
+ <label c:x="50" c:y="1" c:width="8" text="Disc-Id:" />
+ <label c:x="50" c:y="2" c:width="8" text="Year:" />
+ <label c:x="50" c:y="3" c:width="10" text="Base path:" />
+
+ <label c:x="71" c:y="1" c:width="8" text="Length:" />
+
+ <entry c:x="11" c:y="1" c:width="30" block="blkDisc" field="title"
+ focusorder="1" />
+
+ <entry c:x="11" c:y="2" c:width="30" block="blkDisc" field="artist"
+ style="dropdown" />
+
+ <button c:x="42" c:y="2" c:width="3" label="..." navigable="False">
+ <trigger type="ON-ACTION">
+ setParameter ('triggerArg', 'disc')
+ activateTrigger ('selectArtist')
+ </trigger>
+ </button>
+
+ <entry c:x="11" c:y="3" c:width="30" block="blkDisc" field="category"
+ style="dropdown" />
+
+ <entry c:x="60" c:y="1" c:width="10" block="blkDisc" field="discid"
+ style="label" />
+
+ <entry c:x="60" c:y="2" c:width="10" block="blkDisc" field="year" />
+ <entry c:x="60" c:y="3" c:width="39" block="blkDisc" field="url" />
+
+ <entry c:x="79" c:y="1" c:width="10" block="blkDisc" field="length"
+ displaymask="%X" style="label" />
+
+
+ <!-- ================================================================ -->
+ <!-- Button Row (Actions) -->
+ <!-- ================================================================ -->
+
+ <button name="btnQuery" c:x="1" c:y="5" c:width="8" label="Query" >
+ <trigger type="ON-ACTION" src="query_cd" />
+ </button>
+
+ <button c:x="10" c:y="5" c:width="18" label="Audio Extraction" >
+ <trigger type="ON-ACTION" src="extract_audio" />
+ </button>
+
+ <button c:x="29" c:y="5" c:width="12" label="Ogg-Encode" >
+ <trigger type="ON-ACTION" src="ogg_encode" />
+ </button>
+
+ <button c:x="42" c:y="5" c:width="8" label="Tag" >
+ <trigger type="ON-ACTION" src="tag_files" />
+ </button>
+
+ <button c:x="51" c:y="5" c:width="8" label="Import" />
+
+ <button c:x="60" c:y="5" c:width="12" label="Toggle all" >
+ <trigger type="ON-ACTION" src="toggle_action" />
+ </button>
+
+ <!-- ================================================================ -->
+ <!-- Detail-Record (Track) -->
+ <!-- ================================================================ -->
+
+ <label c:x="1" c:y="7" c:width="3" text="Nr" />
+ <label c:x="5" c:y="7" c:width="6" text="Title" />
+ <label c:x="36" c:y="7" c:width="6" text="Length" />
+ <label c:x="45" c:y="7" c:width="6" text="Artist" />
+ <label c:x="61" c:y="7" c:width="6" text="Action" alignment="right" />
+ <label c:x="69" c:y="7" c:width="6" text="URL" />
+
+ <entry c:x="1" c:y="8" c:width="3" block="blkTrack" field="track"/>
+ <entry c:x="5" c:y="8" c:width="30" block="blkTrack" field="title"/>
+
+ <entry c:x="36" c:y="8" c:width="8" block="blkTrack" field="length"
+ inputmask="%X" displaymask="%X" />
+
+ <entry c:x="45" c:y="8" c:width="20" block="blkTrack" field="artist"
+ style="dropdown" />
+
+ <entry c:x="66" c:y="8" c:width="2" block="blkTrack" field="action"
+ style="checkbox" />
+
+ <entry c:x="69" c:y="8" c:width="30" block="blkTrack" field="url" />
+ </page>
+
+ </layout>
+
+
+
+ <!-- ################################################################### -->
+ <!-- Trigger - Code -->
+ <!-- ################################################################### -->
+
+ <!-- ===================================================================
+ Select and/or modify an artist
+
+ @param triggerArg: 'disc' or 'track'; specifies which block to set an
+ artist for if the dialog is closed with Ok.
+ =================================================================== -->
+ <trigger name="selectArtist" type="NAMED">
+ arg = getParameter ('triggerArg')
+ if ';' in arg:
+ (type, default) = arg.split (';')
+ else:
+ (type, default) = (arg, None)
+
+ block = type == 'disc' and blkDisc or blkTrack
+ params = {'cancel': True, 'artist': default or block.artist.get ()}
+
+ runForm ('dlgArtist.gfd', params)
+
+ blkDisc.artist.resetForeignKey ()
+ blkTrack.artist.resetForeignKey ()
+
+ if not params.get ('cancel'):
+ block.artist.set (params.get ('artist'))
+
+ setParameter ('triggerArg', params)
+ </trigger>
+
+
+ <!-- ===================================================================
+ Query a disc
+
+ This trigger clears all blocks, reads the disc information from the
+ default cdrom device and either locates an apropriate record in the
+ backed database or query a remote server for it. In the latter case
+ a new disc record as well as all track records will be generated.
+ =================================================================== -->
+ <trigger name="query_cd" type="NAMED">
+ from lib import helper
+
+ blkDisc.rollback ()
+
+ discInfo = helper.getDiscInfo ()
+
+ <!-- First have a look if the disc is already listed in backend-db. The
+ reocrd must match the disc-id, length and in number of tracks. -->
+ idstr = "%08x" % discInfo [0]
+ length = "%s" % discInfo [-1]
+
+ dtsDisc.createResultSet ({'cddb_discid': idstr, 'cddb_seconds': length})
+ if blkDisc.discid.get () == idstr and dtsTrack.count () == discInfo [1]:
+ return
+
+ <!-- Start off with a new disc. Disc-Id and length in seconds cannot change
+ through match-selection. -->
+ if dtsDisc.count () > 1:
+ blkDisc.rollback ()
+
+ blkDisc.discid.set (idstr)
+ blkDisc.seconds.set (discInfo [-1])
+
+ cddb = helper.openCDDB ()
+
+ try:
+ matches = helper.getMatches (cddb, discInfo)
+
+ if len (matches):
+ params = {'cancel': True, 'matches': matches, 'result': None}
+ runForm ('dlgMatch.gfd', params)
+ if params.get ('cancel'):
+ return
+
+ match = params ['result']
+ else:
+ abort ('No match could be created!')
+
+ <!-- Split the match title into a disc-title and an artist name and start
+ the selection / modification of the artist -->
+ (title, artist) = helper.splitTitle (match ['title'])
+ setParameter ('triggerArg', 'disc;%s' % artist)
+ activateTrigger ('selectArtist')
+ if getParameter ('triggerArg') ['cancel']:
+ return
+
+ blkDisc.title.set (title)
+ blkDisc.category.set (match ['category'])
+ blkDisc.url.set (blkDisc.call ('filedb_defaultURL', None))
+
+ <!-- Download the selected match from the remote cd database -->
+ download = helper.download (cddb, discInfo, match ['matchcode'])
+ blkDisc.year.set (download.get ('year'))
+
+ finally:
+ cddb.close ()
+
+ <!-- Iterate over all downloaded tracks and create a track-record. Note:
+ there is no 'empty' track record, because of the former procedure call
+ on the master record. This led to a post and theirfor removed the
+ pending, but empty detail record. -->
+ for (track, title, length) in download ['tracks']:
+ blkTrack.newRecord ()
+
+ blkTrack.track.set (track + 1)
+
+ <!-- If a track has a different artist than the album, split title and
+ artist and start artist selection / modification. -->
+ if title and '/' in title:
+ (title, artist) = helper.splitTitle (title)
+ setParameter ('triggerArg', 'track;%s' % artist)
+ activateTrigger ('selectArtist')
+ <!-- If the selection has been canceled we use the disc's artist -->
+ if getParameter ('triggerArg') ['cancel']:
+ blkTrack.artist.set (blkDisc.artist.get ())
+
+ else:
+ blkTrack.artist.set (blkDisc.artist.get ())
+
+ blkTrack.title.set (title)
+ blkTrack.length.set (length)
+
+
+ <!-- After adding all tracks move the record pointer to the first track and
+ update the master record's calculated stuff. -->
+
+ blkTrack.firstRecord ()
+ blkDisc.update ()
+ </trigger>
+
+
+ <!-- ===================================================================
+ Run Digital Audio Extraction
+
+ This trigger runs DAE on all selected tracks (having a positive action
+ flag set) whose 'filedb_url' is empty.
+ =================================================================== -->
+ <trigger name="extract_audio" type="NAMED">
+ import mx.DateTime
+ from lib import cdparanoia
+ from os import path, makedirs, unlink
+
+ <!-- Check if the base path exists and create it if needed -->
+ discPath = blkDisc.url.get ()
+ if not path.isdir (discPath):
+ try:
+ makedirs (discPath)
+ except:
+ pass
+
+ dae = cdparanoia.cdparanoia ()
+
+ blkTrack.firstRecord ()
+
+ while not blkTrack.isEmpty ():
+ <!-- If a track is marked for action and has no URL yet, extract it -->
+ if blkTrack.action.get () and blkTrack.url.isEmpty ():
+ track = blkTrack.track.get ()
+ filename = "Track%02d.wav" % track
+ fullpath = path.join (discPath, filename)
+
+ if path.exists (fullpath):
+ unlink (fullpath)
+
+ <!-- Set a message on the status bar and start extraction.
+ FIXME: this message is not displayed by uidriver until this
+ trigger has finished completely ! -->
+ print "Extracting %d to %s" % (track, fullpath)
+ setStatusText ("Extracting track %d to %s ..." % (track, fullpath))
+ dae.runDAE (track, fullpath)
+
+ blkTrack.ripped = mx.DateTime.now ()
+ blkTrack.url.set (fullpath)
+
+ blkTrack.nextRecord ()
+ </trigger>
+
+
+ <!-- ===================================================================
+ Toggle action flag
+
+ This trigger changes the action flag for all non-empty track records by
+ inverting it's current state.
+ =================================================================== -->
+ <trigger name="toggle_action" type="NAMED">
+ for tr in range (dtsTrack.count ()):
+ blkTrack.gotoRecord (tr)
+ if not blkTrack.isEmpty ():
+ blkTrack.action.set (not blkTrack.action.get ())
+ </trigger>
+
+
+ <!-- ===================================================================
+ Encode selected tracks into ogg/vorbis
+
+ This trigger encodes all selected tracks with a valid URL pointing to a
+ wave file into ogg/vorbis files additionally tagging them.
+ =================================================================== -->
+
+ <trigger name="ogg_encode" type="NAMED">
+ import lib.helper
+
+ for tr in range (dtsTrack.count ()):
+ blkTrack.gotoRecord (tr)
+
+ if not blkTrack.isEmpty () and blkTrack.action.get ():
+ print "Encoding track %s to ogg/vorbis ..." % (tr + 1)
+ setStatusText ("Encoding track %s to ogg/vorbis ..." % (tr + 1))
+
+ oggfile = lib.helper.ogg_encode (blkTrack.url.get ())
+ if oggfile:
+ blkTrack.url.set (oggfile)
+
+ activateTrigger ('tag_files')
+ </trigger>
+
+
+ <!-- ===================================================================
+ Create vorbis comments for all selected files
+
+ This trigger creates a set of vorbis comments in all selected tracks
+ with a valid URL pointing to a ogg/vorbis file.
+ =================================================================== -->
+
+ <trigger name="tag_files" type="NAMED">
+ from lib import helper
+
+ blkTrack.firstRecord ()
+ for i in range (dtsTrack.count ()):
+ blkTrack.gotoRecord (i)
+
+ if blkTrack.action.get () and not blkTrack.url.isEmpty ():
+ setStatusText ("Tagging track %s ..." % (i + 1))
+
+ album = blkDisc.title.get ()
+ category = blkDisc.category.getFKDescription ()
+ filename = blkTrack.url.get ()
+ title = blkTrack.title.get ()
+ artist = blkTrack.artist.getFKDescription ()
+ tracknum = blkTrack.track.get ()
+
+ helper.tag_oggfile (filename, album, category, title, artist, tracknum)
+ </trigger>
+</form>
+
Added: gnue-cddb/dlgArtist.gfd
===================================================================
--- gnue-cddb/dlgArtist.gfd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/dlgArtist.gfd 2004-12-02 14:36:52 UTC (rev 151)
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="iso8859-1"?>
+
+<!-- Artist Selection / Modification
+
+ Copyright 2004 Free Software Foundation
+
+ This file is part of GNU Enterprise.
+
+ GNU Enterprise 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.
+
+ GNU Enterprise is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY 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 GNU Enterprise; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ $Id: $ -->
+
+<form title="Artists" style="dialog">
+ <options>
+ </options>
+
+ <parameter name="artist" default="" description="Preselected artist" />
+
+ <!-- =================================================================== -->
+ <!-- Datasources -->
+ <!-- =================================================================== -->
+
+ <datasource connection="appserver" name="dtsArtist" table="cddb_artist"
+ order_by="cddb_name" cache="250" />
+
+ <datasource connection="appserver" name="dtsSearch" table="cddb_artist"
+
explicitfields="cddb_lastname,cddb_middlename,cddb_firstname,cddb_matchcode"
+ cache="250" />
+
+ <!-- =================================================================== -->
+ <!-- Blocks -->
+ <!-- =================================================================== -->
+
+ <logic>
+
+ <block name="blkArtist" datasource="dtsArtist">
+ <field name="first" field="cddb_firstname" maxLength="30" />
+ <field name="middle" field="cddb_middlename" maxLength="30" />
+ <field name="last" field="cddb_lastname" maxLength="30" />
+ <field name="full" field="cddb_name" maxLength="100" />
+ <field name="gnueid" field="gnue_id" readonly="True" />
+ </block>
+
+ </logic>
+
+
+ <!-- =================================================================== -->
+ <!-- Trigger -->
+ <!-- =================================================================== -->
+
+ <trigger type="On-Activation" >
+ <!-- ====================================================================
+ If an 'default' record is requested, first try to find an artist with
+ such a gnue_id. On failure try to find an artist by it's matchcode, using
+ all possible permutations of the name.
+ ==================================================================== -->
+
+ setParameter ('cancel', True)
+ preselect = getParameter ('artist')
+
+ if preselect and len (preselect):
+ res = dtsSearch.simpleQuery ({'gnue_id': preselect})
+ if len (res):
+ dtsArtist.simpleQuery ({'gnue_id': res [0]['gnue_id']})
+ return
+
+ from lib import helper
+
+ rs = dtsSearch.createResultSet ()
+ if rs.getRecordCount ():
+ for name in helper.getArtistNames (preselect):
+ rec = rs.findRecord ({'cddb_matchcode': name.upper ()})
+ if rec is not None:
+ dtsArtist.simpleQuery ({'gnue_id': rec.getField ('gnue_id')})
+ return
+
+ blkArtist.last.set (preselect)
+ </trigger>
+
+ <!-- =================================================================== -->
+ <!-- Layout (Main Form) -->
+ <!-- =================================================================== -->
+
+ <layout xmlns:c="GNUe:Layout:Char" c:height="7" c:width="60" tabbed="none">
+
+ <page name="pgArtist" caption="Artist">
+
+ <label c:x="1" c:y="1" c:width="12" text="First name:" />
+ <label c:x="1" c:y="2" c:width="12" text="Middle Name:" />
+ <label c:x="1" c:y="3" c:width="12" text="Last Name:" />
+ <label c:x="1" c:y="4" c:width="12" text="Full Name:" />
+
+ <entry c:x="13" c:y="1" c:width="40" block="blkArtist" field="first"
+ focusorder="1" />
+
+ <entry c:x="13" c:y="2" c:width="40" block="blkArtist" field="middle" />
+ <entry c:x="13" c:y="3" c:width="40" block="blkArtist" field="last" />
+
+ <entry c:x="13" c:y="4" c:width="60" block="blkArtist" field="full"
+ navigable="False" style="label" />
+
+ <!-- ================================================================ -->
+ <!-- Button Row (Actions) -->
+ <!-- ================================================================ -->
+
+ <button c:x="1" c:y="6" c:width="10" label="Ok" >
+ <trigger name="btnOk" type="ON-ACTION">
+ if not blkArtist.isSaved ():
+ blkArtist.commit ()
+
+ if not len (blkArtist.full.get ()):
+ abort ('Please specify an artist first')
+
+ setParameter ('artist', blkArtist.gnueid.get ())
+ setParameter ('cancel', False)
+
+ close ()
+ </trigger>
+ </button>
+
+ <button c:x="12" c:y="6" c:width="10" label="Cancel">
+ <trigger name="btnCancel" type="ON-ACTION">
+ if not blkArtist.isSaved ():
+ blkArtist.rollback ()
+
+ setParameter ('cancel', True)
+ setParameter ('artist', None)
+
+ close ()
+ </trigger>
+ </button>
+
+ </page>
+
+ </layout>
+</form>
+
Added: gnue-cddb/dlgMatch.gfd
===================================================================
--- gnue-cddb/dlgMatch.gfd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/dlgMatch.gfd 2004-12-02 14:36:52 UTC (rev 151)
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="iso8859-1"?>
+
+<!-- Match Selection
+
+ Copyright 2004 Free Software Foundation
+
+ This file is part of GNU Enterprise.
+
+ GNU Enterprise 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.
+
+ GNU Enterprise is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY 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 GNU Enterprise; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ $Id: $ -->
+
+<form title="Select a match" style="dialog">
+ <options>
+ </options>
+
+ <parameter name="matches" default="" description="List of Match-Dicts" />
+
+ <!-- =================================================================== -->
+ <!-- Datasources -->
+ <!-- =================================================================== -->
+
+ <datasource connection="appserver" name="dtsCategory" table="cddb_category"
+ prequery="True" cache="250" />
+
+ <datasource name="dtsMatch" type="static">
+ <staticset fields="title,category,discid">
+ <staticsetrow>
+ <staticsetfield name="title" value="Various / Unknown" />
+ <staticsetfield name="category" value="misc" />
+ <staticsetfield name="discid" value="" />
+ </staticsetrow>
+ </staticset>
+ </datasource>
+
+
+ <!-- =================================================================== -->
+ <!-- Blocks -->
+ <!-- =================================================================== -->
+
+ <logic>
+
+ <block name="blkMatch" datasource="dtsMatch" rows="10"
+ restrictDelete="True" restrictInsert="True" >
+
+ <field name="title" field="title" readonly="True" />
+
+ <field name="category" field="category" readonly="True"
+ fk_key="cddb_matchcode" fk_description="cddb_name"
+ fk_source="dtsCategory" />
+
+ <field name="catid" field="category" readonly="True"
+ fk_key="cddb_matchcode" fk_description="gnue_id"
+ fk_source="dtsCategory" />
+
+ <field name="discid" field="discid" readonly="True" />
+ </block>
+
+ </logic>
+
+
+ <!-- =================================================================== -->
+ <!-- Trigger -->
+ <!-- =================================================================== -->
+
+ <trigger type="On-Startup">
+ form.setFeature ('GUI:TOOLBAR:SUPPRESS', True)
+ form.setFeature ('GUI:MENUBAR:SUPPRESS', True)
+ </trigger>
+
+
+ <trigger type="On-Activation" >
+ setParameter ('cancel', True)
+ matches = getParameter ('matches')
+
+ if matches and len (matches):
+ record = None
+ rs = dtsMatch.createResultSet ()
+
+ for match in matches:
+ record = record and rs.insertRecord () or rs.firstRecord ()
+
+ blkMatch.title.set (match ['title'])
+ blkMatch.category.set (match ['category'])
+ blkMatch.discid.set (match ['disc_id'])
+
+ blkMatch.firstRecord ()
+ </trigger>
+
+
+ <!-- =================================================================== -->
+ <!-- Layout (Main Form) -->
+ <!-- =================================================================== -->
+
+ <layout xmlns:c="GNUe:Layout:Char" c:height="13" c:width="74" tabbed="none">
+
+ <page name="pgArtist" caption="Artist">
+
+ <label c:x="1" c:y="0" c:width="10" text="Disc-ID" />
+ <label c:x="12" c:y="0" c:width="30" text="Category" />
+ <label c:x="43" c:y="0" c:width="30" text="Title" />
+
+ <entry c:x="1" c:y="1" c:width="10" block="blkMatch" field="discid"
+ focusorder="1" />
+
+ <entry c:x="12" c:y="1" c:width="30" block="blkMatch" field="category"
+ navigable="False" />
+
+ <entry c:x="43" c:y="1" c:width="30" block="blkMatch" field="title"
+ navigable="False" />
+
+ <!-- ================================================================ -->
+ <!-- Button Row (Actions) -->
+ <!-- ================================================================ -->
+
+ <button c:x="1" c:y="12" c:width="10" label="Ok" >
+ <trigger name="btnOk" type="ON-ACTION">
+ cat = blkMatch.category.get ()
+ rs = dtsCategory.simpleQuery ({'cddb_matchcode': cat})
+
+ setParameter ('cancel', False)
+ setParameter ('result', \
+ {'disc_id' : blkMatch.discid.get (),
+ 'category' : blkMatch.catid.getFKDescription (),
+ 'matchcode': blkMatch.category.get (),
+ 'title' : blkMatch.title.get ()})
+
+ close ()
+ </trigger>
+ </button>
+
+ <button c:x="12" c:y="12" c:width="10" label="Cancel">
+ <trigger name="btnCancel" type="ON-ACTION">
+ setParameter ('cancel', True)
+ close ()
+ </trigger>
+ </button>
+
+ </page>
+
+ </layout>
+
+</form>
+
Added: gnue-cddb/lib/cddbplib.py
===================================================================
--- gnue-cddb/lib/cddbplib.py 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/lib/cddbplib.py 2004-12-02 14:36:52 UTC (rev 151)
@@ -0,0 +1,749 @@
+# GNU CD Database - CDDB Protocol Implementation
+#
+# Copyright 2001-2004 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise 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, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY 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 program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id: $
+
+"""
+Module implementing the CD Database Protocol version 1
+This module provides a client class for accessing CDDB server using CDDBP.
+"""
+
+import socket
+import sys
+import os
+import string
+import re
+
+# ===========================================================================
+# Constants
+# ===========================================================================
+
+_DEFAULTS = {'server': 'freedb.org',
+ 'port' : 8880,
+ 'user' : 'unknown',
+ 'host' : 'localhost',
+ 'client': 'unknown',
+ 'clvers': '0.0PL0' }
+
+LF = '\n'
+CRLF = '\r' + LF
+
+# ===========================================================================
+# Exception classes
+# ===========================================================================
+
+class Error (Exception): pass # general exception
+class ECannotPerform (Error): pass # 4xx error-codes
+class EUnImplemented (Error): pass # 5xx error-codes
+class EInvalidProtocol (Error): pass # max. protocol level below 4
+class ENoMatch (Error): pass # cddb query found no match
+class EInvalidData (Error): pass # downloaded match is corrupt
+class EInvalidLine (Error): pass # invalid characters in raw data
+class EEmptyLine (Error): pass # raw data has empty lines
+
+# ===========================================================================
+# CDDBP: implement access to CDDB using CDDB-Protocol
+# ===========================================================================
+
+class CDDBP:
+ """A CDDBP client class"""
+
+ # -------------------------------------------------------------------------
+ # Constructor
+ # -------------------------------------------------------------------------
+ def __init__ (self, server=_DEFAULTS['server'], port=_DEFAULTS['port']):
+ """Constructor: Initializes the instance If the environment
+ variable CDDB_EMAIL is set, both username and hostname are
+ extracted from this variable."""
+ self.server = server
+ self.port = port
+ self.user = _DEFAULTS['user']
+ self.hostname = _DEFAULTS['host']
+ self.clientName = _DEFAULTS['client']
+ self.clientVersion = _DEFAULTS['clvers']
+ self.welcome = None
+ self.readonly = 1
+
+ if os.environ.has_key('CDDB_EMAIL'):
+ (self.user, self.hostname) = string.split (os.environ['CDDB_EMAIL'], '@')
+
+ self.__socket = None
+ self.__file = None
+
+ # -------------------------------------------------------------------------
+ # Connect to the CDDBP-Server
+ # -------------------------------------------------------------------------
+ def connect (self, server='', port=0):
+ """Connect to server:port and run the initial handshake. The
+ protocol level will be set to the maximum level supported by
+ the server"""
+ if server: self.server = server
+ if port : self.port = port
+
+ # open a socket
+ self.__socket = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
+ self.__socket.connect ((self.server, self.port))
+ self.__file = self.__socket.makefile ('rb')
+
+ # after connecting we should recieve the welcome message
+ self.welcome = self.readResponse ()
+ self.readonly = (self.welcome[0] == '200')
+
+ # now start the initial handshake
+ self.sendCommand ("cddb hello %s %s %s %s" % (self.user, self.hostname,
+ self.clientName, self.clientVersion))
+ self.readResponse ()
+
+ # now set the cddb protocol level to the maximum available
+ self.maxProtocol = self.maxProtocolLevel ()
+ if self.maxProtocol < 4:
+ raise EInvalidProtocol, (self.maxProtocol,
+ 'Maximum protocol level supported is too low')
+
+ self.sendCommand ("proto %d" % self.maxProtocol)
+ self.readResponse ()
+
+ # -------------------------------------------------------------------------
+ # Disconnect from CDDBP-Server (sign-off)
+ # -------------------------------------------------------------------------
+ def close (self):
+ """Disconnect from the server."""
+ if self.__file:
+ self.sendCommand ('quit')
+ self.__file.close ()
+ self.__socket.close ()
+ self.__file = self.__socket = None
+
+ # -------------------------------------------------------------------------
+ # Get the maximum protocol level supportet by the remote server
+ # -------------------------------------------------------------------------
+ def maxProtocolLevel (self):
+ """Returns the maximum protocol level supported by the server"""
+ self.sendCommand ('proto')
+ self.readResponse ()
+ patt = re.compile (r'.*(\d+)$')
+
+ lev_match = patt.match (self.data)
+ if not lev_match:
+ raise Error, 'Cannot determine protocol level'
+
+ return int ("%s" % lev_match.groups())
+
+ # -------------------------------------------------------------------------
+ # Fetch a list of valid categories known by the server
+ # -------------------------------------------------------------------------
+ def listCategories (self):
+ """Returns an array with all categories supported by the server"""
+ return self.execArray ('cddb lscat')
+
+ # -------------------------------------------------------------------------
+ # Query the server for the CD specified with discinfo.
+ # -------------------------------------------------------------------------
+ def queryCd (self, discinfo):
+ """Query the server for the CD specified by discinfo.
+ discinfo is an array as returned by the DiscID module's disc_id()
+ function. This array consists of:
+ disc_id, num_tracks, offset_1, ..., offset_n, num_seconds
+ The result is a list of tuples (categ, discid, dtitle) per match.
+ """
+ # prepare the query-string
+ qstr = "cddb query %08lx %d " % (discinfo [0], discinfo [1])
+ for ofs in discinfo [2:]:
+ qstr = qstr + ("%d " % ofs)
+ qstr = string.rstrip (qstr)
+
+ self.sendCommand (qstr)
+ self.readResponse ()
+
+ if self.code == '202':
+ raise ENoMatch
+
+ if self.code == '200':
+ (category, discid, title) = self.data.split (' ', 2)
+ result = {'category': category, 'disc_id': discid, 'title': title}
+ else:
+ result = []
+
+ for line in string.split (self.data, LF) [1:]:
+ (category, discid, title) = line.split (' ', 2)
+ result.append ({'category': category,
+ 'disc_id' : discid,
+ 'title' : title})
+
+ return (int (self.code), result)
+
+
+ # -------------------------------------------------------------------------
+ # Download a specified entry from the database.
+ # -------------------------------------------------------------------------
+ def download (self, entry):
+ """
+ Download a specified entry from the database.
+
+ @param entry: a dictionary with at least two keys: category and disc_id.
+
+ The result is the downloaded text of the record as an array of lines.
+ """
+ return self.execArray ("cddb read %s %s" % (entry ['category'],
+ entry ['disc_id']))
+
+ # -------------------------------------------------------------------------
+ # Like download(), but returns an instance of CDDBMatch.
+ # -------------------------------------------------------------------------
+ def downloadMatch (self, entry):
+ """Like CDDBP.download(), but returns an instance of CDDBMatch
+ instead of the raw record data."""
+ return CDDBMatch (self.download (entry), self.maxProtocol, self.clientName)
+
+ # -------------------------------------------------------------------------
+ # Upload a new/modified entry to the database.
+ # -------------------------------------------------------------------------
+ def upload (self, entry, data):
+ """Upload a new/modified entry to the database. entry must be a
+ tuple of (category, discid) and data must be the database record
+ as an array of lines _without_ trailing CR/LF characters.
+ If the client is allowed to do uploads, the attribute CDDBP.readonly
+ must be flase."""
+ self.sendCommand ("cddb write %s %s" % entry)
+ self.readResponse ()
+
+ if self.code == '320':
+ block = string.join (data, CRLF) + CRLF + '.'
+ self.sendCommand (block)
+ self.readResponse ()
+
+ # -------------------------------------------------------------------------
+ # Like upload(), but expects the data as instance of CDDBMatch.
+ # -------------------------------------------------------------------------
+ def uploadMatch (self, entry, match):
+ """Like CDDBP.upload(), but expects the data as instance of CDDBMatch"""
+ self.upload (entry, match.encode ())
+
+ # -------------------------------------------------------------------------
+ # Disc-ID calculation
+ # -------------------------------------------------------------------------
+ def calcDiscid (self, discinfo):
+ """Disc-ID calculation: returns the calculated discid from values
+ given in discinfo-array, which consists of:
+ num_tracks, offset_1, ... , offset_n, num_seconds."""
+ dstr = string.join (map (lambda x: "%d" % x, discinfo), ' ')
+ self.sendCommand ("discid %s" % dstr)
+ self.readResponse ()
+
+ return string.split (self.data, ' ')[-1]
+
+ # -------------------------------------------------------------------------
+ # Retrieve the message of the day from the server.
+ # -------------------------------------------------------------------------
+ def getMotd (self):
+ """Get the servers message-of-the-day. The result is a tuple of
+ ( date-last-modified, array-with-message )."""
+ self.sendCommand ('motd')
+ self.readResponse ()
+
+ answ = string.split (self.data, LF)
+ mod_date = string.join (string.split (answ[0], ' ')[2:4], ' ')
+
+ return (mod_date, answ[1:])
+
+ # -------------------------------------------------------------------------
+ # Retrieve a list of alternate server-sites.
+ # -------------------------------------------------------------------------
+ def getSiteList (self):
+ """Get a list of alternate server-sites. Each site is given as a
+ tuple of the form ( site, protocol, port, address, latitude,
+ longitude, description ). address is the location of the cgi-
+ script at the remote-site (if protocol is http)."""
+ self.sendCommand ('sites')
+ self.readResponse ()
+
+ result = []
+ for site in string.split (self.data, LF)[1:]:
+ parts = string.split (site, ' ')
+ # site, protocol, port, address, latitude, longitude, description
+ result.append ((parts[0], parts[1], parts[2],
+ parts[3], parts[4], parts[5],
+ string.join (parts[6:], ' ')))
+
+ return result
+
+ # -------------------------------------------------------------------------
+ # Retrieve a status message from the server
+ # -------------------------------------------------------------------------
+ def getStatus (self):
+ """Get the server's status message. See cddbp documentation for more
+ details about this message. The result is an array of lines."""
+ return self.execArray ('stat')
+
+ # -------------------------------------------------------------------------
+ # Retrieve the server's version information
+ # -------------------------------------------------------------------------
+ def getServerVersion (self):
+ """Get the servers version information."""
+ self.sendCommand ('ver')
+ self.readResponse ()
+
+ if self.code == '200':
+ res = [self.data]
+ else:
+ res = string.split (self.data, LF)[1:]
+
+ return res
+
+ # -------------------------------------------------------------------------
+ # Update the database
+ # -------------------------------------------------------------------------
+ def databaseUpdate (self):
+ """Perform a database update (if you have permission to do so)."""
+ self.sendCommand ('update')
+ self.readResponse ()
+
+ # -------------------------------------------------------------------------
+ # Get a list of server users
+ # -------------------------------------------------------------------------
+ def serverUsers (self):
+ """Get a list of users currently logged on at the server."""
+ return self.execArray ('whom')
+
+
+
+ # -------------------------------------------------------------------------
+ # Internal: send a command to remote site
+ # -------------------------------------------------------------------------
+ def sendCommand (self, command):
+ """INTERNAL: send the command plus CRLF to the server."""
+ line = command + CRLF
+ self.__socket.sendall (line)
+
+ # -------------------------------------------------------------------------
+ # Internal: return one line from the server, stripping CRLF.
+ # -------------------------------------------------------------------------
+ def getLine (self):
+ """INTERNAL: Get one line from the server, stripping trailing CRLF.
+ If the server has no data waiting for input, raise EOFError."""
+ line = self.__file.readline ()
+ if not line: raise EOFError
+
+ if line[-2:] == CRLF: line = line[:-2]
+ if line[-1:] in CRLF: line = line[:-1]
+
+ return line
+
+ # -------------------------------------------------------------------------
+ # Internal: get a response from the server
+ # -------------------------------------------------------------------------
+ def getMultiLine (self):
+ """Get a response from the server, which might consist of multiple
+ lines (code = x1x). Multiple lines are concatenated by a newline
+ into a single string result."""
+ line = self.getLine ()
+
+ # code x1x means there's more data waiting for retrieval
+ if line[1] == '1':
+ while 1:
+ nextline = self.getLine ()
+ # a line with a single '.' is treated as termination marker
+ if nextline == '.': break
+ line = line + (LF + nextline)
+
+ return line
+
+ # -------------------------------------------------------------------------
+ # Internal: get a response from the server, raise various errors if needed
+ # -------------------------------------------------------------------------
+ def readResponse (self):
+ """INTERNAL: get a response from the server, raise various errors
+ if the response indicates an error. This method sets the attributes
+ code and data, and returns a tuple (code, data)"""
+ resp = self.getMultiLine ()
+ self.code = resp[:3]
+ self.data = resp[4:]
+
+ if self.code[0] == '4':
+ raise ECannotPerform, (self.code, self.data)
+
+ elif self.code[0] == '5':
+ raise EUnImplemented, (self.code, self.data)
+
+ return (self.code, self.data)
+
+ # -------------------------------------------------------------------------
+ # Executes the 'command' and returns the result as an array
+ # -------------------------------------------------------------------------
+ def execArray (self, command):
+ """Execute command, read the server's response and split it into an
+ array of lines."""
+ self.sendCommand (command)
+ self.readResponse ()
+ return string.split (self.data, LF)[1:]
+
+
+
+
+# ===========================================================================
+# This class implements encoding and decoding of raw cd database matches
+# ===========================================================================
+
+# _XMAP defines a translation-table of attributes supported by the class
+# CDDBMatch. Every key is corresponding to an attribute of this class.
+# The values in _XMAP are used as keys of the dictionary data.
+_XMAP = { 'discTitle' : 'DTITLE',
+ 'discId' : 'DISCID',
+ 'discYear' : 'DYEAR',
+ 'discGenre' : 'DGENRE',
+ 'discExtended' : 'EXTD',
+ 'playorder' : 'PLAYORDER',
+ 'discLength' : 'discLength',
+ 'revision' : 'revision',
+ 'submitted' : 'submitted' }
+
+# Allowed characters for comment-lines and keyword-lines
+_COMMENTS = map (lambda x: chr (x), range (0x20, 0x7F)) + ['\t']
+_KEYWORDS = map (lambda x: chr (x), range (0x20, 0x7F) + range (0xA0,0xFF))
+
+# ===========================================================================
+# Class for encoding and decoding of raw CDDB matches.
+# ===========================================================================
+class CDDBMatch:
+ """This class provides an interface to CDDB records."""
+
+ # -------------------------------------------------------------------------
+ # Constructor
+ # -------------------------------------------------------------------------
+ def __init__ (self, match, proto=5, client='unknown'):
+ """match is a raw record as returnd by CDDBP.download(); if match
+ is specified it will be decoded immediately. proto is the protocol
+ level used by the server. """
+ # don't trigger __setattr__ here :))
+ self.__dict__['raw'] = match
+ self.__dict__['data'] = {}
+ self.__dict__['tracks'] = []
+ self.__dict__['frames'] = []
+ self.__dict__['proto'] = proto
+ self.__dict__['client'] = client
+
+ if len (self.raw):
+ self.decode (self.raw)
+
+ # -------------------------------------------------------------------------
+ # Retrieve an attribute's value (either from data-dict. or from instance)
+ # -------------------------------------------------------------------------
+ def __getattr__ (self, attrname):
+ """Internal: Retrieve an attribute's value (either from the dictionary
+ or the instancde itself."""
+ # if _xmap defines the attribute, return this value from data-dictionary
+ if _XMAP.has_key (attrname):
+ return self.data[_XMAP[attrname]]
+ else:
+ # ohterwise it should be an already defined attribute
+ if self.__dict__.has_key (attrname):
+ return self.getattr (attrname)
+ else:
+ raise AttributeError, attrname
+
+ # -------------------------------------------------------------------------
+ # Set an attribute's value (either in data-dict. or in the instance)
+ # -------------------------------------------------------------------------
+ def __setattr__ (self, attr, value):
+ """Internal: Set an attribute's value either by accessing the
+ dictionary or the instance's attribute."""
+ # if attribute is defined in _xmap, set the value into data-dict.
+ if _XMAP.has_key (attr):
+ self.data[_XMAP[attr]] = value
+ else:
+ # otherwise set it as instance-attribute's value (if possible)
+ if self.__dict__.has_key (attr):
+ self.__dict__[attr] = value
+ else:
+ raise AttributeError, attr
+
+ # -------------------------------------------------------------------------
+ # Decode data of a 'raw match'
+ # -------------------------------------------------------------------------
+ def decode (self, rawdata):
+ """Decode rawdata (which is an array as returned by CDDBP.download)
+ and populate the instances attributes."""
+ dlen = re.compile (r'^#\s*Disc length:\s*(\d+)\s*seconds')
+ revn = re.compile (r'^#\s*Revision:\s*(\d+)')
+ subm = re.compile (r'^#\s*Submitted via:\s*(.*)')
+ frame = re.compile (r'^#\s*(\d+)')
+ kword = re.compile (r'([^=]+)=(.*)')
+
+ # transform the raw-data into a dictionary
+ self.data = {}
+ frix = 0
+
+ for line in rawdata:
+ string.rstrip (line)
+ line = string.replace (line, r'\t', "\t")
+ line = string.replace (line, r'\n', "\n")
+ line = string.replace (line, r'\\', "\\")
+
+ # if the line starts with 'SOMETHING = DATA' we have a keyword
+ kw_match = kword.match (line)
+ if kw_match:
+ (key, data) = kw_match.groups ()
+
+ if self.data.has_key (key):
+ self.data[key] = self.data[key] + data
+ else:
+ self.data[key] = data
+ continue
+
+ # Commentline with disc-length
+ dl_match = dlen.match (line)
+ if dl_match:
+ self.discLength = int (dl_match.group (1))
+ continue
+
+ # Commentline with revision
+ rv_match = revn.match (line)
+ if rv_match:
+ self.revision = int (rv_match.group (1))
+ continue
+
+ # Commentline with sumbission infos
+ su_match = subm.match (line)
+ if su_match:
+ self.submitted = su_match.group (1)
+ continue
+
+ # Commentline with a frame-offset
+ fr_match = frame.match (line)
+ if fr_match:
+ self.data["FRAME%d" % frix] = int (fr_match.group (1))
+ frix = frix + 1
+ continue
+
+ # transform all track-data into a list
+ max = 0
+ for key in self.data.keys ():
+ if key[:6] == 'TTITLE': max = max + 1
+
+ self.tracks = []
+ self.frames = []
+ for ix in range (max):
+ tit = self.data["TTITLE%d" % ix]
+ if self.data.has_key ("EXTT%d" % ix):
+ ext = self.data["EXTT%d" % ix]
+ else:
+ ext = ''
+ if self.data.has_key ("FRAME%d" % ix):
+ fro = self.data["FRAME%d" % ix]
+ self.frames.append (fro)
+ else:
+ fro = 0
+
+ self.tracks.append ({ 'ID' : ix+1,
+ 'TITLE' : tit,
+ 'EXTD' : ext,
+ 'OFFSET': fro })
+
+ # there must be the same number of frames as tracks
+ if len (self.frames) != len (self.tracks):
+ raise EInvalidData, 'Invalid format of raw data; cannot decode.'
+
+ # -------------------------------------------------------------------------
+ # Encode a match to raw data ready for an upload
+ # -------------------------------------------------------------------------
+ def encode (self):
+ """Encode the current data of the instance into an array of raw
+ data, so it will be accepted by CDDBP.upload()."""
+ result = []
+ _empty = '#'
+
+ self.__fmtComment (['# xmcd', _empty, '# Track frame offsets:'], result)
+ self.__fmtComment (map (lambda x: "#\t%d" % x, self.frames), result)
+
+ ### TODO: Increment revision and create an own 'submitted via' string
+ self.__fmtComment ([_empty,
+ "# Disc length: %d seconds" % self.discLength,
+ _empty,
+ "# Revision: %d" % self.revision,
+ "# Submitted via: %s" % self.submitted,
+ _empty], result)
+
+ ### TODO: self.discId might be a list of id's instead of a single id.
+ self.__fmtKeyword (self.__fmtLine ('DISCID', self.discId), result)
+ self.__fmtKeyword (self.__fmtLine ('DTITLE', self.discTitle), result)
+
+ # both keywords DYEAR and DGENRE are supported since protocol level 5
+ if self.proto > 4:
+ self.__fmtKeyword (self.__fmtLine ('DYEAR' , self.discYear), result)
+ self.__fmtKeyword (self.__fmtLine ('DGENRE', self.discGenre), result)
+
+ for trk in self.tracks:
+ self.__fmtKeyword ( self.__fmtLine ("TTITLE%d" % trk['ID'],
trk['TITLE']),
+ result)
+
+ self.__fmtKeyword (self.__fmtLine ('EXTD', self.discExtended), result)
+
+ for trk in self.tracks:
+ self.__fmtKeyword (self.__fmtLine ("EXTT%d" % trk['ID'], trk['EXTD']),
+ result)
+
+ self.__fmtKeyword (self.__fmtLine ('PLAYORDER', self.playorder), result)
+
+ return result
+
+
+ # -------------------------------------------------------------------------
+ # Create a list of lines according to the length-restrictions of a db-match
+ # -------------------------------------------------------------------------
+ def __fmtLine (self, prefix, data, max=78):
+ """INTERNAL: Format a line of 'prefix=data' and make sure it's
+ lenght won't exceed max characters. Result is an array of all
+ parts needed to create this line."""
+ line = "%s=%s" % (prefix, data)
+ result = []
+
+ while len (line) > max:
+ result.append (line[:max])
+ line = "%s=%s" % (prefix, line[max:])
+
+ result.append (line)
+ return result
+
+ # -------------------------------------------------------------------------
+ # Check comment-lines and add them to result
+ # -------------------------------------------------------------------------
+ def __fmtComment (self, toadd, result):
+ """INTERNAL: append all lines in toadd to the array result. Before
+ adding, all lines are checked for invalid characters."""
+ for line in toadd:
+ if not string.strip(line):
+ raise EEmptyLine
+
+ for char in line:
+ if char not in _COMMENTS:
+ raise EInvalidLine, (char, line)
+ result.append (line)
+
+ # -------------------------------------------------------------------------
+ # Check keyword-lines and add them to result
+ # -------------------------------------------------------------------------
+ def __fmtKeyword (self, toadd, result):
+ """INTERNAL: append all lines from toadd to the array result. Before
+ adding all lines are checked for invalid characters."""
+ for line in toadd:
+ if not string.strip(line):
+ raise EEmptyLine
+
+ line = string.replace (line, "\\", r'\\')
+ line = string.replace (line, "\t", r'\t')
+ line = string.replace (line, "\n", r'\n')
+
+ for char in line:
+ if char not in _KEYWORDS:
+ raise EInvalidLine, (char, line)
+
+ result.append (line)
+
+# ===========================================================================
+# Module's self-test
+# ===========================================================================
+if __name__ == '__main__':
+ cddb = CDDBP ()
+
+ cddb.connect ()
+ try:
+ try:
+ # this shoud match the signs - soundtrack :)
+ atest = [ 2701831181L, 13, 150, 8062, 22692, 33167, 41867, 67550,
+ 72732, 82595, 108652, 122200, 146475, 163127, 188075, 2734 ]
+
+ (code, info) = cddb.queryCd (atest)
+ if code == 200:
+ entry = info
+ print "Match [%s]: %s (%s)" % (info ['category'], info ['title'],
+ info ['disc_id'])
+ elif code in [210, 211]:
+ for match in info:
+ print "Match [%s]: %s (%s)" % (match ['category'], match ['title'],
+ match ['disc_id'])
+ entry = info [0]
+
+ match = cddb.downloadMatch (entry)
+
+ print "Title = %s" % match.discTitle
+ print "Length: %d" % match.discLength
+
+ for track in match.tracks:
+ print "%02d [%06d]: %s" % (track['ID'], track['OFFSET'],
track['TITLE'])
+
+ sys.exit ()
+ # change some data and encode match
+ match.discTitle = "Just to change something / Nobody"
+ match.tracks[3]['TITLE'] = "Another new track title."
+ match.tracks[2]['EXTD'] = """This is some very long extended information
+ for the third track. Just to see if linebreaking works as intended."""
+
+ enc = match.encode ()
+
+ print "encoded modified match:"
+ for i in enc:
+ print i
+
+
+ ### -----
+ xy = cddb.calcDiscid (atest[1:])
+ print "calcDiscid == %s" % xy
+
+ ### -----
+ modt = cddb.getMotd ()
+ print "MOTD last modified: %s" % modt[0]
+ for line in modt[1]:
+ print ">> %s" % line
+
+ ### -----
+ print "Server version: %s" % cddb.getServerVersion ()
+
+ ### -----
+ print "Site-List:"
+ for site in cddb.getSiteList ():
+ print "%s://%s:%s %s %s %s %s" % (site[1], site[0], site[2], site[3],
+ site[4], site[5], site[6])
+
+ ### -----
+ print "Categories:"
+ for cat in cddb.listCategories ():
+ print ">> %s" % cat
+
+ ### -----
+ print "Server-Status:"
+ for line in cddb.getStatus ():
+ print ">> %s" % line
+
+ ### -----
+ print "Server-Users:"
+ try:
+ for user in cddb.serverUsers ():
+ print "user %s" % user
+
+ except ECannotPerform, info:
+ print "Error %s: %s" % (info[0], info[1])
+
+ except ENoMatch:
+ print "Sorry, there's no record for this disc found."
+
+ finally:
+ cddb.close ()
+
Property changes on: gnue-cddb/lib/cddbplib.py
___________________________________________________________________
Name: svn:executable
+ *
Modified: gnue-cddb/lib/helper.py
===================================================================
--- gnue-cddb/lib/helper.py 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/lib/helper.py 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,7 +1,9 @@
-
+# GNUe CD Database - Helper functions
#
-# This file is part of GNU Enterprise CD Database.
+# Copyright 2001-2004 Free Software Foundation
#
+# This file is part of GNU Enterprise
+#
# GNU Enterprise 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
@@ -17,106 +19,362 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2001-2004 Free Software Foundation
-#
+# $Id: $
-def processArtists (cddbData, discInfo, dts):
+import string
+import DiscID
+import CDDB
+import mx.DateTime
+import cddbplib
+import wave
+import os.path
+import ogg.vorbis
+from gnue.common.apps import errors
+
+CDDB.proto = 6
+
+
+# -----------------------------------------------------------------------------
+# Esablish a new connection to the remote cd database
+# -----------------------------------------------------------------------------
+
+def openCDDB ():
+ cddb = cddbplib.CDDBP ('at.freedb.org')
+ cddb.connect ()
+ return cddb
+
+# -----------------------------------------------------------------------------
+# Get the disc information array
+# -----------------------------------------------------------------------------
+
+def getDiscInfo ():
"""
- This function processes artists given by a cd database match and returns a
- dictionary with all artist information.
+ This function returns a sequence with disc information usable by the remote
+ cd database.
"""
- result = {'disc' : {},
- 'new' : {},
- 'tracks': {}}
- (discArtist, discTitle) = cddbData ['DTITLE'].split ('/')
- discArtist = discArtist.strip ()
- discTitle = discTitle.strip ()
+ dev = DiscID.open ()
+ return DiscID.disc_id (dev)
+
+
+# -----------------------------------------------------------------------------
+# Get the disc info and all CDDB matches for the current disc
+# -----------------------------------------------------------------------------
- result ['title'] = discTitle
+def getMatches (cddb, discInfo):
+ """
+ This function queries a remote cd database for the disc specified by the
+ discInfo sequence.
- qRes = dts.simpleQuery ({'cddb_name': discArtist})
- artId = qRes [0].get ('gnue_id', None)
- if artId is None:
- result ['new'][discArtist] = {}
+ @param discInfo: sequence as returned by DiscID module describing the disc
+ @return: sequence of dictionaries. Each match is a dictitionary with three
+ keys: 'category', 'disc_id', 'title'
+ """
- result ['disc'] = {'name': discArtist,
- 'id' : artId}
+ try:
+ (code, matches) = cddb.queryCd (discInfo)
- for tNum in range (discInfo [1]):
- parts = cddbData ['TTITLE%d' % tNum].split ('/')
- if len (parts) == 2:
- parts [0] = parts [0].strip ()
- parts [1] = parts [1].strip ()
+ except cddbplib.ENoMatch:
+ code = cddb.code
- artName = parts [0]
- cddbData ['TTITLE%d' % tNum] = parts [1]
+ mlist = []
- qRes = dts.simpleQuery ({'cddb_name': artName})
- artId = qRes [0].get ('gnue_id', None)
- if artId is None:
- result ['new'][artName] = {}
+ if code == 200:
+ mlist = [matches]
- else:
- artName = result ['disc']['name']
- artId = result ['disc']['id']
+ elif code in [210, 211]:
+ mlist = matches
- result ['tracks'][tNum] = {'name': artName,
- 'id' : artId}
+ mlist.append ({'disc_id' : "%08x" % discInfo [0],
+ 'title' : 'Various / Unknown',
+ 'category': 'misc'})
- return result
+ return mlist
-def updateArtists (artists):
+# -----------------------------------------------------------------------------
+# Split a title row into an albumname and an artist
+# -----------------------------------------------------------------------------
+
+def splitTitle (dbTitle):
"""
+ This function splits a disc-title into an albumname and an artist.
+ @param dbTitle: title as retrieved from cd database ('artist/album')
+ @return: tuple with albumname and artist
"""
- if artists ['disc']['id'] is None:
- new = artists ['new'].get (artists ['disc']['name'], None)
- if new is not None:
- artists ['disc']['name'] = new ['name']
- artists ['disc']['id'] = new ['id']
- for track in artists ['tracks'].values ():
- if track ['id'] is None:
- new = artists ['new'].get (track ['name'], None)
- if new is not None:
- track ['name'] = new ['name']
- track ['id'] = new ['id']
+ if '/' in dbTitle:
+ (artist, title) = map (string.strip, dbTitle.split ('/', 1))
+ else:
+ (artist, title) = ('Various', dbTitle)
- print "UPDATE-DISC:", artists ['disc']
- print "UPDATE-TRAC:", artists ['tracks']
+ return (title, artist)
-def getOutputPath (dtsOptions, blkDisc):
- from os import path, environ
+# -----------------------------------------------------------------------------
+# Create a sequence of all possible permutations of a given name
+# -----------------------------------------------------------------------------
- res = dtsOptions.createResultSet ()
- res.firstRecord ()
- if res.current is not None:
- basepath = path.normpath (res.current.getField ('cddb_basepath'))
+def getArtistNames (aName):
+ """
+ This function splits a name by whitespaces and creates a sequence of all
+ permutations of these parts.
+
+ @param aName: name to get permutations for
+ @return: sequence with all permutations of the name
+ """
+
+ parts = aName.split ()
+
+ if len (parts) > 1:
+ perms = [getPermutation (parts, i) for i in range (faculty (len (parts)))]
+ result = [string.join (item, ' ') for item in perms]
+
else:
- basepath = path.normpath (environ ['HOME'])
+ result = [string.join (parts, ' ')]
- catId = blkDisc.fldCategory.get ()
- artistId = blkDisc.fldArtist.get ()
- category = blkDisc.fldCategory.allowedValues () [0][catId] or 'misc'
- artist = blkDisc.fldArtist.allowedValues () [0][artistId] or 'unknown'
- title = blkDisc.fldTitle.get () or 'unknown'
- discPath = path.join (basepath, category, artist, title).replace (' ', '_')
+ return result
- return discPath
+
+# -----------------------------------------------------------------------------
+# Get a permuation of a sequence
+# -----------------------------------------------------------------------------
+
+def getPermutation (seq, index):
+ """
+ Returns the n-th permutation of the sequence seq
+ """
+
+ seqc = list (seq [:])
+ seqn = [seqc.pop ()]
+ divider = 2 # divider is meant to be len (seqn) + 1, just a bit faster
+
+ while seqc:
+ index, new_index = index // divider, index % divider
+ seqn.insert (new_index, seqc.pop ())
+ divider += 1
+
+ return seqn
+
+# -----------------------------------------------------------------------------
+# Caculate the faculty of n
+# -----------------------------------------------------------------------------
+
+def faculty (n):
+ """
+ This function calculates the faculty of n (n!)
+ """
+
+ result = 1
+ for i in range (2, n + 1):
+ result *= i
+
+ return result
+
+
+# -----------------------------------------------------------------------------
+# Download a match from remote db
+# -----------------------------------------------------------------------------
+
+def download (cddb, discInfo, category):
+ """
+ This function downloads a record - specified by a discInfo sequence and a
+ category - from a remote cd database.
+
+ @param discInfo: disc info sequence as returned by DiscId module
+ @param category: name of the category to look in
+ @return: dictionary with the following keys:
+ 'dlength': length of the disc as mx.DateTime.Time
+ 'year' : Year of the recording or None (if not given)
+ 'tracks' : sequence of track-tuples (tracknum, title, length) where the
+ length is given as mx.DateTime.Time
+ """
+
+ tracks = []
+ result = {'tracks' : tracks,
+ 'dlength': mx.DateTime.Time (seconds = discInfo [-1])}
+
+ try:
+ data = cddb.downloadMatch ({'category': category,
+ 'disc_id': "%08x" % discInfo [0]})
+ except cddbplib.ECannotPerform:
+ data = None
+
+ tlen = discInfo [2:]
+ tlen [-1] *= 75
+
+ for i in range (discInfo [1]):
+ title = data and data.tracks [i]['TITLE'] or None
+ length = mx.DateTime.Time (seconds = (tlen [i+1] - tlen [i]) / 75.0)
+ tracks.append ((i, title, length))
+
+ tracks.sort ()
+
+ if data:
+ result ['year'] = data.discYear
+
+ return result
+
+
+# -----------------------------------------------------------------------------
+#
+# -----------------------------------------------------------------------------
+
+def __checkSoundFile (filename):
+ try:
+ oggfile = ogg.vorbis.VorbisFile (filename)
+ return False
+
+ except:
+ pass
+
+ try:
+ wavefile = wave.open (str (filename), 'rb')
+ wavefile.close ()
+ return True
+
+ except:
+ pass
+
+ return None
+
+# -----------------------------------------------------------------------------
+# Encode a wave file into ogg/vorbis
+# -----------------------------------------------------------------------------
+
+def ogg_encode (filename, encQuality = 0.5):
+ """
+ This function encodes the given wave-file into an ogg/vorbis file.
+
+ @param filename: name of the wave-file
+ @return: name of the ogg-file created or None if something went wrong
+ """
+
+ state = __checkSoundFile (filename)
+ if not state:
+ return state is None and state or filename
-def importFiles (blkTrack, basePath):
- from os import path
+ oggname = "%s.ogg" % os.path.splitext (filename) [0]
+ wavefile = wave.open (str (filename), 'rb')
+ oggfile = open (oggname, 'wb')
- blkTrack.firstRecord ()
+ vi = ogg.vorbis.VorbisInfo (channels = wavefile.getnchannels (),
+ rate = wavefile.getframerate (),
+ quality = encQuality)
+ vc = ogg.vorbis.VorbisComment ()
- while not blkTrack.isEmpty ():
- url = blkTrack.fldUrl.get ()
- tNum = blkTrack.fldTrack.get ()
- if not len (url):
- filename = path.join (basePath, 'Track%02d.mp3' % tNum)
- if path.exists (filename):
- blkTrack.fldUrl.set (filename)
+ vd = vi.analysis_init ()
+ vb = vd.create_block ()
+ (header, header_com, header_code) = vd.headerout (vc)
- blkTrack.nextRecord ()
+ try:
+ stream = ogg.OggStreamState (5)
+ stream.packetin (header)
+ stream.packetin (header_com)
+ stream.packetin (header_code)
+
+ og = stream.flush ()
+ while og:
+ og.writeout (oggfile)
+ og = stream.flush ()
+
+ eos = False
+ while not eos:
+ data = wavefile.readframes (2048)
+ if not data:
+ vd.write (None)
+ else:
+ vd.write_wav (data)
+
+ vb = vd.blockout ()
+ while vb:
+ vb.analysis ()
+ vb.addblock ()
+
+ op = vd.bitrate_flushpacket ()
+ while op:
+ stream.packetin (op)
+ while not eos:
+ og = stream.pageout ()
+ if not og:
+ break
+
+ og.writeout (oggfile)
+ eos = og.eos ()
+
+ op = vd.bitrate_flushpacket ()
+
+ vb = vd.blockout ()
+
+ finally:
+ vd.close ()
+ oggfile.close ()
+
+ wavefile.close ()
+ os.unlink (filename)
+
+ return oggname
+
+
+# -----------------------------------------------------------------------------
+# Create a tag in the ogg/vorbis file
+# -----------------------------------------------------------------------------
+
+def tag_oggfile (filename, album, category, title, artist, tracknum):
+
+ try:
+ oggfile = ogg.vorbis.VorbisFile (filename)
+
+ except:
+ print "Sorry, no valid ogg-file"
+ return
+
+ c = {'ALBUM' : album,
+ 'ARTIST': artist,
+ 'GENRE' : category,
+ 'TITLE' : title,
+ 'TRACKNUMBER': "%s" % tracknum}
+
+ comment = ogg.vorbis.VorbisComment ()
+ for (k, v) in c.items ():
+ if v is not None:
+ comment [k] = v
+
+ comment.write_to (filename)
+
+
+
+# =============================================================================
+# Self test code
+# =============================================================================
+
+if __name__ == '__main__':
+
+ title = 'Foo bar / Baz Bar shit'
+ print splitTitle (title), "\n"
+
+ title = 'Troy / James Horner'
+ print splitTitle (title), "\n"
+
+ title = 'Baz / Various'
+ print splitTitle (title), "\n"
+
+ title = 'Bazious'
+ print splitTitle (title), "\n"
+
+ title = 'Foo / Bar / Baz'
+ print splitTitle (title), "\n"
+
+ artist = 'John Williams'
+ print getArtistNames (artist)
+
+ artist = 'John F. Kennedy'
+ print getArtistNames (artist)
+
+ print "Encoding foo.wav"
+ res = ogg_encode ('foo.wav')
+ print "Res =", res
+
+ print "Encoding bar.wav"
+ res = ogg_encode ('bar.wav')
+ print "Res =", res
Deleted: gnue-cddb/schema/auth.gsd
===================================================================
--- gnue-cddb/schema/auth.gsd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/schema/auth.gsd 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,151 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Schema definition created by GNUe Appserver's Schema Support. -->
-<!-- run this file through gnue-schema to create SQL scripts -->
-<schema author="Appserver SchemaSupport" title="Appserver Schema Dump"
- version="1.0">
- <tables>
- <table name="gnue_useraccess">
- <fields>
- <field name="gnue_accesslist"
- description="List of classes with access allowed" length="100"
type="string"/>
- <field name="gnue_id" description="Object ID" length="32" nullable="N"
- type="string"/>
- <field name="gnue_password" description="Password" length="70"
- type="string"/>
- <field name="gnue_username" description="Username" length="20"
- nullable="N" type="string"/>
- </fields>
- <constraints/>
- <indexes/>
- <primarykey name="gnue_id_pk_gnue_useraccess">
- <pkfield name="gnue_id"/>
- </primarykey>
- </table>
- </tables>
- <data>
- <tabledata name="gnue_module_dump" tablename="gnue_module">
- <definition>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_id"
key="Y">00000000000000000000000000000000</value>
- <value field="gnue_name">gnue</value>
- <value field="gnue_comment">GNU Enterprise System Management</value>
- </row>
- </rows>
- </tabledata>
- <tabledata name="gnue_class_dump" tablename="gnue_class">
- <definition>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_module" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_id"
key="Y">00000000000000000000000000000060</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">useraccess</value>
- <value field="gnue_comment">GNU Enterprise User
Authentication</value>
- </row>
- </rows>
- </tabledata>
- <tabledata name="gnue_property_dump" tablename="gnue_property">
- <definition>
- <column field="gnue_class" type="string(32)"/>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_length" type="number(6)"/>
- <column field="gnue_module" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- <column field="gnue_nullable" type="boolean"/>
- <column field="gnue_scale" type="number(4)"/>
- <column field="gnue_type" type="string(35)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_id"
key="Y">00000000000000000000000000000064</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_class">00000000000000000000000000000060</value>
- <value field="gnue_name">accesslist</value>
- <value field="gnue_type">string</value>
- <value field="gnue_length">100</value>
- <value field="gnue_scale">0</value>
- <value field="gnue_comment">List of classes with access
allowed</value>
- <value field="gnue_nullable">TRUE</value>
- </row>
- <row>
- <value field="gnue_id">00000000000000000000000000000061</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_class">00000000000000000000000000000060</value>
- <value field="gnue_name">id</value>
- <value field="gnue_type">id</value>
- <value field="gnue_length">0</value>
- <value field="gnue_scale">0</value>
- <value field="gnue_comment">Object ID</value>
- <value field="gnue_nullable">FALSE</value>
- </row>
- <row>
- <value field="gnue_id">00000000000000000000000000000063</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_class">00000000000000000000000000000060</value>
- <value field="gnue_name">password</value>
- <value field="gnue_type">string</value>
- <value field="gnue_length">70</value>
- <value field="gnue_scale">0</value>
- <value field="gnue_comment">Password</value>
- <value field="gnue_nullable">TRUE</value>
- </row>
- <row>
- <value field="gnue_id">00000000000000000000000000000062</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_class">00000000000000000000000000000060</value>
- <value field="gnue_name">username</value>
- <value field="gnue_type">string</value>
- <value field="gnue_length">20</value>
- <value field="gnue_scale">0</value>
- <value field="gnue_comment">Username</value>
- <value field="gnue_nullable">FALSE</value>
- </row>
- </rows>
- </tabledata>
- <tabledata name="gnue_procedure_dump" tablename="gnue_procedure">
- <definition>
- <column field="gnue_class" type="string(32)"/>
- <column field="gnue_code" type="string"/>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_compiledcode" type="string"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_language" type="string(10)"/>
- <column field="gnue_module" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- </definition>
- <rows/>
- </tabledata>
- <tabledata name="sample_accounts" tablename="gnue_useraccess">
- <definition>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_username" type="string(20)"/>
- <column field="gnue_password" type="string(70)"/>
- <column field="gnue_accesslist" type="string(100)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_id"
key="Y">00000000000000000000001000000001</value>
- <value field="gnue_username">test</value>
- <value field="gnue_password">test</value>
- <value field="gnue_accesslist">address_person,address_country</value>
- </row>
- <row>
- <value field="gnue_id">00000000000000000000001000000002</value>
- <value field="gnue_username">hacker</value>
- <value field="gnue_password">secret</value>
- <value field="gnue_accesslist">all</value>
- </row>
- </rows>
- </tabledata>
- </data>
-</schema>
Deleted: gnue-cddb/schema/base.gsd
===================================================================
--- gnue-cddb/schema/base.gsd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/schema/base.gsd 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,557 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Schema definition created by GNUe Appserver's Schema Support.
- Run this file through gnue-schema to create SQL scripts -->
-<schema author="Appserver SchemaSupport" title="Appserver Schema Dump"
- version="1.0">
- <tables>
- <table name="gnue_class">
- <fields>
- <field name="gnue_comment" description="Comment" length="70"
- type="string"/>
- <field name="gnue_id" description="Object ID" length="32" nullable="N"
- type="string"/>
- <field name="gnue_module" description="Module that defined this class"
- length="32" nullable="N" type="string"/>
- <field name="gnue_name" description="Classname without modulename"
- length="35" nullable="N" type="string"/>
- </fields>
- <indexes/>
- <constraints>
- <constraint name="gnue_class_gnue_module_fk" type="foreignkey">
- <constraintfield name="gnue_module"/>
- <constraintref name="gnue_id" table="gnue_module"/>
- </constraint>
- </constraints>
- <primarykey name="gnue_id_pk_gnue_class">
- <pkfield name="gnue_id"/>
- </primarykey>
- </table>
- <table name="gnue_module">
- <fields>
- <field name="gnue_comment" description="Comment" length="70"
- type="string"/>
- <field name="gnue_id" description="Object ID" length="32" nullable="N"
- type="string"/>
- <field name="gnue_name" description="Name" length="35" nullable="N"
- type="string"/>
- </fields>
- <indexes/>
- <constraints/>
- <primarykey name="gnue_id_pk_gnue_module">
- <pkfield name="gnue_id"/>
- </primarykey>
- </table>
- <table name="gnue_parameter">
- <fields>
- <field name="gnue_comment" description="Comment" length="70"
- type="string"/>
- <field name="gnue_id" description="Object ID" length="32" nullable="N"
- type="string"/>
- <field name="gnue_length" description="Lenght of the parameter"
- length="6" type="number"/>
- <field name="gnue_name" description="Name of the parameter"
- length="35" nullable="N" type="string"/>
- <field name="gnue_procedure"
- description="Procedure the parameter belongs to" length="32"
nullable="N" type="string"/>
- <field name="gnue_scale" description="Scale of numeric data"
- length="4" type="number"/>
- <field name="gnue_type" description="Parameter type" length="35"
- nullable="N" type="string"/>
- </fields>
- <indexes/>
- <constraints>
- <constraint name="gnue_parameter_gnue_procedure_fk" type="foreignkey">
- <constraintfield name="gnue_procedure"/>
- <constraintref name="gnue_id" table="gnue_procedure"/>
- </constraint>
- </constraints>
- <primarykey name="gnue_id_pk_gnue_parameter">
- <pkfield name="gnue_id"/>
- </primarykey>
- </table>
- <table name="gnue_procedure">
- <fields>
- <field name="gnue_class" description="Class the procedure belongs to"
- length="32" nullable="N" type="string"/>
- <field name="gnue_code" description="Procedure code" nullable="N"
- type="string"/>
- <field name="gnue_comment" description="Comment" length="70"
- type="string"/>
- <field name="gnue_compiledcode" description="Compiled procedure code"
- type="string"/>
- <field name="gnue_id" description="Object ID" length="32" nullable="N"
- type="string"/>
- <field name="gnue_language" description="Procedure language"
- length="10" nullable="N" type="string"/>
- <field name="gnue_length"
- description="Length of the procedures result" length="6"
type="number"/>
- <field name="gnue_module"
- description="Module that defined this procedure" length="32"
nullable="N" type="string"/>
- <field name="gnue_name" description="Procedurename without modulename"
- length="35" nullable="N" type="string"/>
- <field name="gnue_nullable"
- description="Result of the procedure can contain NULL values"
nullable="N" type="boolean"/>
- <field name="gnue_scale" description="Scale of the procedures result"
- length="4" type="number"/>
- <field name="gnue_type" description="Type of the procedures result"
- length="35" type="string"/>
- </fields>
- <indexes/>
- <constraints>
- <constraint name="gnue_procedure_gnue_class_fk" type="foreignkey">
- <constraintfield name="gnue_class"/>
- <constraintref name="gnue_id" table="gnue_class"/>
- </constraint>
- <constraint name="gnue_procedure_gnue_module_fk" type="foreignkey">
- <constraintfield name="gnue_module"/>
- <constraintref name="gnue_id" table="gnue_module"/>
- </constraint>
- </constraints>
- <primarykey name="gnue_id_pk_gnue_procedure">
- <pkfield name="gnue_id"/>
- </primarykey>
- </table>
- <table name="gnue_property">
- <fields>
- <field name="gnue_class" description="Class the property belongs to"
- length="32" nullable="N" type="string"/>
- <field name="gnue_comment" description="Comment" length="70"
- type="string"/>
- <field name="gnue_id" description="Object ID" length="32" nullable="N"
- type="string"/>
- <field name="gnue_length" description="Lenght of the property"
- length="6" type="number"/>
- <field name="gnue_module"
- description="Module that defined this property" length="32"
nullable="N" type="string"/>
- <field name="gnue_name" description="Propertyname without modulename"
- length="35" nullable="N" type="string"/>
- <field name="gnue_nullable"
- description="Property can contain NULL values" nullable="N"
type="boolean"/>
- <field name="gnue_scale" description="Scale of numeric data"
- length="4" type="number"/>
- <field name="gnue_type" description="Property type" length="35"
- nullable="N" type="string"/>
- </fields>
- <indexes/>
- <constraints>
- <constraint name="gnue_property_gnue_class_fk" type="foreignkey">
- <constraintfield name="gnue_class"/>
- <constraintref name="gnue_id" table="gnue_class"/>
- </constraint>
- <constraint name="gnue_property_gnue_module_fk" type="foreignkey">
- <constraintfield name="gnue_module"/>
- <constraintref name="gnue_id" table="gnue_module"/>
- </constraint>
- </constraints>
- <primarykey name="gnue_id_pk_gnue_property">
- <pkfield name="gnue_id"/>
- </primarykey>
- </table>
- </tables>
- <data>
- <tabledata name="gnue_module_dump" tablename="gnue_module">
- <definition>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_comment">GNU Enterprise System Management</value>
- <value field="gnue_id">00000000000000000000000000000000</value>
- <value field="gnue_name">gnue</value>
- </row>
- </rows>
- </tabledata>
- <tabledata name="gnue_class_dump" tablename="gnue_class">
- <definition>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_module" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_comment">GNU Enterprise Business Object
Class</value>
- <value field="gnue_id">00000000000000000000000000000020</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">class</value>
- </row>
- <row>
- <value field="gnue_comment">GNU Enterprise Business Object
Module</value>
- <value field="gnue_id">00000000000000000000000000000010</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">module</value>
- </row>
- <row>
- <value field="gnue_comment">GNU Enterprise Business Object Procedure
Parameter</value>
- <value field="gnue_id">00000000000000000000000000000050</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">parameter</value>
- </row>
- <row>
- <value field="gnue_comment">GNU Enterprise Business Object
Procedure</value>
- <value field="gnue_id">00000000000000000000000000000040</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">procedure</value>
- </row>
- <row>
- <value field="gnue_comment">GNU Enterprise Business Object
Property</value>
- <value field="gnue_id">00000000000000000000000000000030</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">property</value>
- </row>
- </rows>
- </tabledata>
- <tabledata name="gnue_property_dump" tablename="gnue_property">
- <definition>
- <column field="gnue_class" type="string(32)"/>
- <column field="gnue_comment" type="string(70)"/>
- <column field="gnue_id" type="string(32)"/>
- <column field="gnue_length" type="number(6)"/>
- <column field="gnue_module" type="string(32)"/>
- <column field="gnue_name" type="string(35)"/>
- <column field="gnue_nullable" type="boolean"/>
- <column field="gnue_scale" type="number(4)"/>
- <column field="gnue_type" type="string(35)"/>
- </definition>
- <rows>
- <row>
- <value field="gnue_class">00000000000000000000000000000020</value>
- <value field="gnue_comment">Comment</value>
- <value field="gnue_id">00000000000000000000000000000024</value>
- <value field="gnue_length">70</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">comment</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000020</value>
- <value field="gnue_comment">Object ID</value>
- <value field="gnue_id">00000000000000000000000000000021</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">id</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">id</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000020</value>
- <value field="gnue_comment">Module that defined this class</value>
- <value field="gnue_id">00000000000000000000000000000022</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">module</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">gnue_module</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000020</value>
- <value field="gnue_comment">Classname without modulename</value>
- <value field="gnue_id">00000000000000000000000000000023</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">name</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000010</value>
- <value field="gnue_comment">Comment</value>
- <value field="gnue_id">00000000000000000000000000000013</value>
- <value field="gnue_length">70</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">comment</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000010</value>
- <value field="gnue_comment">Object ID</value>
- <value field="gnue_id">00000000000000000000000000000011</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">id</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">id</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000010</value>
- <value field="gnue_comment">Name</value>
- <value field="gnue_id">00000000000000000000000000000012</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">name</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Comment</value>
- <value field="gnue_id">00000000000000000000000000000057</value>
- <value field="gnue_length">70</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">comment</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Object ID</value>
- <value field="gnue_id">00000000000000000000000000000051</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">id</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">id</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Lenght of the parameter</value>
- <value field="gnue_id">00000000000000000000000000000055</value>
- <value field="gnue_length">6</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">length</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">number</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Name of the parameter</value>
- <value field="gnue_id">00000000000000000000000000000053</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">name</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Procedure the parameter belongs
to</value>
- <value field="gnue_id">00000000000000000000000000000052</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">procedure</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">gnue_procedure</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Scale of numeric data</value>
- <value field="gnue_id">00000000000000000000000000000056</value>
- <value field="gnue_length">4</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">scale</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">number</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000050</value>
- <value field="gnue_comment">Parameter type</value>
- <value field="gnue_id">00000000000000000000000000000054</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">type</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Class the procedure belongs to</value>
- <value field="gnue_id">00000000000000000000000000000042</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">class</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">gnue_class</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Procedure code</value>
- <value field="gnue_id">00000000000000000000000000000046</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">code</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Comment</value>
- <value field="gnue_id">00000000000000000000000000000048</value>
- <value field="gnue_length">70</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">comment</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Compiled procedure code</value>
- <value field="gnue_id">00000000000000000000000000000047</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">compiledcode</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Object ID</value>
- <value field="gnue_id">00000000000000000000000000000041</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">id</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">id</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Procedure language</value>
- <value field="gnue_id">00000000000000000000000000000045</value>
- <value field="gnue_length">10</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">language</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Length of the procedures result</value>
- <value field="gnue_id">0000000000000000000000000000004A</value>
- <value field="gnue_length">6</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">length</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">number</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Module that defined this
procedure</value>
- <value field="gnue_id">00000000000000000000000000000043</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">module</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">gnue_module</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Procedurename without modulename</value>
- <value field="gnue_id">00000000000000000000000000000044</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">name</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Result of the procedure can contain NULL
values</value>
- <value field="gnue_id">0000000000000000000000000000004C</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">nullable</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">boolean</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Scale of the procedures result</value>
- <value field="gnue_id">0000000000000000000000000000004B</value>
- <value field="gnue_length">4</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">scale</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">number</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000040</value>
- <value field="gnue_comment">Type of the procedures result</value>
- <value field="gnue_id">00000000000000000000000000000049</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">type</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Class the property belongs to</value>
- <value field="gnue_id">00000000000000000000000000000032</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">class</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">gnue_class</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Comment</value>
- <value field="gnue_id">00000000000000000000000000000038</value>
- <value field="gnue_length">70</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">comment</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Object ID</value>
- <value field="gnue_id">00000000000000000000000000000031</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">id</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">id</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Lenght of the property</value>
- <value field="gnue_id">00000000000000000000000000000036</value>
- <value field="gnue_length">6</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">length</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">number</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Module that defined this property</value>
- <value field="gnue_id">00000000000000000000000000000033</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">module</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">gnue_module</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Propertyname without modulename</value>
- <value field="gnue_id">00000000000000000000000000000034</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">name</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Property can contain NULL values</value>
- <value field="gnue_id">00000000000000000000000000000039</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">nullable</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">boolean</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Scale of numeric data</value>
- <value field="gnue_id">00000000000000000000000000000037</value>
- <value field="gnue_length">4</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">scale</value>
- <value field="gnue_nullable">TRUE</value>
- <value field="gnue_type">number</value>
- </row>
- <row>
- <value field="gnue_class">00000000000000000000000000000030</value>
- <value field="gnue_comment">Property type</value>
- <value field="gnue_id">00000000000000000000000000000035</value>
- <value field="gnue_length">35</value>
- <value field="gnue_module">00000000000000000000000000000000</value>
- <value field="gnue_name">type</value>
- <value field="gnue_nullable">FALSE</value>
- <value field="gnue_type">string</value>
- </row>
- </rows>
- </tabledata>
- </data>
-</schema>
Added: gnue-cddb/schema/cddb-C.gld
===================================================================
--- gnue-cddb/schema/cddb-C.gld 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/schema/cddb-C.gld 2004-12-02 14:36:52 UTC (rev 151)
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- CD Database - Standard Language Definitions
+
+ Copyright 2004 Free Software Foundation
+
+ This file is part of GNU Enterprise.
+
+ GNU Enterprise 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.
+
+ GNU Enterprise is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY 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 GNU Enterprise; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ $Id$ -->
+
+<module name="cddb" language="C" >
+
+ <class name="artist" label="Artist" >
+ <property name="firstname" pos="100" label="First name"/>
+ <property name="middlename" pos="200" label="Middle name"/>
+ <property name="lastname" pos="300" label="Last name"/>
+ <property name="name" pos="400" label="Name" search="100" />
+ <property name="matchcode" pos="500" label="Matchcode" />
+ </class>
+
+ <class name="category" label="Category">
+ <property name="name" pos="100" label="Name" search="100" />
+ <property name="matchcode" pos="200" label="Matchcode" />
+ <property name="id3" pos="300" label="ID3-Genre-ID" />
+ <property name="filedb_pattern" pos="400" label="Path-Pattern"
+ page="Cddb" />
+ </class>
+
+ <class name="disc" label="Disc">
+ <property name="title" pos="100" label="Title" search="100" />
+ <property name="artist" pos="200" label="Artist" />
+ <property name="category" pos="300" label="Category" />
+ <property name="discid" pos="400" label="Disc-Id" search="200" />
+ <property name="year" pos="500" label="Year" />
+ <property name="comment" pos="600" label="Comment" />
+ <property name="length" pos="700" label="Length" />
+ </class>
+
+
+ <class name="track" label="Track">
+ <property name="disc" pos="100" label="Disc" />
+ <property name="track" pos="200" label="Track" search="100" />
+ <property name="title" pos="300" label="Title" search="200" />
+ <property name="artist" pos="400" label="Artist" />
+ <property name="length" pos="500" label="Length" />
+ <property name="comment" pos="600" label="Comment" />
+ </class>
+
+ <class name="options" label="Options">
+ <property name="basepath" pos="300" label="Base path" />
+ </class>
+
+</module>
Property changes on: gnue-cddb/schema/cddb-C.gld
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: gnue-cddb/schema/cddb.gcd
===================================================================
--- gnue-cddb/schema/cddb.gcd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/schema/cddb.gcd 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,60 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- CD Database Module
+
+ Copyright 2004 Free Software Foundation
+
+ This file is part of GNU Enterprise.
+
+ GNU Enterprise 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.
+
+ GNU Enterprise is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY 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 GNU Enterprise; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ $Id$ -->
+
<module name="cddb" comment="CD Database">
+
+ <!-- ================================================================= -->
+ <!-- cddb_artist -->
+ <!-- ================================================================= -->
+
<class name="artist" comment="Artists">
- <property name="name" type="string(30)" nullable="N"/>
+ <property name="firstname" type="string(30)" />
+ <property name="middlename" type="string(30)" />
+ <property name="lastname" type="string(30)" nullable="False" />
+
+ <property name="name" type="string(100)">
+ import re
+ result = re.sub ('\s+', ' ', "%s %s %s" % \
+ (self.lastname or '', self.middlename or '', self.firstname or ''))
+ return result.strip ()
+ </property>
+
+ <property name="matchcode" type="string(100)">
+ return self.name.upper ()
+ </property>
</class>
+
+ <!-- ================================================================= -->
+ <!-- cddb_category -->
+ <!-- ================================================================= -->
+
<class name="category" comment="Category/Genre">
- <property name="id" type="number(3)" comment="ID3-Genre-ID" nullable="N"/>
- <property name="name" type="string(30)" comment="Name of the genre"
- nullable="N"/>
- <property name="matchcode" type="string(30)"
- comment="Matchcode of the category" nullable="N"/>
+ <property name="name" type="string(30)" nullable="False" />
+ <property name="matchcode" type="string(30)" nullable="False" />
+
+ <property name="id3" type="number(3)" nullable="False"
+ comment="ID3-Genre-ID" />
</class>
+
+ <!-- ================================================================= -->
+ <!-- cddb_disc -->
+ <!-- ================================================================= -->
+
<class name="disc" comment="Disc">
- <property name="title" type="string(60)" nullable="N"
- comment="Title of the disc"/>
- <property name="artist" type="cddb_artist" comment="Artist of the disc"/>
- <property name="category" type="cddb_category"
- comment="Category of the disc"/>
- <property name="year" type="number(4)" comment="Year of the recording"/>
- <property name="discid" type="string(8)" comment="CDDB-Disc-Id (hex)"
- nullable="N"/>
- <property name="comment" type="string(70)" comment="Comment"/>
+ <property name="title" type="string(60)" nullable="False" />
+ <property name="artist" type="cddb_artist" />
+ <property name="category" type="cddb_category" />
+ <property name="year" type="number(4)" comment="Year of the
recording"/>
+ <property name="comment" type="string(70)" />
+ <property name="discid" type="string(8)" nullable="False"
+ comment="CDDB-Disc-Id (hex)" />
- <property name="length" type="number(4)"
- comment="Length of the disc in seconds">
- <![CDATA[
- cond = ['eq', ['field', 'cddb_disc'], ['const', self.gnue_id]]
- tracks = find ('cddb_track', cond, [], ['cddb_length'])
- res = 0
+ <property name="seconds" type="number(5)" />
+ <property name="length" type="time" comment="Length of the disc">
+ import mx.DateTime
+ tracks = session.find ('cddb_track', {'cddb_disc': self.gnue_id}, [],
+ ['cddb_length'])
+
+ result = [mx.DateTime.Time (0, 0, 0)]
+
for track in tracks:
if track.cddb_length is not None:
- res += track.cddb_length
+ l = track.cddb_length
+ result.append (mx.DateTime.Time (l.hour, l.minute, l.second))
- return res
- ]]>
+ return sum (result)
</property>
+
+
+
+ <!-- ############################################################## -->
+ <!-- Triggers in cddb_disc -->
+ <!-- ############################################################## -->
+
+ <procedure name="OnDelete">
+ <!-- If a disc get's deleted, make sure to remove all tracks too -->
+ tracks = session.find ('cddb_track', {'cddb_disc': self.gnue_id}, [], [])
+ for item in tracks:
+ item.delete ()
+ </procedure>
</class>
+
+ <!-- ================================================================= -->
+ <!-- cddb_track -->
+ <!-- ================================================================= -->
+
<class name="track" comment="Tracks of a disc">
- <property name="disc" type="cddb_disc" nullable="N"
- comment="Disc this track is from"/>
- <property name="track" type="number(3)" nullable="N"
- comment="Number of the track on the disc"/>
- <property name="title" type="string(60)" nullable="N"
- comment="Title of the track"/>
- <property name="artist" type="cddb_artist" comment="Artist of the track"/>
- <property name="length" type="number(4)"
- comment="Length of the track in seconds"/>
- <property name="comment" type="string(28)" comment="Comment on the track"/>
+ <property name="disc" type="cddb_disc" nullable="False" />
+ <property name="track" type="number(3)" nullable="False" />
+ <property name="title" type="string(60)" nullable="False" />
+ <property name="artist" type="cddb_artist" />
+ <property name="length" type="time" />
+ <property name="comment" type="string(28)" />
</class>
+
+ <!-- ================================================================= -->
+ <!-- cddb_options -->
+ <!-- ================================================================= -->
+
<class name="options">
- <property name="ripcmd" type="string(80)"/>
- <property name="enccmd" type="string(80)"/>
- <property name="basepath" type="string(250)"/>
+ <property name="basepath" type="string(250)" />
</class>
+
</module>
Property changes on: gnue-cddb/schema/cddb.gcd
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: gnue-cddb/schema/filedb.gcd
===================================================================
--- gnue-cddb/schema/filedb.gcd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/schema/filedb.gcd 2004-12-02 14:36:52 UTC (rev 151)
@@ -1,29 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- File Database Module
+
+ Copyright 2004 Free Software Foundation
+
+ This file is part of GNU Enterprise.
+
+ GNU Enterprise 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.
+
+ GNU Enterprise is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY 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 GNU Enterprise; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ $Id$ -->
+
<module name="filedb" comment="CD Database in the filesystem">
+
+ <!-- ================================================================= -->
+ <!-- cddb_category -->
+ <!-- ================================================================= -->
+
+ <class module="cddb" name="category">
+ <property name="pattern" type="string(250)" />
+ </class>
+
+
+ <!-- ================================================================= -->
+ <!-- cddb_disc -->
+ <!-- ================================================================= -->
+
<class name="disc" module="cddb">
- <property name="url" type="string" comment="Base dir of the disc">
+ <property name="url" type="string(250)" />
+
+ <procedure name="defaultURL" type="string" >
from os import path, environ
- opt = find ('cddb_options', [], [], ['cddb_basepath'])
- basepath = len (opt) and opt [0].cddb_basepath or environ ['HOME']
- basepath = path.normpath (basepath)
+ opt = session.find ('cddb_options', [], [], ['cddb_basepath'])
+ default = opt and opt [0].cddb_basepath or environ ['HOME']
- category = self.cddb_category.cddb_name
- artist = self.cddb_artist.cddb_name
- title = self.cddb_title
-
- if self.cddb_category.cddb_matchcode == 'soundtrack':
- discPath = path.join (basepath, category, title)
+ if self.cddb_category:
+ pattern = self.cddb_category.filedb_pattern or default
+ category = self.cddb_category.cddb_name
+ matchcode = self.cddb_category.cddb_matchcode
else:
- discPath = path.join (basepath, category, artist, title)
+ pattern = default
+ category = 'Unknown'
+ matchcode = 'unknown'
- return discPath.replace (' ', '_')
- </property>
+ artist = self.cddb_artist and self.cddb_artist.cddb_name or 'Various'
+ title = self.cddb_title or 'Unknown'
+
+ reps = {'%a': artist, '%t': title, '%c': category, '%m': matchcode}
+
+ for (item, value) in reps.items ():
+ if item in pattern:
+ pattern = pattern.replace (item, value)
+
+ return pattern.replace (' ', '_')
+ </procedure>
</class>
<class name="track" module="cddb">
<property name="url" type="string(254)"
comment="location where the track can be found"/>
+
<property name="ripdate" type="date"
comment="Date when this track has been ripped"/>
</class>
Property changes on: gnue-cddb/schema/filedb.gcd
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: gnue-cddb/schema/gen.gsd
===================================================================
--- gnue-cddb/schema/gen.gsd 2004-12-02 13:55:01 UTC (rev 150)
+++ gnue-cddb/schema/gen.gsd 2004-12-02 14:36:52 UTC (rev 151)
@@ -3,899 +3,899 @@
<data>
<tabledata name="cddb_category" tablename="cddb_category">
<definition>
- <column field="gnue_id" type="string"/>
+ <column field="gnue_id" type="string" key="Y"/>
<column field="cddb_name" type="string"/>
<column field="cddb_matchcode" type="string"/>
- <column field="cddb_id" type="number(3)"/>
+ <column field="cddb_id3" type="number(3)"/>
</definition>
<rows>
<row>
- <value field="gnue_id"
key="Y">66701866162529911928725201445908</value>
+ <value field="gnue_id">66701866162529911928725201445908</value>
<value field="cddb_name">Blues</value>
<value field="cddb_matchcode">blues</value>
- <value field="cddb_id">0</value>
+ <value field="cddb_id3">0</value>
</row>
<row>
<value field="gnue_id">00218526255349161424646652034701</value>
<value field="cddb_name">Classic Rock</value>
<value field="cddb_matchcode">classic rock</value>
- <value field="cddb_id">1</value>
+ <value field="cddb_id3">1</value>
</row>
<row>
<value field="gnue_id">35765124130626636119738674886283</value>
<value field="cddb_name">Country</value>
<value field="cddb_matchcode">country</value>
- <value field="cddb_id">2</value>
+ <value field="cddb_id3">2</value>
</row>
<row>
<value field="gnue_id">81276407449117225734881052379489</value>
<value field="cddb_name">Dance</value>
<value field="cddb_matchcode">dance</value>
- <value field="cddb_id">3</value>
+ <value field="cddb_id3">3</value>
</row>
<row>
<value field="gnue_id">40617821044142761915776991535674</value>
<value field="cddb_name">Disco</value>
<value field="cddb_matchcode">disco</value>
- <value field="cddb_id">4</value>
+ <value field="cddb_id3">4</value>
</row>
<row>
<value field="gnue_id">52058749571386082714885708618681</value>
<value field="cddb_name">Funk</value>
<value field="cddb_matchcode">funk</value>
- <value field="cddb_id">5</value>
+ <value field="cddb_id3">5</value>
</row>
<row>
<value field="gnue_id">76361996279967140679858636794335</value>
<value field="cddb_name">Grunge</value>
<value field="cddb_matchcode">grunge</value>
- <value field="cddb_id">6</value>
+ <value field="cddb_id3">6</value>
</row>
<row>
<value field="gnue_id">34940971625955962005215891603019</value>
<value field="cddb_name">Hip-Hop</value>
<value field="cddb_matchcode">hip-hop</value>
- <value field="cddb_id">7</value>
+ <value field="cddb_id3">7</value>
</row>
<row>
<value field="gnue_id">77366474092568650154415024362175</value>
<value field="cddb_name">Jazz</value>
<value field="cddb_matchcode">jazz</value>
- <value field="cddb_id">8</value>
+ <value field="cddb_id3">8</value>
</row>
<row>
<value field="gnue_id">96901223117082517024400665401032</value>
<value field="cddb_name">Metal</value>
<value field="cddb_matchcode">metal</value>
- <value field="cddb_id">9</value>
+ <value field="cddb_id3">9</value>
</row>
<row>
<value field="gnue_id">90335976249381425215540963031148</value>
<value field="cddb_name">New Age</value>
<value field="cddb_matchcode">newage</value>
- <value field="cddb_id">10</value>
+ <value field="cddb_id3">10</value>
</row>
<row>
<value field="gnue_id">29085334926763595781149645474921</value>
<value field="cddb_name">Oldies</value>
<value field="cddb_matchcode">oldies</value>
- <value field="cddb_id">11</value>
+ <value field="cddb_id3">11</value>
</row>
<row>
<value field="gnue_id">33644200081232766128504476940826</value>
<value field="cddb_name">Other</value>
<value field="cddb_matchcode">misc</value>
- <value field="cddb_id">12</value>
+ <value field="cddb_id3">12</value>
</row>
<row>
<value field="gnue_id">79751860849835125979684421095295</value>
<value field="cddb_name">Pop</value>
<value field="cddb_matchcode">pop</value>
- <value field="cddb_id">13</value>
+ <value field="cddb_id3">13</value>
</row>
<row>
<value field="gnue_id">59960660020899644352013251911231</value>
<value field="cddb_name">R & B</value>
<value field="cddb_matchcode">r & b</value>
- <value field="cddb_id">14</value>
+ <value field="cddb_id3">14</value>
</row>
<row>
<value field="gnue_id">91700082290071534136065428088871</value>
<value field="cddb_name">Rap</value>
<value field="cddb_matchcode">rap</value>
- <value field="cddb_id">15</value>
+ <value field="cddb_id3">15</value>
</row>
<row>
<value field="gnue_id">95221275641236371662120424246556</value>
<value field="cddb_name">Reggea</value>
<value field="cddb_matchcode">reggea</value>
- <value field="cddb_id">16</value>
+ <value field="cddb_id3">16</value>
</row>
<row>
<value field="gnue_id">10215867214258687425685630124939</value>
<value field="cddb_name">Rock</value>
<value field="cddb_matchcode">rock</value>
- <value field="cddb_id">17</value>
+ <value field="cddb_id3">17</value>
</row>
<row>
<value field="gnue_id">22660823988001403664484933334615</value>
<value field="cddb_name">Techno</value>
<value field="cddb_matchcode">techno</value>
- <value field="cddb_id">18</value>
+ <value field="cddb_id3">18</value>
</row>
<row>
<value field="gnue_id">40167531571821501287448705768026</value>
<value field="cddb_name">Industrial</value>
<value field="cddb_matchcode">industrial</value>
- <value field="cddb_id">19</value>
+ <value field="cddb_id3">19</value>
</row>
<row>
<value field="gnue_id">89285049801313761427318659151302</value>
<value field="cddb_name">Alternative</value>
<value field="cddb_matchcode">alternative</value>
- <value field="cddb_id">20</value>
+ <value field="cddb_id3">20</value>
</row>
<row>
<value field="gnue_id">83875436357139389972565153538127</value>
<value field="cddb_name">Ska</value>
<value field="cddb_matchcode">ska</value>
- <value field="cddb_id">21</value>
+ <value field="cddb_id3">21</value>
</row>
<row>
<value field="gnue_id">11220442361881550085985618493603</value>
<value field="cddb_name">Death Metal</value>
<value field="cddb_matchcode">death metal</value>
- <value field="cddb_id">22</value>
+ <value field="cddb_id3">22</value>
</row>
<row>
<value field="gnue_id">44290396337211915772457802687764</value>
<value field="cddb_name">Pranks</value>
<value field="cddb_matchcode">pranks</value>
- <value field="cddb_id">23</value>
+ <value field="cddb_id3">23</value>
</row>
<row>
<value field="gnue_id">95100737118440617119068250963228</value>
<value field="cddb_name">Soundtrack</value>
<value field="cddb_matchcode">soundtrack</value>
- <value field="cddb_id">24</value>
+ <value field="cddb_id3">24</value>
</row>
<row>
<value field="gnue_id">17785417424876986843449621388194</value>
<value field="cddb_name">Euro-Techno</value>
<value field="cddb_matchcode">euro-techno</value>
- <value field="cddb_id">25</value>
+ <value field="cddb_id3">25</value>
</row>
<row>
<value field="gnue_id">28213764694219247509976246936588</value>
<value field="cddb_name">Ambient</value>
<value field="cddb_matchcode">ambient</value>
- <value field="cddb_id">26</value>
+ <value field="cddb_id3">26</value>
</row>
<row>
<value field="gnue_id">86439617551457781076943395364402</value>
<value field="cddb_name">Trip-Hop</value>
<value field="cddb_matchcode">trip-hop</value>
- <value field="cddb_id">27</value>
+ <value field="cddb_id3">27</value>
</row>
<row>
<value field="gnue_id">07871356297905626318433262085438</value>
<value field="cddb_name">Vocal</value>
<value field="cddb_matchcode">vocal</value>
- <value field="cddb_id">28</value>
+ <value field="cddb_id3">28</value>
</row>
<row>
<value field="gnue_id">78841042548415367589855954726433</value>
<value field="cddb_name">Jazz+Funk</value>
<value field="cddb_matchcode">jazz+funk</value>
- <value field="cddb_id">29</value>
+ <value field="cddb_id3">29</value>
</row>
<row>
<value field="gnue_id">44109730557254851684921622613068</value>
<value field="cddb_name">Fusion</value>
<value field="cddb_matchcode">fusion</value>
- <value field="cddb_id">30</value>
+ <value field="cddb_id3">30</value>
</row>
<row>
<value field="gnue_id">02686943600137307369951295736875</value>
<value field="cddb_name">Trance</value>
<value field="cddb_matchcode">trance</value>
- <value field="cddb_id">31</value>
+ <value field="cddb_id3">31</value>
</row>
<row>
<value field="gnue_id">58029714176699050813566230485317</value>
<value field="cddb_name">Classical</value>
<value field="cddb_matchcode">classical</value>
- <value field="cddb_id">32</value>
+ <value field="cddb_id3">32</value>
</row>
<row>
<value field="gnue_id">29812540319085453469966223142305</value>
<value field="cddb_name">Instrumental</value>
<value field="cddb_matchcode">instrumental</value>
- <value field="cddb_id">33</value>
+ <value field="cddb_id3">33</value>
</row>
<row>
<value field="gnue_id">27568702327474131529228658180411</value>
<value field="cddb_name">Acid</value>
<value field="cddb_matchcode">acid</value>
- <value field="cddb_id">34</value>
+ <value field="cddb_id3">34</value>
</row>
<row>
<value field="gnue_id">43970929206191803128779680454997</value>
<value field="cddb_name">House</value>
<value field="cddb_matchcode">house</value>
- <value field="cddb_id">35</value>
+ <value field="cddb_id3">35</value>
</row>
<row>
<value field="gnue_id">37702681000521283100050892189287</value>
<value field="cddb_name">Game</value>
<value field="cddb_matchcode">game</value>
- <value field="cddb_id">36</value>
+ <value field="cddb_id3">36</value>
</row>
<row>
<value field="gnue_id">95911720659292655925869556323755</value>
<value field="cddb_name">Sound Clip</value>
<value field="cddb_matchcode">sound clip</value>
- <value field="cddb_id">37</value>
+ <value field="cddb_id3">37</value>
</row>
<row>
<value field="gnue_id">42592318770541561780719561000648</value>
<value field="cddb_name">Gospel</value>
<value field="cddb_matchcode">gospel</value>
- <value field="cddb_id">38</value>
+ <value field="cddb_id3">38</value>
</row>
<row>
<value field="gnue_id">29589953054634694104173066597473</value>
<value field="cddb_name">Noise</value>
<value field="cddb_matchcode">noise</value>
- <value field="cddb_id">39</value>
+ <value field="cddb_id3">39</value>
</row>
<row>
<value field="gnue_id">20592838984603503210087320071803</value>
<value field="cddb_name">Alt. Rock</value>
<value field="cddb_matchcode">alt. rock</value>
- <value field="cddb_id">40</value>
+ <value field="cddb_id3">40</value>
</row>
<row>
<value field="gnue_id">48757509453564626473763128907241</value>
<value field="cddb_name">Bass</value>
<value field="cddb_matchcode">bass</value>
- <value field="cddb_id">41</value>
+ <value field="cddb_id3">41</value>
</row>
<row>
<value field="gnue_id">04919185963943906109925801278230</value>
<value field="cddb_name">Soul</value>
<value field="cddb_matchcode">soul</value>
- <value field="cddb_id">42</value>
+ <value field="cddb_id3">42</value>
</row>
<row>
<value field="gnue_id">73927086405639579940901558470711</value>
<value field="cddb_name">Punk</value>
<value field="cddb_matchcode">punk</value>
- <value field="cddb_id">43</value>
+ <value field="cddb_id3">43</value>
</row>
<row>
<value field="gnue_id">91433799844331669775531486844441</value>
<value field="cddb_name">Space</value>
<value field="cddb_matchcode">space</value>
- <value field="cddb_id">44</value>
+ <value field="cddb_id3">44</value>
</row>
<row>
<value field="gnue_id">27472857179004275197190369270596</value>
<value field="cddb_name">Meditative</value>
<value field="cddb_matchcode">meditative</value>
- <value field="cddb_id">45</value>
+ <value field="cddb_id3">45</value>
</row>
<row>
<value field="gnue_id">37080212594853356587745246589261</value>
<value field="cddb_name">Instrumental Pop</value>
<value field="cddb_matchcode">instrumental pop</value>
- <value field="cddb_id">46</value>
+ <value field="cddb_id3">46</value>
</row>
<row>
<value field="gnue_id">17982473067048442168117750841731</value>
<value field="cddb_name">Instrumental Rock</value>
<value field="cddb_matchcode">instrumental rock</value>
- <value field="cddb_id">47</value>
+ <value field="cddb_id3">47</value>
</row>
<row>
<value field="gnue_id">22893981031194399847611735219524</value>
<value field="cddb_name">Ethnic</value>
<value field="cddb_matchcode">ethnic</value>
- <value field="cddb_id">48</value>
+ <value field="cddb_id3">48</value>
</row>
<row>
<value field="gnue_id">06301987749808109719612360352708</value>
<value field="cddb_name">Gothic</value>
<value field="cddb_matchcode">gothic</value>
- <value field="cddb_id">49</value>
+ <value field="cddb_id3">49</value>
</row>
<row>
<value field="gnue_id">77708840238518963607988104218290</value>
<value field="cddb_name">Darkwave</value>
<value field="cddb_matchcode">darkwave</value>
- <value field="cddb_id">50</value>
+ <value field="cddb_id3">50</value>
</row>
<row>
<value field="gnue_id">47742859607452832752972178229577</value>
<value field="cddb_name">Techno-Industrial</value>
<value field="cddb_matchcode">techno-industrial</value>
- <value field="cddb_id">51</value>
+ <value field="cddb_id3">51</value>
</row>
<row>
<value field="gnue_id">73087271431351657263589816638698</value>
<value field="cddb_name">Electronic</value>
<value field="cddb_matchcode">electronic</value>
- <value field="cddb_id">52</value>
+ <value field="cddb_id3">52</value>
</row>
<row>
<value field="gnue_id">10440536357325185361305205669166</value>
<value field="cddb_name">Pop-Folk</value>
<value field="cddb_matchcode">pop-folk</value>
- <value field="cddb_id">53</value>
+ <value field="cddb_id3">53</value>
</row>
<row>
<value field="gnue_id">40858869305243497297564597819507</value>
<value field="cddb_name">Eurodance</value>
<value field="cddb_matchcode">eurodance</value>
- <value field="cddb_id">54</value>
+ <value field="cddb_id3">54</value>
</row>
<row>
<value field="gnue_id">63175318176656070094765088882782</value>
<value field="cddb_name">Dream</value>
<value field="cddb_matchcode">dream</value>
- <value field="cddb_id">55</value>
+ <value field="cddb_id3">55</value>
</row>
<row>
<value field="gnue_id">06404618275235933937112732290648</value>
<value field="cddb_name">Southern Rock</value>
<value field="cddb_matchcode">southern rock</value>
- <value field="cddb_id">56</value>
+ <value field="cddb_id3">56</value>
</row>
<row>
<value field="gnue_id">66305564033441826319248502634948</value>
<value field="cddb_name">Comedy</value>
<value field="cddb_matchcode">comedy</value>
- <value field="cddb_id">57</value>
+ <value field="cddb_id3">57</value>
</row>
<row>
<value field="gnue_id">93991799085286060136737906909649</value>
<value field="cddb_name">Cult</value>
<value field="cddb_matchcode">cult</value>
- <value field="cddb_id">58</value>
+ <value field="cddb_id3">58</value>
</row>
<row>
<value field="gnue_id">81872436418932463688015141880448</value>
<value field="cddb_name">Gangsta Rap</value>
<value field="cddb_matchcode">gangsta rap</value>
- <value field="cddb_id">59</value>
+ <value field="cddb_id3">59</value>
</row>
<row>
<value field="gnue_id">13999598585465379583160276315076</value>
<value field="cddb_name">Top 40</value>
<value field="cddb_matchcode">top 40</value>
- <value field="cddb_id">60</value>
+ <value field="cddb_id3">60</value>
</row>
<row>
<value field="gnue_id">72189552068680123645283782201095</value>
<value field="cddb_name">Christian Rap</value>
<value field="cddb_matchcode">christian rap</value>
- <value field="cddb_id">61</value>
+ <value field="cddb_id3">61</value>
</row>
<row>
<value field="gnue_id">17583933017162517302598789918750</value>
<value field="cddb_name">Pop/Funk</value>
<value field="cddb_matchcode">pop/funk</value>
- <value field="cddb_id">62</value>
+ <value field="cddb_id3">62</value>
</row>
<row>
<value field="gnue_id">59494040682148369323201438805404</value>
<value field="cddb_name">Jungle</value>
<value field="cddb_matchcode">jungle</value>
- <value field="cddb_id">63</value>
+ <value field="cddb_id3">63</value>
</row>
<row>
<value field="gnue_id">53997376895665093106457409976905</value>
<value field="cddb_name">Native American</value>
<value field="cddb_matchcode">native american</value>
- <value field="cddb_id">64</value>
+ <value field="cddb_id3">64</value>
</row>
<row>
<value field="gnue_id">12649698699945247265339951841617</value>
<value field="cddb_name">Cabaret</value>
<value field="cddb_matchcode">cabaret</value>
- <value field="cddb_id">65</value>
+ <value field="cddb_id3">65</value>
</row>
<row>
<value field="gnue_id">36451569275671911969390638816653</value>
<value field="cddb_name">New Wave</value>
<value field="cddb_matchcode">new wave</value>
- <value field="cddb_id">66</value>
+ <value field="cddb_id3">66</value>
</row>
<row>
<value field="gnue_id">80281330043254501247543251151786</value>
<value field="cddb_name">Psychedelic</value>
<value field="cddb_matchcode">psychedelic</value>
- <value field="cddb_id">67</value>
+ <value field="cddb_id3">67</value>
</row>
<row>
<value field="gnue_id">88292858410908156134063151676974</value>
<value field="cddb_name">Rave</value>
<value field="cddb_matchcode">rave</value>
- <value field="cddb_id">68</value>
+ <value field="cddb_id3">68</value>
</row>
<row>
<value field="gnue_id">65455069700988714628984145421224</value>
<value field="cddb_name">Showtunes</value>
<value field="cddb_matchcode">showtunes</value>
- <value field="cddb_id">69</value>
+ <value field="cddb_id3">69</value>
</row>
<row>
<value field="gnue_id">49824828123564496458135096460258</value>
<value field="cddb_name">Trailer</value>
<value field="cddb_matchcode">trailer</value>
- <value field="cddb_id">70</value>
+ <value field="cddb_id3">70</value>
</row>
<row>
<value field="gnue_id">61653578555156607713964973570004</value>
<value field="cddb_name">Lo-Fi</value>
<value field="cddb_matchcode">lo-fi</value>
- <value field="cddb_id">71</value>
+ <value field="cddb_id3">71</value>
</row>
<row>
<value field="gnue_id">48264714576801299921510443672292</value>
<value field="cddb_name">Tribal</value>
<value field="cddb_matchcode">tribal</value>
- <value field="cddb_id">72</value>
+ <value field="cddb_id3">72</value>
</row>
<row>
<value field="gnue_id">40265716738335812893192259650524</value>
<value field="cddb_name">Acid Punk</value>
<value field="cddb_matchcode">acid punk</value>
- <value field="cddb_id">73</value>
+ <value field="cddb_id3">73</value>
</row>
<row>
<value field="gnue_id">12100889003685752752375330032054</value>
<value field="cddb_name">Acid Jazz</value>
<value field="cddb_matchcode">acid jazz</value>
- <value field="cddb_id">74</value>
+ <value field="cddb_id3">74</value>
</row>
<row>
<value field="gnue_id">13613372866137118273152719599162</value>
<value field="cddb_name">Polka</value>
<value field="cddb_matchcode">polka</value>
- <value field="cddb_id">75</value>
+ <value field="cddb_id3">75</value>
</row>
<row>
<value field="gnue_id">62144662958123128909645381793358</value>
<value field="cddb_name">Retro</value>
<value field="cddb_matchcode">retro</value>
- <value field="cddb_id">76</value>
+ <value field="cddb_id3">76</value>
</row>
<row>
<value field="gnue_id">89525304541875758193824761068278</value>
<value field="cddb_name">Musical</value>
<value field="cddb_matchcode">musical</value>
- <value field="cddb_id">77</value>
+ <value field="cddb_id3">77</value>
</row>
<row>
<value field="gnue_id">63614692867659499557079218357300</value>
<value field="cddb_name">Rock & Roll</value>
<value field="cddb_matchcode">rock & roll</value>
- <value field="cddb_id">78</value>
+ <value field="cddb_id3">78</value>
</row>
<row>
<value field="gnue_id">32882539661462108873672536579731</value>
<value field="cddb_name">Hard Rock</value>
<value field="cddb_matchcode">hard rock</value>
- <value field="cddb_id">79</value>
+ <value field="cddb_id3">79</value>
</row>
<row>
<value field="gnue_id">29478318130247644864406058691023</value>
<value field="cddb_name">Folk</value>
<value field="cddb_matchcode">folk</value>
- <value field="cddb_id">80</value>
+ <value field="cddb_id3">80</value>
</row>
<row>
<value field="gnue_id">78132195209540626594770655762882</value>
<value field="cddb_name">Folk/Rock</value>
<value field="cddb_matchcode">folk/rock</value>
- <value field="cddb_id">81</value>
+ <value field="cddb_id3">81</value>
</row>
<row>
<value field="gnue_id">21047689577134160999043954322132</value>
<value field="cddb_name">National Folk</value>
<value field="cddb_matchcode">national folk</value>
- <value field="cddb_id">82</value>
+ <value field="cddb_id3">82</value>
</row>
<row>
<value field="gnue_id">19089819891746467199714776790066</value>
<value field="cddb_name">Swing</value>
<value field="cddb_matchcode">swing</value>
- <value field="cddb_id">83</value>
+ <value field="cddb_id3">83</value>
</row>
<row>
<value field="gnue_id">25147045177113572787273851121591</value>
<value field="cddb_name">Fast-Fusion</value>
<value field="cddb_matchcode">fast-fusion</value>
- <value field="cddb_id">84</value>
+ <value field="cddb_id3">84</value>
</row>
<row>
<value field="gnue_id">27471736827354061256004497983924</value>
<value field="cddb_name">Bebob</value>
<value field="cddb_matchcode">bebob</value>
- <value field="cddb_id">85</value>
+ <value field="cddb_id3">85</value>
</row>
<row>
<value field="gnue_id">07793971034894454769270504371796</value>
<value field="cddb_name">Latin</value>
<value field="cddb_matchcode">latin</value>
- <value field="cddb_id">86</value>
+ <value field="cddb_id3">86</value>
</row>
<row>
<value field="gnue_id">60498238144083329597103495211186</value>
<value field="cddb_name">Revival</value>
<value field="cddb_matchcode">revival</value>
- <value field="cddb_id">87</value>
+ <value field="cddb_id3">87</value>
</row>
<row>
<value field="gnue_id">57885876441077439698033313017974</value>
<value field="cddb_name">Celtic</value>
<value field="cddb_matchcode">celtic</value>
- <value field="cddb_id">88</value>
+ <value field="cddb_id3">88</value>
</row>
<row>
<value field="gnue_id">63688791660379709051431162480550</value>
<value field="cddb_name">Bluegrass</value>
<value field="cddb_matchcode">bluegrass</value>
- <value field="cddb_id">89</value>
+ <value field="cddb_id3">89</value>
</row>
<row>
<value field="gnue_id">82783069969179696950205246665203</value>
<value field="cddb_name">Avantgarde</value>
<value field="cddb_matchcode">avantgarde</value>
- <value field="cddb_id">90</value>
+ <value field="cddb_id3">90</value>
</row>
<row>
<value field="gnue_id">98644970504440423078095225393791</value>
<value field="cddb_name">Gothic Rock</value>
<value field="cddb_matchcode">gothic rock</value>
- <value field="cddb_id">91</value>
+ <value field="cddb_id3">91</value>
</row>
<row>
<value field="gnue_id">49214527806577983579266382187053</value>
<value field="cddb_name">Progressive Rock</value>
<value field="cddb_matchcode">progressive rock</value>
- <value field="cddb_id">92</value>
+ <value field="cddb_id3">92</value>
</row>
<row>
<value field="gnue_id">42109545139200694337441346902374</value>
<value field="cddb_name">Psychedelic Rock</value>
<value field="cddb_matchcode">psychedelic rock</value>
- <value field="cddb_id">93</value>
+ <value field="cddb_id3">93</value>
</row>
<row>
<value field="gnue_id">62629945210463848971626835732999</value>
<value field="cddb_name">Symphonic Rock</value>
<value field="cddb_matchcode">symphonic rock</value>
- <value field="cddb_id">94</value>
+ <value field="cddb_id3">94</value>
</row>
<row>
<value field="gnue_id">05105596192676406137481275862923</value>
<value field="cddb_name">Slow Rock</value>
<value field="cddb_matchcode">slow rock</value>
- <value field="cddb_id">95</value>
+ <value field="cddb_id3">95</value>
</row>
<row>
<value field="gnue_id">75627783131405317464107500151166</value>
<value field="cddb_name">Big Band</value>
<value field="cddb_matchcode">big band</value>
- <value field="cddb_id">96</value>
+ <value field="cddb_id3">96</value>
</row>
<row>
<value field="gnue_id">77558967585728977821136576939525</value>
<value field="cddb_name">Chorus</value>
<value field="cddb_matchcode">chorus</value>
- <value field="cddb_id">97</value>
+ <value field="cddb_id3">97</value>
</row>
<row>
<value field="gnue_id">69695051754699783346286384433574</value>
<value field="cddb_name">Easy Listening</value>
<value field="cddb_matchcode">easy listening</value>
- <value field="cddb_id">98</value>
+ <value field="cddb_id3">98</value>
</row>
<row>
<value field="gnue_id">49578803358034034276543585284440</value>
<value field="cddb_name">Acoustic</value>
<value field="cddb_matchcode">acoustic</value>
- <value field="cddb_id">99</value>
+ <value field="cddb_id3">99</value>
</row>
<row>
<value field="gnue_id">18086924775608029347346867959230</value>
<value field="cddb_name">Humour</value>
<value field="cddb_matchcode">humour</value>
- <value field="cddb_id">100</value>
+ <value field="cddb_id3">100</value>
</row>
<row>
<value field="gnue_id">44683471388167167037364729180508</value>
<value field="cddb_name">Speech</value>
<value field="cddb_matchcode">speech</value>
- <value field="cddb_id">101</value>
+ <value field="cddb_id3">101</value>
</row>
<row>
<value field="gnue_id">33255805384581798289539613557449</value>
<value field="cddb_name">Chanson</value>
<value field="cddb_matchcode">chanson</value>
- <value field="cddb_id">102</value>
+ <value field="cddb_id3">102</value>
</row>
<row>
<value field="gnue_id">17410350969689700588940938547048</value>
<value field="cddb_name">Opera</value>
<value field="cddb_matchcode">opera</value>
- <value field="cddb_id">103</value>
+ <value field="cddb_id3">103</value>
</row>
<row>
<value field="gnue_id">07960967650668730770880512299941</value>
<value field="cddb_name">Chamber Music</value>
<value field="cddb_matchcode">chamber music</value>
- <value field="cddb_id">104</value>
+ <value field="cddb_id3">104</value>
</row>
<row>
<value field="gnue_id">12515828113282307306833482620270</value>
<value field="cddb_name">Sonata</value>
<value field="cddb_matchcode">sonata</value>
- <value field="cddb_id">105</value>
+ <value field="cddb_id3">105</value>
</row>
<row>
<value field="gnue_id">47675474224023131227193278067302</value>
<value field="cddb_name">Symphony</value>
<value field="cddb_matchcode">symphony</value>
- <value field="cddb_id">106</value>
+ <value field="cddb_id3">106</value>
</row>
<row>
<value field="gnue_id">26008406302255464865855808750925</value>
<value field="cddb_name">Booty Bass</value>
<value field="cddb_matchcode">booty bass</value>
- <value field="cddb_id">107</value>
+ <value field="cddb_id3">107</value>
</row>
<row>
<value field="gnue_id">18381878326008673623470673372089</value>
<value field="cddb_name">Primus</value>
<value field="cddb_matchcode">primus</value>
- <value field="cddb_id">108</value>
+ <value field="cddb_id3">108</value>
</row>
<row>
<value field="gnue_id">88075370894526952273074838090125</value>
<value field="cddb_name">Porn Grove</value>
<value field="cddb_matchcode">porn grove</value>
- <value field="cddb_id">109</value>
+ <value field="cddb_id3">109</value>
</row>
<row>
<value field="gnue_id">28826655636244665527579339030441</value>
<value field="cddb_name">Satire</value>
<value field="cddb_matchcode">satire</value>
- <value field="cddb_id">110</value>
+ <value field="cddb_id3">110</value>
</row>
<row>
<value field="gnue_id">26462847698462243084683270142356</value>
<value field="cddb_name">Slow Jam</value>
<value field="cddb_matchcode">slow jam</value>
- <value field="cddb_id">111</value>
+ <value field="cddb_id3">111</value>
</row>
<row>
<value field="gnue_id">53260547276376099177779434722371</value>
<value field="cddb_name">Club</value>
<value field="cddb_matchcode">club</value>
- <value field="cddb_id">112</value>
+ <value field="cddb_id3">112</value>
</row>
<row>
<value field="gnue_id">49229313233830021492915210123128</value>
<value field="cddb_name">Tango</value>
<value field="cddb_matchcode">tango</value>
- <value field="cddb_id">113</value>
+ <value field="cddb_id3">113</value>
</row>
<row>
<value field="gnue_id">38575838137836537421750358377795</value>
<value field="cddb_name">Samba</value>
<value field="cddb_matchcode">samba</value>
- <value field="cddb_id">114</value>
+ <value field="cddb_id3">114</value>
</row>
<row>
<value field="gnue_id">24213536962270350908403902560833</value>
<value field="cddb_name">Folklore</value>
<value field="cddb_matchcode">folklore</value>
- <value field="cddb_id">115</value>
+ <value field="cddb_id3">115</value>
</row>
<row>
<value field="gnue_id">32265929046692559877459697474424</value>
<value field="cddb_name">Ballad</value>
<value field="cddb_matchcode">ballad</value>
- <value field="cddb_id">116</value>
+ <value field="cddb_id3">116</value>
</row>
<row>
<value field="gnue_id">65756800363438344723655076240414</value>
<value field="cddb_name">Power Ballad</value>
<value field="cddb_matchcode">power ballad</value>
- <value field="cddb_id">117</value>
+ <value field="cddb_id3">117</value>
</row>
<row>
<value field="gnue_id">85015586358331776279358456511791</value>
<value field="cddb_name">Rhythmic Soul</value>
<value field="cddb_matchcode">rhythmic soul</value>
- <value field="cddb_id">118</value>
+ <value field="cddb_id3">118</value>
</row>
<row>
<value field="gnue_id">72652292817382074678426880213775</value>
<value field="cddb_name">Freestyle</value>
<value field="cddb_matchcode">freestyle</value>
- <value field="cddb_id">119</value>
+ <value field="cddb_id3">119</value>
</row>
<row>
<value field="gnue_id">55765496432138428423200153915597</value>
<value field="cddb_name">Duet</value>
<value field="cddb_matchcode">duet</value>
- <value field="cddb_id">120</value>
+ <value field="cddb_id3">120</value>
</row>
<row>
<value field="gnue_id">12745144784874063605799389089625</value>
<value field="cddb_name">Punk Rock</value>
<value field="cddb_matchcode">punk rock</value>
- <value field="cddb_id">121</value>
+ <value field="cddb_id3">121</value>
</row>
<row>
<value field="gnue_id">48230208647196736830751298337937</value>
<value field="cddb_name">Drum Solo</value>
<value field="cddb_matchcode">drum solo</value>
- <value field="cddb_id">122</value>
+ <value field="cddb_id3">122</value>
</row>
<row>
<value field="gnue_id">62558858920620957194078666671697</value>
<value field="cddb_name">A Cappella</value>
<value field="cddb_matchcode">a cappella</value>
- <value field="cddb_id">123</value>
+ <value field="cddb_id3">123</value>
</row>
<row>
<value field="gnue_id">52678748736733873194093288042772</value>
<value field="cddb_name">Euro-House</value>
<value field="cddb_matchcode">euro-house</value>
- <value field="cddb_id">124</value>
+ <value field="cddb_id3">124</value>
</row>
<row>
<value field="gnue_id">95995169125526380140436737425304</value>
<value field="cddb_name">Dance Hall</value>
<value field="cddb_matchcode">dance hall</value>
- <value field="cddb_id">125</value>
+ <value field="cddb_id3">125</value>
</row>
<row>
<value field="gnue_id">49181567725454580922754977799494</value>
<value field="cddb_name">Goa</value>
<value field="cddb_matchcode">goa</value>
- <value field="cddb_id">126</value>
+ <value field="cddb_id3">126</value>
</row>
<row>
<value field="gnue_id">03290804280881122639640728385338</value>
<value field="cddb_name">Drum & Bass</value>
<value field="cddb_matchcode">drum & bass</value>
- <value field="cddb_id">127</value>
+ <value field="cddb_id3">127</value>
</row>
<row>
<value field="gnue_id">57886011079776899270764489269270</value>
<value field="cddb_name">Club-House</value>
<value field="cddb_matchcode">club-house</value>
- <value field="cddb_id">128</value>
+ <value field="cddb_id3">128</value>
</row>
<row>
<value field="gnue_id">59949198638528069894359189928221</value>
<value field="cddb_name">Hardcore</value>
<value field="cddb_matchcode">hardcore</value>
- <value field="cddb_id">129</value>
+ <value field="cddb_id3">129</value>
</row>
<row>
<value field="gnue_id">86174932529628690292212716588512</value>
<value field="cddb_name">Terror</value>
<value field="cddb_matchcode">terror</value>
- <value field="cddb_id">130</value>
+ <value field="cddb_id3">130</value>
</row>
<row>
<value field="gnue_id">34998820100578081340968442032572</value>
<value field="cddb_name">Indie</value>
<value field="cddb_matchcode">indie</value>
- <value field="cddb_id">131</value>
+ <value field="cddb_id3">131</value>
</row>
<row>
<value field="gnue_id">61478697229297297008918680782458</value>
<value field="cddb_name">BritPop</value>
<value field="cddb_matchcode">britpop</value>
- <value field="cddb_id">132</value>
+ <value field="cddb_id3">132</value>
</row>
<row>
<value field="gnue_id">55852832742951796485460107358839</value>
<value field="cddb_name">NegerPunk</value>
<value field="cddb_matchcode">negerpunk</value>
- <value field="cddb_id">133</value>
+ <value field="cddb_id3">133</value>
</row>
<row>
<value field="gnue_id">98444631587441731134381000873361</value>
<value field="cddb_name">PolskPunk</value>
<value field="cddb_matchcode">polskpunk</value>
- <value field="cddb_id">134</value>
+ <value field="cddb_id3">134</value>
</row>
<row>
<value field="gnue_id">93983533225639269410317273438986</value>
<value field="cddb_name">Beat</value>
<value field="cddb_matchcode">beat</value>
- <value field="cddb_id">135</value>
+ <value field="cddb_id3">135</value>
</row>
<row>
<value field="gnue_id">02459127420165062942118616225232</value>
<value field="cddb_name">Christian GanstaRap</value>
<value field="cddb_matchcode">christian ganstarap</value>
- <value field="cddb_id">136</value>
+ <value field="cddb_id3">136</value>
</row>
<row>
<value field="gnue_id">76749776816155577254765763922590</value>
<value field="cddb_name">Heavy Metal</value>
<value field="cddb_matchcode">heavy metal</value>
- <value field="cddb_id">137</value>
+ <value field="cddb_id3">137</value>
</row>
<row>
<value field="gnue_id">93823148939625682498916790270374</value>
<value field="cddb_name">Black Metal</value>
<value field="cddb_matchcode">black metal</value>
- <value field="cddb_id">138</value>
+ <value field="cddb_id3">138</value>
</row>
<row>
<value field="gnue_id">83005761662283054145337367147868</value>
<value field="cddb_name">Crossover</value>
<value field="cddb_matchcode">crossover</value>
- <value field="cddb_id">139</value>
+ <value field="cddb_id3">139</value>
</row>
<row>
<value field="gnue_id">03167378290707082533943235184850</value>
<value field="cddb_name">Contemporary Christian</value>
<value field="cddb_matchcode">contemporary christian</value>
- <value field="cddb_id">140</value>
+ <value field="cddb_id3">140</value>
</row>
<row>
<value field="gnue_id">80024595667757763069936159381757</value>
<value field="cddb_name">Christian Rock</value>
<value field="cddb_matchcode">christian rock</value>
- <value field="cddb_id">141</value>
+ <value field="cddb_id3">141</value>
</row>
<row>
<value field="gnue_id">22417156925207224270261794438355</value>
<value field="cddb_name">Merengue</value>
<value field="cddb_matchcode">merengue</value>
- <value field="cddb_id">142</value>
+ <value field="cddb_id3">142</value>
</row>
<row>
<value field="gnue_id">84345077684357090757855813011150</value>
<value field="cddb_name">Salsa</value>
<value field="cddb_matchcode">salsa</value>
- <value field="cddb_id">143</value>
+ <value field="cddb_id3">143</value>
</row>
<row>
<value field="gnue_id">79492183360817918687992709279828</value>
<value field="cddb_name">Trash Metal</value>
<value field="cddb_matchcode">trash metal</value>
- <value field="cddb_id">144</value>
+ <value field="cddb_id3">144</value>
</row>
<row>
<value field="gnue_id">37433373555270910197913138925903</value>
<value field="cddb_name">Anime</value>
<value field="cddb_matchcode">anime</value>
- <value field="cddb_id">145</value>
+ <value field="cddb_id3">145</value>
</row>
<row>
<value field="gnue_id">69545103302249279429922020219231</value>
<value field="cddb_name">JPop</value>
<value field="cddb_matchcode">jpop</value>
- <value field="cddb_id">146</value>
+ <value field="cddb_id3">146</value>
</row>
<row>
<value field="gnue_id">55429642853283235682066707379246</value>
<value field="cddb_name">Synthpop</value>
<value field="cddb_matchcode">synthpop</value>
- <value field="cddb_id">147</value>
+ <value field="cddb_id3">147</value>
</row>
</rows>
</tabledata>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r151 - in gnue-cddb: . lib schema,
johannes <=