emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Need help with Windows implementation of play-sound


From: Ben Key
Subject: Need help with Windows implementation of play-sound
Date: Thu, 19 Sep 2002 14:53:09 -0400

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 <address@hidden>.
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 via email to

[Prev in Thread] Current Thread [Next in Thread]