Commit 2297eff4 authored by Jean-Francois Dockes's avatar Jean-Francois Dockes
Browse files

uprcl: create recoll documents for the albums (those do not actually exist in the file system)

parent 8f44d4a7
...@@ -101,7 +101,7 @@ import uprclinit ...@@ -101,7 +101,7 @@ import uprclinit
# store than by using an exclusion list, but it's a bit more difficult # store than by using an exclusion list, but it's a bit more difficult
# to manage. # to manage.
# #
# + possibly 'xdocid' if/when needed? # + possibly 'xdocid' and/or 'rcludi' if/when needed?
# #
_otherneededfields = [ _otherneededfields = [
'albumartist', 'allartists', 'comment', 'composer', 'conductor', 'albumartist', 'allartists', 'comment', 'composer', 'conductor',
...@@ -220,15 +220,15 @@ class Folders(object): ...@@ -220,15 +220,15 @@ class Folders(object):
def _pathbeyondtopdirs(self, doc): def _pathbeyondtopdirs(self, doc):
url = uprclutils.docpath(doc).decode('utf-8', errors='replace') url = uprclutils.docpath(doc).decode('utf-8', errors='replace')
# Determine the root entry (topdirs element). Special because # Determine the root entry (topdirs element). Special because
# its path is not a simple name. # its path is not a simple name. Fathidx is its index in _dirvec
fathidx = -1 firstdiridx = -1
for rtpath,idx in self._dirvec[0].items(): for rtpath,idx in self._dirvec[0].items():
#uplog("type(url) %s type(rtpath) %s rtpath %s url %s" % #uplog("type(url) %s type(rtpath) %s rtpath %s url %s" %
# (type(url),type(rtpath),rtpath, url)) # (type(url),type(rtpath),rtpath, url))
if url.startswith(rtpath): if url.startswith(rtpath):
fathidx = idx[0] firstdiridx = idx[0]
break break
if fathidx == -1: if firstdiridx == -1:
# uplog("No parent in topdirs: %s" % url) # uplog("No parent in topdirs: %s" % url)
return None,None return None,None
...@@ -248,7 +248,7 @@ class Folders(object): ...@@ -248,7 +248,7 @@ class Folders(object):
# Split path. The caller will walk the list (possibly creating # Split path. The caller will walk the list (possibly creating
# directory entries as needed, or doing something else). # directory entries as needed, or doing something else).
path = url1.split('/')[1:] path = url1.split('/')[1:]
return fathidx, path return firstdiridx, path
# Main folders build method: walk the recoll docs array and split # Main folders build method: walk the recoll docs array and split
...@@ -299,7 +299,8 @@ class Folders(object): ...@@ -299,7 +299,8 @@ class Folders(object):
# For linking item search results to the main # For linking item search results to the main
# array. Deactivated for now as it does not seem to be # array. Deactivated for now as it does not seem to be
# needed. # needed (and we would need to add xdocid to the
# resultstore fields).
#self._xid2idx[doc["xdocid"]] = docidx #self._xid2idx[doc["xdocid"]] = docidx
fathidx, path = self._pathbeyondtopdirs(doc) fathidx, path = self._pathbeyondtopdirs(doc)
...@@ -409,8 +410,7 @@ class Folders(object): ...@@ -409,8 +410,7 @@ class Folders(object):
pathremain = '' pathremain = ''
else: else:
if dirpth[0:2] != '$d': if dirpth[0:2] != '$d':
raise Exception("folders:browse: called on non dir objid %s" % raise Exception("folders:browse: called on non dir objid %s" % pid)
pid)
# Other $sign? # Other $sign?
nextdol = dirpth.find("$", 1) nextdol = dirpth.find("$", 1)
if nextdol > 0: if nextdol > 0:
...@@ -573,15 +573,22 @@ class Folders(object): ...@@ -573,15 +573,22 @@ class Folders(object):
return path return path
# Compute object id for doc out of recoll search. Not used at the moment. # Compute object id for doc out of recoll search. Not used at the
# and _xid2idx is not built # moment, and _xid2idx is not built.
def _objidforxdocid(self, doc): def _objidforxdocid(self, doc):
if doc["xdocid"] not in self._xid2idx: if doc["xdocid"] not in self._xid2idx:
return None return None
return self._idprefix + '$i' + str(self._xid2idx[doc["xdocid"]]) return self._idprefix + '$i' + str(self._xid2idx[doc["xdocid"]])
# Given a doc, we walk its url down from the part in root to find
# its directory entry, and return the _dirvec and _rcldocs indices
# it holds, either of which can be -1
def _stat(self, doc): def _stat(self, doc):
# _pathbeyond... returns the _dirvec index of the root entry
# we start from (root is special), and the split rest of path.
# That is if the doc url has /av/mp3/classique/bach/ and the root entry is /av/mp3,
# we get the _dirvec entry index for /av/mp3 and [classique, bach]
fathidx, pathl = self._pathbeyondtopdirs(doc) fathidx, pathl = self._pathbeyondtopdirs(doc)
if not fathidx: if not fathidx:
return -1,-1 return -1,-1
...@@ -603,10 +610,13 @@ class Folders(object): ...@@ -603,10 +610,13 @@ class Folders(object):
def objidfordoc(self, doc): def objidfordoc(self, doc):
id=None
if doc["mtype"] == 'inode/directory': if doc["mtype"] == 'inode/directory':
id = self._objidforpath(doc) id = self._objidforpath(doc)
else: #else:
id = self._objidforxdocid(doc) # # Note: not currently doing anything, see method comments
# id = self._objidforxdocid(doc)
if not id: if not id:
id = self._idprefix + '$' + 'seeyoulater' id = self._idprefix + '$' + 'seeyoulater'
return id return id
...@@ -22,6 +22,7 @@ from recoll import recoll ...@@ -22,6 +22,7 @@ from recoll import recoll
from upmplgutils import uplog from upmplgutils import uplog
from conftree import stringToStrings from conftree import stringToStrings
import uprclutils import uprclutils
import uprclinit
def _getchar(s, i): def _getchar(s, i):
if i < len(s): if i < len(s):
...@@ -223,11 +224,12 @@ def _upnpsearchtorecoll(s): ...@@ -223,11 +224,12 @@ def _upnpsearchtorecoll(s):
return " ".join(out) return " ".join(out)
# inobjid is for the container this search is run from.
def search(foldersobj, rclconfdir, objid, upnps, idprefix, httphp, pathprefix): def search(foldersobj, rclconfdir, inobjid, upnps, idprefix, httphp, pathprefix):
tags = uprclinit.getTree('tags')
rcls = _upnpsearchtorecoll(upnps) rcls = _upnpsearchtorecoll(upnps)
filterdir = foldersobj.dirpath(objid) filterdir = foldersobj.dirpath(inobjid)
if filterdir and filterdir != "/": if filterdir and filterdir != "/":
rcls += " dir:\"" + filterdir + "\"" rcls += " dir:\"" + filterdir + "\""
...@@ -250,8 +252,24 @@ def search(foldersobj, rclconfdir, objid, upnps, idprefix, httphp, pathprefix): ...@@ -250,8 +252,24 @@ def search(foldersobj, rclconfdir, objid, upnps, idprefix, httphp, pathprefix):
while True: while True:
docs = rclq.fetchmany() docs = rclq.fetchmany()
for doc in docs: for doc in docs:
id = foldersobj.objidfordoc(doc) # The doc is either an actual recollindex product from the
e = uprclutils.rcldoctoentry(id, objid, httphp, pathprefix, doc) # FS or a synthetic one from uprcltags creating album
# entries. Different processing for either
e = None
if doc["rcludi"].find("albid") == 0:
albid = doc["rcludi"][5:]
uplog("rcludi %s albid %s" % (doc["rcludi"], albid))
e = tags.direntryforalbid(albid)
else:
# Objidfordoc uses the path from the url to walk the
# _dirvec and determine the right entry if doc is a
# container. If doc is an item, the returned id is bogus
# (0$uprcl$folders$seeyoulater), because it's not useful
# at the moment. Of course, this breaks the recommendation
# for the objids to be consistent and unchanging
id = foldersobj.objidfordoc(doc)
uplog("Search: id [%s] for doc udi [%s]\n" % (id, doc["rcludi"]))
e = uprclutils.rcldoctoentry(id, inobjid, httphp, pathprefix, doc)
if e: if e:
entries.append(e) entries.append(e)
if (maxcnt > 0 and len(entries) >= maxcnt) or \ if (maxcnt > 0 and len(entries) >= maxcnt) or \
......
...@@ -316,6 +316,23 @@ class Tagged(object): ...@@ -316,6 +316,23 @@ class Tagged(object):
upnpclass='object.container.album.musicAlbum')) upnpclass='object.container.album.musicAlbum'))
return entries return entries
# Called when the search finds one of our synthetic album search
# results. Create a container entry for it
def direntryforalbid(self, albid):
intalbid = int(albid)
c = self._conn.cursor()
stmt = '''SELECT album_id, albtitle, albarturi, albdate, artist.value
FROM albums LEFT JOIN artist ON artist.artist_id = albums.artist_id
WHERE album_id = ? AND albtdisc is NULL ORDER BY albtitle'''
args = (intalbid,)
c.execute(stmt, args)
for r in c:
pid = uprclinit.getObjPrefix() + 'albums'
id = pid + '$' + albid
return rcldirentry(id, pid, r[1], arturi=r[2], date=r[3],artist=r[4],
upnpclass='object.container.album.musicAlbum')
return None
# This is called when an 'albums' element is encountered in the # This is called when an 'albums' element is encountered in the
# selection path. i is the index of the albums element. The tree under # selection path. i is the index of the albums element. The tree under
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
import os import os
import time import time
import re import re
from recoll import recoll
from timeit import default_timer as timer from timeit import default_timer as timer
from uprclutils import audiomtypes, docfolder, uplog from uprclutils import audiomtypes, docfolder, uplog
...@@ -353,7 +354,27 @@ def _setalbumartists(conn): ...@@ -353,7 +354,27 @@ def _setalbumartists(conn):
c1.execute('''UPDATE albums SET artist_id = ? c1.execute('''UPDATE albums SET artist_id = ?
WHERE album_id = ?''', (r[1], r[0])) WHERE album_id = ?''', (r[1], r[0]))
# Update the recoll index for the albums
def _albumstorecoll(conn):
rcldb = recoll.connect(confdir=uprclinit.getRclConfdir(), writable=True)
c = conn.cursor()
# 0 1 2 3 4 5
stmt = '''SELECT album_id, albfolder, albtitle, albarturi, albdate, artist.value
FROM albums LEFT JOIN artist ON artist.artist_id = albums.artist_id
WHERE albtdisc is NULL'''
c.execute(stmt, ())
for r in c:
udi = "albid" + str(r[0])
doc = recoll.Doc()
doc["album"] = r[2]
doc["title"] = r[2]
doc["mtype"] = "inode/directory"
if r[5]:
doc["albumartist"] = r[5]
doc["url"] = "file://" + r[1]
uplog("_albumstorecoll: creating album for: %s" % doc["album"])
rcldb.addOrUpdate(udi, doc)
# Check that the numbers are sequential # Check that the numbers are sequential
def _checkseq(seq): def _checkseq(seq):
num = seq[0] num = seq[0]
...@@ -544,4 +565,5 @@ def recolltosql(conn, rcldocs): ...@@ -544,4 +565,5 @@ def recolltosql(conn, rcldocs):
end = timer() end = timer()
uplog("recolltosql: processed %d docs in %.2f Seconds" % uplog("recolltosql: processed %d docs in %.2f Seconds" %
(totcnt, end-start)) (totcnt, end-start))
_albumstorecoll(conn)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment