Home | History | Annotate | Download | only in PC
      1 /* Author: Toby Dickenson <htrd90 (at) zepler.org>
      2  *
      3  * Copyright (c) 1999 Toby Dickenson
      4  *
      5  * Permission to use this software in any way is granted without
      6  * fee, provided that the copyright notice above appears in all
      7  * copies. This software is provided "as is" without any warranty.
      8  */
      9 
     10 /* Modified by Guido van Rossum */
     11 /* Beep added by Mark Hammond */
     12 /* Win9X Beep and platform identification added by Uncle Timmy */
     13 
     14 /* Example:
     15 
     16    import winsound
     17    import time
     18 
     19    # Play wav file
     20    winsound.PlaySound('c:/windows/media/Chord.wav', winsound.SND_FILENAME)
     21 
     22    # Play sound from control panel settings
     23    winsound.PlaySound('SystemQuestion', winsound.SND_ALIAS)
     24 
     25    # Play wav file from memory
     26    data=open('c:/windows/media/Chimes.wav',"rb").read()
     27    winsound.PlaySound(data, winsound.SND_MEMORY)
     28 
     29    # Start playing the first bit of wav file asynchronously
     30    winsound.PlaySound('c:/windows/media/Chord.wav',
     31                    winsound.SND_FILENAME|winsound.SND_ASYNC)
     32    # But dont let it go for too long...
     33    time.sleep(0.1)
     34    # ...Before stopping it
     35    winsound.PlaySound(None, 0)
     36 */
     37 
     38 #include <Python.h>
     39 #include <windows.h>
     40 #include <mmsystem.h>
     41 
     42 PyDoc_STRVAR(sound_module_doc,
     43 "PlaySound(sound, flags) - play a sound\n"
     44 "SND_FILENAME - sound is a wav file name\n"
     45 "SND_ALIAS - sound is a registry sound association name\n"
     46 "SND_LOOP - Play the sound repeatedly; must also specify SND_ASYNC\n"
     47 "SND_MEMORY - sound is a memory image of a wav file\n"
     48 "SND_PURGE - stop all instances of the specified sound\n"
     49 "SND_ASYNC - PlaySound returns immediately\n"
     50 "SND_NODEFAULT - Do not play a default beep if the sound can not be found\n"
     51 "SND_NOSTOP - Do not interrupt any sounds currently playing\n"  // Raising RuntimeError if needed
     52 "SND_NOWAIT - Return immediately if the sound driver is busy\n" // Without any errors
     53 "\n"
     54 "Beep(frequency, duration) - Make a beep through the PC speaker.\n"
     55 "MessageBeep(type) - Call Windows MessageBeep.");
     56 
     57 /*[clinic input]
     58 module winsound
     59 [clinic start generated code]*/
     60 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a18401142d97b8d5]*/
     61 
     62 #include "clinic/winsound.c.h"
     63 
     64 /*[clinic input]
     65 winsound.PlaySound
     66 
     67     sound: object
     68         The sound to play; a filename, data, or None.
     69     flags: int
     70         Flag values, ored together.  See module documentation.
     71 
     72 A wrapper around the Windows PlaySound API.
     73 [clinic start generated code]*/
     74 
     75 static PyObject *
     76 winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags)
     77 /*[clinic end generated code: output=49a0fd16a372ebeb input=c63e1f2d848da2f2]*/
     78 {
     79     int ok;
     80     wchar_t *wsound;
     81     Py_buffer view = {NULL, NULL};
     82 
     83     if (sound == Py_None) {
     84         wsound = NULL;
     85     } else if (flags & SND_MEMORY) {
     86         if (flags & SND_ASYNC) {
     87             /* Sidestep reference counting headache; unfortunately this also
     88                 prevent SND_LOOP from memory. */
     89             PyErr_SetString(PyExc_RuntimeError,
     90                             "Cannot play asynchronously from memory");
     91             return NULL;
     92         }
     93         if (PyObject_GetBuffer(sound, &view, PyBUF_SIMPLE) < 0) {
     94             return NULL;
     95         }
     96         wsound = (wchar_t *)view.buf;
     97     } else {
     98         if (!PyUnicode_Check(sound)) {
     99             PyErr_Format(PyExc_TypeError,
    100                          "'sound' must be str or None, not '%s'",
    101                          Py_TYPE(sound)->tp_name);
    102             return NULL;
    103         }
    104         wsound = PyUnicode_AsWideCharString(sound, NULL);
    105         if (wsound == NULL) {
    106             return NULL;
    107         }
    108     }
    109 
    110 
    111     Py_BEGIN_ALLOW_THREADS
    112     ok = PlaySoundW(wsound, NULL, flags);
    113     Py_END_ALLOW_THREADS
    114     if (view.obj) {
    115         PyBuffer_Release(&view);
    116     } else if (sound != Py_None) {
    117         PyMem_Free(wsound);
    118     }
    119     if (!ok) {
    120         PyErr_SetString(PyExc_RuntimeError, "Failed to play sound");
    121         return NULL;
    122     }
    123     Py_RETURN_NONE;
    124 }
    125 
    126 /*[clinic input]
    127 winsound.Beep
    128 
    129     frequency: int
    130         Frequency of the sound in hertz.
    131         Must be in the range 37 through 32,767.
    132     duration: int
    133         How long the sound should play, in milliseconds.
    134 
    135 A wrapper around the Windows Beep API.
    136 [clinic start generated code]*/
    137 
    138 static PyObject *
    139 winsound_Beep_impl(PyObject *module, int frequency, int duration)
    140 /*[clinic end generated code: output=f32382e52ee9b2fb input=40e360cfa00a5cf0]*/
    141 {
    142     BOOL ok;
    143 
    144     if (frequency < 37 || frequency > 32767) {
    145         PyErr_SetString(PyExc_ValueError,
    146                         "frequency must be in 37 thru 32767");
    147         return NULL;
    148     }
    149 
    150     Py_BEGIN_ALLOW_THREADS
    151     ok = Beep(frequency, duration);
    152     Py_END_ALLOW_THREADS
    153     if (!ok) {
    154         PyErr_SetString(PyExc_RuntimeError,"Failed to beep");
    155         return NULL;
    156     }
    157 
    158     Py_RETURN_NONE;
    159 }
    160 
    161 /*[clinic input]
    162 winsound.MessageBeep
    163 
    164     type: int(c_default="MB_OK") = MB_OK
    165 
    166 Call Windows MessageBeep(x).
    167 
    168 x defaults to MB_OK.
    169 [clinic start generated code]*/
    170 
    171 static PyObject *
    172 winsound_MessageBeep_impl(PyObject *module, int type)
    173 /*[clinic end generated code: output=120875455121121f input=db185f741ae21401]*/
    174 {
    175     BOOL ok;
    176 
    177     Py_BEGIN_ALLOW_THREADS
    178     ok = MessageBeep(type);
    179     Py_END_ALLOW_THREADS
    180 
    181     if (!ok) {
    182         PyErr_SetExcFromWindowsErr(PyExc_RuntimeError, 0);
    183         return NULL;
    184     }
    185 
    186     Py_RETURN_NONE;
    187 }
    188 
    189 static struct PyMethodDef sound_methods[] =
    190 {
    191     WINSOUND_PLAYSOUND_METHODDEF
    192     WINSOUND_BEEP_METHODDEF
    193     WINSOUND_MESSAGEBEEP_METHODDEF
    194     {NULL,  NULL}
    195 };
    196 
    197 static void
    198 add_define(PyObject *dict, const char *key, long value)
    199 {
    200     PyObject *k = PyUnicode_FromString(key);
    201     PyObject *v = PyLong_FromLong(value);
    202     if (v && k) {
    203         PyDict_SetItem(dict, k, v);
    204     }
    205     Py_XDECREF(k);
    206     Py_XDECREF(v);
    207 }
    208 
    209 #define ADD_DEFINE(tok) add_define(dict,#tok,tok)
    210 
    211 
    212 static struct PyModuleDef winsoundmodule = {
    213     PyModuleDef_HEAD_INIT,
    214     "winsound",
    215     sound_module_doc,
    216     -1,
    217     sound_methods,
    218     NULL,
    219     NULL,
    220     NULL,
    221     NULL
    222 };
    223 
    224 PyMODINIT_FUNC
    225 PyInit_winsound(void)
    226 {
    227     PyObject *dict;
    228     PyObject *module = PyModule_Create(&winsoundmodule);
    229     if (module == NULL)
    230         return NULL;
    231     dict = PyModule_GetDict(module);
    232 
    233     ADD_DEFINE(SND_ASYNC);
    234     ADD_DEFINE(SND_NODEFAULT);
    235     ADD_DEFINE(SND_NOSTOP);
    236     ADD_DEFINE(SND_NOWAIT);
    237     ADD_DEFINE(SND_ALIAS);
    238     ADD_DEFINE(SND_FILENAME);
    239     ADD_DEFINE(SND_MEMORY);
    240     ADD_DEFINE(SND_PURGE);
    241     ADD_DEFINE(SND_LOOP);
    242     ADD_DEFINE(SND_APPLICATION);
    243 
    244     ADD_DEFINE(MB_OK);
    245     ADD_DEFINE(MB_ICONASTERISK);
    246     ADD_DEFINE(MB_ICONEXCLAMATION);
    247     ADD_DEFINE(MB_ICONHAND);
    248     ADD_DEFINE(MB_ICONQUESTION);
    249     return module;
    250 }
    251