source: src/mlx/sound.py@ 133:dcbe33497899

Last change on this file since 133:dcbe33497899 was 133:dcbe33497899, checked in by István Váradi <ivaradi@…>, 12 years ago

The general message sending works and the most important messages are sent

File size: 6.3 KB
RevLine 
[133]1# Module to handle sound playback
2
3#------------------------------------------------------------------------------
4
5import os
6
7#------------------------------------------------------------------------------
8
9if os.name=="nt":
10 import time
11 import threading
12 from ctypes import windll, c_buffer
13
14 class MCIException(Exception):
15 """MCI exception."""
16 def __init__(self, mci, command, errorCode):
17 """Construct an MCI exception for the given error code."""
18 message = "MCI error: %s: %s" % (command, mci.getErrorString(errorCode))
19 super(MCIException, self).__init__(message)
20
21 class MCI:
22 """Interface for the Media Control Interface."""
23 def __init__(self):
24 """Construct the interface."""
25 self.w32mci = windll.winmm.mciSendStringA
26 self.w32mcierror = windll.winmm.mciGetErrorStringA
27
28 def send(self, command):
29 """Send the given command to the MCI."""
30 buffer = c_buffer(255)
31 errorCode = self.w32mci(str(command), buffer, 254, 0)
32 if errorCode:
33 raise MCIException(self, command, errorCode)
34 else:
35 return buffer.value
36
37 def getErrorString(self, errorCode):
38 """Get the string representation of the given error code."""
39 buffer = c_buffer(255)
40 self.w32mcierror(int(errorCode), buffer, 254)
41 return buffer.value
42
43 class SoundThread(threading.Thread):
44 """The thread controlling the playback of sounds."""
45 def __init__(self, soundsDirectory):
46 threading.Thread.__init__(self)
47
48 self._soundsDirectory = soundsDirectory
49 self._mci = MCI()
50
51 self._requestCondition = threading.Condition()
52 self._requestedPaths = []
53 self._pendingAliases = []
54 self._count = 0
55
56 self.daemon = True
57
58 def requestSound(self, name):
59 """Request the playback of the sound with the given name."""
60 path = os.path.join(self._soundsDirectory, name)
61 with self._requestCondition:
62 self._requestedPaths.append(path)
63 self._requestCondition.notify()
64
65 def run(self):
66 """Perform the operation of the thread.
67
68 It waits for a request or a timeout. If a request is received, that
69 is started to be played back. If a timeout occurs, the file is
70 closed."""
71
72 while True:
73 with self._requestCondition:
74 if not self._requestedPaths:
75 if self._pendingAliases:
76 timeout = max(time.time() -
77 self._pendingAliases[0][0], 0.0)
78 else:
79 timeout = 10.0
80
81 self._requestCondition.wait(timeout)
82
83 requestedPaths = []
84 for path in self._requestedPaths:
85 requestedPaths.append((path, self._count))
86 self._count += 1
87 self._requestedPaths = []
88
89 now = time.time()
90 aliasesToClose = []
91 while self._pendingAliases and \
92 self._pendingAliases[0][0]<=now:
93 aliasesToClose.append(self._pendingAliases[0][1])
94 del self._pendingAliases[0]
95
96 for alias in aliasesToClose:
97 try:
98 print "Closing", alias
99 self._mci.send("close " + alias)
100 print "Closed", alias
101 except Exception, e:
102 print "Failed closing " + alias + ":", str(e)
103
104 for (path, counter) in requestedPaths:
105 try:
106 alias = "mlxsound%d" % (counter,)
107 print "Starting to play", path, "as", alias
108 self._mci.send("open \"%s\" alias %s" % \
109 (path, alias))
110 self._mci.send("set %s time format milliseconds" % \
111 (alias,))
112 lengthBuffer = self._mci.send("status %s length" % \
113 (alias,))
114 self._mci.send("play %s from 0 to %s" % \
115 (alias, lengthBuffer))
116 length = int(lengthBuffer)
117 timeout = time.time() + length / 1000.0
118 with self._requestCondition:
119 self._pendingAliases.append((timeout, alias))
120 self._pendingAliases.sort()
121 print "Started to play", path
122 except Exception, e:
123 print "Failed to start playing " + path + ":", str(e)
124
125 _thread = None
126
127 def initializeSound(soundsDirectory):
128 """Initialize the sound handling with the given directory containing
129 the sound files."""
130 global _thread
131 _thread = SoundThread(soundsDirectory)
132 _thread.start()
133
134 def startSound(name):
135 """Start playing back the given sound.
136
137 name should be the name of a sound file relative to the sound directory
138 given in initializeSound."""
139 _thread.requestSound(name)
140
141#------------------------------------------------------------------------------
142
143else: # os.name!="nt"
144 def initializeSound(soundsDirectory):
145 """Initialize the sound handling with the given directory containing
146 the sound files."""
147 pass
148
149 def startSound(name):
150 """Start playing back the given sound.
151
152 FIXME: it does not do anything currently, but it should."""
153 pass
154
155#------------------------------------------------------------------------------
156#------------------------------------------------------------------------------
157
158if __name__ == "__main__":
159 initializeSound("e:\\home\\vi\\tmp")
160 startSound("malev.mp3")
161 time.sleep(5)
162 startSound("ding.wav")
163 time.sleep(5)
164 startSound("ding.wav")
165 time.sleep(5)
166 startSound("ding.wav")
167 time.sleep(50)
168
169#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.