Example #1
0
def browse(a):
    msgproc.log("browse: %s" % a)
    if 'objid' not in a:
        raise Exception("No objid in args")

    objid = a['objid']
    bflg = a['flag'] if 'flag' in a else 'children'

    if not objid.startswith(g_myprefix):
        raise Exception("bad objid <%s>" % objid)

    idpath = objid.replace(g_myprefix, '', 1)
    msgproc.log("browse: idpath: <%s>" % idpath)

    entries = []
    nocache = "0"
    if bflg == 'meta':
        raise Exception("uprcl-app: browse: can't browse meta for now")
    else:
        if not _ready():
            entries = [
                rcldirentry(objid + 'notready', objid, 'Initializing...'),
            ]
            nocache = "1"
        elif not idpath:
            entries = _rootentries()
        else:
            entries = _browsedispatch(objid, bflg, httphp, pathprefix)

    #msgproc.log("%s" % entries)
    encoded = json.dumps(entries)
    return {"entries": encoded, "nocache": nocache}
Example #2
0
 def _tagsbrowseitems(self, pid, qpath, i, selwhere, values):
     stmt = 'SELECT docidx FROM tracks ' + selwhere
     c = self._conn.cursor()
     rows = c.execute(stmt, values)
     docids = [r[0] for r in rows]
     albids = self._subtreealbums(selwhere, values)
     entries = []
     displaytracks = True
     if len(albids) == 1:
         # Only display '>> Complete album' if not all tracks
         # already there. If all tracks are there, we display
         # the album entry (with the same id value: show album)
         albid = albids[0]
         tlist = self._trackentriesforalbum(albid, pid)
         # Replace $items with $albums for the album entry
         id = pid.replace('$items',
                          '$albums') + '$' + str(albid) + '$showca'
         if len(tlist) != len(docids):
             entries.append(rcldirentry(id, pid, '>> Complete Album'))
         else:
             displaytracks = False
             el = self._direntriesforalbums(pid,
                                            "WHERE album_id = %s" % albid)
             el[0]['id'] = id
             entries.append(el[0])
     if displaytracks:
         rcldocs = uprclinit.g_trees['folders'].rcldocs()
         entries += [
             rcldoctoentry(pid + '$i' + str(docid), pid, self._httphp,
                           self._pprefix, rcldocs[docid])
             for docid in docids
         ]
     return sorted(entries, key=cmpentries)
Example #3
0
    def _direntriesforalbums(self, pid, where, path=''):
        uplog("_direntriesforalbums. where: %s" % where)
        c = self._conn.cursor()
        args = (path + '%', ) if path else ()
        if path:
            if not where:
                where = '''WHERE albfolder LIKE ?'''
            else:
                where += ''' AND albfolder LIKE ?'''
            substmt = '''SELECT DISTINCT albalb FROM ALBUMS %s''' % where
            where = '''WHERE album_id IN (%s)''' % substmt
        else:
            if not where:
                where = '''WHERE albtdisc IS NULL'''
            else:
                where += ''' AND albtdisc IS NULL'''

        stmt = '''SELECT album_id, albtitle, albarturi, albdate, artist.value
        FROM albums LEFT JOIN artist ON artist.artist_id = albums.artist_id
        %s ORDER BY albtitle''' % where

        uplog('direntriesforalbums: %s' % stmt)
        c.execute(stmt, args)
        entries = []
        for r in c:
            id = pid + '$' + str(r[0])
            entries.append(
                rcldirentry(id,
                            pid,
                            r[1],
                            arturi=r[2],
                            date=r[3],
                            artist=r[4],
                            upnpclass='object.container.album.musicAlbum'))
        return entries
Example #4
0
 def rootentries(self, pid, path=''):
     uplog("rootentries: pid %s path %s" % (pid, path))
     entries = []
     nalbs = self._albcntforfolder(path)
     entries.append(rcldirentry(pid + 'albums', pid, nalbs + ' albums'))
     if path:
         where = ' WHERE tracks.path LIKE ? '
         args = (path + '%', )
     else:
         where = ' '
         args = ()
     c = self._conn.cursor()
     stmt = "SELECT COUNT(*) from tracks"
     c.execute(stmt + where, args)
     nitems = str(c.fetchone()[0])
     entries.append(rcldirentry(pid + 'items', pid, nitems + ' items'))
     subqs = self._subtreetags(where, args)
     for tt in subqs:
         entries.append(
             rcldirentry(pid + '=' + tt, pid, g_tagdisplaytag[tt]))
     return entries
