This repository was archived by the owner on Jan 9, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathwinamp.py
230 lines (197 loc) · 7.03 KB
/
winamp.py
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
###########################################################
# winamp.py
# Python Winamp Controller
#
# Version 1.1 21-Oct-2006 minor bugfix
# Version 1.0, 1-Feb-2001
#
# About:
# Class to control running instance
# or Winamp mp3 player on current
# machine.
#
# Requirements:
# Winamp and Win32 (of course).
# ActivePython or Win32 Python extensions.
# Tested with Winamp 2.71 and ActivePython 2.0
# on WinNT4.
#
# Usage:
# Copy this file anywhere in your
# pythonpath.
# Create an instance of winamp class
# and call methods on it to control
# a running winamp program on current
# machine.
#
# Example:
# >>> import winamp
# >>> w = winamp.Winamp()
# >>> w.getPlayingStatus()
# 'stopped'
# >>> w.play()
# >>> w.getPlayingStatus()
# 'playing'
# >>>
#
# Uses the winamp api http://www.winamp.com
# /nsdn/winamp2x/dev/sdk/api.jhtml
# and windows messaging to control winamp.
#
#
# Copyright (c) 2001-2006, Shalabh Chaturvedi
#
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the
# Software without restriction, including without
# limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software
# is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice
# shall be included in all copies or substantial portions
# of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
###########################################################
import wa_ipc as ipc
import argparse
import sys
import win32api
import win32gui
# wonder why win32 imports dont define these
WM_COMMAND = 0x0111
WM_USER = 0x400
class NoWinampOpened(Exception):
pass
class Winamp:
COMMANDS = {
"prev": ipc.WINAMP_BUTTON1,
"next": ipc.WINAMP_BUTTON5,
"play": ipc.WINAMP_BUTTON2,
"pause": ipc.WINAMP_BUTTON3,
"stop": ipc.WINAMP_BUTTON4,
"fadeout": ipc.WINAMP_BUTTON4_CTRL,
"forward": ipc.WINAMP_BUTTON5_SHIFT,
"rewind": ipc.WINAMP_BUTTON1_SHIFT,
"raisevol": ipc.WINAMP_VOLUMEUP,
"lowervol": ipc.WINAMP_VOLUMEDOWN,
}
def __init__(self):
self.hWinamp = win32gui.FindWindow("Winamp v1.x", None)
if self.hWinamp is 0:
raise NoWinampOpened()
iVersionNumber = self.usercommand(0)
sVersionString = hex(iVersionNumber)
sVersionString = sVersionString[2:3] + "." + sVersionString[3:]
self.sVersion = sVersionString
def command(self, sCommand):
if sCommand in Winamp.COMMANDS:
return win32api.SendMessage(
self.hWinamp, WM_COMMAND, Winamp.COMMANDS[sCommand], 0
)
else:
raise Exception("NoSuchWinampCommand")
def __getattr__(self, attr):
self.command(attr)
return lambda: None
def usercommand(self, id, data=0):
return win32api.SendMessage(self.hWinamp, WM_USER, data, id)
def getVersion(self):
"""Returns the version number of Winamp"""
return self.sVersion
def getPlayingStatus(self):
"""Returns the current status string which is one of
'playing', 'paused' or 'stopped'"""
iStatus = self.usercommand(ipc.IPC_ISPLAYING)
if iStatus == 1:
return "playing"
elif iStatus == 3:
return "paused"
else:
return "stopped"
def getTrackStatus(self):
"""Returns a tuple (total_length, current_position) where both are in msecs"""
# the usercommand returns the number in seconds:
iTotalLength = self.usercommand(ipc.IPC_GETOUTPUTTIME, 1) * 1000
iCurrentPos = self.usercommand(ipc.IPC_GETOUTPUTTIME, 0)
return iTotalLength, iCurrentPos
def setCurrentTrack(self, iTrackNumber):
"""Changes the track selection to the number specified"""
return self.usercommand(ipc.IPC_SETPLAYLISTPOS, iTrackNumber)
def getCurrentTrack(self):
return self.usercommand(ipc.IPC_GETLISTPOS)
def getCurrentTrackName(self):
return win32gui.GetWindowText(self.hWinamp)
def seekWithinTrack(self, iPositionMsecs):
"""Seeks within currently playing track to specified milliseconds since start"""
return self.usercommand(ipc.IPC_JUMPTOTIME, iPositionMsecs)
def setVolume(self, iVolumeLevel):
"""Sets the volume to number specified (range is 0 to 255)"""
return self.usercommand(ipc.IPC_SETVOLUME, iVolumeLevel)
def getNumTracks(self):
"""Returns number of tracks in current playlist"""
return self.usercommand(ipc.IPC_GETLISTLENGTH)
def getTrackInfo(self):
"""Returns a tuple (samplerate, bitrate, number of channels)"""
iSampleRate = self.usercommand(ipc.IPC_GETINFO, 0)
iBitRate = self.usercommand(ipc.IPC_GETINFO, 1)
iNumChannels = self.usercommand(ipc.IPC_GETINFO, 2)
return iSampleRate, iBitRate, iNumChannels
def dumpList(self):
"""Dumps the current playlist into WINAMPDIR/winamp.m3u"""
return self.usercommand(ipc.IPC_WRITEPLAYLIST)
def getTrackList(sPlaylistFilepath):
playlist = []
with open(sPlaylistFilepath, "r") as playlistfile:
for line in playlistfile.readlines():
if line.startswith("#"):
continue
playlist.append(line.strip())
return playlist
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Winamp control",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("command", nargs="?", default="status", help="Command")
parser.add_argument("subcommand", nargs="?", help="Sub-command")
args = parser.parse_args()
try:
w = Winamp()
except NoWinampOpened:
sys.stderr.write("Winamp not open.\n")
sys.exit(1)
if args.command == "status":
# state = w.getPlayingStatus()
# print(state)
print(w.getCurrentTrackName())
# if state == "playing":
elif args.command == "vol":
if args.subcommand == "up":
# TODO: increase volume by 10%
w.command("raisevol")
elif args.subcommand == "down":
# TODO: decrease volume by 10%
w.command("lowervol")
elif args.subcommand:
print(args.subcommand)
# scale volume 0-100 to 0-255
newvol = float(args.subcommand) * 255 / 100
print(newvol)
w.setVolume(newvol)
elif args.command:
w.command(args.command)
# End of file