/* 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 */
/* Beep added by Mark Hammond */
/* Win9X Beep and platform identification added by Uncle Timmy */

/* Example:

   import winsound
   import time

   # Play wav file
   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)
*/

#include <windows.h>
#include <mmsystem.h>
#include <conio.h>	/* port functions on Win9x */
#include <Python.h>

static char sound_playsound_doc[] =
"PlaySound(sound, flags) - a wrapper around the Windows PlaySound API\n"
"\n"
"The sound argument can be a filename, data, or None.\n"
"For flag values, ored together, see module documentation.\n";

static char sound_beep_doc[] =
"Beep(frequency, duration) - a wrapper around the Windows Beep API\n"
"\n"
"The frequency argument specifies frequency, in hertz, of the sound.\n"
"This parameter must be in the range 37 through 32,767.\n"
"The duration argument specifies the number of milliseconds.\n"
"On WinNT and 2000, the platform Beep API is used directly.  Else funky\n"
"code doing direct port manipulation is used; it's unknown whether that\n"
"will work on all systems.\n";

static char sound_module_doc[] =
"PlaySound(sound, flags) - play a sound\n"
"SND_FILENAME - sound is a wav file name\n"
"SND_ALIAS - sound is a control panel sound association name\n"
"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
"\n"
"Beep(frequency, duration) - Make a beep through the PC speaker.\n";

PyObject *
sound_playsound(PyObject *s, PyObject *args)
{
    const char *sound;
    int flags;
    int length;
    int ok;

    if(!PyArg_ParseTuple(args,"z#i:PlaySound",&sound,&length,&flags)) {
        return NULL;
    }

    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 = PlaySound(sound,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;
}

enum OSType {Win9X, WinNT2000};
static enum OSType whichOS;	/* set by module init */

static PyObject *
sound_beep(PyObject *self, PyObject *args)
{
	int freq;
	int dur;

	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;
	}

	/* On NT and 2000, the SDK Beep() function does the whole job.
	 * But while Beep() exists before NT, it ignores its arguments and
	 * plays the system default sound.  Sheesh ...
	 * The Win9X code is mondo bizarre.  I (Tim) pieced it together from
	 * crap all over the web.  The original IBM PC used some particular
	 * pieces of hardware (Intel 8255 and 8254 chips) hardwired to
	 * particular port addresses and running at particular clock speeds,
	 * and the poor sound card folks have been forced to emulate that in
	 * all particulars ever since.  But NT and 2000 don't support port
	 * manipulation,   Don't know about WinME; guessing it's like 98.
	 */

	if (whichOS == WinNT2000) {
		BOOL ok;
		Py_BEGIN_ALLOW_THREADS
		ok = Beep(freq, dur);
		Py_END_ALLOW_THREADS
		if (!ok) {
			PyErr_SetString(PyExc_RuntimeError,"Failed to beep");
			return NULL;
		}
	}
	else if (whichOS == Win9X) {
		int speaker_state;
		/* Force timer into oscillator mode via timer control port. */
		_outp(0x43, 0xb6);
		/* Compute ratio of ancient hardcoded timer frequency to
		 * frequency we want.  Then feed that ratio (lowest byte
		 * first) into timer data port.
		 */
		freq = 1193180 / freq;
		_outp(0x42, freq & 0xff);
		_outp(0x42, (freq >> 8) & 0xff);
		/* Get speaker control state. */
		speaker_state = _inp(0x61);
		/* Turn the speaker on (bit 1)
		 * and drive speaker from timer (bit 0).
		 */
		_outp(0x61, speaker_state | 0x3);
		/* Let it blast in peace for the duration. */
		Py_BEGIN_ALLOW_THREADS
		Sleep(dur);
		Py_END_ALLOW_THREADS
		/* Restore speaker control to original state. */
		_outp(0x61, speaker_state);
	}
	else {
		assert(!"winsound's whichOS has insane value");
	}
	Py_INCREF(Py_None);
	return Py_None;
}

static struct PyMethodDef sound_methods[] =
{
    {"PlaySound", sound_playsound, 1, sound_playsound_doc},
    {"Beep",      sound_beep,      1, sound_beep_doc},
    {NULL,  NULL}
};

static void
add_define(PyObject *dict, const char *key, long value)
{
    PyObject *k=PyString_FromString(key);
    PyObject *v=PyLong_FromLong(value);
    if(v&&k)
    {
        PyDict_SetItem(dict,k,v);
    }
    Py_XDECREF(k);
    Py_XDECREF(v);
}

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

DL_EXPORT(void)
initwinsound(void)
{
	OSVERSIONINFO version;

	PyObject *module = Py_InitModule3("winsound",
					  sound_methods,
					  sound_module_doc);
	PyObject *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);

	version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&version);
        whichOS = Win9X;
	if (version.dwPlatformId != VER_PLATFORM_WIN32s &&
	    version.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
		whichOS = WinNT2000;
}