Example #5
0
    def browse(self, pid, flag):
        idx = self._objidtoidx(pid)

        folders = uprclinit.g_trees['folders']
        rcldocs = folders.rcldocs()
        entries = []
        if idx == 0:
            # Browsing root
            for i in range(len(self.utidx))[1:]:
                doc = rcldocs[self.utidx[i]]
                id = self._idprefix + '$p' + str(i)
                title = doc.title if doc.title else doc.filename
                e = rcldirentry(id,
                                pid,
                                title,
                                upnpclass='object.container.playlistContainer')
                if e:
                    entries.append(e)

        else:
            pldoc = rcldocs[self.utidx[idx]]
            plpath = uprclutils.docpath(pldoc)
            #uplog("playlists: plpath %s" % plpath)
            try:
                m3u = uprclutils.M3u(plpath)
            except Exception as ex:
                uplog("M3u open failed: %s %s" % (plpath, ex))
                return entries
            cnt = 1
            for url in m3u:
                doc = recoll.Doc()
                if m3u.urlRE.match(url):
                    # Actual URL (usually http). Create bogus doc
                    doc.setbinurl(bytearray(url))
                    elt = os.path.split(url)[1]
                    doc.title = elt.decode('utf-8', errors='ignore')
                    doc.mtype = "audio/mpeg"
                else:
                    doc.setbinurl(bytearray(b'file://' + url))
                    fathidx, docidx = folders._stat(doc)
                    if docidx < 0:
                        uplog("playlists: can't stat %s" % doc.getbinurl())
                        continue
                    doc = rcldocs[docidx]

                id = pid + '$e' + str(len(entries))
                e = rcldoctoentry(id, pid, self._httphp, self._pprefix, doc)
                if e:
                    entries.append(e)

        return sorted(entries, key=cmpentries)
Example #6
0
def browse(pid, flag, httphp, pathprefix):

    diridx = _objidtodiridx(pid)

    # If there is only one entry in root, skip it. This means that 0
    # and 1 point to the same dir, but this does not seem to be an
    # issue
    if diridx == 0 and len(dirvec[0]) == 2:
        diridx = 1

    entries = []

    # The basename call is just for diridx==0 (topdirs). Remove it if
    # this proves a performance issue
    for nm, ids in _dirvec[diridx].iteritems():
        if nm == "..":
            continue
        thisdiridx = ids[0]
        thisdocidx = ids[1]
        if thisdocidx >= 0:
            doc = g_alldocs[thisdocidx]
        else:
            uplog("No doc for %s" % pid)
            doc = None

        if thisdiridx >= 0:
            # Skip empty directories
            if len(dirvec[thisdiridx]) == 1:
                continue
            id = _foldersIdPfx + '$' + 'd' + str(thisdiridx)
            if doc and doc.albumarturi:
                arturi = doc.albumarturi
            else:
                arturi = _arturifordir(thisdiridx)
            entries.append(
                rcldirentry(id, pid, os.path.basename(nm), arturi=arturi))
        else:
            # Not a directory. docidx had better been set
            if thisdocidx == -1:
                uplog("folders:docidx -1 for non-dir entry %s" % nm)
                continue
            doc = g_alldocs[thisdocidx]
            id = _foldersIdPfx + '$i' + str(thisdocidx)
            e = rcldoctoentry(id, pid, httphp, pathprefix, doc)
            if e:
                entries.append(e)

    return sorted(entries, cmp=cmpentries)
