import es, os, os.path, random, pickle, popuplib, ojiiupdater, playerlib, gamethread, sys, traceback, string info = es.AddonInfo() info.name = "Guess The Song" info.version = "2.0.0" info.url = "http://addons.eventscripts.com/addons/view/guessthesong" info.author = "Ojii" info.basename = "guessthesong" updateurl = "http://www.gkclan.com/members/uploads/01112@guessthesong.update" path = es.getAddonPath('') path = path.replace('\\','/') cfgfile = path.replace('addons/eventscripts/','cfg/gts_config.cfg') players = {} score = {} mp3dir = 'guessthesong/' path = es.getAddonPath('') path = path.replace('\\','/') sounddir = path.replace('addons/eventscripts','sound/') active = 0 try: string_types = [ types.StringType, types.UnicodeType ] except AttributeError: string_types = [ types.StringType ] def lengthen(string, num_spaces): string = string[:num_spaces] return string + (' ' * (num_spaces - len(string))) def strip_padding(s): while len(s) > 0 and s[-1] in string.whitespace + "\0": s = s[:-1] return s def load(): global gts_rank, gts ver = es.ServerVar('guess_the_song',info.version,'GTS version') ver.makepublic() es.dbgmsg(1, '[GTS_DBG] loaded') load_score() es.addons.registerSayFilter(gts_filter) if not es.exists('saycommand','rank'): es.regsaycmd('rank','guessthesong/rank') if not es.exists('saycommand','top10'): es.regsaycmd('top10','guessthesong/top10') if not es.exists('clientcommand','gts'): es.regclientcmd('gts','guessthesong/gts') if not es.exists('clientcommand','gts_admin') es.regclientcmd('gts_admin','guessthesong/admin') if not es.exists('command','gts_getsongs'): es.regcmd('gts_getsongs','guessthesong/get_songs') if not es.exists('command','gts_update'): es.regcmd('gts_update','guessthesong/update') if not es.exists('command','gts_checkversion'): es.regcmd('gts_checkversion','guessthesong/checkversion') if not es.exists('clientcommand','togglegts'): es.regclientcmd('togglegts','guessthesong/togglegts') if not es.exists('command','togglegts'): es.regcmd('togglegts','guessthesong/stogglegts') if not es.exists('saycommand','guessthesong!'): es.regsaycmd('guessthesong!','guessthesong/gts') if not es.exists('clientcommand','gts_updatemenu'): es.regclientcmd('gts_updatemenu','guessthesong/updatemenu') if not es.exists('command','gts_settings'): es.regcmd('gts_settings','guessthesong/settings') read_configs() get_players() get_songs() check_gts_tool() database = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','rb') songslist = pickle.load(database) database.close() if len(songslist) == 0: es.dbgmsg(0,'[GTS] No songs found in the database') elif len(songslist) == 1: es.dbgmsg(0,'[GTS] One song found in the database') else: es.dbgmsg(0,'[GTS] ' + str(len(songslist)) + ' songs found in the database') es.dbgmsg(0,'[GTS] Maximum songs per map: ' + str(max_songs)) es.dbgmsg(0,'[GTS] Maximum megabytes per map: ' + str(max_size / 1048576)) es.dbgmsg(0,'[GTS] Priority: ' + priority) if gts == 0: enabled = 'no' else: enabled = 'yes' es.dbgmsg(0,'[GTS] Enabled: ' + enabled) def unload(): es.dbgmsg(1, '[GTS_DBG] unloaded') es.addons.unregisterSayFilter(gts_filter) save_score() write_configs() es.unregsaycmd('rank') es.unregsaycmd('top10') es.unregclientcmd('gts') es.unregclientcmd('togglegts') es.unregclientcmd('gts_updatemenu') def get_players(): global players, score playerlist = playerlib.getUseridList('#human') for p in playerlist: s = es.getplayersteamid(p) if score.has_key(s): players[s] = score[s] else: players[s] = (1, 0, es.getplayername(p)) def map_start(): get_songs() def gts_filter(userid, message, teamonly): global guess, active text = message.strip('"') if text == '!stop': stop(userid) elif active == 1: try: text.index('-') check(userid, text) return (0, None, None) except: for line in traceback.format_exception(*sys.exc_info()): es.dbgmsg(0, line[:-1]) es.tell(userid, '[GTS] To guess use the following syntax: title - interpret or interpret - title') return (0, None, None) else: return (userid, text, teamonly) def gts(): global active, gts, players, mp3dir, guessthis, currentsong es.msg('[GTS] Guess this song!!!') read_configs() if gts == 1: if active == 1: es.dbgmsg(0,'[GTS_DBG] Already active!') else: random_song() currentsong = mp3dir + guessthis[2] playerlist = playerlib.getUseridList('#human') for u in playerlist: s = es.getplayersteamid(u) if players.has_key(s): if players[s][0] == 1: es.playsound(u, currentsong, 1.0) else: es.msg('[GTS] Chat temporarily disabled because of GuessTheSong') else: es.msg('[GTS] Chat temporarily disabled because of GuessTheSong') active = 1 gamethread.delayed(30, deac) def check(userid, guess): global players, active, score, guessthis sid = es.getplayersteamid(userid) guess.index('-') split = guess.find('-') a = guess[:split] b = guess[split + 1:] guesslist = [a.replace(' ','').lower(), b.replace(' ','').lower()] if guessthis[0] in guesslist: if guessthis[1] in guesslist: es.tell(userid, 'Correct!') name = es.getplayername(userid) es.msg('[GTS] ' + name + ' guessed right! The song is: ' + guessthis[3]) players[sid] = (players[sid][0], players[sid][1] + 1, name) rank = get_rank(userid) rank = str(rank + 1) if rank.endswith('1'): suffix = 'st' elif rank.endswith('2'): suffix = 'nd' elif rank.endswith('3'): suffix = 'rd' else: suffix = 'th' if players[sid][1] > 1: point = 'points' else: point = 'point' es.msg('[GTS] ' + name + ' has now ' + str(players[sid][1]) + ' ' + point + ' and is ranked ' + rank + suffix) active = 0 else: es.tell(userid, 'Wrong!') def get_rank(u): return map(lambda x: players[x][2], sorted(players, key=lambda x: players[x][1], reverse=True)).index(es.getplayername(u)) def get_randoms(): global randomnumbers es.dbgmsg(1,'[GTS] Getting random number list...') if priority == 'songs': if len(randomnumbers) < max_songs: if get_size() < max_size: r = random.randrange(0,len(slist)) if not r in randomnumbers: size = get_size() + os.path.getsize(sounddir + 'guessthesong/' + slist[r][2]) if not size > max_size: randomnumbers.append(r) get_randoms() elif randomnumbers == []: if check_song_sizes(): get_randoms() else: es.dbgmsg(0,'[GTS] No songs matching the size limit in the database!') else: get_randoms() else: if get_size() < max_size: if len(randomnumbers) < max_songs: r = random.randrange(0,len(slist)) if not r in randomnumbers: size = get_size() + os.path.getsize(sounddir + 'guessthesong/' + slist[r][2]) if not size > max_size: randomnumbers.append(r) get_randoms() elif randomnumbers == []: if check_song_sizes(): get_randoms() else: es.dbgmsg(0,'[GTS] No songs matching the size limit in the database!') else: get_randoms() def get_size(): size = 0 for r in randomnumbers: size = size + os.path.getsize(sounddir + 'guessthesong/' + slist[r][2]) es.dbgmsg(1,'[GTS] size of current list: ' + str(size)) es.dbgmsg(1,'[GTS] max_size: ' + str(max_size)) return size def check_song_sizes(): for s in slist: if os.path.getsize(sounddir + 'guessthesong/' + s[2]) < max_size: return True return False def get_songs(): global songslist, randomnumbers, slist randomnumbers = [] es.dbgmsg(0,'[GTS] Getting songslist for this map...') try: database = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','rb') songslist = pickle.load(database) database.close() slist = songslist songslist = [] if len(slist) > max_songs: get_randoms() for x in randomnumbers: es.stringtable('downloadables', 'sound/guessthesong/' + slist[x][2]) songslist.append(slist[x]) es.dbgmsg(0,'[GTS] Following songs are in the GTS database:') for song in songslist: es.dbgmsg(0,'[GTS] ' + song[3]) else: for s in slist: es.stringtable('downloadables', 'sound/guessthesong/' +s[2]) songslist.append(s) es.dbgmsg(0,'[GTS] Following songs are in the GTS database:') for song in songslist: es.dbgmsg(0,'[GTS] ' + song[3]) except: for line in traceback.format_exception(*sys.exc_info()): es.dbgmsg(0, line[:-1]) es.dbgmsg(0,'[GTS_ERROR] Could not get gts_databse, add mp3s using gts_addmp3...') def addmp3(): if es.getargc() == 4: if not os.path.lexists(es.getAddonPath('guessthesong') + '/gts_database.pkl'): songslist = [] database = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','wb') pickle.dump(songslist,database) database.close() database = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','rb') songslist = pickle.load(database) database.close() nr = len(songslist) + 1 file = es.getargv(1) path = es.getAddonPath('') path = path.replace('\\','/') path = path.replace('addons/eventscripts','sound/guessthesong') os.rename(file, path + str(nr) + '.mp3') title = es.getargv(2).replace(' ','').lower() interpret = es.getargv(3).replace(' ','').lower() realname = "'" + es.getargv(2) + "' by '" + es.getargv(3) + "'" songslist.append([title,interpret,str(nr) + '.mp3', realname]) database = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','wb') pickle.dump(songslist,database) database.close() es.dbgmsg(0,'[GTS] Added ' + file + ' to the guessthesong database') else: es.dbgmsg(0,'[GTS_ERROR] Use following syntax: [rcon] gts_addmp3 <interpret>') es.dbgmsg(0,'[GTS_ERROR] For example: rcon gts_addmp3 "C:/guessthesong/My Interpret - Title04.mp3" "My Interpret" "Title04"') def delmp3(): global songslist if es.getargc() == 3: if not os.path.lexists(es.getAddonPath('guessthesong') + '/gts_database.pkl'): es.dbgmsg(0,'[GTS_ERROR] No mp3s in database to delete...') else: db = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','rb') songslist = pickle.load(db) db.close() title = es.getargv(1).replace(' ','').lower() interpret = es.getargv(2).replace(' ','').lower() test = search(title,interpret) if test != -1: del songslist[test] db = open(es.getAddonPath('guessthesong') + '/gts_database.pkl','wb') pickle.dump(songslist,db) db.close() es.dbgmsg(0, '[GTS] Song successfully removed from database...') else: es.dbgmsg(0,'[GTS_ERROR] No such song or wrong syntax!') es.dbgmsg(0,'[GTS_ERROR] Syntax: [rcon] delmp3 <title> <interpret>') es.dbgmsg(0,'[GTS_ERROR] Songs in database:') for song in songslist: es.dbgmsg(0,'[GTS_ERROR] ' + song[3]) else: es.dbgmsg(0,'[GTS_ERROR] Wrong syntax, try the following:') es.dbgmsg(0,'[GTS_ERROR] [rcon] delmp3 <title> <interpret>') def search(t,i): n = 0 for s in songslist: if s[0] == t and s[1] == i: return n n = n + 1 return -1 def random_song(): global guessthis guessthis = songslist[random.randrange(0, len(songslist))] def rank(): es.dbgmsg(1, '[GTS_DBG] rank') u = es.getcmduserid() rank = get_rank(u) rank = str(rank + 1) if rank.endswith('1'): suffix = 'st' elif rank.endswith('2'): suffix = 'nd' elif rank.endswith('3'): suffix = 'rd' else: suffix = 'th' es.tell(u, 'You are ranked ' + rank + suffix) def top10(): es.dbgmsg(1, '[GTS_DBG] top10') u = es.getcmduserid() s = es.getplayersteamid(u) list = [] dict = players for p in score: if not dict.has_key(p): dict[p] = score[p] x = 0 for d in dict: if x < 10: rank = get_ranktop10(d,dict) rank = str(rank + 1) if rank.endswith('1'): suffix = 'st' elif rank.endswith('2'): suffix = 'nd' elif rank.endswith('3'): suffix = 'rd' else: suffix = 'th' if players[d][1] > 1: point = ' points' else: point = ' point' list.append([rank + suffix, dict[d][2],str(dict[d][1]) + point]) else: break top10 = popuplib.easymenu('top10', '_popup_choice', nothing) top10.settitle('Guess the song top 10:') for p in list: top10.addoption('', p[0] + ': ' + p[1] + ' with ' + p[2]) top10.send(u) def get_ranktop10(s, dict): return map(lambda x: players[x][2], sorted(players, key=lambda x: players[x][1], reverse=True)).index(dict[s][2]) def save_score(): es.dbgmsg(1, '[GTS_DBG] Saving score...') scorefile = open(es.getAddonPath('guessthesong') + '/score.pkl', 'wb') pickle.dump(score,scorefile) scorefile.close() es.dbgmsg(1, '[GTS_DBG] score saved') def load_score(): global score es.dbgmsg(1, '[GTS_DBG] Loading score') if os.path.lexists(es.getAddonPath('guessthesong') + '/score.pkl'): scorefile = open(es.getAddonPath('guessthesong') + '/score.pkl', 'rb') score = pickle.load(scorefile) scorefile.close() es.dbgmsg(1, '[GTS_DBG] score loaded') else: score = {} es.dbgmsg(1, '[GTS_DBG] No score found, starting empty one') def player_activate(event_var): global players, score es.dbgmsg(1, '[GTS_DBG] Player activated') u = event_var['es_steamid'] if score.has_key(u): es.dbgmsg(1, '[GTS_DBG] Player is in score database') players[u] = score[u] es.dbgmsg(1, '[GTS_DBG] Player: ' + str(players[u])) else: es.dbgmsg(1, '[GTS_DBG] Player is new!') players[u] = (1, 0, es.getplayername(event_var['userid'])) es.dbgmsg(1, '[GTS_DBG] Player: ' + str(players[u])) es.dbgmsg(1, '[GTS_DBG] Players: ' + str(players)) if gts == 1: es.tell(event_var['userid'], 'This server uses Guess The Song! ' + info.version) es.tell(event_var['userid'], 'Use gts in the console to start it') es.tell(event_var['userid'], 'Guess the song with the following syntax: <title> - <interpret>') es.tell(event_var['userid'], 'Use rank or top10 in chat to get information about the rankings') es.tell(event_var['userid'], 'Use togglegts in console to turn gts on or off') def player_disconnect(event_var): global players, score es.dbgmsg(1, '[GTS_DBG] Player disconnecting') u = event_var['es_steamid'] if players.has_key(u): score[u] = players[u] es.dbgmsg(1, '[GTS_DBG] Player written to score db') es.dbgmsg(1, '[GTS_DBG] Player score: ' + str(score[u])) del players[u] es.dbgmsg(1, '[GTS_DBG] Player deleted from players') def stop(u): global currentsong try: es.stopsound(u, currentsong) except: es.dbgmsg(1, '[GTS_DBG] User has no sound playing') def togglegts(): global players u = es.getcmduserid s = es.getplayersteamid(u) if players[s][0] == 1: players[s] = (0, players[s][1], players[s][2]) es.tell(u, 'You have disabled GTS for yourself') else: players[s] = (1, players[s][1], players[s][2]) es.tell(u, 'You have enabled GTS for yourself') def stogglegts(): global gts read_configs() if gts == 1: gts = 0 es.dbgmsg(0, '[GTS] has been disabled') else: gts = 1 write_configs() es.dbgmsg(0, '[GTS] has been enabled') def deac(): global active active = 0 def nothing(a,b,c): pass def update(): ojiiupdater.update(info, updateurl) def checkversion(): check = ojiiupdater.checkversion(info, updateurl) if check.newversion == 1: es.dbgmsg(0, '[GTS] New version available: ' + check.latest_version) else: es.dbgmsg(0, "[GTS] You're version (" + check.latest_version + ') is up to date') def updatemenu(): es.dbgmsg(1,'DBG: updatemenu triggered') userid = es.getcmduserid() if es.getargc() == 2: es.dbgmsg(1,'DBG: getarc correct') if es.getargv(1) == adminpw: es.dbgmsg(0,'DBG: adminpw correct') ojiiupdater.popup(info,updateurl,userid) else: es.dbgmsg(0,'DBG: adminpw incorrect') else: es.dbgmsg(1,'DBG: getarc incorrect') def es_map_start(event_var): for song in songslist: es.stringtable('downloadables', 'sound/guessthesong/' + song[2]) es.dbgmsg(0,'[GTS] Following songs are in the GTS database:') for song in songslist: es.dbgmsg(0,'[GTS] ' + song[3]) playerlist = playerlib.getPlayerList('#human') if len(playerlist) == 0: check = ojiiupdater.checkversion(info, updateurl) if check.newversion == 1: ojiiupdater.update(info, updateurl) def read_configs(): global gts, max_songs, max_size, priority, adminpw if not os.path.lexists(cfgfile): adminpw = get_random_pw() tempfile = open(cfgfile, 'w') tempfile.write('// Guess The Song! Standard Config file:\nenable 1\n//enable accepts either 1 or 0\nmax_songs 10\n//max_songs can be any positive number (0 does not make any sense but would work)\nmax_size 5 MB\n//max_size accepts any amount in Bytes, or an amount followed by a space and then either B for Bytes, KB for Kilobytes or MB for Megabytes\npriority size\n//priority is either size or songs\nadminpw ' + adminpw + '\n//The update password is used for the command gts_updatemenu') tempfile.close() tempfile = open(cfgfile, 'r') templines = tempfile.read().splitlines() tempfile.close() max_songs = None max_size = None priority = None adminpw = None gts = 0 for line in templines: if line.startswith('enable'): split = line.find(' ') + 1 if int(line[split:]) in [1,0]: gts = int(line[split:]) elif line.startswith('max_songs'): split = line.find(' ') + 1 nr = line[split:] if checkint(nr): max_songs = int(line[split:]) elif line.startswith('max_size'): if line.count(' ') == 2: linelist = line.split(' ') amount = linelist[1] unit = linelist[2] if unit == 'B': if checkint(amount): max_size = int(amount) else: max_size = None elif unit == 'KB': if checkint(amount): max_size = int(amount) * 1024 else: max_size = None elif unit == 'MB': if checkint(amount): max_size = int(amount) * 1048576 else: max_size = None else: max_size = None else: split = line.find(' ') + 1 size = line[split:] if checkint(size): max_size = int(size) else: max_size = None elif line.startswith('priority'): split = line.find(' ') + 1 temp = line[split:] if temp in ['songs','size']: priority = temp else: priority = None elif line.startswith('adminpw'): split = line.find(' ') + 1 adminpw = line[split:] if max_songs == None: if max_size == None: max_songs = 10 priority = 'songs' elif priority == None: priority = 'size' if max_size == None: if priority == None: priority = 'songs' if priority == None: if max_songs == None: priority = 'size' else: priority = 'songs' if adminpw == None: adminpw = get_random_pw() def get_random_pw(): letters = [] for x in range(0,len(string.ascii_letters)): letters.append(string.ascii_letters[x]) pw = '' for x in range(0,10): pw = pw + random.choice(letters) return pw def checkint(nr): for x in range(0,len(nr)): if not nr[x] in string.digits: return False return True def write_configs(): tempfile = open(cfgfile, 'r') templines = tempfile.readlines() tempfile.close() writestring = '' e = 0 s1 = 0 s2 = 0 p = 0 u = 0 for line in templines: if line.startswith('enable'): writestring = writestring + 'enable ' + str(gts) + '\n' e = 1 elif line.startswith('max_songs'): writestring = writestring + 'max_songs ' + str(max_songs) + '\n' s1 = 1 elif line.startswith('max_size'): writestring = writestring + 'max_size ' + str(max_size) + ' B\n' s2 = 1 elif line.startswith('priority'): writestring = writestring + 'priority ' + priority + '\n' p = 1 elif line.startswith('adminpw'): writestring = writestring + 'adminpw ' + adminpw + '\n' u = 1 elif line != '' and line != '\n' and line != '\r' and line != ' ': writestring = writestring + line + '\n' if e != 1: writestring = writestring + 'enable ' + str(gts) + '\n' if s1 != 1: writestring = writestring + 'max_songs ' + str(max_songs) + '\n' if s2 != 1: writestring = writestring + 'max_size ' + str(max_size) + '\n' if p != 1: writestring = writestring + 'priority ' + priority + '\n' if u != 1: writestring = writestring + 'adminpw ' + adminpw + '\n' tempfile = open(cfgfile, 'w') tempfile.write(writestring[:-1]) tempfile.close() def check_gts_tool(): if not os.path.lexists(es.getAddonPath('guessthesong') + '/gts_database_tool.py'): url = urllib2.urlopen('http://www.gkclan.com/members/uploads/01112@gts_database_tool.py') f = open(es.getAddonPath('guessthesong') + '/gts_database_tool.py') f.write(url.read().replace('\r','')) f.close() def settings(): global max_songs,max_size,gts,priority,adminpw read_configs() if es.getargc() == 3: if es.getargv(1) == 'max_songs': if checkint(es.getargv(2)): max_songs = int(es.getargv(2)) elif es.getargv(1) == 'max_size': if checkint(es.getargv(2)): max_size = int(es.getargv(2)) elif es.getargv(1) == 'enable': if es.getargv(2) in ['1','0']: gts = int(es.getargv(2)) elif es.getargv(1) == 'priority': if es.getargv(2) in ['size','songs']: priority = es.getargv(2) elif es.getargv(1) == 'adminpw': adminpw = es.getargv(2) elif es.getargc() == 4: if es.getargv(1) == 'max_size': if checkint(es.getargv(2)): if es.getargv(3) == 'B': max_size = int(es.getargv(2)) elif es.getargv(3) == 'KB': max_size = int(es.getargv(2)) * 1024 elif es.getargv(3) == 'MB': max_size = int(es.getargv(2)) * 1048576 else: es.dbgmsg(0,'[GTS] Wrong syntax...') es.dbgmsg(0,'[GTS] Maximum songs per map: ' + str(max_songs)) es.dbgmsg(0,'[GTS] Maximum megabytes per map: ' + str(max_size / 1048576)) es.dbgmsg(0,'[GTS] Priority: ' + priority) if gts == 0: enabled = 'no' else: enabled = 'yes' es.dbgmsg(0,'[GTS] Enabled: ' + enabled) write_configs() def admin(): read_configs() userid = es.getcmduserid() if es.getargv(1) == adminpw: database_tool(userid) else: es.server.cmd('kickid ' + userid + ' GTS') class database_tool(): def __init__(self, userid): self.userid = userid self.database = es.getAddonPath('guessthesong') + '/gts_database.pkl' path = es.getAddonPath('') path = path.replace('\\','/') self.sounddir = path.replace('addons/eventscripts','sound/') self.maxsize = 0 self.run() def run(self): self.main = easymenu('main_menu','_popup_choice',self.main_choice) self.main.settitle('GuessTheSong! Grafical Database Tool') self.main.addoption('add','Add songs') if self.maxsize == 0: max = 'unlimited' else: max = str(self.maxsize / 1024) + ' kb' self.main.addoption('set','Set filesize limit (' + max + ')') self.main.addoption('del','Delete songs') self.main.addoption('update','Update menu') if not popuplib.isqueued('main_menu', self.userid): self.main.send(self.userid) def main_choice(self,userid,choice,menuname): if choice == 'add': self.add() elif choice == 'del': self.delete() elif choice == 'set': self.set() elif choice == 'edit': self.edit() elif choice == 'update': ojiiupdater.popup(info,updateurl,self.userid) def add(self): self.root = easymenu('root_dir','_popup_choice',self.root_choice) self.root.settitle('Choose a drive:') if os.name == 'nt': self.letters = self.checkHDwin() for letter in self.letters: self.root.addoption(letter,letter) self.root.send(self.userid) else: es.tell(self.userid,'Does not support linux yet... sorry') def set(self): self.setmenu = easymenu('set_menu','_popup_choice',self.set_choice) self.setmenu.settitle('Choose a maximum size for the mp3 files:\n') self.setmenu.addoption('0','Unlimited') self.setmenu.addoption('250','250 kb') self.setmenu.addoption('300','300 kb') self.setmenu.addoption('400','400 kb') self.setmenu.addoption('500','500 kb') self.setmenu.addoption('600','600 kb') self.setmenu.addoption('700','700 kb') self.setmenu.addoption('800','800 kb') self.setmenu.addoption('900','900 kb') self.setmenu.addoption('1024','1 MB') self.setmenu.send(self.userid) def set_choice(self,userid,choice,menuname): self.maxsize = int(choice) * 1024 self.run() def root_choice(self,userid,choice,menuname): self.path = choice + ':/' self.dir() def dir(self): cdir = [] self.path = self.get_path(self.path) for file in os.listdir(self.path.replace('\\','/')): if file.endswith('.mp3'): cdir.insert(0,file) elif file.count('.') == 0: cdir.append(file) self.dirmenu = easymenu('dir_menu','_popup_choice',self.dir_choice) self.dirmenu.settitle('Choose a file or a folder') self.dirmenu.addoption('..','/..') for file in cdir: if file.endswith('.mp3'): self.dirmenu.addoption(file,file) else: self.dirmenu.addoption(file,'/' + file) self.dirmenu.send(self.userid) def get_path(self, path): try: path = unicode(path,'utf-8') return path except: return path def dir_choice(self,userid,choice,menuname): if choice == '..': if self.path.count('/') == 1: self.add() else: self.path = self.path[:self.path[:-1].rfind('/') + 1] self.dir() elif choice.endswith('.mp3'): self.add_mp3(self.path + '/' + choice) else: self.path = self.path + '/' + choice self.dir() def add_mp3(self,file): db = open(self.database,'rb') songslist = pickle.load(db) db.close() nr = len(songslist) + 1 self.copy_mp3(file,nr) self.okay = easymenu('done','_popup_choice',self.done) try: info = ID3(open(file,'rb')) songslist.append([info.title.replace(' ','').lower(),info.artist.replace(' ','').lower(),str(nr) + '.mp3',"'" + info.title + "' by '" + info.artist + "'"]) db = open(self.database,'wb') pickle.dump(songslist,db) db.close() self.okay.settitle("Successfully added '" + info.title + "' by '" + info.artist + "' to the database") except InvalidTagError: self.okay.settitle('Error reading ID3 tags!') self.okay.addoption('go_on','Add another file') self.okay.send(self.userid) def delete(self): db = open(self.database,'rb') songslist = pickle.load(db) db.close() self.deletemenu = easymenu('delete_menu','_popup_choice',self.really) if songslist == []: self.deletemenu.settitle('No songs in the database!') self.deletemenu.addoption('add','Add a song?') else: self.deletemenu.settitle('Choose a song to delete:') for song in songslist: self.deletemenu.addoption(song[2],song[3]) self.deletemenu.send(self.userid) def really(self,userid,choice,menuname): if choice == 'add': self.add() else: song = self.get_song(choice) self.delcandidate = choice self.rly = easymenu('oh_rly','_popup_choice',self.really_choice) self.rly.settitle('Do you really want to delete ' + song + '?\n (The mp3 file will also be deleted!)') self.rly.settitle('y','Yes') self.rly.settitle('n','No') self.rly.send(self.userid) def really_choice(self,userid,choice,menuname): self.donemenu = easymenu('donemenu_menu','_popup_choice',self.done) if choice == 'y': os.remove(self.sounddir + self.delcandidate) self.del_song(self.delcandidate) self.donemenu.settitle('The song has been removed from the database') else: self.donemenu.settitle('Cancelled...') self.donemenu.addoption('del','Delete another song') self.donemenu.addoption('go_on','Add a song') self.donemenu.send(self.userid) def done(self,userid,choice,menuname): if choice == 'go_on': self.dir() else: self.delete() def copy_mp3(self,a,b): z = open(a,'rb') y = open(self.sounddir + str(b) + '.mp3', 'wb') x = self.get_sized_data(z) y.write(x) z.close() y.close() def get_sized_data(self,z): a = z.read() if self.maxsize == 0: return a else: ws = '' for x in range(0,self.max_size): ws = ws + a[x] return ws def checkHDwin(self): x = 0 letters = [] for a in range(2,len(string.ascii_uppercase)): letters.append(string.ascii_uppercase[a]) silent = [] for letter in letters: try: silent = os.listdir(letter + ':/') x = x + 1 except: return letters[:x] return ['C'] def get_id3(self,file): mp3 = open(file,'rb') a = mp3.read() mp3.close() artist = None title = None tag_value = self.get_tags(a) if not tag_value == None: artist = self.get_artist(tag_value) title = self.get_title(tag_value) if None in [tag_value,artist,title]: return None else: return [title,artist] def get_tags(self,a): letters = [] temp = '' taglist = [] tag_value = [] thelist = [] for x in range(0,len(string.ascii_letters)): letters.append(string.ascii_letters[x]) for x in range(10,1000): if a[x] in letters: temp = temp + a[x] if temp.endswith('TRCK'): thelist.append('TRCK') elif temp.endswith('TALB'): thelist.append('TALB') elif temp.endswith('TIT2'): thelist.append('TIT2') elif temp.endswith('TSOP'): thelist.append('TSOP') elif temp.endswith('TITT'): thelist.append('TITT') elif temp.endswith('TPE'): thelist.append('TPE') elif self.alltags(thelist): for tag in thelist: temp = temp.replace(tag,'-' + tag + ',') temp = temp[1:] taglist = temp.split('-') for tag in taglist: tag_value.append(tag.split(',')) return tag_value return None def alltags(self,thelist): if 'TPE' in thelist: if 'TIT2' in thelist: return True elif 'TITT' in thelist: return True return False def get_artist(self,a): for list in a: if list[0] == 'TPE1': return list[1] elif list[0] == 'TPE': return list[1] return None def get_title(self,a): for list in a: if list[0] == 'TIT2': return list[1] elif list[0] == 'TITT': return list[1] return None def get_song(self,mp3nr): db = open(self.database,'rb') songslist = pickle.load(db) db.close() for song in songslis: if song[2] == mp3nr: return song[3] def del_song(self,mp3nr): db = open(self.database,'rb') songslist = pickle.load(db) db.close() for song in songslist: if song[2] == mp3nr: songslist.remove(song) db = open(self.database,'wb') pickle.dump(songslist,db) db.close() class InvalidTagError: def __init__(self, msg): self.msg = msg def __str__(self): return self.msg # The following class is not written by myself # I got it from http://id3-py.sourceforge.net/ class ID3: genres = [ "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrum. Pop", "Instrum. Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Indust.", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progress. Rock", "Psychadel. Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Capella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "Jpop", "Synthpop" ] def __init__(self, file, name='unknown filename', as_tuple=0): if type(file) in string_types: self.filename = file # We don't open in r+b if we don't have to, to allow read-only access self.file = open(file, 'rb') self.can_reopen = 1 elif hasattr(file, 'seek'): # assume it's an open file if name == 'unknown filename' and hasattr(file, 'name'): self.filename = file.name else: self.filename = name self.file = file self.can_reopen = 0 self.d = {} self.as_tuple = as_tuple self.delete_tag = 0 self.zero() self.modified = 0 self.has_tag = 0 self.had_tag = 0 try: self.file.seek(-128, 2) except IOError, msg: self.modified = 0 raise InvalidTagError("Can't open %s: %s" % (self.filename, msg)) return try: if self.file.read(3) == 'TAG': self.has_tag = 1 self.had_tag = 1 self.title = self.file.read(30) self.artist = self.file.read(30) self.album = self.file.read(30) self.year = self.file.read(4) self.comment = self.file.read(30) if ord(self.comment[-2]) == 0 and ord(self.comment[-1]) != 0: self.track = ord(self.comment[-1]) self.comment = self.comment[:-2] else: self.track = None self.genre = ord(self.file.read(1)) self.title = strip_padding(self.title) self.artist = strip_padding(self.artist) self.album = strip_padding(self.album) self.year = strip_padding(self.year) self.comment = strip_padding(self.comment) self.setup_dict() except IOError, msg: self.modified = 0 raise InvalidTagError("Invalid ID3 tag in %s: %s" % (self.filename, msg)) self.modified = 0 def setup_dict(self): self.d = {} if self.title: self.d["TITLE"] = self.tupleize(self.title) if self.artist: self.d["ARTIST"] = self.tupleize(self.artist) if self.album: self.d["ALBUM"] = self.tupleize(self.album) if self.year: self.d["YEAR"] = self.tupleize(self.year) if self.comment: self.d["COMMENT"] = self.tupleize(self.comment) if self.legal_genre(self.genre): self.d["GENRE"] = self.tupleize(self.genres[self.genre]) else: self.d["GENRE"] = self.tupleize("Unknown Genre") if self.track: self.d["TRACKNUMBER"] = self.tupleize(str(self.track)) def delete(self): self.zero() self.delete_tag = 1 self.has_tag = 0 def zero(self): self.title = '' self.artist = '' self.album = '' self.year = '' self.comment = '' self.track = None self.genre = 255 # 'unknown', not 'blues' self.setup_dict() def tupleize(self, s): if self.as_tuple and type(s) is not types.TupleType: return (s,) else: return s def find_genre(self, genre_to_find): i = 0 find_me = string.lower(genre_to_find) for genre in self.genres: if string.lower(genre) == find_me: break i = i + 1 if i == len(self.genres): return -1 else: return i def legal_genre(self, genre): if type(genre) is types.IntType and 0 <= genre < len(self.genres): return 1 else: return 0 def write(self): if self.modified: try: # We see if we can re-open in r+ mode now, as we need to write if self.can_reopen: self.file = open(self.filename, 'r+b') if self.had_tag: self.file.seek(-128, 2) else: self.file.seek(0, 2) # a new tag is appended at the end if self.delete_tag and self.had_tag: self.file.truncate() self.had_tag = 0 elif self.has_tag: go_on = 1 if self.had_tag: if self.file.read(3) == "TAG": self.file.seek(-128, 2) else: # someone has changed the file in the mean time go_on = 0 raise IOError("File has been modified, losing tag changes") if go_on: self.file.write('TAG') self.file.write(lengthen(self.title, 30)) self.file.write(lengthen(self.artist, 30)) self.file.write(lengthen(self.album, 30)) self.file.write(lengthen(self.year, 4)) comment = lengthen(self.comment, 30) if self.track < 0 or self.track > 255: self.track = None if self.track != None: comment = comment[:-2] + "\0" + chr(self.track) self.file.write(comment) if self.genre < 0 or self.genre > 255: self.genre = 255 self.file.write(chr(self.genre)) self.had_tag = 1 self.file.flush() except IOError, msg: raise InvalidTagError("Cannot write modified ID3 tag to %s: %s" % (self.filename, msg)) else: self.modified = 0 def as_dict(self): return self.d def items(self): return map(None, self.keys(), self.values()) def keys(self): return self.d.keys() def values(self): if self.as_tuple: return map(lambda x: x[0], self.d.values()) else: return self.d.values() def has_key(self, k): return self.d.has_key(k) def get(self, k, x=None): if self.d.has_key(k): return self.d[k] else: return x def __getitem__(self, k): return self.d[k] def __setitem__(self, k, v): key = k if not key in ['TITLE', 'ARTIST', 'ALBUM', 'YEAR', 'COMMENT', 'TRACKNUMBER', 'GENRE']: return if k == 'TRACKNUMBER': if type(v) is types.IntType: self.track = v else: self.track = string.atoi(v) self.d[k] = self.tupleize(str(v)) elif k == 'GENRE': if type(v) is types.IntType: if self.legal_genre(v): self.genre = v self.d[k] = self.tupleize(self.genres[v]) else: self.genre = v self.d[k] = self.tupleize("Unknown Genre") else: self.genre = self.find_genre(str(v)) if self.genre == -1: print v, "not found" self.genre = 255 self.d[k] = self.tupleize("Unknown Genre") else: print self.genre, v self.d[k] = self.tupleize(str(v)) else: self.__dict__[string.lower(key)] = v self.d[k] = self.tupleize(v) self.__dict__['modified'] = 1 self.__dict__['has_tag'] = 1 def __del__(self): self.write() def __str__(self): if self.has_tag: if self.genre != None and self.genre >= 0 and \ self.genre < len(self.genres): genre = self.genres[self.genre] else: genre = 'Unknown' if self.track != None: track = str(self.track) else: track = 'Unknown' return "File : %s\nTitle : %-30.30s Artist: %-30.30s\nAlbum : %-30.30s Track : %s Year: %-4.4s\nComment: %-30.30s Genre : %s (%i)" % (self.filename, self.title, self.artist, self.album, track, self.year, self.comment, genre, self.genre) else: return "%s: No ID3 tag." % self.filename # intercept setting of attributes to set self.modified def __setattr__(self, name, value): if name in ['title', 'artist', 'album', 'year', 'comment', 'track', 'genre']: self.__dict__['modified'] = 1 self.__dict__['has_tag'] = 1 if name == 'track': self.__dict__['d']['TRACKNUMBER'] = self.tupleize(str(value)) elif name == 'genre': if self.legal_genre(value): self.__dict__['d']['GENRE'] = self.tupleize(self.genres[value]) else: self.__dict__['d']['GENRE'] = self.tupleize('Unknown Genre') else: self.__dict__['d'][string.upper(name)] = self.tupleize(value) self.__dict__[name] = value