Пример #1
0
def getSelection(unselect = True):
    # return an array of all selected elements, and unselect by default
    # these elements
    if MpGlobal.Player.selCount == 0 :
        return []
    R = [[]]*MpGlobal.Player.selCount
    i = 0;
    time = DateTime.now() - 60*60*24
    for song in MpGlobal.Player.library:
        if song[MpMusic.SELECTED] and not song.banish :
        
            if MpGlobal.PLAYLIST_SKIP_RECENT and song[MpMusic.DATEVALUE] >= time:
                # if skip recent is enabled remove them from the selection.
                    song[MpMusic.SELECTED] = False
                    MpGlobal.Player.selCount -= 1
            else:    
                R[i] = song
                i += 1

                if unselect :
                    song[MpMusic.SELECTED] = False
                    MpGlobal.Player.selCount -= 1
                
    MpGlobal.Window.emit(SIGNAL("UPDATE_STATUSBAR"),0,MpGlobal.Player.selCount)
    
    MpGlobal.PLAYLIST_SKIP_RECENT = False
    
    return R[:i]
Пример #2
0
def getSelection(unselect=True):
    # return an array of all selected elements, and unselect by default
    # these elements
    if MpGlobal.Player.selCount == 0:
        return []
    R = [[]] * MpGlobal.Player.selCount
    i = 0
    time = DateTime.now() - 60 * 60 * 24
    for song in MpGlobal.Player.library:
        if song[MpMusic.SELECTED] and not song.banish:

            if MpGlobal.PLAYLIST_SKIP_RECENT and song[
                    MpMusic.DATEVALUE] >= time:
                # if skip recent is enabled remove them from the selection.
                song[MpMusic.SELECTED] = False
                MpGlobal.Player.selCount -= 1
            else:
                R[i] = song
                i += 1

                if unselect:
                    song[MpMusic.SELECTED] = False
                    MpGlobal.Player.selCount -= 1

    MpGlobal.Window.emit(SIGNAL("UPDATE_STATUSBAR"), 0,
                         MpGlobal.Player.selCount)

    MpGlobal.PLAYLIST_SKIP_RECENT = False

    return R[:i]
Пример #3
0
def testbench_build_library():
    library = []
    time = DateTime.now()
    for i in range(30):
        song=Song("C:/Folder%d/Artist%d/Title%d.mp3"%(i,i,i))
        song[MpMusic.ARTIST]    = u"%dArtist The Band"%(i%10) # id will have 10 different A,B,T
        song[MpMusic.TITLE]     = u"%dTitle of The Song"%(i%10)  
        song[MpMusic.ALBUM]     = u"%dMonthly Album"%(i%10) 
        song[MpMusic.GENRE]     = (u"ROCK",u"POP","ALT")[(i%3)]
        song[MpMusic.DATEVALUE] = time - (60*60*24*i)# each song is one day older
        song[MpMusic.DATESTAMP] = DateTime.formatDateTime(song[MusicContainer.DATEVALUE])
        song[MpMusic.COMMENT]   = ""
        song[MpMusic.RATING]    = i%6   # in 30 songs, 5 of each rating value
        song[MpMusic.LENGTH]    = 15*i
        song[MpMusic.SONGINDEX] = 0
        song[MpMusic.PLAYCOUNT] = i
        song[MpMusic.SKIPCOUNT] = i
        song[MpMusic.FILESIZE]  = 0
        song[MpMusic.FREQUENCY] = 2*i
        song[MpMusic.BITRATE]   = 0
        song[MpMusic.SPECIAL]   = False
        song[MpMusic.SELECTED]  = False
        
        song.update()

        library.append(song)
    return library;
Пример #4
0
def testbench_build_library():
    library = []
    time = DateTime.now()
    for i in range(30):
        song = Song("C:/Folder%d/Artist%d/Title%d.mp3" % (i, i, i))
        song[MpMusic.ARTIST] = u"%dArtist The Band" % (
            i % 10)  # id will have 10 different A,B,T
        song[MpMusic.TITLE] = u"%dTitle of The Song" % (i % 10)
        song[MpMusic.ALBUM] = u"%dMonthly Album" % (i % 10)
        song[MpMusic.GENRE] = (u"ROCK", u"POP", "ALT")[(i % 3)]
        song[MpMusic.DATEVALUE] = time - (60 * 60 * 24 * i
                                          )  # each song is one day older
        song[MpMusic.DATESTAMP] = DateTime.formatDateTime(
            song[MusicContainer.DATEVALUE])
        song[MpMusic.COMMENT] = ""
        song[MpMusic.RATING] = i % 6  # in 30 songs, 5 of each rating value
        song[MpMusic.LENGTH] = 15 * i
        song[MpMusic.SONGINDEX] = 0
        song[MpMusic.PLAYCOUNT] = i
        song[MpMusic.SKIPCOUNT] = i
        song[MpMusic.FILESIZE] = 0
        song[MpMusic.FREQUENCY] = 2 * i
        song[MpMusic.BITRATE] = 0
        song[MpMusic.SPECIAL] = False
        song[MpMusic.SELECTED] = False

        song.update()

        library.append(song)
    return library
Пример #5
0
    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"))
Пример #6
0
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 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
Пример #8
0
    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
Пример #9
0
    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)
