unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Need help with Windows implementation of play-sound
@ 2002-09-19 18:53 Ben Key
  2002-09-21  9:34 ` Harald.Maier.BW
  0 siblings, 1 reply; 4+ messages in thread
From: Ben Key @ 2002-09-19 18:53 UTC (permalink / 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
***********************/

^ permalink raw reply	[flat|nested] 4+ messages in thread
* RE: Need help with Windows implementation of play-sound
@ 2002-09-22  5:01 Ben Key
  0 siblings, 0 replies; 4+ messages in thread
From: Ben Key @ 2002-09-22  5:01 UTC (permalink / raw)
  Cc: 'emacs-devel@gnu.org'

Thanks.  I will try the change you suggested Monday.  If it works, I will
attempt to gernerate a patch for Emacs that includes this and the changes to
the make files, and send it to this list. 

-----Original Message-----
From: Harald.Maier.BW@t-online.de
To: Ben Key
Cc: emacs-devel@gnu.org
Sent: 9/21/02 5:34 AM
Subject: Re: Need help with Windows implementation of play-sound


Ben Key <BenK@FreedomScientific.com> writes:

> Can someone take a look at what I have done so far and give me a few 
> pointers?

> {
>   len=XSTRING(attrs[SOUND_FILE])->size;
>   lpszFile=(char *)alloca(len+1);
...
>   free(lpszFile);
!!! remove that line !!!

>   unbind_to (count, Qnil);
>   return Qnil;
> }

You are using alloca so you don't have to call free. free is necessary
by using malloc. The memory allocated by alloca will be automatically
be freed by leaving the funciton.

I am very interested in testing this. 

Harald

^ permalink raw reply	[flat|nested] 4+ messages in thread
* RE: Need help with Windows implementation of play-sound
@ 2002-09-23  8:31 jasonr
  0 siblings, 0 replies; 4+ messages in thread
From: jasonr @ 2002-09-23  8:31 UTC (permalink / raw)
  Cc: emacs-devel

Please check the GNU coding standards (available as an info file from ftp.gnu.org) and where necessary change your layout and function/variable naming to match them. This will make less work if we decide to use your code.

>  from:    Ben Key <BenK@FreedomScientific.com>
>  date:    Sun, 22 Sep 2002 06:01:04
>  to:      Harald.Maier.BW@t-online.de
>  cc:      emacs-devel@gnu.org
>  subject: RE: Need help with Windows implementation of play-sound
> 
> Thanks.  I will try the change you suggested Monday.  If it works, I will
> attempt to gernerate a patch for Emacs that includes this and the changes to
> the make files, and send it to this list. 
> 
> -----Original Message-----
> From: Harald.Maier.BW@t-online.de
> To: Ben Key
> Cc: emacs-devel@gnu.org
> Sent: 9/21/02 5:34 AM
> Subject: Re: Need help with Windows implementation of play-sound
> 
> 
> Ben Key <BenK@FreedomScientific.com> writes:
> 
> > Can someone take a look at what I have done so far and give me a few 
> > pointers?
> 
> > {
> >   len=XSTRING(attrs[SOUND_FILE])->size;
> >   lpszFile=(char *)alloca(len 1);
> ...
> >   free(lpszFile);
> !!! remove that line !!!
> 
> >   unbind_to (count, Qnil);
> >   return Qnil;
> > }
> 
> You are using alloca so you don't have to call free. free is necessary
> by using malloc. The memory allocated by alloca will be automatically
> be freed by leaving the funciton.
> 
> I am very interested in testing this. 
> 
> Harald
> 
> 
> _______________________________________________
> Emacs-devel mailing list
> Emacs-devel@gnu.org
> http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-09-23  8:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-09-19 18:53 Need help with Windows implementation of play-sound Ben Key
2002-09-21  9:34 ` Harald.Maier.BW
  -- strict thread matches above, loose matches on Subject: below --
2002-09-22  5:01 Ben Key
2002-09-23  8:31 jasonr

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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).