|
a/src/mediaserver/cdplugins/uprcl/uprcltags.py |
|
b/src/mediaserver/cdplugins/uprcl/uprcltags.py |
|
... |
|
... |
13 |
#
|
13 |
#
|
14 |
# You should have received a copy of the GNU General Public License
|
14 |
# You should have received a copy of the GNU General Public License
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16 |
|
16 |
|
17 |
import sys
|
17 |
import sys
|
|
|
18 |
import os
|
18 |
import sqlite3
|
19 |
import sqlite3
|
19 |
from timeit import default_timer as timer
|
20 |
from timeit import default_timer as timer
|
20 |
|
21 |
|
21 |
from uprclutils import g_myprefix, audiomtypes, docfolder, uplog, \
|
22 |
from uprclutils import g_myprefix, audiomtypes, docfolder, uplog, \
|
22 |
rcldirentry, rcldoctoentry, cmpentries
|
23 |
rcldirentry, rcldoctoentry, cmpentries
|
|
... |
|
... |
67 |
c.execute('''DROP TABLE albums''')
|
68 |
c.execute('''DROP TABLE albums''')
|
68 |
c.execute('''DROP TABLE tracks''')
|
69 |
c.execute('''DROP TABLE tracks''')
|
69 |
except:
|
70 |
except:
|
70 |
pass
|
71 |
pass
|
71 |
c.execute(
|
72 |
c.execute(
|
72 |
'''CREATE TABLE albums
|
73 |
'''CREATE TABLE albums (album_id INTEGER PRIMARY KEY, artist_id INT,
|
73 |
(album_id INTEGER PRIMARY KEY, albtitle TEXT, albfolder TEXT)''')
|
74 |
albtitle TEXT, albfolder TEXT)''')
|
74 |
|
75 |
|
75 |
tracksstmt = '''CREATE TABLE tracks
|
76 |
tracksstmt = '''CREATE TABLE tracks
|
76 |
(docidx INT, album_id INT, trackno INT, title TEXT'''
|
77 |
(docidx INT, album_id INT, trackno INT, title TEXT'''
|
77 |
|
78 |
|
78 |
for tb in tagtables.itervalues():
|
79 |
for tb in tagtables.itervalues():
|
|
... |
|
... |
127 |
totcnt = 0
|
128 |
totcnt = 0
|
128 |
for docidx in range(len(docs)):
|
129 |
for docidx in range(len(docs)):
|
129 |
doc = docs[docidx]
|
130 |
doc = docs[docidx]
|
130 |
totcnt += 1
|
131 |
totcnt += 1
|
131 |
|
132 |
|
132 |
# No need to include non-audio types in the visible
|
133 |
# No need to include non-audio types in the visible tree.
|
133 |
# tree.
|
134 |
if doc.mtype not in audiomtypes or doc.mtype == 'inode/directory':
|
134 |
# TBD: We'll have to do some processing on image types though
|
|
|
135 |
# (will go before these lines)
|
|
|
136 |
if doc.mtype not in audiomtypes:
|
|
|
137 |
continue
|
135 |
continue
|
138 |
|
136 |
|
|
|
137 |
# Create album record if needed.
|
|
|
138 |
# The albums table is special, can't use auxtableinsert()
|
|
|
139 |
folder = docfolder(doc).decode('utf-8', errors = 'replace')
|
139 |
album = getattr(doc, 'album', None)
|
140 |
album = getattr(doc, 'album', None)
|
140 |
if not album:
|
141 |
if not album:
|
141 |
if doc.mtype != 'inode/directory':
|
|
|
142 |
pass
|
|
|
143 |
#uplog("No album: mtype %s title %s" % (doc.mtype, doc.url))
|
142 |
uplog("No album: mtype %s title %s" % (doc.mtype, doc.url))
|
|
|
143 |
album = os.path.basename(folder)
|
|
|
144 |
if doc.albumartist:
|
|
|
145 |
albartist_id = _auxtableinsert(sqconn, 'artist', doc.albumartist)
|
|
|
146 |
else:
|
|
|
147 |
albartist_id = None
|
|
|
148 |
c.execute('''SELECT album_id,artist_id FROM albums
|
|
|
149 |
WHERE albtitle = ? AND albfolder = ?''', (album, folder))
|
|
|
150 |
r = c.fetchone()
|
|
|
151 |
if r:
|
144 |
album = '[no album]'
|
152 |
album_id = r[0]
|
145 |
continue
|
153 |
albartist_id = r[1]
|
146 |
|
154 |
else:
|
147 |
folder = docfolder(doc).decode('utf-8', errors = 'replace')
|
155 |
c.execute('''INSERT INTO albums(albtitle, albfolder, artist_id)
|
|
|
156 |
VALUES (?,?,?)''', (album, folder, albartist_id))
|
|
|
157 |
album_id = c.lastrowid
|
148 |
|
158 |
|
149 |
# tracknos like n/max are now supposedly processed by rclaudio
|
159 |
# tracknos like n/max are now supposedly processed by rclaudio
|
150 |
# and should not arrive here
|
160 |
# and should not arrive here
|
151 |
try:
|
161 |
try:
|
152 |
l= doc.tracknumber.split('/')
|
162 |
l= doc.tracknumber.split('/')
|
153 |
trackno = int(l[0])
|
163 |
trackno = int(l[0])
|
154 |
except:
|
164 |
except:
|
155 |
trackno = 0
|
165 |
trackno = 0
|
156 |
|
|
|
157 |
# Create album record if needed. There is probably a
|
|
|
158 |
# single-statement syntax for this. The albums table is
|
|
|
159 |
# special, can't use auxtableinsert()
|
|
|
160 |
c.execute('''SELECT album_id FROM albums
|
|
|
161 |
WHERE albtitle = ? AND albfolder = ?''', (album, folder))
|
|
|
162 |
r = c.fetchone()
|
|
|
163 |
if r:
|
|
|
164 |
album_id = r[0]
|
|
|
165 |
else:
|
|
|
166 |
c.execute('''INSERT INTO albums(albtitle, albfolder)
|
|
|
167 |
VALUES (?,?)''', (album, folder))
|
|
|
168 |
album_id = c.lastrowid
|
|
|
169 |
|
166 |
|
170 |
# set base values for column names, values list, placeholders,
|
167 |
# Set base values for column names, values list, placeholders,
|
171 |
# then append data from auxiliary tables array
|
168 |
# then append data from auxiliary tables array
|
172 |
columns = 'docidx,album_id,trackno,title'
|
169 |
columns = 'docidx,album_id,trackno,title'
|
173 |
values = [docidx, album_id, trackno, doc.title]
|
170 |
values = [docidx, album_id, trackno, doc.title]
|
174 |
placehold = '?,?,?,?'
|
171 |
placehold = '?,?,?,?'
|
175 |
for tb,rclfld in tabfields:
|
172 |
for tb,rclfld in tabfields:
|
|
... |
|
... |
179 |
rowid = _auxtableinsert(sqconn, tb, value)
|
176 |
rowid = _auxtableinsert(sqconn, tb, value)
|
180 |
columns += ',' + _clid(tb)
|
177 |
columns += ',' + _clid(tb)
|
181 |
values.append(rowid)
|
178 |
values.append(rowid)
|
182 |
placehold += ',?'
|
179 |
placehold += ',?'
|
183 |
|
180 |
|
|
|
181 |
# Finally create the main record in the tracks table with
|
|
|
182 |
# references to the aux tables
|
184 |
stmt = 'INSERT INTO tracks(' + columns + ') VALUES(' + placehold + ')'
|
183 |
stmt = 'INSERT INTO tracks(' + columns + ') VALUES(' + placehold + ')'
|
185 |
c.execute(stmt, values)
|
184 |
c.execute(stmt, values)
|
186 |
#uplog(doc.title)
|
185 |
#uplog(doc.title)
|
187 |
|
186 |
|
|
|
187 |
if not albartist_id:
|
|
|
188 |
lcols = columns.split(',')
|
|
|
189 |
try:
|
|
|
190 |
i = lcols.index('artist_id')
|
|
|
191 |
artist_id = values[i]
|
|
|
192 |
stmt = 'UPDATE albums SET artist_id = ? WHERE album_id = ?'
|
|
|
193 |
c.execute(stmt, (artist_id, album_id))
|
|
|
194 |
except:
|
|
|
195 |
pass
|
|
|
196 |
|
188 |
sqconn.commit()
|
197 |
sqconn.commit()
|
189 |
uplog("recolltosql: processed %d docs" % totcnt)
|
198 |
uplog("recolltosql: processed %d docs" % totcnt)
|
190 |
|
199 |
|
191 |
|
200 |
|
192 |
# Create our top-level directories, with fixed entries, and stuff from
|
201 |
# Create our top-level directories, with fixed entries, and stuff from
|
|
... |
|
... |
245 |
return [r[0] for r in c.fetchall()]
|
254 |
return [r[0] for r in c.fetchall()]
|
246 |
|
255 |
|
247 |
def _trackentriesforalbum(albid, pid, httphp, pathprefix):
|
256 |
def _trackentriesforalbum(albid, pid, httphp, pathprefix):
|
248 |
stmt = 'SELECT docidx FROM tracks WHERE album_id = ? ORDER BY trackno'
|
257 |
stmt = 'SELECT docidx FROM tracks WHERE album_id = ? ORDER BY trackno'
|
249 |
return _trackentriesforstmt(stmt, (albid,), pid, httphp, pathprefix)
|
258 |
return _trackentriesforstmt(stmt, (albid,), pid, httphp, pathprefix)
|
250 |
|
259 |
|
|
|
260 |
def _direntriesforalbums(pid, where):
|
|
|
261 |
entries = []
|
|
|
262 |
c = sqconn.cursor()
|
|
|
263 |
if not where:
|
|
|
264 |
where = 'WHERE artist.artist_id = albums.artist_id'
|
|
|
265 |
else:
|
|
|
266 |
where += ' AND artist.artist_id = albums.artist_id'
|
|
|
267 |
|
|
|
268 |
stmt = 'SELECT album_id, albtitle, artist.value FROM albums,artist ' + \
|
|
|
269 |
where + ' ORDER BY albtitle'
|
|
|
270 |
uplog('direntriesforalbums: %s' % stmt)
|
|
|
271 |
c.execute(stmt)
|
|
|
272 |
for r in c:
|
|
|
273 |
id = pid + '$' + str(r[0])
|
|
|
274 |
entries.append(rcldirentry(id, pid, r[1], artist=r[2]))
|
|
|
275 |
return entries
|
|
|
276 |
|
251 |
# This is called when an 'albums' element is encountered in the
|
277 |
# This is called when an 'albums' element is encountered in the
|
252 |
# selection path.
|
278 |
# selection path.
|
253 |
def _tagsbrowsealbums(pid, qpath, i, selwhere, values, httphp, pathprefix):
|
279 |
def _tagsbrowsealbums(pid, qpath, i, selwhere, values, httphp, pathprefix):
|
254 |
c = sqconn.cursor()
|
280 |
c = sqconn.cursor()
|
255 |
docidsl = _docidsforsel(selwhere, values)
|
281 |
docidsl = _docidsforsel(selwhere, values)
|
256 |
entries = []
|
282 |
entries = []
|
257 |
if i == len(qpath)-1:
|
283 |
if i == len(qpath)-1:
|
258 |
albidsl = _subtreealbums(docidsl)
|
284 |
albidsl = _subtreealbums(docidsl)
|
259 |
albids = ','.join([str(a) for a in albidsl])
|
285 |
albids = ','.join([str(a) for a in albidsl])
|
260 |
c.execute('SELECT album_id, albtitle FROM albums WHERE album_id in (' +
|
286 |
where = ' WHERE album_id in (' + albids + ') '
|
261 |
albids + ') ORDER BY albtitle')
|
287 |
entries = _direntriesforalbums(pid, where)
|
262 |
for r in c:
|
|
|
263 |
id = pid + '$' + str(r[0])
|
|
|
264 |
entries.append(rcldirentry(id, pid, r[1]))
|
|
|
265 |
elif i == len(qpath)-2:
|
288 |
elif i == len(qpath)-2:
|
266 |
albid = int(qpath[-1])
|
289 |
albid = int(qpath[-1])
|
267 |
docids = ','.join([str(i) for i in docidsl])
|
290 |
docids = ','.join([str(i) for i in docidsl])
|
268 |
stmt = 'SELECT COUNT(docidx) FROM tracks WHERE album_id = ?'
|
291 |
stmt = 'SELECT COUNT(docidx) FROM tracks WHERE album_id = ?'
|
269 |
c.execute(stmt, (albid,))
|
292 |
c.execute(stmt, (albid,))
|
|
... |
|
... |
391 |
# ORDER BY col.value
|
414 |
# ORDER BY col.value
|
392 |
stmt = "SELECT " + selwhat + " FROM tracks, " + col + \
|
415 |
stmt = "SELECT " + selwhat + " FROM tracks, " + col + \
|
393 |
selwhere + \
|
416 |
selwhere + \
|
394 |
" GROUP BY tracks." + _clid(col) + \
|
417 |
" GROUP BY tracks." + _clid(col) + \
|
395 |
" ORDER BY value"
|
418 |
" ORDER BY value"
|
396 |
uplog("tagsbrowse: executing <%s> values %s" % (stmt, values))
|
419 |
uplog("tagsbrowse: executing <%s> values %s" % (stmt,values))
|
397 |
c = sqconn.cursor()
|
420 |
c = sqconn.cursor()
|
398 |
c.execute(stmt, values)
|
421 |
c.execute(stmt, values)
|
399 |
for r in c:
|
422 |
for r in c:
|
400 |
id = pid + '$' + str(r[0])
|
423 |
id = pid + '$' + str(r[0])
|
401 |
entries.append(rcldirentry(id, pid, r[1]))
|
424 |
entries.append(rcldirentry(id, pid, r[1]))
|
|
... |
|
... |
407 |
# albums track list
|
430 |
# albums track list
|
408 |
def _albumsbrowse(pid, qpath, flag, httphp, pathprefix):
|
431 |
def _albumsbrowse(pid, qpath, flag, httphp, pathprefix):
|
409 |
c = sqconn.cursor()
|
432 |
c = sqconn.cursor()
|
410 |
entries = []
|
433 |
entries = []
|
411 |
if len(qpath) == 1:
|
434 |
if len(qpath) == 1:
|
412 |
c.execute('SELECT album_id, albtitle FROM albums ORDER BY albtitle')
|
435 |
entries = _direntriesforalbums(pid, '')
|
413 |
for r in c:
|
|
|
414 |
id = pid + '$*' + str(r[0])
|
|
|
415 |
entries.append(rcldirentry(id, pid, r[1]))
|
|
|
416 |
elif len(qpath) == 2:
|
436 |
elif len(qpath) == 2:
|
417 |
e1 = qpath[1]
|
437 |
e1 = qpath[1]
|
418 |
if not e1.startswith("*"):
|
|
|
419 |
raise Exception("Bad album id in albums tree. Pth: %s" %idpath)
|
|
|
420 |
album_id = int(e1[1:])
|
438 |
album_id = int(e1)
|
421 |
entries = _trackentriesforalbum(album_id, pid, httphp, pathprefix)
|
439 |
entries = _trackentriesforalbum(album_id, pid, httphp, pathprefix)
|
422 |
else:
|
440 |
else:
|
423 |
raise Exception("Bad path in album tree (too deep): <%s>"%idpath)
|
441 |
raise Exception("Bad path in album tree (too deep): <%s>" % qpath)
|
424 |
|
442 |
|
425 |
return entries
|
443 |
return entries
|
426 |
|
444 |
|
427 |
|
445 |
|
428 |
# Top level browse routine. Handle the special cases and call the
|
446 |
# Top level browse routine. Handle the special cases and call the
|