def info_UpdateDisplay(song): obj = MpGlobal.Window.dsp_info if song == None: obj.text_time = "" obj.text_playcount = "" obj.text_artist = "" obj.text_title = "Select a Song to Play" obj.text_album = "Drag and Drop music to Load" obj.text_index = "-/-" obj.text_date = "" obj.int_rating = 0 obj.int_freq = 0 obj.stopScrolling() obj.update() else: obj.text_playcount = str(song[MpMusic.PLAYCOUNT]) obj.text_artist = song[MpMusic.ARTIST] obj.text_title = song[MpMusic.TITLE] obj.text_album = song[MpMusic.ALBUM] obj.int_rating = song[MpMusic.RATING] obj.int_freq = song[MpMusic.FREQUENCY] obj.text_date = song[MpMusic.DATESTAMP] obj.text_index = "%d/%d" % (MpGlobal.Player.CurrentIndex + 1, len(MpGlobal.Player.playList)) obj.setScrolling() obj.update() d = DateTime().daysElapsed(song[MpMusic.DATESTAMP]) if (d > 0): obj.text_date += " {%d}" % (d)
def updateSongRecord(self,song,newtime=-1): # update the given song because it has just finished playing # update the lengths if there is a discrepancy using newtime as the new length if song == None: debug("None Song Passed to updateSongRecord") return if newtime >= 0: if (newtime < song[MpMusic.LENGTH]-1 or newtime > song[MpMusic.LENGTH]+1) and newtime > 1 : MpGlobal.Window.emit(SIGNAL("DEBUG_MESSAGE"),"%s : OldTime: %d NewTime: %d"%(song[MpMusic.TITLE],song[MpMusic.LENGTH],newtime)) song[MpMusic.LENGTH] = newtime dt = DateTime() days_elapsed = dt.daysElapsed(song[MpMusic.DATESTAMP]) # number of days since the date stamp song[MpMusic.DATESTAMP] = dt.currentDateTime(); song[MpMusic.DATEVALUE] = DateTime.now(); song.updateFrequency(days_elapsed) song[MpMusic.PLAYCOUNT] += 1 song.calcBaseScore(); song.calcScore(MpGlobal.Histogram); song.update(); # refill the library, if it was in view, its text needs to be updated #Player_set_unsaved() MpGlobal.Window.emit(SIGNAL("QUEUE_FUNCTION"),Player_set_unsaved) MpGlobal.Window.emit(SIGNAL("FILL_LIBRARY"))
def setSearchTime(): dt = DateTime() date = dt.currentDate() MpGlobal.RecentEpochTime = dt.getEpochTime( date + " 00:00") # return seconds at start of this day MpGlobal.LaunchEpochTime = MpGlobal.RecentEpochTime - ( 14 * 24 * 60 * 60) # date of two weeks ago
def playList_Load_M3U(filepath, library): """ load an M3U playlist, the file paths in the the meu file will be converted to a list of Song objects filepath - path to the file to load library - a list of songs already in memory """ dt = DateTime() dt.timer_start() if not os.path.exists(filepath): return [] try: rf = codecs.open(filepath, "r", encoding='utf-8') except: print "cannot open m3u file:\n %s" % filepath return [] bsearch = SongPath_Lookup(library) playlist = [] line = rf.readline() count = 0 while line: try: line = line.strip() if line[0] == '#': line = rf.readline() # load the next line ( a file path?) continue song = bsearch.find(line) #path_to_song(line,library) if song != None: playlist.append(song) except Exception as e: print "\n\n\nerror\n\n\n" print e finally: line = rf.readline() count += 1 rf.close() dt.timer_end() print "Loaded %d songs from m3u container in %s" % ( len(playlist), DateTime.formatTimeDeltams(dt.timedelta)) return playlist
def musicBackup(path, songList, format=0, force=False): """ save a copy of the current library to ./backup/ only save if one has not been made today, delete old backups adding new music, deleting music, are good reasons to force backup """ #path = os.path.join(MpGlobal.installPath,'backup') #songList = MpGlobal.Player.library if not os.path.exists(path): os.mkdir(path) print "backup directory created" dt = DateTime() # create a new date time object date = dt.currentDate() hourmin = dt.currentTime() date = date.replace('/', '-').replace('\\', '-') name = 'music_backup-' fullname = name + date + '.libz' h, m = hourmin.split(':') #if (atoi(h) > 12) or force: # save backups in the afternoon only R = [] dir = os.listdir(path) for file in dir: if file.startswith(name) and fileGetExt(file) == "libz": R.append(file) newestbu = "" R.sort(reverse=True) if len(R) > 0: #remove old backups # while there are more than 6, # and one has not been saved today while len(R) > 6 and R[0] != fullname: delfile = R.pop() print "Deleting %s" % delfile os.remove(os.path.join(path, delfile)) # record name of most recent backup, one backup per day unless forced newestbu = R[0] # save a new backup if force or newestbu != fullname: print "Saving %s" % fullname newbu = os.path.join(path, fullname) musicSave_LIBZ(newbu, songList, format)
def format_datefield(self,FMT,string_index,num_index): """ format a date string, using FMT to format the integer value comes from num_index the formated string value is stored in string_index """ ds = "" try: dt = DateTime(FMT) if self[num_index]: ds = dt.formatDateTime(self[num_index]) except Exception as e: print e finally: self[string_index] = ds
def id3_createSongFromPath(path): """ attempt to read the id3 data from the song if the songs format is not supported, return a blank song with the path set. """ #check the extension and build a new song array from that type fext = fileGetExt(path).lower() song = Song(path) try: if fext in ext_mp3: id3_mp3_createSongFromPath(song) if fext in ext_mp4: id3_mp4_createSongFromPath(song) if fext in ext_asf: id3_asf_createSongFromPath(song) if fext in ext_flac: id3_flac_createSongFromPath(song) except Exception as e: print traceback.format_exc() print " *** Error [%s] Reading Tags for Type: %s" % (song, fext) for i in e: print "%s" % str(i) song[EnumSong.FILESIZE] = fileGetSize(path) song[EnumSong.DATEADDED] = DateTime.now() song[EnumSong.DATEADDEDS] = DateTime().currentDateTime() if song[EnumSong. LENGTH] > 2000: # 2k seconds = 32 minutes. is that a good break point? song[ EnumSong. LENGTH] /= 1000 # assume that th time measured was in milliseconds song.update() return song # return the blank song instead
def calcBaseScore(self): """ s=1000 t=255 MpGlobal.Hist = [0]*(s+1) MpGlobal.Histpcnt = [0]*(t+1) for song in MpGlobal.Player.library: delta = DateTime().daysElapsedUTC(song[EnumSong.DATEADDED],DateTime.now()) song[EnumSong.SPECIAL] = int((s)*(float(song[EnumSong.PLAYCOUNT])/delta)) MpGlobal.Hist [ min(s,song[ EnumSong.SPECIAL ] )] += 1 MpGlobal.Histpcnt[ min(t,song[ EnumSong.PLAYCOUNT ] )] += 1 l = len(MpGlobal.Player.library) for song in MpGlobal.Player.library: m = min(s,song[ EnumSong.SPECIAL ] ); n = min(t,song[ EnumSong.PLAYCOUNT ] ); _m = float(sum(MpGlobal.Hist [:m])); _n = float(sum(MpGlobal.Histpcnt[:n])); _d = int( 1000*(_m/l) ) _p = int( 1000*(_n/l) ) song[ EnumSong.SCORE ] = int(.25*_p+.75*_d) """ MAX_SCORE = 9999 delta = DateTime().daysElapsedUTC(self[EnumSong.DATEADDED],DateTime.now()) p = int(MAX_SCORE*(float(self[EnumSong.PLAYCOUNT])/delta)) _f = float(9999 if self[EnumSong.FREQUENCY] == 0 else self[EnumSong.FREQUENCY]) f = int( MAX_SCORE*(1/_f)*7 ) # 7 scales such that once a week is really good self.basescore = (min(MAX_SCORE,f) + min(MAX_SCORE,p)) / 2 self[EnumSong.SPECIAL] = self.basescore return self.basescore
def playList_Save_M3U(filepath, data, typ=0): driveList = systemDriveList() wf = codecs.open(filepath, "w", encoding='utf-8') dt = DateTime() dt.timer_start() for x in range(len(data)): path = data[x][EnumSong.PATH] if typ > 0: #alternate save formats remove the drive path = stripDriveFromPath(driveList, path) wf.write("%s\n" % (unicode(path))) wf.close() dt.timer_end() print "Saved %d songs to m3u container in %s" % ( len(data), DateTime.formatTimeDeltams(dt.timedelta))
def getData(self): MULTIDATA = len(self.data) > 1 OPERATION = self.cbox.currentIndex() for item in self.editList: if not item[2].isEnabled(): item[2].setCheckState(Qt.Unchecked) for song in self.data: if self.editList[self.art][2].isChecked(): song[MpMusic.ARTIST] = unicode( self.editList[self.art][1].currentText()) if self.editList[self.cmp][2].isChecked(): print unicode(self.editList[self.cmp][1].currentText()) print self.cmp, self.lng song[MpMusic.COMPOSER] = unicode( self.editList[self.cmp][1].currentText()) if self.editList[self.ttl][2].isChecked(): song[MpMusic.TITLE] = unicode( self.editList[self.ttl][1].currentText()) if self.editList[self.abm][2].isChecked(): song[MpMusic.ALBUM] = unicode( self.editList[self.abm][1].currentText()) if self.editList[self.gen][2].isChecked(): song[MpMusic.GENRE] = unicode( self.editList[self.gen][1].currentText()) if self.editList[self.lng][2].isChecked(): song[MpMusic.LANG] = unicode( self.editList[self.lng][1].currentText()) if self.editList[self.com][2].isChecked(): song[MpMusic.COMMENT] = unicode( self.editList[self.com][1].currentText()) if self.editList[self.rte][2].isChecked(): if MULTIDATA: song[MpMusic.RATING] += self.editList[self.rte][1].value() else: song[MpMusic.RATING] = self.editList[self.rte][1].value() if song[MpMusic.RATING] > MpMusic.MAX_RATING: song[MpMusic.RATING] = MpMusic.MAX_RATING if song[MpMusic.RATING] < 0: song[MpMusic.RATING] = 0 if self.editList[self.pct][2].isChecked(): if MULTIDATA: song[MpMusic.PLAYCOUNT] += self.editList[ self.pct][1].value() else: song[MpMusic.PLAYCOUNT] = self.editList[ self.pct][1].value() if song[MpMusic.PLAYCOUNT] < 0: song[MpMusic.PLAYCOUNT] = 0 if self.editList[self.sct][2].isChecked(): if MULTIDATA: song[MpMusic.SKIPCOUNT] += self.editList[ self.sct][1].value() else: song[MpMusic.SKIPCOUNT] = self.editList[ self.sct][1].value() if song[MpMusic.SKIPCOUNT] < 0: song[MpMusic.SKIPCOUNT] = 0 if self.editList[self.frq][2].isChecked(): if MULTIDATA: song[MpMusic.FREQUENCY] += self.editList[ self.frq][1].value() else: song[MpMusic.FREQUENCY] = self.editList[ self.frq][1].value() if song[MpMusic.FREQUENCY] < 0: song[MpMusic.FREQUENCY] = 0 if self.editList[self.ind][2].isChecked(): song[MpMusic.SONGINDEX] = self.editList[self.ind][1].value() if self.editList[self.yer][2].isChecked(): song[MpMusic.YEAR] = self.editList[self.yer][1].value() if self.editList[self.pth][2].isChecked(): # auto strip any quotes around the path name s = unicode(self.editList[self.pth][1].text()) if s[0] in "'\"" and s[0] == s[-1]: s = s[1:-1] song[MpMusic.PATH] = s if self.editList[self.dte][2].isChecked(): dt = DateTime.QDateTimeToFmt( self.editList[self.dte][1].dateTime()) song[MpMusic.DATESTAMP] = dt song[MpMusic.DATEVALUE] = DateTime().getEpochTime(dt) if self.editList[self.add][2].isChecked(): dt = DateTime.QDateTimeToFmt( self.editList[self.add][1].dateTime()) song[MpMusic.DATEADDED] = DateTime().getEpochTime(dt) song[MpMusic.DATEADDEDS] = dt if OPERATION == 4: t = DateTime().getEpochTime(song[MpMusic.DATESTAMP]) SECONDS_IN_DAY = 86400 #60*60*24 t -= song[MpMusic.FREQUENCY] * SECONDS_IN_DAY song[MpMusic.DATESTAMP] = DateTime().formatDateTime(t) song[MpMusic.DATEVALUE] = t song[MpMusic.PLAYCOUNT] -= 1 #song[MpMusic.FREQUENCY] = 0 song.update()
def musicSave_LIBZ(filepath, songList, typ=1, block_size=128): """ save a new file, but first compress it using LZMA. file is saved as a binary file. HEADER: several 8 byte frames in a 4:4 byte pattern 4 bytes describing the value in format 'LXXX' 4 byte integer the header ends when the first string 'SIZE' is found Frame 8 byte header, followed by SIZE bytes corresponding to X LZMA compressed song representations. Frame Header: 4 bytes - the word 'SIZE' 4 bytes - unsigned integer, size of frame, excluding frame header Frame Body: SIZE bytes compressed using pyLZMA.compress() each frame will compress HEADERS: LVER - VERSION :outlines if any changes to reading will be needed (future proofing) LTYP - TYPE : bitwise or combination of save settings : 1 - no compression : 2 - remove drie list from start of path ( multi os mode ) LBLK - BLOCK SIZE : maximum number of songs per block, after decompression LCNT - COUNT : count of all songs saved to the file LFMT - SNG FORMAT : number of lines per song record Based off of the following two docstrings. there is no reason to store the parameters used for saving. compress(string, dictionary=23, fastBytes=128, literalContextBits=3, literalPosBits=0, posBits=2, algorithm=2, eos=1, multithreading=1, matchfinder='bt4') Compress the data in string using the given parameters, returning a string containing the compressed data. decompress(data[, maxlength]) Decompress the data, returning a string containing the decompressed data. If the string has been compressed without an EOS marker, you must provide the maximum length as keyword parameter. decompress(data, bufsize[, maxlength]) Decompress the data using an initial output buffer of size bufsize. If the string has been compressed without an EOS marker, you must provide the maximum length as keyword parameter. """ dt = DateTime() dt.timer_start() with open(filepath, "wb") as FILE: FILE.write(struct.pack("4sI", "LVER", 1)) # FILE.write(struct.pack("4sI", "LTYP", typ | 1)) # FILE.write(struct.pack("4sI", "LBLK", block_size)) # number of songs in each block FILE.write(struct.pack("4sI", "LCNT", len(songList))) # FILE.write(struct.pack("4sI", "LFMT", Song.repr_length())) LIBZ_write_songList(FILE, songList, typ, block_size) dt.timer_end() print "Saved %d songs to libz container in %s" % ( len(songList), DateTime.formatTimeDeltams(dt.timedelta))
def musicLoad_LIBZ(filepath): """ load the specified .libz file and return an array of songs. #todo : read 8 bytes # read in : LVERABCD # if A== 0x3D == '=' then file is ascii format # when saving a non binary version save version as '=001' or 3D 30 30 31 # increment the version count for new ascii file formats # for binary formats: # LVERABCD, where A,B,C,D are a little endian 32 bit integer with A=0x00 """ srclib = fileGetName(filepath) if not os.path.exists(filepath): return [] R = [] drivelist = [] cnt = 0 dt = DateTime() dt.timer_start() with open(filepath, "rb") as FILE: # ################################## # read the header header = {} bin = FILE.read(8) key, val = struct.unpack("4sI", bin) while key != "SIZE" and bin: header[key] = val bin = FILE.read(8) if bin: key, val = struct.unpack("4sI", bin) # ################################## # process the header dictionary typ = header.get("LTYP", 0) # needed for restoring file paths blk = header.get("LBLK", 128) # not really needed fmt = header.get( "LFMT", Song.repr_length()) # needed to restore each song record. cnt = header.get("LCNT", 0) if typ & 2 == 2: drivelist = systemDriveList() # ################################## # now read the data from the file. bin = FILE.read(val) while bin: if typ & 1 == 0 and pylzma != None: #compression is only used when typ&1 == 0. bin = pylzma.decompress(bin) R += LIBZ_process_block(bin, typ, fmt, drivelist, srclib) bin = FILE.read(8) if bin: key, size = struct.unpack("4sI", bin) bin = FILE.read(size) # read val bytes from the frame dt.timer_end() print "Loaded %d/%d songs from libz container in %s" % ( len(R), cnt, DateTime.formatTimeDeltams(dt.timedelta)) return R
def _cpy_files(self): dt = DateTime(); r = len(self.listc) - 1 if r < 0: return True self.parent.emit(SIGNAL("SYNC_SET_RANGE"),self.parent,0,r) self.parent.emit(SIGNAL("SYNC_SET_VALUE"),self.parent,0) # ########################################################### # Copy Songs self.index = 0 rTime = 0 byteAvg = 0 time_remaining=0 stime = None dt.timer_start(); while self.alive and self.index < len(self.listc): free = driveGetFreeSpace(self.dir) MBfree = free[2] if MBfree < 75: self.alive = False print " *** Out Of Free Space. Error." break; createDirStructure(self.listc[self.index][1]) # ---------------------------------------------- s = "Copying %d/%d - %s - %d MB free" p = (self.index,len(self.listc),DateTime.formatTimeDeltams(time_remaining),MBfree) self.parent.emit(SIGNAL("SYNC_SET_TEXT"),self.parent,s%p) # ---------------------------------------------- bytes=0 try: src = self.listc[self.index][0] dst = self.listc[self.index][1] self.parent.debug("src:%s"%src); self.parent.debug("dst:%s"%dst); if os.path.exists(src) == False: self.parent.debug("Cannot Find Source File"); elif os.path.exists(dst) == False: #e32.file_copy(self.listc[self.index][0],self.listc[self.index][1]) bytes = os.path.getsize(self.listc[self.index][0]) #MpTest.fcopy(src,dst) PYCOPY (src, dst) #copy(self.listc[self.index][0],self.listc[self.index][1]) except: self.parent.debug( "*** ERROR: %s"%self.listc[self.index][1] ) # get the end time right before the next update dt.timer_end(); try: if bytes > 0: delta = dt.usdelta #print delta, float(delta)/bytes, bytes/delta delta = float(delta)/float(bytes) if rTime > 0: rTime = (rTime*9 + delta)/10 else: rTime = delta if byteAvg > 0: byteAvg = (byteAvg*9 + bytes)/10 else: byteAvg = bytes time_remaining = byteAvg*rTime #average microseconds per song time_remaining *= (r-self.index) # times the total songs remaining time_remaining /= 1000 # to milliseconds except: pass finally: dt.timer_start(); self.parent.emit(SIGNAL("UPDATE_SYNC_DIALOG"),self.parent,self.index) # get the next start time immediatley after updating. self.index += 1 self.parent.emit(SIGNAL("SYNC_SET_TEXT"),self.parent,"Copying - Done") return;
def _compileTerm(self,flag_type,flag,ostr): """ flag_type: either EXIF, ARTIST,PLAYCOUNT ETC flag : OR combination of SEARCH dir and mod. < <= >= > = and . + ! * ostr : relevant string term for a search of flag_type """ if ostr == "": return None ostr = unicode(ostr) cf = ostr[:] rf = None; fptr = None; if flag_type < EnumSong.STRINGTERM: fptr = self._compareTerm_String if (flag_type == EnumSong.SPEC_DATESTD ) : dt = DateTime(flag_type&0xF) cf = dt.getEpochTime(dt.repairDateTime(cf)) rf = cf + 24*60*60 if cf == 0: return None dt = DateTime(flag_type&0xF) ostr = dt.repairDateTime(ostr) if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT flag_type = EnumSong.DATESTAMP # change type to standard date format fptr = self._compareSongElement elif (flag_type == EnumSong.SPEC_DATEEU ) : dt = DateTime(flag_type&0xF) # set which format to use for dates, for help check the definition for SPEC_DATESTD, and the enumeration in DateTime cf = dt.getEpochTime(dt.repairDateTime(cf)) # autocomplete the entered date then convert to seconds rf = cf + 24*60*60 if cf == 0: return None dt = DateTime(flag_type&0xF) ostr = dt.repairDateTime(ostr) if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT flag_type = EnumSong.DATESTAMP # change type to standard date format fptr = self._compareSongElement elif (flag_type == EnumSong.SPEC_DATEUS ) : dt = DateTime(flag_type&0xF) cf = dt.getEpochTime(dt.repairDateTime(cf)) rf = cf + 24*60*60 if cf == 0: return None dt = DateTime(flag_type&0xF) ostr = dt.repairDateTime(ostr) if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT flag_type = EnumSong.DATESTAMP # change type to standard date format fptr = self._compareSongElement elif (flag_type == EnumSong.SPEC_MONTH ) : if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT flag_type = EnumSong.DATESTAMP cf = DateTime.now() try : cf -= 30*int(ostr)*24*60*60 rf = cf + 28*24*60*60 ostr = "month: %s"%ostr except: pass fptr = self._compareSongElement elif (flag_type == EnumSong.SPEC_WEEK ) : if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT flag_type = EnumSong.DATESTAMP cf = DateTime.now() try : cf -= 7*int(ostr)*24*60*60 rf = cf + 7*24*60*60 ostr = "week: %s"%ostr except: pass fptr = self._compareSongElement elif (flag_type == EnumSong.DATESTAMP) : if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT cf = DateTime.now() try : cf -= int(ostr)*24*60*60 rf = cf + 24*60*60 ostr = "day: %s"%ostr except: pass fptr = self._compareSongElement elif (flag_type == EnumSong.DATEADDED) : dt = DateTime(EnumSong.SPEC_DATESTD&0xF) cf = dt.getEpochTime(dt.repairDateTime(cf)) rf = cf + 24*60*60 if cf == 0: return None dt = DateTime(EnumSong.SPEC_DATESTD&0xF) ostr = dt.repairDateTime(ostr) if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.GT fptr = self._compareSongElement elif (flag_type == EnumSong.PATH ) : if cf == u"": return None rf = None fptr = self._compareSongElement elif flag_type >= EnumSong.STRINGTERM and flag_type < EnumSong.NUMTERM : if flag&SEARCH.DIR == 0:# if no DIR flags set, set EQ flag flag = flag|SEARCH.EQ try: cf = int(cf) except: cf = 0 return None rf = None # set the function to do the compare if flag_type == EnumSong.FREQUENCY: fptr = self._compareTerm_Frequency else: fptr = self._compareTerm_Number if flag_type == EnumSong.LENGTH: cf = DateTime.parseTimeDelta(ostr) term = SearchTerm(ostr,flag_type,flag,cf,rf,fptr) self.addTerm(flag&SEARCH.MOD,term)