summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/winsound.rst5
-rw-r--r--Lib/test/test_winsound.py16
-rw-r--r--Misc/NEWS3
-rw-r--r--PC/clinic/winsound.c.h8
-rw-r--r--PC/winsound.c49
5 files changed, 64 insertions, 17 deletions
diff --git a/Doc/library/winsound.rst b/Doc/library/winsound.rst
index d2c4210..e72d025 100644
--- a/Doc/library/winsound.rst
+++ b/Doc/library/winsound.rst
@@ -25,7 +25,8 @@ provided by Windows platforms. It includes functions and several constants.
.. function:: PlaySound(sound, flags)
Call the underlying :c:func:`PlaySound` function from the Platform API. The
- *sound* parameter may be a filename, audio data as a string, or ``None``. Its
+ *sound* parameter may be a filename, a system sound alias, audio data as a
+ :term:`bytes-like object`, or ``None``. Its
interpretation depends on the value of *flags*, which can be a bitwise ORed
combination of the constants described below. If the *sound* parameter is
``None``, any currently playing waveform sound is stopped. If the system
@@ -92,7 +93,7 @@ provided by Windows platforms. It includes functions and several constants.
.. data:: SND_MEMORY
The *sound* parameter to :func:`PlaySound` is a memory image of a WAV file, as a
- string.
+ :term:`bytes-like object`.
.. note::
diff --git a/Lib/test/test_winsound.py b/Lib/test/test_winsound.py
index 4a8ab7d..1cfef77 100644
--- a/Lib/test/test_winsound.py
+++ b/Lib/test/test_winsound.py
@@ -87,6 +87,22 @@ class PlaySoundTest(unittest.TestCase):
winsound.PlaySound,
"none", winsound.SND_ASYNC | winsound.SND_MEMORY
)
+ self.assertRaises(TypeError, winsound.PlaySound, b"bad", 0)
+ self.assertRaises(TypeError, winsound.PlaySound, "bad",
+ winsound.SND_MEMORY)
+ self.assertRaises(TypeError, winsound.PlaySound, 1, 0)
+
+ def test_snd_memory(self):
+ with open(support.findfile('pluck-pcm8.wav',
+ subdir='audiodata'), 'rb') as f:
+ audio_data = f.read()
+ safe_PlaySound(audio_data, winsound.SND_MEMORY)
+ audio_data = bytearray(audio_data)
+ safe_PlaySound(audio_data, winsound.SND_MEMORY)
+
+ def test_snd_filename(self):
+ fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
+ safe_PlaySound(fn, winsound.SND_FILENAME | winsound.SND_NODEFAULT)
def test_aliases(self):
aliases = [
diff --git a/Misc/NEWS b/Misc/NEWS
index e503547..5fdabe0 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -75,6 +75,9 @@ Core and Builtins
Library
-------
+- Issue #11620: Fix support for SND_MEMORY in winsound.PlaySound. Based on a
+ patch by Tim Lesher.
+
- Issue #11734: Add support for IEEE 754 half-precision floats to the
struct module. Based on a patch by Eli Stevens.
diff --git a/PC/clinic/winsound.c.h b/PC/clinic/winsound.c.h
index cdb2045..a4c3938 100644
--- a/PC/clinic/winsound.c.h
+++ b/PC/clinic/winsound.c.h
@@ -17,16 +17,16 @@ PyDoc_STRVAR(winsound_PlaySound__doc__,
{"PlaySound", (PyCFunction)winsound_PlaySound, METH_VARARGS, winsound_PlaySound__doc__},
static PyObject *
-winsound_PlaySound_impl(PyObject *module, Py_UNICODE *sound, int flags);
+winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags);
static PyObject *
winsound_PlaySound(PyObject *module, PyObject *args)
{
PyObject *return_value = NULL;
- Py_UNICODE *sound;
+ PyObject *sound;
int flags;
- if (!PyArg_ParseTuple(args, "Zi:PlaySound",
+ if (!PyArg_ParseTuple(args, "Oi:PlaySound",
&sound, &flags)) {
goto exit;
}
@@ -100,4 +100,4 @@ winsound_MessageBeep(PyObject *module, PyObject *args)
exit:
return return_value;
}
-/*[clinic end generated code: output=1044b2adf3c67014 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b999334e2e444ad2 input=a9049054013a1b77]*/
diff --git a/PC/winsound.c b/PC/winsound.c
index 6b79d23..000ddd8 100644
--- a/PC/winsound.c
+++ b/PC/winsound.c
@@ -64,7 +64,7 @@ module winsound
/*[clinic input]
winsound.PlaySound
- sound: Py_UNICODE(accept={str, NoneType})
+ sound: object
The sound to play; a filename, data, or None.
flags: int
Flag values, ored together. See module documentation.
@@ -74,22 +74,49 @@ A wrapper around the Windows PlaySound API.
[clinic start generated code]*/
static PyObject *
-winsound_PlaySound_impl(PyObject *module, Py_UNICODE *sound, int flags)
-/*[clinic end generated code: output=ec24b3a2b4368378 input=3411b1b7c1f36d93]*/
+winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags)
+/*[clinic end generated code: output=49a0fd16a372ebeb input=7bdf637f10201d37]*/
{
int ok;
-
- 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;
+ wchar_t *wsound;
+ Py_buffer view = {NULL, NULL};
+
+ if (sound == Py_None) {
+ wsound = NULL;
+ } else if (flags & SND_MEMORY) {
+ 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 {
+ if (!PyUnicode_Check(sound)) {
+ PyErr_Format(PyExc_TypeError,
+ "'sound' must be str or None, not '%s'",
+ Py_TYPE(sound)->tp_name);
+ return NULL;
+ }
+ wsound = PyUnicode_AsWideCharString(sound, NULL);
+ if (wsound == NULL) {
+ return NULL;
+ }
}
+
Py_BEGIN_ALLOW_THREADS
- ok = PlaySoundW(sound, NULL, flags);
+ ok = PlaySoundW(wsound, NULL, flags);
Py_END_ALLOW_THREADS
+ if (view.obj) {
+ PyBuffer_Release(&view);
+ } else if (sound != Py_None) {
+ PyMem_Free(wsound);
+ }
if (!ok) {
PyErr_SetString(PyExc_RuntimeError, "Failed to play sound");
return NULL;