00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 import os, sys
00026 import time
00027 try:
00028 from pysqlite2 import dbapi2 as sqlite3
00029 except ImportError:
00030 import sqlite3
00031
00032 import Queue, thread
00033 from threading import Thread
00034
00035
00036 from modules import functions
00037 from modules.clGstreamer010 import Track
00038 from modules.errors import DatabaseQueryException
00039
00040 ConnectCmd = "connect"
00041 SqlCmd = "SQL"
00042 StopCmd = "stop"
00043
00044 class Query:
00045 def __init__(self, cmd=None, params=[]):
00046 if cmd is None: cmd = SqlCmd
00047 self.cmd = cmd
00048 self.params = params
00049
00050 _threadex_settings = thread.allocate_lock()
00051 qthreads_settings = 0
00052 sqlqueue_settings = Queue.Queue()
00053 class SettingsThread(Thread):
00054 def __init__(self, path, nr):
00055 Thread.__init__(self)
00056 self.path = path
00057 self.nr = nr
00058 def run(self):
00059 global qthreads_settings
00060 con = sqlite3.connect(self.path)
00061 cur = con.cursor()
00062 while True:
00063 s = sqlqueue_settings.get()
00064 if "print-queries" in sys.argv:
00065 print "Conn %d -> %s -> %s" % (self.nr, s.cmd, s.params)
00066 if s.cmd == SqlCmd:
00067 commitneeded = False
00068 res = []
00069
00070 for sql in s.params:
00071 error = False
00072 inst = None
00073 try:
00074 if type(sql) == type(()):
00075 cur.execute(sql[0],sql[1])
00076 else:
00077 cur.execute(sql)
00078 except Exception, inst:
00079 error = True
00080 if not sql.upper().startswith("SELECT"):
00081 commitneeded = True
00082 if not error:
00083 try:
00084 for row in cur.fetchall(): res.append(row)
00085 except Exception, inst:
00086 error = True
00087 if not error:
00088 try:
00089 if commitneeded: con.commit()
00090 except Exception, inst:
00091 error = True
00092 if not error:
00093 s.resultqueue.put(res)
00094 else:
00095 error = DatabaseQueryException()
00096 error.inst = inst
00097 s.resultqueue.put(error)
00098 else:
00099 _threadex_settings.acquire()
00100 qthreads_settings -= 1
00101 _threadex_settings.release()
00102
00103 sqlqueue_settings.put(s)
00104 s.resultqueue.put(None)
00105 break
00106
00107 _threadex_db = thread.allocate_lock()
00108 qthreads_db = 0
00109 sqlqueue_db = Queue.Queue()
00110 class DBThread(Thread):
00111 def __init__(self, path, nr):
00112 Thread.__init__(self)
00113 self.path = path
00114 self.nr = nr
00115 def run(self):
00116 global qthreads_db
00117 con = sqlite3.connect(self.path)
00118 cur = con.cursor()
00119 while True:
00120 s = sqlqueue_db.get()
00121 if "print-queries" in sys.argv:
00122 print "Conn %d -> %s -> %s" % (self.nr, s.cmd, s.params)
00123 if s.cmd == SqlCmd:
00124 commitneeded = False
00125 res = []
00126
00127 for sql in s.params:
00128 cur.execute(sql)
00129 if not sql.upper().startswith("SELECT"):
00130 commitneeded = True
00131 for row in cur.fetchall(): res.append(row)
00132 if commitneeded: con.commit()
00133 s.resultqueue.put(res)
00134 else:
00135 _threadex_db.acquire()
00136 qthreads_db -= 1
00137 _threadex_db.release()
00138
00139 sqlqueue_db.put(s)
00140 s.resultqueue.put(None)
00141 break
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 class DB_Settings():
00153
00154
00155
00156 def __init__(self, pyjama):
00157
00158 self.pyjama = pyjama
00159
00160 self.db = os.path.join(functions.preparedirs(), "settings.db")
00161
00162 self.connection = None
00163
00164 self.query_counter = 0
00165
00166 if not os.path.exists(self.db):
00167 self.open()
00168 self.create_database()
00169 else:
00170 self.open()
00171
00172
00173
00174
00175
00176
00177
00178 def set_value(self, section, option, value, table="settings"):
00179 option = str(option).replace("'", "''")
00180
00181 sql = "SELECT COUNT(*) FROM '%s' WHERE section='%s' and option='%s'" % (table, section, option)
00182 ret = self.query(sql)
00183
00184 if ret[0][0] == 0:
00185 sql = "INSERT INTO '%s' (section, option, value) values('%s', '%s', '%s')"% (table, section, option, value)
00186 else:
00187 sql = "UPDATE '%s' SET value='%s' WHERE section='%s' and option='%s'"% (table, value, section, option)
00188
00189 ret = self.query(sql)
00190
00191 return ret
00192
00193 def increase_value(self, section, option, table="settings"):
00194 option = str(option).replace("'", "''")
00195 sql = "SELECT value FROM %s WHERE section='%s' and option='%s'" % (table, section, option)
00196 ret = self.query(sql)
00197
00198 if ret == []:
00199 sql = "INSERT INTO %s (section, option, value) values('%s', '%s', '1')" % (table, section, option)
00200 else:
00201 sql = "UPDATE %s SET value=value+1 WHERE section='%s' and option='%s'" % (table, section, option)
00202
00203 ret = self.query(sql)
00204
00205 return ret
00206
00207
00208
00209
00210
00211
00212
00213 def get_value(self, section, option, default=None, table="settings"):
00214 option = str(option).replace("'", "''")
00215
00216 sql = "SELECT value FROM %s WHERE section='%s' and option='%s'" % (table, section, option)
00217 ret = self.query(sql)
00218
00219 if ret == [] or ret == -1:
00220 return default
00221 else:
00222 if len(ret[0]) == 1:
00223 return ret[0][0]
00224 else:
00225 return ret[0]
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 def create_table(self, table_name):
00239 sql = "select count(name) from sqlite_master where name = '%s'" % table_name
00240 ret = self.query(sql)
00241
00242 if ret[0][0] == 0:
00243 sql = """
00244 CREATE TABLE %s (
00245 uid INTEGER PRIMARY KEY,
00246 section STRING,
00247 option STRING,
00248 value string
00249 )
00250 """ % table_name
00251 ret = self.query(sql)
00252 return "created"
00253 else:
00254 return "existant"
00255
00256
00257
00258 def create_database(self):
00259 print("Creating settings database 'settings.db'")
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 sql = """
00272 CREATE TABLE settings (
00273 uid INTEGER PRIMARY KEY,
00274 section STRING,
00275 option STRING,
00276 value string
00277 )
00278 """
00279 ret = self.query(sql)
00280
00281
00282
00283 def open(self):
00284 global qthreads_settings
00285 _threadex_settings.acquire()
00286 qthreads_settings += 1
00287 _threadex_settings.release()
00288 wrap = SettingsThread(self.db, qthreads_settings)
00289 wrap.start()
00290
00291 def quit(self):
00292 s = Query(StopCmd)
00293 s.resultqueue = Queue.Queue()
00294 sqlqueue_settings.put(s)
00295
00296 while qthreads_settings > 0: time.sleep(0.1)
00297
00298
00299
00300
00301
00302 def close(self):
00303 self.connection.close()
00304
00305
00306
00307
00308 def query(self, query):
00309 s = Query(None, [query])
00310 s.resultqueue = Queue.Queue()
00311 sqlqueue_settings.put(s)
00312 self.query_counter += 1
00313 ret = s.resultqueue.get()
00314
00315 if isinstance(ret, DatabaseQueryException):
00316 desc = "There was an error while querying the settings database:\n"
00317 desc += str(ret.inst)
00318 self.pyjama.Events.raise_event("error", None, desc)
00319 return -1
00320 else:
00321 return ret
00322
00323 try:
00324 cur = self.connection.cursor()
00325 cur.execute(query)
00326 rows = cur.fetchall()
00327 return rows
00328 except Exception, inst:
00329 desc = "There was an error while querying the settings database"
00330 self.pyjama.Events.raise_event("error", inst, desc)
00331 return -1
00332
00333
00334
00335
00336
00337
00338
00339 class DB():
00340
00341
00342
00343 def __init__(self, par):
00344
00345 self.parent = par
00346
00347 self.home=functions.preparedirs()
00348
00349 self.db = os.path.join(self.home, "pyjama.db")
00350
00351 self.tracks, self.albums, self.artists = 0, 0, 0
00352 self.query_counter = 0
00353
00354
00355 self.results = {}
00356
00357
00358 self.queue = []
00359
00360
00361 self.connection = None
00362
00363 self.open()
00364
00365 self.database_ok = True
00366 if not os.path.exists(os.path.join(functions.preparedirs(),"pyjama.db")):
00367 self.database_ok = False
00368 else:
00369 sql = "select count(name) from sqlite_master where name = 'albums' or name = 'artists' or name = 'tracks'"
00370 try:
00371 tablecount = self.__query(sql)
00372 if tablecount[0][0] < 3:
00373 print("Some tables in the database seems to be missing")
00374 print ("Marking the database as corrupt")
00375 self.database_ok = False
00376 except Exception:
00377 self.database_ok = False
00378
00379 if self.database_ok:
00380 try:
00381
00382 self.tracks = self.__query("SELECT COUNT (*) FROM tracks WHERE 1")[0][0]
00383
00384 self.albums = self.__query("SELECT COUNT (*) FROM albums WHERE 1")[0][0]
00385
00386 self.artists = self.__query("SELECT COUNT (*) FROM artists WHERE 1")[0][0]
00387 except TypeError, inst:
00388 self.database_ok = False
00389 desc = "\n\n+-------------------------------------------------------+\n"
00390 desc += "| A neccessary table wasn't found. |\n"
00391 desc += "| Pyjama will now download and convert the needed files |\n"
00392 desc += "| If any problems occur, run 'pyjama -u' |\n"
00393 desc += "+-------------------------------------------------------+"
00394
00395 print desc
00396
00397
00398 if self.tracks < 135000 or self.albums < 19000 or self.artists < 10000:
00399 print ("There seem to be a lot of entries missing in the database")
00400 print ("Marking the database as corrupt")
00401 self.database_ok = False
00402
00403
00404
00405
00406
00407
00408
00409
00410 def open(self):
00411 global qthreads_db
00412 _threadex_db.acquire()
00413 qthreads_db += 1
00414 _threadex_db.release()
00415 wrap = DBThread(self.db, qthreads_db)
00416 wrap.start()
00417
00418
00419
00420
00421 def close(self):
00422 self.connection.close()
00423
00424 def quit(self):
00425 s = Query(StopCmd)
00426 s.resultqueue = Queue.Queue()
00427 sqlqueue_db.put(s)
00428
00429 while qthreads_db > 0: time.sleep(0.1)
00430
00431
00432
00433
00434
00435 def query(self, query):
00436 if not self.parent.window.check_alldone():
00437 self.parent.Events.raise_event("error", None, "You are not allowed to query the database before the main-module was loaded succesfully. If you are writing a plugin, please connect to the 'alldone' event.")
00438 return -2
00439
00440 s = Query(None, [query])
00441 s.resultqueue = Queue.Queue()
00442 sqlqueue_db.put(s)
00443 self.query_counter += 1
00444 return s.resultqueue.get()
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 def __query(self, query):
00464 s = Query(None, [query])
00465 s.resultqueue = Queue.Queue()
00466 sqlqueue_db.put(s)
00467 self.query_counter += 1
00468 return s.resultqueue.get()
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 def artistinfos(self, id, thread_id = 0):
00525 sql = """
00526 SELECT
00527 artists.name, artists.country, artists.image, artists.url, artists.id, albums.name, albums.id, artists.albumcount
00528 FROM
00529 artists, albums
00530 WHERE
00531 artists.id=%s and albums.artist_id=artists.id
00532 """ % str(id)
00533 ret = self.query(sql)
00534 counter = 0
00535 artist = {}
00536 for info in ret:
00537 artist[counter] = {}
00538 artist[counter]['artist_name'] = info[0]
00539 artist[counter]['artist_country'] = info[1]
00540 artist[counter]['artist_image'] = info[2]
00541 artist[counter]['artist_url'] = info[3]
00542 artist[counter]['artist_id'] = info[4]
00543 artist[counter]['album_name'] = info[5]
00544 artist[counter]['album_id'] = info[6]
00545 artist[counter]['artist_albumcount'] = info[7]
00546 counter += 1
00547 self.results[thread_id]=artist
00548 return artist
00549
00550 def multiple_albuminfos(self, ids):
00551 album_string = "("
00552 for album in ids:
00553 album_string += " albums.id=%s or" % album
00554 album_string = album_string[:-3] + ") and albums.artist_id=artists.id"
00555
00556 sql = """
00557 SELECT
00558 albums.id, albums.name, artists.id, artists.name
00559 FROM
00560 albums, artists
00561 WHERE
00562 %s
00563 """ % album_string
00564
00565 ret = self.query(sql)
00566 return ret
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 def get_multiple_trackinfos(self, tracks):
00610 track_string = "("
00611 for track in tracks:
00612 track_string += " tracks.id=%s or" % track
00613 track_string = track_string[:-3] + ") and tracks.artist_id=artists.id and albums.id=tracks.album_id"
00614 sql = """
00615 SELECT
00616 tracks.name, tracks.duration, tracks.numalbum, tracks.license, tracks.album_id, tracks.artist_id, artists.name, albums.name, tracks.uid, tracks.id3genre, tracks.id
00617 FROM
00618 tracks, artists, albums
00619 WHERE
00620 %s
00621 """ % track_string
00622
00623 ret = self.query(sql)
00624
00625 tracks=[]
00626 for track in ret:
00627 tr = Track()
00628 tr.name = track[0]
00629 tr.duration = track[1]
00630 tr.numalbum = track[2]
00631 tr.license = track[3]
00632 tr.album_id = track[4]
00633 tr.artist_id = track[5]
00634 tr.artist_name = track[6]
00635 tr.album_name = track[7]
00636 tr.uid = track[8]
00637 tr.id3genre = track[9]
00638 tr.id = track[10]
00639 tr.stream = "http://api.jamendo.com/get2/stream/track/redirect/?id=%i&streamencoding=%s" % (track[10], self.parent.settings.get_value("JAMENDO", "format_stream", "mp31"))
00640 tracks.append(tr)
00641 return tracks
00642
00643
00644
00645
00646
00647 def get_trackinfos2(self, trackid):
00648 sql = """
00649 SELECT
00650 tracks.name, tracks.duration, tracks.numalbum, tracks.license, tracks.album_id, tracks.artist_id, artists.name, albums.name, tracks.uid, tracks.id3genre, tracks.id
00651 FROM
00652 tracks, albums, artists
00653 WHERE
00654 tracks.id=%s and albums.id=tracks.album_id and artists.id=tracks.artist_id
00655 """ % str(trackid)
00656 ret = self.query(sql)
00657 if ret == []:
00658 return []
00659 ret = ret[0]
00660 tr = Track()
00661 tr.name = ret[0]
00662 tr.duration = ret[1]
00663 tr.numalbum = ret[2]
00664 tr.license = ret[3]
00665 tr.album_id = ret[4]
00666 tr.artist_id = ret[5]
00667 tr.artist_name = ret[6]
00668 tr.album_name = ret[7]
00669 tr.uid = ret[8]
00670 tr.id3genre = ret[9]
00671 tr.id = ret[10]
00672 tr.stream = "http://api.jamendo.com/get2/stream/track/redirect/?id=%i&streamencoding=%s" % (ret[10], self.parent.settings.get_value("JAMENDO", "format_stream", "mp31"))
00673
00674 return tr
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 def artisttracks(self, id):
00685 sql = """
00686 SELECT
00687 tracks.name, tracks.duration, tracks.numalbum, tracks.license, tracks.album_id, tracks.artist_id, artists.name, albums.name, tracks.uid, tracks.id3genre, tracks.id
00688 FROM
00689 tracks, albums, artists
00690 WHERE
00691 tracks.album_id=albums.id and tracks.artist_id=%s and albums.artist_id=%s and artists.id=tracks.artist_id
00692 """ % (str(id), str(id))
00693 ret = self.query(sql)
00694 tracks=[]
00695 for track in ret:
00696 tr = Track()
00697 tr.name = track[0]
00698 tr.duration = track[1]
00699 tr.numalbum = track[2]
00700 tr.license = track[3]
00701 tr.album_id = track[4]
00702 tr.artist_id = track[5]
00703 tr.artist_name = track[6]
00704 tr.album_name = track[7]
00705 tr.uid = track[8]
00706 tr.id3genre = track[9]
00707 tr.id = track[10]
00708 tr.stream = "http://api.jamendo.com/get2/stream/track/redirect/?id=%i&streamencoding=%s" % (track[10], self.parent.settings.get_value("JAMENDO", "format_stream", "mp31"))
00709 tracks.append(tr)
00710 return tracks
00711
00712
00713
00714
00715
00716 def albumtracks(self, id):
00717 sql = """
00718 SELECT
00719 tracks.name, tracks.duration, tracks.numalbum, tracks.license, tracks.album_id, tracks.artist_id, artists.name, albums.name, tracks.uid, tracks.id3genre, tracks.id
00720 FROM
00721 tracks, albums, artists
00722 WHERE
00723 tracks.album_id=%s and albums.id=%s and artists.id=albums.artist_id
00724 """ % (str(id), str(id))
00725 ret = self.query(sql)
00726 tracks=[]
00727 for track in ret:
00728 tr = Track()
00729 tr.name = track[0]
00730 tr.duration = track[1]
00731 tr.numalbum = track[2]
00732 tr.license = track[3]
00733 tr.album_id = track[4]
00734 tr.artist_id = track[5]
00735 tr.artist_name = track[6]
00736 tr.album_name = track[7]
00737 tr.uid = track[8]
00738 tr.id3genre = track[9]
00739 tr.id = track[10]
00740 tr.stream = "http://api.jamendo.com/get2/stream/track/redirect/?id=%i&streamencoding=%s" % (track[10], self.parent.settings.get_value("JAMENDO", "format_stream", "mp31"))
00741 tracks.append(tr)
00742 return tracks
00743
00744
00745
00746
00747
00748 def Search_tag(self, string):
00749
00750 sql = """
00751 SELECT
00752 albums.name, albums.id, artists.name, artists.id
00753 FROM
00754 albums, artists, tags
00755 WHERE
00756 tags.idstr='""" + string + """' and albums.id=tags.album_id LIMIT """ + str(self.parent.settings.get_value("PERFORMANCE", "db_search_limit"))
00757 ret = self.query(sql)
00758 tags = {}
00759 counter = 0
00760 for tag in ret:
00761 tags[counter] = {}
00762 tags[counter]['album_name'] = tag[0]
00763 tags[counter]['album_id'] = tag[1]
00764 tags[counter]['artist_name'] = tag[2]
00765 tags[counter]['artist_id'] = tag[3]
00766 counter += 1
00767 print tags
00768 return tags
00769
00770
00771
00772
00773
00774
00775 def search_track(self, string):
00776
00777 sql = """
00778 SELECT
00779 tracks.name, tracks.duration, tracks.numalbum, tracks.id, tracks.license, tracks.id3genre, albums.id, albums.name, artists.id, artists.name, tracks.uid
00780 FROM
00781 tracks, albums, artists
00782 WHERE
00783 tracks.name LIKE '%""" + string + """%' and tracks.album_id=albums.id and albums.artist_id=artists.id LIMIT """ + str(self.parent.settings.get_value("PERFORMANCE", "db_search_limit"))
00784 ret = self.query(sql)
00785 tracks=[]
00786 for track in ret:
00787 tr = Track()
00788 tr.name = track[0]
00789 tr.duration = track[1]
00790 tr.numalbum = track[2]
00791 tr.id = track[3]
00792 tr.license = track[4]
00793 tr.id3genre = track[5]
00794 tr.album_id = track[6]
00795 tr.album_name = track[7]
00796 tr.artist_id = track[8]
00797 tr.artist_name = track[9]
00798 tr.uid = track[10]
00799 tr.stream = "http://api.jamendo.com/get2/stream/track/redirect/?id=%i&streamencoding=%s" % (track[3], self.parent.settings.get_value("JAMENDO", "format_stream", "mp31"))
00800 tracks.append(tr)
00801 return tracks
00802
00803
00804
00805
00806
00807 def search_artist(self, string):
00808 sql = """
00809 SELECT
00810 artists.name, artists.id
00811 FROM
00812 artists
00813 WHERE
00814 artists.name LIKE '%""" + string + """%' LIMIT """ + str(self.parent.settings.get_value("PERFORMANCE", "db_search_limit"))
00815 ret = self.query(sql)
00816 artists = {}
00817 counter = 0
00818 for artist in ret:
00819 artists[counter] = {}
00820 artists[counter]['artist_name'] = artist[0]
00821 artists[counter]['artist_id'] = artist[1]
00822
00823
00824 counter += 1
00825 return artists
00826
00827
00828
00829
00830
00831 def search_album(self, string):
00832
00833 sql = """
00834 SELECT
00835 albums.name, albums.id, artists.name, artists.id
00836 FROM
00837 albums, artists
00838 WHERE
00839 albums.name LIKE '%""" + string + """%' and albums.artist_id=artists.id LIMIT """ + str(self.parent.settings.get_value("PERFORMANCE", "db_search_limit"))
00840 ret = self.query(sql)
00841 albums = {}
00842 counter = 0
00843 for album in ret:
00844 albums[counter] = {}
00845 albums[counter]['album_name'] = album[0]
00846 albums[counter]['album_id'] = album[1]
00847 albums[counter]['artist_name'] = album[2]
00848 albums[counter]['artist_id'] = album[3]
00849 counter += 1
00850 return albums
00851
00852
00853
00854
00855
00856 def gettags(self, id):
00857
00858 sql = """
00859 SELECT
00860 tags
00861 FROM
00862 albums
00863 WHERE
00864 id=%s
00865 """ % str(id)
00866 ret = self.query(sql)
00867 return ret
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895