#appModules/winamp.py #A part of NonVisual Desktop Access (NVDA) #Copyright (C) 2006-2012 NVDA Contributors #This file is covered by the GNU General Public License. #See the file COPYING for more details. from ctypes import * from ctypes.wintypes import * import winKernel import winUser from scriptHandler import isScriptWaiting from NVDAObjects.IAccessible import IAccessible import appModuleHandler import speech import locale import controlTypes import api import watchdog import braille import ui # message used to sent many messages to winamp's main window. # most all of the IPC_* messages involve sending the message in the form of: # result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*); WM_WA_IPC=winUser.WM_USER # winamp window IPC_GET_SHUFFLE=250 IPC_GET_REPEAT=251 # playlist editor IPC_PLAYLIST_GET_NEXT_SELECTED=3029 IPC_PE_GETCURINDEX=100 IPC_PE_GETINDEXTOTAL=101 # in_process ONLY IPC_PE_GETINDEXTITLE=200 # lParam = pointer to fileinfo2 structure class fileinfo2(Structure): _fields_=[ ('fileindex',c_int), ('filetitle',c_char*256), ('filelength',c_char*16), ] hwndWinamp=0 def getShuffle(): global hwndWinamp return watchdog.cancellableSendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_SHUFFLE) def getRepeat(): global hwndWinamp return watchdog.cancellableSendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_REPEAT) class AppModule(appModuleHandler.AppModule): def event_NVDAObject_init(self,obj): global hwndWinamp hwndWinamp=windll.user32.FindWindowA("Winamp v1.x",None) def chooseNVDAObjectOverlayClasses(self, obj, clsList): windowClass = obj.windowClassName if windowClass == "Winamp PE": clsList.insert(0, winampPlaylistEditor) elif windowClass == "Winamp v1.x": clsList.insert(0, winampMainWindow) class winampMainWindow(IAccessible): def event_nameChange(self): pass def script_shuffleToggle(self,gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if getShuffle(): # Translators: the user has pressed the shuffle tracks toggle in winamp, shuffle is now on. onOff=pgettext("shuffle", "on") else: # Translators: the user has pressed the shuffle tracks toggle in winamp, shuffle is now off. onOff=pgettext("shuffle", "off") ui.message(onOff) def script_repeatToggle(self,gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if getRepeat(): # Translators: the user has pressed the repeat track toggle in winamp, repeat is now on. onOff=pgettext("repeat", "on") else: # Translators: the user has pressed the repeat track toggle in winamp, repeat is now off. onOff=pgettext("repeat", "off") ui.message(onOff) __gestures = { "kb:s": "shuffleToggle", "kb:r": "repeatToggle", } class winampPlaylistEditor(winampMainWindow): def _get_name(self): curIndex=watchdog.cancellableSendMessage(hwndWinamp,WM_WA_IPC,-1,IPC_PLAYLIST_GET_NEXT_SELECTED) if curIndex <0: return None info=fileinfo2() info.fileindex=curIndex internalInfo=winKernel.virtualAllocEx(self.processHandle,None,sizeof(info),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) try: winKernel.writeProcessMemory(self.processHandle,internalInfo,byref(info),sizeof(info),None) watchdog.cancellableSendMessage(self.windowHandle,WM_WA_IPC,IPC_PE_GETINDEXTITLE,internalInfo) winKernel.readProcessMemory(self.processHandle,internalInfo,byref(info),sizeof(info),None) finally: winKernel.virtualFreeEx(self.processHandle,internalInfo,0,winKernel.MEM_RELEASE) return unicode("%d.\t%s\t%s"%(curIndex+1,info.filetitle,info.filelength), errors="replace", encoding=locale.getlocale()[1]) def _get_role(self): return controlTypes.ROLE_LISTITEM def script_changeItem(self,gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() speech.speakObject(self,reason=controlTypes.REASON_FOCUS) braille.handler.handleGainFocus(self) def event_nameChange(self): return super(winampMainWindow,self).event_nameChange() __changeItemGestures = ( "kb:upArrow", "kb:downArrow", "kb:pageUp", "kb:pageDown", ) def initOverlayClass(self): for gesture in self.__changeItemGestures: self.bindGesture(gesture, "changeItem")