--- a/src/mediaserver/cdplugins/uprcl/uprcltags.py
+++ b/src/mediaserver/cdplugins/uprcl/uprcltags.py
@@ -203,37 +203,116 @@
 
 # Check what tags still have multiple values inside the selected set,
 # and return their list.
-def subtreetags(sqconn, docids):
+def subtreetags(docidsl):
+    docids = ','.join([str(i) for i in docidsl])
     uplog("subtreetags, docids %s" % docids)
-    c1 = sqconn.cursor()
+    c = sqconn.cursor()
     tags = []
     for tt,tb in tagtables.iteritems():
         stmt = 'SELECT COUNT(DISTINCT ' + colid(tb) + \
                ') FROM tracks WHERE docidx IN (' + docids + ')'
         uplog("subtreetags: executing: <%s>" % stmt)
-        c1.execute(stmt)
-        for r in c1:
+        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)
     return tags
 
-def subtreealbums(sqconn, docids):
-    c1 = sqconn.cursor()
+def trackentriesforstmt(stmt, values, pid, httphp, pathprefix):
+    c = sqconn.cursor()
+    c.execute(stmt, values)
+    entries = []
+    for r in c:
+        docidx = r[0]
+        id = pid + '$i' + str(docidx)
+        entries.append(rcldoctoentry(id, pid, httphp, pathprefix,
+                                     g_alldocs[docidx]))
+    return sorted(entries, cmp=cmpentries)
+    
+
+# Return a list of trackids as selected by the current
+# path <selwhere> is like: WHERE col1_id = ? AND col2_id = ? [...], and
+# <values> holds the corresponding values
+def docidsforsel(selwhere, values):
+    c = sqconn.cursor()
+    stmt = 'SELECT docidx FROM tracks ' + selwhere + ' ORDER BY trackno'
+    uplog("docidsforsel: executing <%s> values %s" % (stmt, values))
+    c.execute(stmt, values)
+    return [r[0] for r in c.fetchall()]
+
+def trackentriesforalbum(albid, pid, httphp, pathprefix):
+    stmt = 'SELECT docidx FROM tracks WHERE album_id = ? ORDER BY trackno'
+    return trackentriesforstmt(stmt, (albid,), pid, httphp, pathprefix)
+    
+# This is called when an 'albums' element is encountered in the
+# selection path.
+def tagsbrowsealbums(pid, qpath, i, selwhere, values, httphp, pathprefix):
+    c = sqconn.cursor()
+    docidsl = docidsforsel(selwhere, values)
+    entries = []
+    if i == len(qpath)-1:
+        albidsl = subtreealbums(docidsl)
+        albids = ','.join([str(a) for a in albidsl])
+        c.execute('SELECT album_id, albtitle FROM albums WHERE album_id in (' +
+                  albids + ') ORDER BY albtitle')
+        for r in c:
+            id = pid + '$' + str(r[0])
+            entries.append(rcldirentry(id, pid, r[1]))
+    elif i == len(qpath)-2:
+        albid = int(qpath[-1])
+        docids = ','.join([str(i) for i in docidsl])
+        stmt = 'SELECT COUNT(docidx) FROM tracks WHERE album_id = ?'
+        c.execute(stmt, (albid,))
+        r = c.fetchone()
+        ntracks = int(r[0])
+        stmt = 'SELECT docidx FROM tracks WHERE album_id = ? AND docidx IN (' +\
+               docids + ')'
+        entries = trackentriesforstmt(stmt, (albid,), pid, httphp, pathprefix)
+        if ntracks != len(entries):
+            id = pid + '$' + 'showca'
+            entries = [rcldirentry(id, pid, '>> Complete Album')] + entries
+    elif i == len(qpath)-3:
+        # Note that minim has an additional level here, probably to
+        # present groups or multiple groups ? The trackids ids are
+        # like: 
+        #    0$=Composer$17738$albums$2$showca.0$hcalbum$*i13458
+        # I don't know what the .0 is for.
+        # The 'hcalbum' level usually has 2 entries '>> Hide Content' 
+        # and the album title. TBD
+        albid = int(qpath[-2])
+        entries = trackentriesforalbum(albid, pid, httphp, pathprefix)
+        
+    return entries
+
+# This is called when an 'items' element is encountered in the
+# selection path. We just list the selected tracks
+def tagsbrowseitems(pid, qpath, i, selwhere, values, httphp, pathprefix):
+    stmt = 'SELECT docidx FROM tracks ' + selwhere
+    return trackentriesforstmt(stmt, values, pid, httphp, pathprefix)
+
+
+# Return all albums ids to which any of the currently selected tracks
+# (designated by a docid set) belong
+def subtreealbums(docidsl):
+    docids = ','.join([str(r) for r in docidsl])
     albids = []
     stmt = 'SELECT album_id from tracks where docidx IN (' + docids + ') ' + \
            'GROUP BY album_id'
