(root)/
Python-3.11.7/
PC/
winsound.c
       1  /* Author: Toby Dickenson <htrd90@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 don't 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  }