Пример #10
0
    def compile(self,string):
        """
            Dot Words
            
            
            \\<table\\>
            \\<b\\>Dot Word\\</b\\> | \\<b\\>Field\\</b\\> | \\<b\\>Description\\</b\\>
            
            \\<b\\>Text Info\\</b\\>
            .alb .abm .album | Album | Search by album info.
            .art .artist     | Artist | Search by artist info.
            .comm .comment   | Comment | Search by user set comments.
            .gen .genre      | Genre | Search by the songs genre.
            .path            | Path  | Search by the file path.
            .ttl .tit .title | Title | Search by song title.
            
            \\<b\\>Numerical\\</b\\>
            .freq            | Frequency | Search by the average number of days between song plays.
            .pcnt .playcount | Play Count | Search by the playcount 
            .scnt .skipcount | Skip Count | Search by the skipcount 
            .size            | File Size | Search by file size, in KB.
            .rte .rating     | Rating | Search by the song rating, 0-5.
            \\</table\\>
            \\<table\\>
            \\<b\\>Advanced\\</b\\> | \\<b\\>Format\\</b\\> | \\<b\\>Description\\</b\\>
            .day        | number     | By number of days since last playing.
            .week       | number     | By number of weeks since last playing.
            .month      | number     | By number of months since last playing.
            .date       | YYYY/MM/DD | enter a specific date to search by. formatted by year-month-day
            .dateUS     | MM/DD/YYYY | see date. American date format
            .dateEU     | DD/MM/YYYY | see date. Sane people format.
            
            \\<b\\>Special\\</b\\>
            .sel | Selected | Display songs from the selection pool
            .preset # |  | This text is replaced with the text found in the given preset.
            .favorite | | Expands to a OR list of favorite artists. Set your favorite artists by right clicking their name in the Quick Selection tab
            \\</table\\>
            
        """
        # # 
        # #     given a unicode string formatted as a search string, parse, set the 3 tupples for this object
        # #     Parameters:
        # #         str: a user input str
        # # there are three types of searchs to perform
        # # "c" or contains    : target must contain any of these elements 
        # # "o" or boolean or  : target must contain at least one of these elements
        # # "n" or boolean not : target must contain none of these elements
        # # 
        # # format:
        # #   The following will be considered one search 'field':
        # # [.param] [.+!] [dir] term [ [.+!] [dir] term2 ...] [,;] ...
        # # where :
        # #   .param : search type, eg .date, defaults to .exif when not included
        # #   .+!    : AND,OR,NOT include the following term in search results
        # #   dir    : <=,<,=,>,=> can be used to specify comparison direction
        # #   term * : only mandatory string term, this will be compared against each song              
        # #   ,;     : these optionally end a field 
        # #            if multiply fields are wanted, they must be separated by a comma or semicolon
        # # 
        self._original = unicode(string) # create a copy of the string

        self._searchC = []
        self._searchO = []
        self._searchN = []
        self._searchX = [[]]
        
        self.termCount = 0;
                
        fflag = {
                '<' : SEARCH.LT,
                '=' : SEARCH.EQ,
                '>' : SEARCH.GT,
            }
                    
        ftype = {
                '.' : 0,
                '+' : SEARCH.OR,
                '!' : SEARCH.NT,
                '*' : SEARCH.IO,
            } 
        
        #expand preset modifiers into their expressions
        for i in range(10):
            string = self._expand_preset(string,i)
        # expand favorite modifier
        if string[1:].find("favorite") >= 0:
            result = ".art +"
            if string[0] == "*":
                result = ".art *"
            for art in SearchObject_Controller.getFavoriteArtistList():
                if len(art) > 0:
                    result += u" \"%s\""%(art)
            result += ';'
            string = string[1:].replace("favorite",result,1);
        
        # ########################################################
        # Begin Parsing User Input
         # quote first to protect anything the user wants protected.
        string = self.q.quote(string.lower())

        # split the user input string into frames
        R = stringSplit(string,",;")

        # for each field in the string break into terms
        for x in range(len(R)):
            field = R[x]            # the field is the entire string seperated by ;
            temp = field.split()
            if (len(temp) > 0):
                dword = temp[0]    # the dot word will be the first word prepended with a sigil
            else:
                continue;
            frame = field.replace(dword,"",1).strip()   # frame is everything but the dword
            key=""
            sigil = dword[0];
            sigil_type = ftype.get(sigil,0) # integer translation of the sigil
            
            if not dword[0].isalpha():
                key   = dword[1:]       #the dword with the sigil removed
           
            flag_type = EnumSong.EXIF
            
      
            if key == "sel":
                term = SearchTerm(dword,EnumSong.SELECTED,0,None,None,self._compareSongElement) 
                self.addTerm(sigil_type,term)
                continue
            elif key == "spec":
                term = SearchTerm(dword,EnumSong.SPECIAL,0,None,None,self._compareSongElement)
                self.addTerm(sigil_type,term)
                continue
            elif key == "ban" or key == 'banish':
                term = SearchTerm(dword,EnumSong.BANISH,0,None,None,self._compareSongElement)
                self.addTerm(sigil_type,term)
                continue
            elif key[:4] == "freq" and key[4:5] in "<=>" and key[4:5] != "": # a slice never throws an exception, but can return empty
                # allow $freqX , where X is <=>,
                fdict = {
                    '<' : EnumSong.SPEC_FREQ_L,
                    '=' : EnumSong.SPEC_FREQ_E,
                    '>' : EnumSong.SPEC_FREQ_G,
                }
                flag = fflag.get(key[4],0)|sigil_type          
                term = SearchTerm(key,fdict[key[4]],flag,DateTime.now(),None,self._compareSongElement)
                self.addTerm(sigil_type,term)
                continue
            else: # get key or return the default value
                flag_type = SearchObject_Controller.getSearchDictionary().get(key,flag_type)
                
            #print flag_type,frame
            if flag_type == EnumSong.EXIF:
                self._parseFrame(flag_type,field)
            else:
                self._parseFrame(flag_type,frame)
            #self._addTerms(flag_type,frame,S)

        self.termCount = len(self._searchC)+len(self._searchO)+len(self._searchN)
        for lst in self._searchX:
            self.termCount += len(lst)