From: Ben Key <BenK@FreedomScientific.com>
Subject: Need help with Windows implementation of play-sound
Date: Thu, 19 Sep 2002 14:57:18 -0400 [thread overview]
Message-ID: <762A7BB74D6AD51195EF00B0D0AA16602C37E5@STPETE> (raw)
As my first attempt at modifying GNU Emacs, I decided to write a
Windows compatible implementation of play-sound. I have written a
function that will play any sound file that Windows Media Player can
play using the mciSendString function. That part was easy. Then
came the hard part, integrating that function into Emacs. The
following is the contents of w32sound.c, which represents my first
attempts at accomplishing this task. I used sound.c as a template
for w32sound.c. I was able to get it to compile without difficulty,
but now when Emacs starts up (or possibly when play-sound is used for
the first time), Emacs crashes.
Can someone take a look at what I have done so far and give me a few
pointers?
Thank you.
/***********************
@@ BEGIN w32sound.c
***********************/
/*
*****************************************************************
w32sound.c -- sound support for Windows.
Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*****************************************************************
*/
/*
*****************************************************************
Written by Ben Key <Bkey1@tampabay.rr.com>.
Tested In Windows 98 SE and Windows XP.
*****************************************************************
*/
#include <config.h>
#if !defined(HAVE_SOUND) && defined(USE_W32SOUND)
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include "lisp.h"
#include "dispextern.h"
#include "atimer.h"
#include <signal.h>
#include "syssignal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <io.h>
#include <limits.h>
#include <windows.h>
#include <mmsystem.h>
#if defined(_MSC_VER) && (_MSC_VER>1000)
#pragma comment (lib,"winmm.lib")
#endif /* #if defined(_MSC_VER) && (_MSC_VER>1000) */
#undef min
#undef max
#define min(x, y) (((x) < (y)) ? (x) : (y))
#define max(x, y) (((x) > (y)) ? (x) : (y))
enum sound_attr
{
SOUND_FILE,
SOUND_DATA,
SOUND_DEVICE,
SOUND_VOLUME,
SOUND_ATTR_SENTINEL
};
/* Symbols. */
extern Lisp_Object QCfile, QCdata;
Lisp_Object QCvolume, QCdevice;
Lisp_Object Qsound;
Lisp_Object Qplay_sound_functions;
/* Function prototypes. */
static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
static int DoPlaySoundP_ ((const char *,unsigned long));
/*
DoPlaySound
Worker function that provides the implementation of
play-sound.
Plays any sound file supported by Windows Media Player
via the Multimedia Command Interface.
This function has been tested and proven to work with the
following media types: .wav, .mp3, .au, .rmi.
The tests were conducted using a simple command line program
that was written for the purpose.
*/
int DoPlaySound(lpszFile,dwVolume)
const char * lpszFile;
unsigned long dwVolume;
{
int iResult=0;
MCIERROR mciError=0;
char szCmdBuf[520]={0};
char szRetBuf[520]={0};
MMRESULT mmResult=MMSYSERR_NOERROR;
DWORD dwVolumeOrg=0;
BOOL bResetVolume=FALSE;
ZeroMemory(szCmdBuf,sizeof(szCmdBuf));
ZeroMemory(szRetBuf,sizeof(szRetBuf));
sprintf(
szCmdBuf,
"open \"%s\" alias SulliTech_PlaySound_Device wait",
lpszFile);
mciError=mciSendString(szCmdBuf,szRetBuf,520,NULL);
if (mciError!=0)
{
iResult=(int)mciError;
return iResult;
}
if (dwVolume!=UINT_MAX)
{
mmResult=waveOutGetVolume((HWAVEOUT)WAVE_MAPPER,&dwVolumeOrg);
if (mmResult==MMSYSERR_NOERROR)
{
bResetVolume=TRUE;
mmResult=waveOutSetVolume((HWAVEOUT)WAVE_MAPPER,dwVolume);
}
}
ZeroMemory(szCmdBuf,sizeof(szCmdBuf));
ZeroMemory(szRetBuf,sizeof(szRetBuf));
strcpy(szCmdBuf,"play SulliTech_PlaySound_Device wait");
mciError=mciSendString(szCmdBuf,szRetBuf,520,NULL);
if (mciError!=0)
{
iResult=(int)mciError;
}
ZeroMemory(szCmdBuf,sizeof(szCmdBuf));
ZeroMemory(szRetBuf,sizeof(szRetBuf));
strcpy(szCmdBuf,"close SulliTech_PlaySound_Device wait");
mciError=mciSendString(szCmdBuf,szRetBuf,520,NULL);
if (bResetVolume==TRUE)
{
mmResult=waveOutSetVolume((HWAVEOUT)WAVE_MAPPER,dwVolumeOrg);
}
return iResult;
}
/* Parse sound specification SOUND, and fill ATTRS with what is
found. Value is non-zero if SOUND Is a valid sound specification.
A valid sound specification is a list starting with the symbol
`sound'. The rest of the list is a property list which may
contain the following key/value pairs:
- `:file FILE'
FILE is the sound file to play. If it isn't an absolute name,
it's searched under `data-directory'.
- `:data DATA'
DATA is a string containing sound data. Either :file or :data
may be present, but not both.
- `:device DEVICE'
DEVICE is the name of the device to play on, e.g. "/dev/dsp2".
If not specified, a default device is used.
- `:volume VOL'
VOL must be an integer in the range [0, 100], or a float in the
range [0, 1]. */
static int
parse_sound (sound, attrs)
Lisp_Object sound;
Lisp_Object *attrs;
{
/*
SOUND must be a list starting with the symbol `sound'.
*/
if (!CONSP (sound) || !EQ (XCAR (sound), Qsound))
{
return 0;
}
sound=XCDR(sound);
attrs[SOUND_FILE]=Fplist_get(sound,QCfile);
attrs[SOUND_DATA]=Fplist_get(sound,QCdata);
attrs[SOUND_DEVICE]=Fplist_get(sound,QCdevice);
attrs[SOUND_VOLUME]=Fplist_get(sound,QCvolume);
/*
File name must be specified. Sound Data is not supported in
Windows.
*/
if (!STRINGP(attrs[SOUND_FILE]))
{
return 0;
}
/* Volume must be in the range 0..100 or unspecified. */
if (!NILP(attrs[SOUND_VOLUME]))
{
if (INTEGERP(attrs[SOUND_VOLUME]))
{
if (
XINT(attrs[SOUND_VOLUME])<0
|| XINT(attrs[SOUND_VOLUME])>100
)
{
return 0;
}
}
else if (FLOATP(attrs[SOUND_VOLUME]))
{
if (
XFLOAT_DATA(attrs[SOUND_VOLUME])<0
|| XFLOAT_DATA(attrs[SOUND_VOLUME])>1
)
{
return 0;
}
}
else
{
return 0;
}
}
/*
Device is unsupported in Windows. Therefore the test
for device that was at this position of the version of this
function that is in sound.c has been removed.
*/
return 1;
}
DEFUN ("play-sound", Fplay_sound, Splay_sound, 1, 1, 0,
"Play sound SOUND.\n\
SOUND is a list of the form `(sound KEYWORD VALUE...)'.\n\
The following keywords are recognized:\n\
\n\
:file FILE.- read sound data from FILE. If FILE isn't an\n\
absolute file name, it is searched in `data-directory'.\n\
\n\
:data DATA - read sound data from string DATA.\n\
NOTE: :data is not supported in the Microsoft Windows\n\
implementation of play-sound.\n\
\n\
Exactly one of :file or :data must be present.\n\
\n\
:volume VOL - set volume to VOL. VOL must an integer in the\n\
range 0..100 or a float in the range 0..1.0. If not specified,\n\
don't change the volume setting of the sound device.\n\
\n\
:device DEVICE - play sound on DEVICE. If not specified,\n\
a system-dependent default device name is used.\n\
NOTE: :device is not supported in the Microsoft Windows\n\
implementation of play-sound.")
(sound)
Lisp_Object sound;
{
Lisp_Object attrs[SOUND_ATTR_SENTINEL];
int count=specpdl_ptr-specpdl;
int len=0;
char * lpszFile=NULL;
unsigned long dwVolume=0;
int iRet=0;
if (
parse_sound(sound, attrs)==0
|| STRINGP(attrs[SOUND_FILE])==0
)
{
error("Invalid sound specification");
}
len=XSTRING(attrs[SOUND_FILE])->size;
lpszFile=(char *)alloca(len+1);
strcpy(lpszFile,XSTRING(attrs[SOUND_FILE])->data);
if (INTEGERP (attrs[SOUND_VOLUME]))
{
dwVolume=XFASTINT(attrs[SOUND_VOLUME]);
}
else if (FLOATP(attrs[SOUND_VOLUME]))
{
dwVolume=XFLOAT_DATA(attrs[SOUND_VOLUME])*100;
}
iRet=DoPlaySound(lpszFile,dwVolume);
free(lpszFile);
unbind_to (count, Qnil);
return Qnil;
}
/*
*****************************************************************
Initialization
*****************************************************************
*/
void
syms_of_sound ()
{
QCdevice = intern (":device");
staticpro (&QCdevice);
QCvolume = intern (":volume");
staticpro (&QCvolume);
Qsound = intern ("sound");
staticpro (&Qsound);
Qplay_sound_functions = intern ("play-sound-functions");
staticpro (&Qplay_sound_functions);
defsubr (&Splay_sound);
}
void
init_sound ()
{
}
#endif /* #if !defined(HAVE_SOUND) && defined(USE_W32SOUND) */
/***********************
@@ END w32sound.c
***********************/
reply other threads:[~2002-09-19 18:57 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=762A7BB74D6AD51195EF00B0D0AA16602C37E5@STPETE \
--to=benk@freedomscientific.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).