diff --git a/Menu/GameShell/Music Player/mpd_spectrum_page.py b/Menu/GameShell/Music Player/mpd_spectrum_page.py index f544762..e86f403 100644 --- a/Menu/GameShell/Music Player/mpd_spectrum_page.py +++ b/Menu/GameShell/Music Player/mpd_spectrum_page.py @@ -3,7 +3,7 @@ import time import pygame -from numpy import fromstring,ceil,abs,log10,isnan,isinf,int16 +from numpy import fromstring,ceil,abs,log10,isnan,isinf,int16,sqrt,mean from numpy import fft as Fft import gobject @@ -11,12 +11,14 @@ import gobject from beeprint import pp ## local UI import -from UI.constants import Width,Height +from UI.constants import Width,Height,ICON_TYPES from UI.page import Page,PageSelector from UI.label import Label from UI.fonts import fonts from UI.util_funcs import midRect from UI.keys_def import CurKeys +from UI.icon_item import IconItem +from UI.icon_pool import MyIconPool from Queue import Queue, Empty from threading import Thread @@ -37,6 +39,9 @@ class PIFI(object): count = 0 average = 0 + + rmscount=0 + rmsaverage=0 def __init__(self): self.sampleSize = self._SAMPLE_SIZE @@ -54,7 +59,14 @@ class PIFI(object): def resetSmoothing(self): self.count = 0 self.average = 0 - + self.rmscount = 0 + self.rmsaverage = 0 + + def rms_smoothOut(self, x): + self.rmscount += 1 + self.rmsaverage = (self.rmsaverage*self.rmscount + x) / (self.rmscount+1) + return self.rmsaverage + def smoothOut(self, x): self.count += 1 self.average = (self.average*self.count + x) / (self.count+1) @@ -75,7 +87,8 @@ class PIFI(object): # Compute the scaled list of values scaledList = [int(x*scaleFactor) for x in _list ] return scaledList - + + def computeSpectrum(self, fifoFile): # Read PCM samples from fifo @@ -91,6 +104,17 @@ class PIFI(object): # Normalize [-1; +1] pcm = pcm / (2.**15) + + # Compute RMS directly from signal + rms = sqrt(mean(pcm**2)) + # Compute a simple 'moving maximum' + maximum = 2*self.rms_smoothOut(rms) + if maximum == 0: + scaleFactor = 0.0 + else: + scaleFactor = self._SCALE_WIDTH/float(maximum) + + final_rms = int(rms*scaleFactor) # Compute FFT N = pcm.size @@ -127,8 +151,8 @@ class PIFI(object): # Scale the spectrum scaledSpectrum = self.scaleList(spectrum) - - return (self.bins, scaledSpectrum) + scaledSpectrum.append( final_rms) + return scaledSpectrum class MPDSpectrumPage(Page): @@ -140,11 +164,28 @@ class MPDSpectrumPage(Page): _ListFont = fonts["veramono12"] _PIFI = None - _FiFo = None + _FIFO = None _Color = pygame.Color(126,206,244) _GobjectIntervalId = -1 _Queue = None _KeepReading = True + + _BGpng = None + _BGwidth = 320 + _BGheight = 200 + + _SheepHead = None + _SheepHeadW = 69 + _SheepHeadH = 66 + + _SheepBody = None + _SheepBodyW = 105 + _SheepBodyH = 81 + + _freq_count = 0 + _head_dir = 0 + + _Neighbor = None def __init__(self): Page.__init__(self) @@ -160,8 +201,27 @@ class MPDSpectrumPage(Page): self._CanvasHWND = self._Screen._CanvasHWND - self.Start() + self._BGpng = IconItem() + self._BGpng._ImgSurf = MyIconPool._Icons["sheep_bg"] + self._BGpng._MyType = ICON_TYPES["STAT"] + self._BGpng._Parent = self + self._BGpng.Adjust(0,0,self._BGwidth,self._BGheight,0) + + self._SheepHead = IconItem() + self._SheepHead._ImgSurf = MyIconPool._Icons["sheep_head"] + self._SheepHead._MyType = ICON_TYPES["STAT"] + self._SheepHead._Parent = self + self._SheepHead.Adjust(0,0,self._SheepHeadW,self._SheepHeadH,0) + + self._SheepBody = IconItem() + self._SheepBody._ImgSurf = MyIconPool._Icons["sheep_body"] + self._SheepBody._MyType = ICON_TYPES["STAT"] + self._SheepBody._Parent = self + self._SheepBody.Adjust(0,0,self._SheepBodyW,self._SheepBodyH,0) + + + self.Start() self._GobjectIntervalId = gobject.timeout_add(50,self.Playing) def Start(self): @@ -186,7 +246,7 @@ class MPDSpectrumPage(Page): print("self._FIFO none") return - (bins,scaledSpectrum) = self._PIFI.computeSpectrum(self._FIFO) + scaledSpectrum = self._PIFI.computeSpectrum(self._FIFO) self._Queue.put( scaledSpectrum ) self._KeepReading = False @@ -212,7 +272,9 @@ class MPDSpectrumPage(Page): return True def OnLoadCb(self): - + if self._FIFO == None: + self.Start() + if self._Queue != None: with self._Queue.mutex: self._Queue.queue.clear() @@ -228,6 +290,14 @@ class MPDSpectrumPage(Page): def KeyDown(self,event): if event.key == CurKeys["Menu"] or event.key == CurKeys["A"]: + if self._FIFO != None and self._FIFO.closed == False: + try: + self._FIFO.close() + self._FIFO = None + except Exception, e: + print(e) + + self.ReturnToUpLevelPage() self._Screen.Draw() self._Screen.SwapAndShow() @@ -239,22 +309,140 @@ class MPDSpectrumPage(Page): if event.key == CurKeys["Enter"]: pass + def Draw(self): + self.ClearCanvas() + self._BGpng.NewCoord(self._Width/2,self._Height/2) + self._BGpng.Draw() + +# print(self._Neighbor._CurSongTime) + + phrase1 = False + phrase2 = False + parts = self._Neighbor._CurSongTime.split(":") + if len(parts) > 1: + cur = float(parts[0]) + end = float(parts[1]) + pros = int((cur/end)*100.0) + + if pros > 30 and pros < 55: + phrase1 = True + if pros > 55 and pros < 100: + phrase2 = True + + + try: + spects = self._Queue.get_nowait() ## last element is rms + #print("get_nowait: " , spects) + except Empty: + return + else: # got line + if len(spects) == 0: + return + + rms = spects[-1] + ratio = float(rms)/float(self._Height) + # 139,62 + dx = 0 + if ratio < 0.5: + dx = 5 + else: + dx = 16 + self._freq_count+=1 ## like frames + + sheepbody_xy = (181,92) + sheephead_xy = (139,62) + sheepeye_xy = (129,60) ## eye2 ==> 129+20 + + eye_dx = sheephead_xy[0] - sheepeye_xy[0] + eye_dy = sheephead_xy[1] - sheepeye_xy[1] + + self._SheepBody.NewCoord(sheepbody_xy[0],sheepbody_xy[1]) + leg_dx = 2 + if self._freq_count % 2 == 0: + self._SheepHead.NewCoord(sheephead_xy[0]+dx, sheephead_xy[1]) + + elif self._freq_count % 3 == 0: + self._SheepHead.NewCoord(sheephead_xy[0]-dx, sheephead_xy[1]) + elif self._freq_count % 4 == 0: + self._SheepHead.NewCoord(sheephead_xy[0],sheephead_xy[1]+dx*2) + + elif self._freq_count % 5 == 0: + self._SheepBody.NewCoord(sheepbody_xy[0],sheepbody_xy[1]-dx*3) + self._SheepHead.NewCoord(sheephead_xy[0],sheephead_xy[1]-dx*3) + + elif self._freq_count % 7 == 0: + leg_dx = 0 + self._SheepBody.NewCoord(sheepbody_xy[0],sheepbody_xy[1]) + + + self._SheepBody.Draw() + self._SheepHead.Draw() + + ## eyes + pygame.draw.circle(self._CanvasHWND,(255,255,255),(self._SheepHead._PosX-eye_dx,self._SheepHead._PosY-eye_dy),8,0) + pygame.draw.circle(self._CanvasHWND,(0,0,0),(self._SheepHead._PosX-eye_dx,self._SheepHead._PosY-eye_dy),8,2) + + pygame.draw.circle(self._CanvasHWND,(0,0,0),(self._SheepHead._PosX-eye_dx,self._SheepHead._PosY-eye_dy),2,0) + + pygame.draw.circle(self._CanvasHWND,(255,255,255),(self._SheepHead._PosX-eye_dx+20,self._SheepHead._PosY-eye_dy),8,0) + pygame.draw.circle(self._CanvasHWND,(0,0,0),(self._SheepHead._PosX-eye_dx+20,self._SheepHead._PosY-eye_dy),8,2) + + pygame.draw.circle(self._CanvasHWND,(0,0,0),(self._SheepHead._PosX-eye_dx+20,self._SheepHead._PosY-eye_dy),2,0) + + ##legs + legs1_xy = (self._SheepBody._PosX+13,self._SheepBody._PosY+38) + legs1_xy_end = (legs1_xy[0],legs1_xy[1]+16) + + legs1_1_xy = (legs1_xy_end[0]-leg_dx,legs1_xy_end[1]) + legs1_1_xy_end = (legs1_1_xy[0],legs1_1_xy[1]+14) + + legs2_xy = (self._SheepBody._PosX+23,self._SheepBody._PosY+36) + legs2_xy_end = (legs2_xy[0],legs2_xy[1]+16) + + + legs3_xy = (self._SheepBody._PosX-23,self._SheepBody._PosY+38) + legs3_xy_end = (legs3_xy[0],legs3_xy[1]+16) + + legs4_xy = (self._SheepBody._PosX-33,self._SheepBody._PosY+26) + legs4_xy_end = (legs4_xy[0],legs4_xy[1]+22) + + legs4_1_xy = (legs4_xy_end[0]-leg_dx,legs4_xy_end[1]) + legs4_1_xy_end = (legs4_1_xy[0],legs4_1_xy[1]+14) + + + pygame.draw.line(self._CanvasHWND,(0,0,0), legs1_xy,legs1_xy_end,4) + pygame.draw.line(self._CanvasHWND,(0,0,0), legs2_xy,legs2_xy_end,4) + + pygame.draw.line(self._CanvasHWND,(0,0,0), legs3_xy,legs3_xy_end,4) + pygame.draw.line(self._CanvasHWND,(0,0,0), legs4_xy,legs4_xy_end,4) + + pygame.draw.line(self._CanvasHWND,(0,0,0), legs1_1_xy,legs1_1_xy_end,4) + + pygame.draw.line(self._CanvasHWND,(0,0,0), legs4_1_xy,legs4_1_xy_end,4) + + + + +""" def Draw(self): self.ClearCanvas() bw = 10 spects = None try: - spects = self._Queue.get_nowait() + spects = self._Queue.get_nowait() ## last element is rms # print("get_nowait: " , spects) except Empty: return else: # got line if len(spects) == 0: return - w = self._Width / len(spects) + w = self._Width / len( spects[0:-1] ) left_margin = (w-bw)/2 - for i,v in enumerate(spects): + for i,v in enumerate(spects[0:-1]): pygame.draw.rect(self._CanvasHWND,self._Color,(i*w+left_margin,self._Height-v,bw,v),0) +""" + + diff --git a/Menu/GameShell/Music Player/play_list_page.py b/Menu/GameShell/Music Player/play_list_page.py index a8334c6..308a888 100644 --- a/Menu/GameShell/Music Player/play_list_page.py +++ b/Menu/GameShell/Music Player/play_list_page.py @@ -64,6 +64,7 @@ class PlayListPage(Page): _ListFont = fonts["notosanscjk15"] _Scroller = None + _CurSongTime="0:0" _BGpng = None _BGwidth = 75 @@ -110,12 +111,13 @@ class PlayListPage(Page): self.SyncPlaying() - def GObjectInterval(self): ## 250 ms + def GObjectInterval(self): ## 250 ms + self.SyncPlaying() + if self._Screen.CurPage() == self: - self.SyncPlaying() self._Screen.Draw() self._Screen.SwapAndShow() - + return True def SyncPlaying(self): @@ -138,13 +140,14 @@ class PlayListPage(Page): else: self._MyList[posid]._Playing = True if "time" in current_song: + self._CurSongTime = current_song["time"] times_ = current_song["time"].split(":") if len(times_)> 1: cur = float(times_[0]) end = float(times_[1]) pros = int((cur/end)*100.0) self._MyList[posid]._PlayingProcess = pros - + def InPlayList(self,path): for i,v in enumerate(self._MyList): @@ -271,6 +274,7 @@ class PlayListPage(Page): self.Click() if event.key == CurKeys["Start"]: # start spectrum + myvars.SpectrumPage._Neighbor = self self._Screen.PushPage(myvars.SpectrumPage) self._Screen.Draw() self._Screen.SwapAndShow() diff --git a/skin/default/sys.py/gameshell/icons/sheep_bg.png b/skin/default/sys.py/gameshell/icons/sheep_bg.png new file mode 100644 index 0000000..f373475 Binary files /dev/null and b/skin/default/sys.py/gameshell/icons/sheep_bg.png differ diff --git a/skin/default/sys.py/gameshell/icons/sheep_body.png b/skin/default/sys.py/gameshell/icons/sheep_body.png new file mode 100644 index 0000000..148ff46 Binary files /dev/null and b/skin/default/sys.py/gameshell/icons/sheep_body.png differ diff --git a/skin/default/sys.py/gameshell/icons/sheep_head.png b/skin/default/sys.py/gameshell/icons/sheep_head.png new file mode 100644 index 0000000..615246b Binary files /dev/null and b/skin/default/sys.py/gameshell/icons/sheep_head.png differ