winsound.c 5.45 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* Author: Toby Dickenson <htrd90@zepler.org>
 *
 * Copyright (c) 1999 Toby Dickenson
 *
 * Permission to use this software in any way is granted without
 * fee, provided that the copyright notice above appears in all
 * copies. This software is provided "as is" without any warranty.
 */

/* Modified by Guido van Rossum */
Guido van Rossum's avatar
Guido van Rossum committed
11
/* Beep added by Mark Hammond */
12
/* Win9X Beep and platform identification added by Uncle Timmy */
13 14 15 16 17 18

/* Example:

   import winsound
   import time

19
   # Play wav file
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
   winsound.PlaySound('c:/windows/media/Chord.wav', winsound.SND_FILENAME)

   # Play sound from control panel settings
   winsound.PlaySound('SystemQuestion', winsound.SND_ALIAS)

   # Play wav file from memory
   data=open('c:/windows/media/Chimes.wav',"rb").read()
   winsound.PlaySound(data, winsound.SND_MEMORY)

   # Start playing the first bit of wav file asynchronously
   winsound.PlaySound('c:/windows/media/Chord.wav',
                   winsound.SND_FILENAME|winsound.SND_ASYNC)
   # But dont let it go for too long...
   time.sleep(0.1)
   # ...Before stopping it
   winsound.PlaySound(None, 0)
*/

38
#include <Python.h>
39 40 41
#include <windows.h>
#include <mmsystem.h>

42
PyDoc_STRVAR(sound_playsound_doc,
43 44 45
"PlaySound(sound, flags) - a wrapper around the Windows PlaySound API\n"
"\n"
"The sound argument can be a filename, data, or None.\n"
46
"For flag values, ored together, see module documentation.");
47

48
PyDoc_STRVAR(sound_beep_doc,
Guido van Rossum's avatar
Guido van Rossum committed
49 50 51
"Beep(frequency, duration) - a wrapper around the Windows Beep API\n"
"\n"
"The frequency argument specifies frequency, in hertz, of the sound.\n"
52
"This parameter must be in the range 37 through 32,767.\n"
53
"The duration argument specifies the number of milliseconds.\n");
Guido van Rossum's avatar
Guido van Rossum committed
54

55 56 57
PyDoc_STRVAR(sound_msgbeep_doc,
"MessageBeep(x) - call Windows MessageBeep(x). x defaults to MB_OK.");

58
PyDoc_STRVAR(sound_module_doc,
59 60
"PlaySound(sound, flags) - play a sound\n"
"SND_FILENAME - sound is a wav file name\n"
61
"SND_ALIAS - sound is a registry sound association name\n"
62 63 64 65 66 67 68
"SND_LOOP - Play the sound repeatedly; must also specify SND_ASYNC\n"
"SND_MEMORY - sound is a memory image of a wav file\n"
"SND_PURGE - stop all instances of the specified sound\n"
"SND_ASYNC - PlaySound returns immediately\n"
"SND_NODEFAULT - Do not play a default beep if the sound can not be found\n"
"SND_NOSTOP - Do not interrupt any sounds currently playing\n"  // Raising RuntimeError if needed
"SND_NOWAIT - Return immediately if the sound driver is busy\n" // Without any errors
Guido van Rossum's avatar
Guido van Rossum committed
69
"\n"
70
"Beep(frequency, duration) - Make a beep through the PC speaker.");
71

72
static PyObject *
73
sound_playsound(PyObject *s, PyObject *args)
74
{
Victor Stinner's avatar
Victor Stinner committed
75
    wchar_t *wsound;
76 77 78
    int flags;
    int ok;

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    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;
        }
        Py_BEGIN_ALLOW_THREADS
        ok = PlaySoundW(wsound, NULL, flags);
        Py_END_ALLOW_THREADS
        if (!ok) {
            PyErr_SetString(PyExc_RuntimeError, "Failed to play sound");
            return NULL;
        }
        Py_INCREF(Py_None);
        return Py_None;
95
    }
96
    return NULL;
97 98
}

99 100
static PyObject *
sound_beep(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
101
{
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    int freq;
    int dur;
    BOOL ok;

    if (!PyArg_ParseTuple(args, "ii:Beep", &freq,  &dur))
        return NULL;

    if (freq < 37 || freq > 32767) {
        PyErr_SetString(PyExc_ValueError,
                        "frequency must be in 37 thru 32767");
        return NULL;
    }

    Py_BEGIN_ALLOW_THREADS
    ok = Beep(freq, dur);
    Py_END_ALLOW_THREADS
    if (!ok) {
        PyErr_SetString(PyExc_RuntimeError,"Failed to beep");
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
125 126
}

127 128 129
static PyObject *
sound_msgbeep(PyObject *self, PyObject *args)
{
130 131 132 133 134 135
    int x = MB_OK;
    if (!PyArg_ParseTuple(args, "|i:MessageBeep", &x))
        return NULL;
    MessageBeep(x);
    Py_INCREF(Py_None);
    return Py_None;
136 137
}

138 139
static struct PyMethodDef sound_methods[] =
{
140 141
    {"PlaySound", sound_playsound, METH_VARARGS, sound_playsound_doc},
    {"Beep",      sound_beep,      METH_VARARGS, sound_beep_doc},
142
    {"MessageBeep", sound_msgbeep, METH_VARARGS, sound_msgbeep_doc},
143 144 145
    {NULL,  NULL}
};

146 147
static void
add_define(PyObject *dict, const char *key, long value)
148
{
149 150 151
    PyObject *k = PyUnicode_FromString(key);
    PyObject *v = PyLong_FromLong(value);
    if (v && k) {
152
        PyDict_SetItem(dict, k, v);
153 154 155 156 157 158 159
    }
    Py_XDECREF(k);
    Py_XDECREF(v);
}

#define ADD_DEFINE(tok) add_define(dict,#tok,tok)

160 161

static struct PyModuleDef winsoundmodule = {
162 163 164 165 166 167 168 169 170
    PyModuleDef_HEAD_INIT,
    "winsound",
    sound_module_doc,
    -1,
    sound_methods,
    NULL,
    NULL,
    NULL,
    NULL
171 172
};

173
PyMODINIT_FUNC
174
PyInit_winsound(void)
175
{
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    PyObject *dict;
    PyObject *module = PyModule_Create(&winsoundmodule);
    if (module == NULL)
        return NULL;
    dict = PyModule_GetDict(module);

    ADD_DEFINE(SND_ASYNC);
    ADD_DEFINE(SND_NODEFAULT);
    ADD_DEFINE(SND_NOSTOP);
    ADD_DEFINE(SND_NOWAIT);
    ADD_DEFINE(SND_ALIAS);
    ADD_DEFINE(SND_FILENAME);
    ADD_DEFINE(SND_MEMORY);
    ADD_DEFINE(SND_PURGE);
    ADD_DEFINE(SND_LOOP);
    ADD_DEFINE(SND_APPLICATION);

    ADD_DEFINE(MB_OK);
    ADD_DEFINE(MB_ICONASTERISK);
    ADD_DEFINE(MB_ICONEXCLAMATION);
    ADD_DEFINE(MB_ICONHAND);
    ADD_DEFINE(MB_ICONQUESTION);
    return module;
199
}