--- a/src/mediaserver/cdplugins/uprcl/uprcltags.py
+++ b/src/mediaserver/cdplugins/uprcl/uprcltags.py
@@ -32,8 +32,11 @@
#
# TBD: All Artists
#
-# Maybe we'd actually need a 3rd value for the recoll field name, but
-# it can be the same for the currently relevant fields.
+# The key is the presentation name (container title). The value is the
+# auxiliary table name, used also as base for unique id and join
+# columns (with _id) appended, and is also currently the recoll field
+# name (with a provision to differ if needed, thanks to the
+# currently empty _coltorclfield dict).
_tagtotable = {
'Artist' : 'artist',
'Date' : 'date',
@@ -46,15 +49,17 @@
'Comment' : 'comment'
}
+def _clid(table):
+ return table + '_id'
+
# Translation only used when fetching fields from the recoll
# record. None at the moment
_coltorclfield = {
}
-def _clid(col):
- return col + '_id'
-
+
+# The browseable object which defines the tree of tracks organized by tags.
class Tagged(object):
def __init__(self, docs, httphp, pathprefix):
self._httphp = httphp
@@ -62,6 +67,15 @@
self._conn = None
self._rcldocs = docs
self._init_sqconn()
+ # Compute an array of (table name, recoll field) translations. Most
+ # often they are identical.
+ self._tabtorclfield = []
+ for tb in _tagtotable.values():
+ if tb in _coltorclfield:
+ rclfld = _coltorclfield[tb]
+ else:
+ rclfld = tb
+ self._tabtorclfield.append((tb, rclfld))
self._recolltosql(docs)
@@ -125,6 +139,42 @@
return rowid
+ # tracknos like n/max are now supposedly processed by rclaudio and
+ # should not arrive here, but let's play it safe.
+ def _tracknofordoc(self, doc):
+ try:
+ return int(doc.tracknumber.split('/')[0])
+ except:
+ return 0
+
+ # Create album record if needed.
+ # The albums table is special, can't use auxtableinsert()
+ def _maybecreatealbum(self, c, doc):
+ folder = docfolder(doc).decode('utf-8', errors = 'replace')
+ album = getattr(doc, 'album', None)
+ if not album:
+ album = os.path.basename(folder)
+ #uplog("Using %s for alb: mime %s title %s" %
+ #(album,doc.mtype, doc.url))
+ if doc.albumartist:
+ albartist_id = self._auxtableinsert('artist', doc.albumartist)
+ else:
+ albartist_id = None
+ c.execute('''SELECT album_id, artist_id FROM albums
+ WHERE albtitle = ? AND albfolder = ?''', (album, folder))
+ r = c.fetchone()
+ if r:
+ album_id = r[0]
+ albartist_id = r[1]
+ else:
+ c.execute('''INSERT INTO albums(albtitle, albfolder, artist_id,
+ albdate, albarturi)
+ VALUES (?,?,?,?,?)''', (album, folder, albartist_id, doc.date,
+ doc.albumarturi))
+ album_id = c.lastrowid
+ return album_id, albartist_id
+
+
# Create the db and fill it up with the values we need, taken out of
# the recoll records list
def _recolltosql(self, docs):
@@ -132,16 +182,6 @@
self._createsqdb()
- # Compute a list of table names and corresponding recoll
- # fields. most often they are identical
- tabfields = []
- for tb in _tagtotable.values():
- if tb in _coltorclfield:
- rclfld = _coltorclfield[tb]
- else:
- rclfld = tb
- tabfields.append((tb, rclfld))
-
c = self._conn.cursor()
maxcnt = 0
totcnt = 0
@@ -156,45 +196,18 @@
if doc.mtype not in audiomtypes or doc.mtype == 'inode/directory':
continue
- # Create album record if needed.
- # The albums table is special, can't use auxtableinsert()
- folder = docfolder(doc).decode('utf-8', errors = 'replace')
- album = getattr(doc, 'album', None)
- if not album:
- album = os.path.basename(folder)
- #uplog("Using %s for alb: mime %s title %s" %
- #(album,doc.mtype, doc.url))
- if doc.albumartist:
- albartist_id = self._auxtableinsert('artist', doc.albumartist)
- else:
- albartist_id = None
- c.execute('''SELECT album_id,artist_id FROM albums
- WHERE albtitle = ? AND albfolder = ?''', (album, folder))
- r = c.fetchone()
- if r:
- album_id = r[0]
- albartist_id = r[1]
- else:
- c.execute('''INSERT INTO albums(albtitle, albfolder, artist_id,
- albdate, albarturi)
- VALUES (?,?,?,?,?)''', (album, folder, albartist_id, doc.date,
- doc.albumarturi))
- album_id = c.lastrowid
-
- # tracknos like n/max are now supposedly processed by rclaudio
- # and should not arrive here
- try:
- l= doc.tracknumber.split('/')
- trackno = int(l[0])
- except:
- trackno = 0
-
- # Set base values for column names, values list, placeholders,
- # then append data from auxiliary tables array
+ album_id, albartist_id = self._maybecreatealbum(c, doc)
+
+ trackno = self._tracknofordoc(doc)
+
+ # Set base values for column names, values list,
+ # placeholders
columns = 'docidx,album_id,trackno,title'
values = [docidx, album_id, trackno, doc.title]
placehold = '?,?,?,?'
- for tb,rclfld in tabfields:
+ # Append data for each auxiliary table if the doc has a value
+ # for the corresponding field (else let SQL set a dflt/null value)
+ for tb, rclfld in self._tabtorclfield:
value = getattr(doc, rclfld, None)
if not value:
continue
@@ -203,12 +216,15 @@
values.append(rowid)
placehold += ',?'
- # Finally create the main record in the tracks table with
- # references to the aux tables
+ # Create the main record in the tracks table.
stmt='INSERT INTO tracks(' + columns + ') VALUES(' + placehold + ')'
c.execute(stmt, values)
#uplog(doc.title)
+ # If the album had no artist yet, set it from the track
+ # artist. Means that if tracks for the same album have
+ # different artist values, we arbitrarily use the first
+ # one.
if not albartist_id:
lcols = columns.split(',')
try:
@@ -218,7 +234,8 @@
c.execute(stmt, (artist_id, album_id))
except:
pass
-
+ ## End Big doc loop
+
self._conn.commit()
end = timer()
uplog("recolltosql: processed %d docs in %.2f Seconds" %
@@ -240,8 +257,8 @@
return entries
- # Check what tags still have multiple values inside the selected set,
- # and return their list.
+ # Return the list of tags which have multiple values inside the
+ # input list of docids.
def _subtreetags(self, docidsl):
docids = ','.join([str(i) for i in docidsl])
uplog("subtreetags, docids %s" % docids)
@@ -252,23 +269,21 @@
') FROM tracks WHERE docidx IN (' + docids + ')'
uplog("subtreetags: executing: <%s>" % stmt)
c.execute(stmt)
- for r in c:
- cnt = r[0]
- uplog("Found %d distinct values for %s" % (cnt, tb))
- if cnt > 1:
- tags.append(tt)
+ cnt = c.fetchone()[0]
+ uplog("Found %d distinct values for %s" % (cnt, tb))
+ if cnt > 1:
+ tags.append(tt)
return tags
+ # Build a list of track directory entries for an SQL statement
+ # which selects docidxs (SELECT docidx,... FROM tracks WHERE...)
def _trackentriesforstmt(self, stmt, values, pid):
c = self._conn.cursor()
c.execute(stmt, values)
- entries = []
- for r in c:
- docidx = r[0]
- id = pid + '$i' + str(docidx)
- entries.append(rcldoctoentry(id, pid, self._httphp, self._pprefix,
- self._rcldocs[docidx]))
+ entries = [rcldoctoentry(pid + '$i' + str(r[0]),
+ pid, self._httphp, self._pprefix,
+ self._rcldocs[r[0]]) for r in c]
return sorted(entries, cmp=cmpentries)
@@ -285,7 +300,7 @@
def _trackentriesforalbum(self, albid, pid):
stmt = 'SELECT docidx FROM tracks WHERE album_id = ? ORDER BY trackno'
- return self._trackentriesforstmt(stmt,(albid,), pid)
+ return self._trackentriesforstmt(stmt, (albid,), pid)
def _direntriesforalbums(self, pid, where):