-    c1.execute(stmt)
-    for r in c1:
+    c = sqconn.cursor()
+    uplog('subtreealbums: executing %s' % stmt)
+    c.execute(stmt)
+    for r in c:
         albids.append(r[0])
+    uplog('subtreealbums: returning %s' % albids)
     return albids
     
 # Main browsing routine. Given an objid, translate it into a select
 # statement, plus further processing, and return the corresponding
 # records
-def seltagsbrowse(pid, qpath, flag, httphp, pathprefix):
-    uplog("seltagsbrowse. qpath %s" % qpath)
+def tagsbrowse(pid, qpath, flag, httphp, pathprefix):
+    uplog("tagsbrowse. pid %s qpath %s" % (pid, qpath))
     qlen = len(qpath)
     selwhat = ''
     selwhere = ''
@@ -241,13 +320,24 @@
     i = 0
     while i < qlen:
         elt = qpath[i]
+
+        # '=colname'. Set the current column name, which will be used
+        # in different ways depending if this is the last element or
+        # not.
         if elt.startswith('='):
             col = tagtables[elt[1:]] 
 
-        #detect the special values albums items etc. here. Their
-        #presence changes how we process the rest (showing tracks and
-       #albums and not dealing with other tags any more
-
+        
+        # detect the special values albums items etc. here. Their
+        # presence changes how we process the rest (showing tracks and
+        # albums and not dealing with other tags any more)
+        if elt == 'albums':
+            return tagsbrowsealbums(pid, qpath, i, selwhere, values, httphp,
+                                    pathprefix)
+        elif elt == 'items':
+            return tagsbrowseitems(pid, qpath, i, selwhere, values, httphp,
+                                  pathprefix)
+            
         selwhere = selwhere + ' AND ' if selwhere else ' WHERE '
         if i == qlen - 1:
             # We want to display all unique values for the column
@@ -264,32 +354,26 @@
             values.append(int(qpath[i]))
         i += 1
             
-    c = sqconn.cursor()
-    #for r in c:
-    #    uplog("selres: %s" % r)
+
+    # TBD: Need a ">> Complete Album" entry if there is a single
+    # album, no subqs and not all the tracks are listed
     entries = []
     if selwhat == 'tracks.docidx':
-        # SELECT docidx FROM tracks
-        # WHERE col1_id = ? AND col2_id = ?
-        stmt = "SELECT docidx FROM tracks %s ORDER BY trackno" % selwhere
-        uplog("seltagsbrowse: executing <%s> values %s" % (stmt, values))
-        c.execute(stmt, values)
-        recs = c.fetchall()
-        docids = ','.join([str(r[0]) for r in recs])
-        albids = subtreealbums(sqconn, docids)
+        docids = docidsforsel(selwhere, values)
+        albids = subtreealbums(docids)
+        subqs = subtreetags(docids)
         if len(albids) > 1:
             id = pid + '$albums'
             entries.append(rcldirentry(id, pid, str(len(albids)) + ' albums'))