Example #7
0
    def _tagsbrowsealbums(self, pid, qpath, i, selwhere, values):
        uplog("_tagsbrowsealbums: pid %s qpath %s i %s selwhere %s values %s" %
              (pid, qpath, i, selwhere, values))
        c = self._conn.cursor()
        entries = []
        if i == len(qpath) - 1:
            # List of albums to which belong any track from selection
            albidsl = self._subtreealbums(selwhere, values)
            albids = ','.join([str(a) for a in albidsl])
            where = ' WHERE album_id in (' + albids + ') '
            entries = self._direntriesforalbums(pid, where)
        elif i == len(qpath) - 2:
            # Album track list. Maybe a merged album->multiple phys albids
            albid = int(qpath[-1])
            rawalbids = self._albids2rawalbids((albid, ))
            uplog("_tagsbrowsealbums: albid %s rawalbids %s" %
                  (albid, rawalbids))
            stmt = '''SELECT COUNT(docidx) FROM tracks
                WHERE album_id IN (%s)''' % ','.join('?' * len(rawalbids))
            c.execute(stmt, rawalbids)
            r = c.fetchone()
            ntracks = int(r[0])
            docidsl = self._docidsforsel(selwhere, values)
            stmt = '''SELECT docidx FROM tracks 
                WHERE album_id IN (%s) AND docidx IN (%s)''' % \
            (','.join('?'*len(rawalbids)), ','.join('?'*len(docidsl)))
            entries = self._trackentriesforstmt(stmt, rawalbids + docidsl, pid)
            if ntracks != len(entries):
                id = pid + '$' + 'showca'
                entries = [rcldirentry(id, pid, '>> Complete Album')] + entries
        elif i == len(qpath) - 3:
            # 'Complete album' entry
            # 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 = self._trackentriesforalbum(albid, pid)

        return entries
Example #8
0
def search(a):
    msgproc.log("search: [%s]" % a)
    objid = a['objid']
    if re.match('0\$uprcl\$', objid) is None:
        raise Exception("bad objid [%s]" % objid)

    upnps = a['origsearch']
    nocache = "0"

    if not _ready():
        entries = [
            rcldirentry(objid + 'notready', objid, 'Initializing...'),
        ]
        nocache = "1"
    else:
        entries = uprclsearch.search(rclconfdir, objid, upnps, g_myprefix,
                                     httphp, pathprefix)

    encoded = json.dumps(entries)
    return {"entries": encoded, "nocache": nocache}
Example #9
0
    def browse(self, pid, flag):
        
        diridx,pthremain = self._objidtodiridx(pid)

        # If pthremain is set, this is pointing to 'Tag View'. Pass
        # the request along to the tags browser.
        if pthremain:
            if not pthremain.find('$tagview.0') == 0:
                raise Exception("uprclfolders: pid [%s]. bad pthremain"%pid)
            return uprclinit.g_trees['tags'].browseFolder(pid, flag, pthremain,
                                                          self.dirpath(pid))
        
        # If there is only one entry in root, skip it. This means that 0
        # and 1 point to the same dir, but this does not seem to be an
        # issue
        if diridx == 0 and len(self._dirvec[0]) == 2:
            diridx = 1
        
        #uplog("Folders browse: diridx %d content: [%s]" %
        #    (diridx,self._dirvec[diridx]))

        entries = []
        # The basename call is just for diridx==0 (topdirs). Remove it if
        # this proves a performance issue
        for nm,ids in self._dirvec[diridx].items():
            if nm == ".." or nm == ".":
                continue
            thisdiridx = ids[0]
            thisdocidx = ids[1]
            if thisdocidx >= 0:
                doc = self._rcldocs[thisdocidx]
            else:
                # uplog("No doc for %s" % pid)
                doc = None
            
            if thisdiridx >= 0:
                # Skip empty directories
                if len(self._dirvec[thisdiridx]) == 1:
                    continue
                id = self._idprefix + '$d' + str(thisdiridx)
                if doc and doc.albumarturi:
                    arturi = doc.albumarturi
                else:
                    arturi = self._arturifordir(thisdiridx)
                entries.append(rcldirentry(id, pid, os.path.basename(nm),
                                           arturi=arturi))
            else:
                # Not a directory. docidx had better been set
                if thisdocidx == -1:
                    uplog("folders:docidx -1 for non-dir entry %s"%nm)
                    continue
                doc = self._rcldocs[thisdocidx]
                id = self._idprefix + '$i' + str(thisdocidx)
                e = rcldoctoentry(id, pid, self._httphp, self._pprefix, doc)
                if e:
                    entries.append(e)

        entries.sort(key=cmpentries)

        # Add "Browse subtree by tags" entry
        if pid != self._idprefix and self._enabletags:
            id = pid + '$tagview.0'
            entries.insert(0, rcldirentry(id, pid, ">> Tag View"))
        return entries
Example #10
0
 def rootentries(self, pid):
     return [rcldirentry(pid + 'folders', pid, '[folders]'),]
Example #11
0
 def rootentries(self, pid):
     return [
         rcldirentry(pid + 'playlists', pid,
                     str(len(self.utidx) - 1) + ' playlists'),
     ]
