winamp.py
4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#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")