+            if subqs:
+                id = pid + '$items'
+                entries.append(rcldirentry(id,pid, str(len(docids)) + ' items'))
+        elif len(albids) == 1 and subqs:
             id = pid + '$items'
-            entries.append(rcldirentry(id, pid, str(len(recs)) + ' items'))
-        elif len(albids) == 1:
-            id = pid + '$items'
-            entries.append(rcldirentry(id, pid, str(len(recs)) + ' items'))
-
-        subqs = subtreetags(sqconn, docids)
+            entries.append(rcldirentry(id, pid, str(len(docids)) + ' items'))
+
         if not subqs:
-            for r in recs:
-                docidx = r[0]
+            for docidx in docids:
                 id = pid + '$*i' + str(docidx)
                 entries.append(rcldoctoentry(id, pid, httphp, pathprefix,
                                              g_alldocs[docidx]))
@@ -307,7 +391,8 @@
                selwhere + \
                " GROUP BY tracks." + colid(col) + \
                " ORDER BY value"
-        uplog("seltagsbrowse: executing <%s> values %s" % (stmt, values))
+        uplog("tagsbrowse: executing <%s> values %s" % (stmt, values))
+        c = sqconn.cursor()
         c.execute(stmt, values)
         for r in c:
             id = pid + '$' + str(r[0])
@@ -315,12 +400,14 @@
     return entries
 
 
+# Browse the top-level tree named like 'xxx albums'. There are just 2
+# levels: the whole albums list, then for each entry the specified
+# albums track list
 def albumsbrowse(pid, qpath, flag, httphp, pathprefix):
     c = sqconn.cursor()
     entries = []
     if len(qpath) == 1:
-        c.execute('''SELECT album_id, albtitle FROM albums
-        ORDER BY albtitle''')
+        c.execute('SELECT album_id, albtitle FROM albums ORDER BY albtitle')
         for r in c:
             id = pid + '$*' + str(r[0])
             entries.append(rcldirentry(id, pid, r[1]))
@@ -329,13 +416,7 @@
         if not e1.startswith("*"):
             raise Exception("Bad album id in albums tree. Pth: %s" %idpath)
         album_id = int(e1[1:])
-        c.execute('''SELECT docidx FROM tracks WHERE album_id = ? ORDER BY
-        trackno''', (album_id,))
-        for r in c:
-            docidx = r[0]
-            id = pid + '$*i' + str(docidx)
-            entries.append(rcldoctoentry(id, pid, httphp, pathprefix,
-                                         g_alldocs[docidx]))
+        entries = trackentriesforalbum(album_id, pid, httphp, pathprefix)
     else:
         raise Exception("Bad path in album tree (too deep): <%s>"%idpath)
 
@@ -350,17 +431,12 @@
     entries = []
     qpath = idpath.split('$')
     if idpath.startswith('items'):
-        c = sqconn.cursor()
-        c.execute('''SELECT docidx FROM tracks ORDER BY title''')
-        for r in c:
-            docidx = r[0]
-            id = pid + '$*i' + str(docidx)
-            entries.append(rcldoctoentry(id, pid, httphp, pathprefix,
-                                         g_alldocs[docidx]))
+        stmt = 'SELECT docidx FROM tracks'
+        entries = trackentriesforstmt(stmt, (), pid, httphp, pathprefix)
     elif idpath.startswith('albums'):
         entries = albumsbrowse(pid, qpath, flag, httphp, pathprefix)
     elif idpath.startswith('='):
-        entries = seltagsbrowse(pid, qpath, flag, httphp, pathprefix)
+        entries = tagsbrowse(pid, qpath, flag, httphp, pathprefix)
     else:
         raise Exception('Bad path in tags tree (start): <%s>' % idpath)
     return entries