Example #12
0
    def _tagsbrowse(self, pid, qpath, flag, path=''):
        uplog("tagsbrowse. pid %s qpath %s" % (pid, qpath))

        # Walk the qpath, which was generated from the objid and
        # defines what tracks are selected and what we want to
        # display. E.g =Artist$21$=Date would display all distinct
        # dates for tracks by Artist #21. =Artist$21$=Date$48 the data
        # for date 48 (the numbers are indexes into the aux tables)
        qlen = len(qpath)
        selwhat = ''
        if path:
            selwhere = ' WHERE tracks.path LIKE ? '
            values = [
                path + '%',
            ]
        else:
            selwhere = ''
            values = []
        i = 0
        while i < qlen:
            elt = qpath[i]

            # 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 self._tagsbrowsealbums(pid, qpath, i, selwhere, values)
            elif elt == 'items':
                return self._tagsbrowseitems(pid, qpath, i, selwhere, values)

            # '=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 = g_tagtotable[elt[1:]]

            selwhere = selwhere + ' AND ' if selwhere else ' WHERE '
            if i == qlen - 1:
                # We can only get here if the qpath ends with '=colname'
                # (otherwise the else branch below fetches the 2 last
                # elements and breaks the loop). We want to fetch all
                # unique values for the column inside the current selection.

                # e.g. artist.artist_id, artist.value
                selwhat = '%s.%s, %s.value' % (col, _clid(col), col)
                # e.g. tracks.artist_id = artist.artist_id
                selwhere += 'tracks.%s = %s.%s' % (_clid(col), col, _clid(col))
            else:
                # Look at the value specified for the =xx column. The
                # selwhat value is only used as a flag
                selwhat = 'tracks.docidx'
                selwhere += 'tracks.%s =  ?' % _clid(col)
                i += 1
                values.append(int(qpath[i]))
            i += 1

        entries = []
        if selwhat == 'tracks.docidx':
            # We are displaying content for a given value of a given tag
            docids = self._docidsforsel(selwhere, values)
            albids = self._subtreealbums(selwhere, values)
            subqs = self._subtreetags(selwhere, values)
            displaytracks = True
            if len(albids) > 1:
                id = pid + '$albums'
                label = '%d albums'
                entries.append(rcldirentry(id, pid, label % len(albids)))
            elif len(albids) == 1 and not subqs:
                # Only display '>> Complete album' if not all tracks
                # already there. If all tracks are there, we display
                # the album entry (with the same id value: show album)
                albid = albids[0]
                tlist = self._trackentriesforalbum(albid, pid)
                id = pid + '$albums$' + str(albid) + '$showca'
                if len(tlist) != len(docids):
                    entries.append(rcldirentry(id, pid, '>> Complete Album'))
                else:
                    displaytracks = False
                    el = self._direntriesforalbums(
                        pid, "WHERE album_id = %s" % albid)
                    el[0]['id'] = id
                    entries.append(el[0])

            if subqs:
                id = pid + '$items'
                label = '%d items'
                entries.append(rcldirentry(id, pid, label % len(docids)))
                for tt in subqs:
                    id = pid + '$=' + tt
                    entries.append(rcldirentry(id, pid, g_tagdisplaytag[tt]))
            elif displaytracks:
                rcldocs = uprclinit.g_trees['folders'].rcldocs()
                for docidx in docids:
                    id = pid + '$*i' + str(docidx)
                    entries.append(
                        rcldoctoentry(id, pid, self._httphp, self._pprefix,
                                      rcldocs[docidx]))
                    entries = sorted(entries, key=cmpentries)
        else:
            # SELECT col.col_id, col.value FROM tracks, col
            # WHERE tracks.col_id = col.col_id
            # GROUP BY tracks.col_id
            # ORDER BY col.value
            stmt = "SELECT " + selwhat + " FROM tracks, " + col + \
                   selwhere + \
                   " GROUP BY tracks." + _clid(col) + \
                   " ORDER BY value"
            uplog("tagsbrowse: executing <%s> values %s" % (stmt, values))
            c = self._conn.cursor()
            c.execute(stmt, values)
            for r in c:
                id = pid + '$' + str(r[0])
                entries.append(rcldirentry(id, pid, r[1]))
        return entries
Example #13
0
 def rootentries(self, pid):
     return [
         rcldirentry(pid + 'untagged', pid, '[untagged]'),
     ]