From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Ben Key Newsgroups: gmane.emacs.devel Subject: Need help with Windows implementation of play-sound Date: Thu, 19 Sep 2002 14:53:09 -0400 Sender: emacs-devel-admin@gnu.org Message-ID: <762A7BB74D6AD51195EF00B0D0AA16602C37E3@STPETE> NNTP-Posting-Host: localhost.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: main.gmane.org 1032462418 18353 127.0.0.1 (19 Sep 2002 19:06:58 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Thu, 19 Sep 2002 19:06:58 +0000 (UTC) Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 17s6dc-0004ll-00 for ; Thu, 19 Sep 2002 21:06:56 +0200 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 17s7IW-0003yw-00 for ; Thu, 19 Sep 2002 21:49:13 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 17s6dy-0005S9-00; Thu, 19 Sep 2002 15:07:18 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 17s6cI-0005MJ-00 for emacs-devel@gnu.org; Thu, 19 Sep 2002 15:05:34 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 17s6cF-0005M7-00 for emacs-devel@gnu.org; Thu, 19 Sep 2002 15:05:34 -0400 Original-Received: from stpete.freedomscientific.com ([209.101.206.132] helo=stpete.FreedomScientific) by monty-python.gnu.org with esmtp (Exim 4.10) id 17s6cF-0005Lp-00 for emacs-devel@gnu.org; Thu, 19 Sep 2002 15:05:31 -0400 Original-Received: by STPETE with Internet Mail Service (5.5.2656.59) id ; Thu, 19 Sep 2002 14:53:12 -0400 Original-To: "'emacs-devel@gnu.org'" X-Mailer: Internet Mail Service (5.5.2656.59) Errors-To: emacs-devel-admin@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.devel:8025 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:8025 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 . Tested In Windows 98 SE and Windows XP. ***************************************************************** */ #include #if !defined(HAVE_SOUND) && defined(USE_W32SOUND) #include #include #include #include #include "lisp.h" #include "dispextern.h" #include "atimer.h" #include #include "syssignal.h" #include #include #include #include #include #include #include #include #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 ***********************/