diff -r bf6f306ad5cf Lib/test/test_winsound.py --- a/Lib/test/test_winsound.py Thu Feb 09 18:27:48 2012 +0800 +++ b/Lib/test/test_winsound.py Thu Feb 09 15:42:43 2012 -0500 @@ -11,6 +11,15 @@ ctypes = support.import_module('ctypes') import winreg + +def lookup_sound(sound): + """Return the WAV file configured to play for a sound.""" + key = winreg.OpenKeyEx( + winreg.HKEY_CURRENT_USER, + "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) + return winreg.ExpandEnvironmentStrings(winreg.EnumValue(key, 0)[1]) + + def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: @@ -19,10 +28,7 @@ if ctypes.windll.winmm.mixerGetNumDevs() is 0: return False - key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, - "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) - value = winreg.EnumValue(key, 0)[1] - if value is not "": + if lookup_sound(sound) != "": return True else: return False @@ -102,6 +108,16 @@ winsound.PlaySound, "none", winsound.SND_ASYNC | winsound.SND_MEMORY ) + self.assertRaises( + TypeError, + winsound.PlaySound, + 'bad', winsound.SND_MEMORY + ) + self.assertRaises( + TypeError, + winsound.PlaySound, + b'bad', 0 + ) @unittest.skipUnless(has_sound("SystemAsterisk"), "No default SystemAsterisk") @@ -225,6 +241,14 @@ # does not raise on systems without a sound card. pass + @unittest.skipUnless(has_sound("SystemAsterisk"), + "No default SystemAsterisk") + def test_memory(self): + if _have_soundcard(): + with open(lookup_sound('SystemAsterisk'), 'rb') as sound: + winsound.PlaySound(sound.read(), winsound.SND_MEMORY) + + def _get_cscript_path(): """Return the full path to cscript.exe or None.""" diff -r bf6f306ad5cf Misc/ACKS --- a/Misc/ACKS Thu Feb 09 18:27:48 2012 +0800 +++ b/Misc/ACKS Thu Feb 09 15:42:43 2012 -0500 @@ -594,6 +594,7 @@ Marc-Andre Lemburg John Lenton Christopher Tur Lesniewski-Laas +Tim Lesher Alain Leufroy Mark Levinson William Lewis diff -r bf6f306ad5cf Misc/NEWS --- a/Misc/NEWS Thu Feb 09 18:27:48 2012 +0800 +++ b/Misc/NEWS Thu Feb 09 15:42:43 2012 -0500 @@ -7588,6 +7588,8 @@ - Issue #5228: Make functools.partial objects can now be pickled. +- Issue #11620: Fix the SND_MEMORY flag for winsound.PlaySound. + Tests ----- diff -r bf6f306ad5cf PC/winsound.c --- a/PC/winsound.c Thu Feb 09 18:27:48 2012 +0800 +++ b/PC/winsound.c Thu Feb 09 15:42:43 2012 -0500 @@ -72,20 +72,55 @@ static PyObject * sound_playsound(PyObject *s, PyObject *args) { + PyObject* sound; + Py_buffer view; wchar_t *wsound; int flags; int ok; - if (PyArg_ParseTuple(args, "Zi:PlaySound", &wsound, &flags)) { - if (flags & SND_ASYNC && flags & SND_MEMORY) { - /* Sidestep reference counting headache; unfortunately this also - prevent SND_LOOP from memory. */ - PyErr_SetString(PyExc_RuntimeError, "Cannot play asynchronously from memory"); - return NULL; + view.buf = 0; + if (PyArg_ParseTuple(args, "Oi:PlaySound", &sound, &flags)) { + if (sound == Py_None) { + /* Stop currently-playing waveform sound */ + wsound = NULL; } + else if (flags & SND_MEMORY) { + /* Playing from memory--sound must be a buffer object */ + Py_buffer view; + if (flags & SND_ASYNC) { + /* Sidestep reference counting headache; unfortunately + this also prevent SND_LOOP from memory. */ + PyErr_SetString(PyExc_RuntimeError, + "Cannot play asynchronously from memory"); + return NULL; + } + + if (PyObject_GetBuffer(sound, &view, PyBUF_SIMPLE) < 0) { + return NULL; + } + wsound = (wchar_t*) view.buf; + } + else { + /* Playing from alias or filename--sound must be a string */ + if (!PyUnicode_Check(sound)) { + PyErr_SetString(PyExc_TypeError, + "Sound must be str or None."); + return NULL; + } + else { + wsound = PyUnicode_AS_UNICODE(sound); + if (!wsound) { + return NULL; + } + } + } + Py_BEGIN_ALLOW_THREADS ok = PlaySoundW(wsound, NULL, flags); Py_END_ALLOW_THREADS + + if (view.buf) + PyBuffer_Release(&view); if (!ok) { PyErr_SetString(PyExc_RuntimeError, "Failed to play sound"); return NULL;