* Patches for Gnu Emacs
@ 2002-11-16 4:04 Ben Key
0 siblings, 0 replies; only message in thread
From: Ben Key @ 2002-11-16 4:04 UTC (permalink / raw)
[-- Attachment #1: Type: text/plain, Size: 2180 bytes --]
Attached to this message are 2 patches for Gnu Emacs. The
patches are as follows:
emacs-21.3.50-w32-play-sound.diff
A patch to provide a partial Windows implementation of
the function play-sound-internal.
It is only a partial implementation in that only the
:file and :volume keywords are supported. The :device
keyword, if present, is ignored. The :data keyword, if
present, will cause an error to be generated.
This patch has not been changed since I last sent it to
this list.
emacs-21.3.50-windows-crash-fix.diff
A patch that address the following entry in etc/PROBLEMS:
Emacs built on Windows 9x/ME crashes at startup on
Windows XP, or Emacs built on XP crashes at startup
on Windows 9x/ME.
This patch has been updated since I last sent it to this
list. In my most recent version of the patch, I removed
all calls to the functions OpenProcessToken,
GetTokenInformation, LookupAccountSid, and
GetSidIdentifierAuthority from init_user_info and replaced
them with calls to wrapper functions. These wrapper
functions internally verify that Emacs is not running on
Windows 9x, obtain the address of the wrapped function, and
call the function via a pointer to the function.
This change was suggested by Juanma Barranquero
[lektu@terra.es]. The reason for this change is that these
functions are only officially supported by Microsoft under
Windows NT / 2K / XP. We can get away with calling them
directly under Windows 9x except this is taking advantage
of an undocumented feature of the version of advapi32.dll
found in Windows 9x and doing so causes an exception to be
generated under Windows 9x.
If there are no objections from individuals on this list, I
will be adding these changes to CVS Monday. In the
meantime, I would appreciate it if as many people as possible
were to test this patch. I have already tested this patch
by building Emacs on Windows XP using both MSVC 6.0 and
MinGW 2.0 and verifying that the build of Emacs runs on
Windows 98 and that play-sound-internal functions properly.
In addition I have verified that nothing in my patch
inadvertently breaks the build in Gnu/Linux.
[-- Attachment #2: emacs-21.3.50-windows-crash-fix.diff --]
[-- Type: application/octet-stream, Size: 11974 bytes --]
--- _21.3/src/w32.c 2002-07-14 20:00:37.000000000 -0400
+++ 21.3/src/w32.c 2002-11-15 12:50:32.000000000 -0500
@@ -105,6 +105,171 @@
extern Lisp_Object Vw32_num_mouse_buttons;
\f
+/*
+ BEGIN: Wrapper functions around OpenProcessToken
+ and other functions in advapi32.dll that are only
+ supported in Windows NT / 2k / XP
+*/
+ /* ** Function pointer typedefs ** */
+typedef BOOL (WINAPI * OpenProcessToken_Proc) (
+ HANDLE ProcessHandle,
+ DWORD DesiredAccess,
+ PHANDLE TokenHandle);
+typedef BOOL (WINAPI * GetTokenInformation_Proc) (
+ HANDLE TokenHandle,
+ TOKEN_INFORMATION_CLASS TokenInformationClass,
+ LPVOID TokenInformation,
+ DWORD TokenInformationLength,
+ PDWORD ReturnLength);
+#ifdef _UNICODE
+const char * const LookupAccountSid_Name = "LookupAccountSidW";
+#else
+const char * const LookupAccountSid_Name = "LookupAccountSidA";
+#endif
+typedef BOOL (WINAPI * LookupAccountSid_Proc) (
+ LPCTSTR lpSystemName,
+ PSID Sid,
+ LPTSTR Name,
+ LPDWORD cbName,
+ LPTSTR DomainName,
+ LPDWORD cbDomainName,
+ PSID_NAME_USE peUse);
+typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
+ PSID pSid);
+
+ /* ** A utility function ** */
+static BOOL is_windows_9x ()
+{
+ BOOL b_ret=0;
+ OSVERSIONINFO os_ver;
+ ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
+ os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx (&os_ver))
+ {
+ b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ }
+ return b_ret;
+}
+
+ /* ** The wrapper functions ** */
+
+BOOL WINAPI open_process_token (
+ HANDLE ProcessHandle,
+ DWORD DesiredAccess,
+ PHANDLE TokenHandle)
+{
+ OpenProcessToken_Proc pfn_Open_Process_Token = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return FALSE;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Open_Process_Token =
+ (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
+ if (pfn_Open_Process_Token == NULL)
+ {
+ return FALSE;
+ }
+ return (
+ pfn_Open_Process_Token (
+ ProcessHandle,
+ DesiredAccess,
+ TokenHandle)
+ );
+}
+
+BOOL WINAPI get_token_information (
+ HANDLE TokenHandle,
+ TOKEN_INFORMATION_CLASS TokenInformationClass,
+ LPVOID TokenInformation,
+ DWORD TokenInformationLength,
+ PDWORD ReturnLength)
+{
+ GetTokenInformation_Proc pfn_Get_Token_Information = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return FALSE;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Get_Token_Information =
+ (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
+ if (pfn_Get_Token_Information == NULL)
+ {
+ return FALSE;
+ }
+ return (
+ pfn_Get_Token_Information (
+ TokenHandle,
+ TokenInformationClass,
+ TokenInformation,
+ TokenInformationLength,
+ ReturnLength)
+ );
+}
+
+BOOL WINAPI lookup_account_sid (
+ LPCTSTR lpSystemName,
+ PSID Sid,
+ LPTSTR Name,
+ LPDWORD cbName,
+ LPTSTR DomainName,
+ LPDWORD cbDomainName,
+ PSID_NAME_USE peUse)
+{
+ LookupAccountSid_Proc pfn_Lookup_Account_Sid = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return FALSE;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Lookup_Account_Sid =
+ (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
+ if (pfn_Lookup_Account_Sid == NULL)
+ {
+ return FALSE;
+ }
+ return (
+ pfn_Lookup_Account_Sid (
+ lpSystemName,
+ Sid,
+ Name,
+ cbName,
+ DomainName,
+ cbDomainName,
+ peUse)
+ );
+}
+
+PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
+ PSID pSid)
+{
+ GetSidIdentifierAuthority_Proc pfn_Get_Sid_Identifier_Authority = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return NULL;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Get_Sid_Identifier_Authority =
+ (GetSidIdentifierAuthority_Proc) GetProcAddress (
+ hm_advapi32, "GetSidIdentifierAuthority");
+ if (pfn_Get_Sid_Identifier_Authority == NULL)
+ {
+ return NULL;
+ }
+ return (pfn_Get_Sid_Identifier_Authority (pSid));
+}
+
+/*
+ END: Wrapper functions around OpenProcessToken
+ and other functions in advapi32.dll that are only
+ supported in Windows NT / 2k / XP
+*/
+
+\f
/* Equivalent of strerror for W32 error codes. */
char *
w32_strerror (int error_no)
@@ -254,11 +419,15 @@
HANDLE token = NULL;
SID_NAME_USE user_type;
- if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
- && GetTokenInformation (token, TokenUser,
+ if (
+ open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
+ && get_token_information (
+ token, TokenUser,
(PVOID) user_sid, sizeof (user_sid), &trash)
- && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
- domain, &dlength, &user_type))
+ && lookup_account_sid (
+ NULL, *((PSID *) user_sid), name, &length,
+ domain, &dlength, &user_type)
+ )
{
strcpy (the_passwd.pw_name, name);
/* Determine a reasonable uid value. */
@@ -271,7 +440,7 @@
{
SID_IDENTIFIER_AUTHORITY * pSIA;
- pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
+ pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
/* I believe the relative portion is the last 4 bytes (of 6)
with msb first. */
the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
@@ -282,12 +451,12 @@
the_passwd.pw_uid = the_passwd.pw_uid % 60001;
/* Get group id */
- if (GetTokenInformation (token, TokenPrimaryGroup,
+ if (get_token_information (token, TokenPrimaryGroup,
(PVOID) user_sid, sizeof (user_sid), &trash))
{
SID_IDENTIFIER_AUTHORITY * pSIA;
- pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
+ pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
(pSIA->Value[3] << 16) +
(pSIA->Value[4] << 8) +
--- _21.3/src/w32.h 2002-05-03 16:41:03.000000000 -0400
+++ 21.3/src/w32.h 2002-11-15 12:44:48.000000000 -0500
@@ -124,5 +124,10 @@
extern void init_ntproc ();
extern void term_ntproc ();
+extern void syms_of_w32term ();
+extern void syms_of_w32fns ();
+extern void syms_of_w32select ();
+extern void syms_of_w32menu ();
+extern void syms_of_fontset ();
#endif /* EMACS_W32_H */
--- _21.3/src/w32fns.c 2002-10-23 12:55:07.000000000 -0400
+++ 21.3/src/w32fns.c 2002-11-15 12:44:48.000000000 -0500
@@ -283,7 +283,12 @@
/* Window that is tracking the mouse. */
static HWND track_mouse_window;
-FARPROC track_mouse_event_fn;
+
+typedef BOOL (WINAPI * TrackMouseEvent_Proc) (
+ IN OUT LPTRACKMOUSEEVENT lpEventTrack
+ );
+
+TrackMouseEvent_Proc track_mouse_event_fn=NULL;
/* W95 mousewheel handler */
unsigned int msh_mousewheel = 0;
@@ -4929,6 +4934,30 @@
goto dflt;
case WM_SETFOCUS:
+ /*
+ Reinitialize the function pointer track_mouse_event_fn here.
+ This is required even though it is initialized in syms_of_w32fns
+ which is called in main (emacs.c).
+ Reinitialize the function pointer track_mouse_event_fn here.
+ Even though this function pointer is initialized in
+ syms_of_w32fns which is called from main (emacs.c),
+ we need to initialize it again here in order to prevent
+ a crash that occurs in Windows 9x (possibly only when Emacs
+ was built on Windows NT / 2000 / XP?) when handling the
+ WM_MOUSEMOVE message.
+ The crash occurs when attempting to call the Win32 API
+ function TrackMouseEvent through the function pointer.
+ It appears as if the function pointer that is obtained when
+ syms_of_w32fns is called from main is no longer valid
+ (possibly due to DLL relocation?).
+ To resolve this issue, I have placed a call to reinitialize
+ this function pointer here because this message gets received
+ when the Emacs window gains focus.
+ */
+ track_mouse_event_fn =
+ (TrackMouseEvent_Proc) GetProcAddress (
+ GetModuleHandle ("user32.dll"),
+ "TrackMouseEvent");
dpyinfo->faked_key = 0;
reset_modifiers ();
register_hot_keys (hwnd);
@@ -14801,7 +14830,7 @@
/* TrackMouseEvent not available in all versions of Windows, so must load
it dynamically. Do it once, here, instead of every time it is used. */
- track_mouse_event_fn = GetProcAddress (user32_lib, "TrackMouseEvent");
+ track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
track_mouse_window = NULL;
w32_visible_system_caret_hwnd = NULL;
--- _21.3/src/w32menu.c 2002-08-05 12:33:44.000000000 -0400
+++ 21.3/src/w32menu.c 2002-11-15 12:44:48.000000000 -0500
@@ -129,8 +129,23 @@
static HMENU current_popup_menu;
-FARPROC get_menu_item_info;
-FARPROC set_menu_item_info;
+void syms_of_w32menu ();
+
+typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
+ IN HMENU,
+ IN UINT,
+ IN BOOL,
+ IN OUT LPMENUITEMINFOA
+ );
+typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
+ IN HMENU,
+ IN UINT,
+ IN BOOL,
+ IN LPCMENUITEMINFOA
+ );
+
+GetMenuItemInfoA_Proc get_menu_item_info=NULL;
+SetMenuItemInfoA_Proc set_menu_item_info=NULL;
Lisp_Object Vmenu_updating_frame;
@@ -1591,6 +1606,26 @@
initialize_frame_menubar (f)
FRAME_PTR f;
{
+ HMODULE user32 = GetModuleHandle ("user32.dll");
+ /*
+ Reinitialize the function pointers set_menu_item_info and
+ get_menu_item_info here.
+ Even though these function pointers are initialized in
+ syms_of_w32menu which is called from main (emacs.c),
+ we need to initialize them again here in order to prevent
+ a crash that occurs in Windows 9x (possibly only when Emacs
+ was built on Windows NT / 2000 / XP?) in add_menu_item.
+ The crash occurs when attempting to call the Win32 API
+ function SetMenuItemInfo through the function pointer.
+ It appears as if the function pointer that is obtained when
+ syms_of_w32menu is called from main is no longer valid
+ (possibly due to DLL relocation?).
+ To resolve this issue, I have placed calls to reinitialize
+ these function pointers here because this function is the
+ entry point for menu creation.
+ */
+ get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
+ set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
@@ -2355,13 +2390,12 @@
#endif /* HAVE_MENUS */
-\f
-syms_of_w32menu ()
+void syms_of_w32menu ()
{
/* See if Get/SetMenuItemInfo functions are available. */
HMODULE user32 = GetModuleHandle ("user32.dll");
- get_menu_item_info = GetProcAddress (user32, "GetMenuItemInfoA");
- set_menu_item_info = GetProcAddress (user32, "SetMenuItemInfoA");
+ get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
+ set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
staticpro (&menu_items);
menu_items = Qnil;
[-- Attachment #3: dopatch21_3.sh --]
[-- Type: application/octet-stream, Size: 406 bytes --]
#!/bin/sh
if [ -f emacs-21.3.50-w32-play-sound.diff ]
then
echo "Applying patch emacs-21.3.50-w32-play-sound.diff"
patch --unified --quiet --strip=1 --input=emacs-21.3.50-w32-play-sound.diff
fi
if [ -f emacs-21.3.50-windows-crash-fix.diff ]
then
echo "Applying patch emacs-21.3.50-windows-crash-fix.diff"
patch --unified --quiet --strip=1 --input=emacs-21.3.50-windows-crash-fix.diff
fi
[-- Attachment #4: emacs-21.3.50-w32-play-sound.diff --]
[-- Type: application/octet-stream, Size: 17950 bytes --]
--- _21.3/nt/nmake.defs 2002-01-04 09:04:53.000000000 -0500
+++ 21.3/nt/nmake.defs 2002-11-15 12:44:48.000000000 -0500
@@ -123,6 +123,7 @@
SHELL32 = shell32.lib
USER32 = user32.lib
WSOCK32 = wsock32.lib
+WINMM = winmm.lib
!ifdef NOOPT
DEBUG_CFLAGS = -DEMACSDEBUG
--- _21.3/nt/gmake.defs 2002-01-04 09:04:26.000000000 -0500
+++ 21.3/nt/gmake.defs 2002-11-15 12:44:48.000000000 -0500
@@ -166,6 +166,7 @@
SHELL32 = -lshell32
USER32 = -luser32
WSOCK32 = -lwsock32
+WINMM = -lwinmm
ifdef NOOPT
DEBUG_CFLAGS = -DEMACSDEBUG
--- _21.3/src/makefile.w32-in 2002-09-04 02:20:50.000000000 -0400
+++ 21.3/src/makefile.w32-in 2002-11-15 12:44:48.000000000 -0500
@@ -94,6 +94,7 @@
$(BLD)/regex.$(O) \
$(BLD)/scroll.$(O) \
$(BLD)/search.$(O) \
+ $(BLD)/sound.$(O) \
$(BLD)/syntax.$(O) \
$(BLD)/sysdep.$(O) \
$(BLD)/term.$(O) \
@@ -133,6 +134,7 @@
$(TLIB1) \
$(TLIBW32) \
$(TLASTLIB) \
+ $(WINMM) \
$(ADVAPI32) \
$(GDI32) \
$(COMDLG32) \
@@ -1094,6 +1096,13 @@
$(SRC)/w32bdf.h \
$(SRC)/w32gui.h
+$(BLD)/sound.$(O) : \
+ $(SRC)/sound.c \
+ $(SRC)/lisp.h \
+ $(SRC)/dispextern.h \
+ $(SRC)/atimer.h \
+ $(SRC)/syssignal.h
+
$(BLD)/strftime.$(O) : \
$(SRC)/strftime.c \
$(EMACS_ROOT)/src/s/ms-w32.h \
--- _21.3/src/s/ms-w32.h 2002-05-03 16:42:33.000000000 -0400
+++ 21.3/src/s/ms-w32.h 2002-11-15 12:44:48.000000000 -0500
@@ -217,6 +217,7 @@
#define MAXPATHLEN _MAX_PATH
#endif
+#define HAVE_SOUND 1
#define LISP_FLOAT_TYPE 1
#undef HAVE_SYS_SELECT_H
--- _21.3/src/sound.c 2002-07-19 10:27:20.000000000 -0400
+++ 21.3/src/sound.c 2002-11-15 12:44:48.000000000 -0500
@@ -21,10 +21,26 @@
/* Written by Gerd Moellmann <gerd@gnu.org>. Tested with Luigi's
driver on FreeBSD 2.2.7 with a SoundBlaster 16. */
+/*
+ Modified by Ben Key <Bkey1@tampabay.rr.com> to add a partial
+ implementation of the play-sound specification for Windows.
+
+ Notes:
+ In the Windows implementation of play-sound-internal only the
+ :file and :volume keywords are supported. The :device keyword,
+ if present, is ignored. The :data keyword, if present, will
+ cause an error to be generated.
+
+ The Windows implementation of play-sound is implemented via the
+ Win32 API functions mciSendString, waveOutGetVolume, and
+ waveOutGetVolume which are exported by Winmm.dll.
+*/
+
#include <config.h>
#if defined HAVE_SOUND
+/* BEGIN: Common Includes */
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
@@ -34,6 +50,11 @@
#include "atimer.h"
#include <signal.h>
#include "syssignal.h"
+/* END: Common Includes */
+
+
+/* BEGIN: Non Windows Includes */
+#ifndef WINDOWSNT
#ifndef MSDOS
#include <sys/ioctl.h>
@@ -51,12 +72,55 @@
#ifdef HAVE_SOUNDCARD_H
#include <soundcard.h>
#endif
+/* END: Non Windows Includes */
+
+#else /* WINDOWSNT */
+
+/* BEGIN: Windows Specific Includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <windows.h>
+#include <mmsystem.h>
+/* END: Windows Specific Includes */
+
+#endif /* WINDOWSNT */
+
+/* BEGIN: Common Definitions */
+#define abs(X) ((X) < 0 ? -(X) : (X))
+
+/* Symbols. */
+
+extern Lisp_Object QCfile, QCdata;
+Lisp_Object QCvolume, QCdevice;
+Lisp_Object Qsound;
+Lisp_Object Qplay_sound_functions;
+
+/* Indices of attributes in a sound attributes vector. */
+
+enum sound_attr
+{
+ SOUND_FILE,
+ SOUND_DATA,
+ SOUND_DEVICE,
+ SOUND_VOLUME,
+ SOUND_ATTR_SENTINEL
+};
+
+static void sound_perror P_ ((char *));
+static void sound_warning P_ ((char *));
+static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
+
+/* END: Common Definitions */
+
+/* BEGIN: Non Windows Definitions */
+#ifndef WINDOWSNT
#ifndef DEFAULT_SOUND_DEVICE
#define DEFAULT_SOUND_DEVICE "/dev/dsp"
#endif
-#define abs(X) ((X) < 0 ? -(X) : (X))
/* Structure forward declarations. */
@@ -203,24 +267,6 @@
void (* play) P_ ((struct sound *s, struct sound_device *sd));
};
-/* Indices of attributes in a sound attributes vector. */
-
-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;
-
/* These are set during `play-sound-internal' so that sound_cleanup has
access to them. */
@@ -235,9 +281,6 @@
static void vox_choose_format P_ ((struct sound_device *, struct sound *));
static void vox_init P_ ((struct sound_device *));
static void vox_write P_ ((struct sound_device *, const char *, int));
-static void sound_perror P_ ((char *));
-static void sound_warning P_ ((char *));
-static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
static void find_sound_type P_ ((struct sound *));
static u_int32_t le2hl P_ ((u_int32_t));
static u_int16_t le2hs P_ ((u_int16_t));
@@ -251,12 +294,22 @@
static u_int16_t be2hs P_ ((u_int16_t));
#endif
+/* END: Non Windows Definitions */
+#else /* WINDOWSNT */
+
+/* BEGIN: Windows Specific Definitions */
+static int do_play_sound P_ ((const char *, unsigned long));
+/*
+ END: Windows Specific Definitions */
+#endif /* WINDOWSNT */
\f
/***********************************************************************
General
***********************************************************************/
+/* BEGIN: Common functions */
+
/* Like perror, but signals an error. */
static void
@@ -327,10 +380,21 @@
attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
+#ifndef WINDOWSNT
/* File name or data must be specified. */
if (!STRINGP (attrs[SOUND_FILE])
&& !STRINGP (attrs[SOUND_DATA]))
return 0;
+#else /* WINDOWSNT */
+ /*
+ Data is not supported in Windows. Therefore a
+ File name MUST be supplied.
+ */
+ if (!STRINGP (attrs[SOUND_FILE]))
+ {
+ return 0;
+ }
+#endif /* WINDOWSNT */
/* Volume must be in the range 0..100 or unspecified. */
if (!NILP (attrs[SOUND_VOLUME]))
@@ -351,14 +415,23 @@
return 0;
}
+#ifndef WINDOWSNT
/* Device must be a string or unspecified. */
if (!NILP (attrs[SOUND_DEVICE])
&& !STRINGP (attrs[SOUND_DEVICE]))
return 0;
-
+#endif /* WINDOWSNT */
+ /*
+ Since device is ignored in Windows, it does not matter
+ what it is.
+ */
return 1;
}
+/* END: Common functions */
+
+/* BEGIN: Non Windows functions */
+#ifndef WINDOWSNT
/* Find out the type of the sound file whose file descriptor is FD.
S is the sound file structure to fill in. */
@@ -389,105 +462,6 @@
return Qnil;
}
-
-DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
- doc: /* Play sound SOUND.
-
-Internal use only, use `play-sound' instead. */)
- (sound)
- Lisp_Object sound;
-{
- Lisp_Object attrs[SOUND_ATTR_SENTINEL];
- Lisp_Object file;
- struct gcpro gcpro1, gcpro2;
- struct sound_device sd;
- struct sound s;
- Lisp_Object args[2];
- int count = SPECPDL_INDEX ();
-
- file = Qnil;
- GCPRO2 (sound, file);
- bzero (&sd, sizeof sd);
- bzero (&s, sizeof s);
- current_sound_device = &sd;
- current_sound = &s;
- record_unwind_protect (sound_cleanup, Qnil);
- s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
-
- /* Parse the sound specification. Give up if it is invalid. */
- if (!parse_sound (sound, attrs))
- error ("Invalid sound specification");
-
- if (STRINGP (attrs[SOUND_FILE]))
- {
- /* Open the sound file. */
- s.fd = openp (Fcons (Vdata_directory, Qnil),
- attrs[SOUND_FILE], Qnil, &file, Qnil);
- if (s.fd < 0)
- sound_perror ("Could not open sound file");
-
- /* Read the first bytes from the file. */
- s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES);
- if (s.header_size < 0)
- sound_perror ("Invalid sound file header");
- }
- else
- {
- s.data = attrs[SOUND_DATA];
- s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));
- bcopy (SDATA (s.data), s.header, s.header_size);
- }
-
- /* Find out the type of sound. Give up if we can't tell. */
- find_sound_type (&s);
-
- /* Set up a device. */
- if (STRINGP (attrs[SOUND_DEVICE]))
- {
- int len = SCHARS (attrs[SOUND_DEVICE]);
- sd.file = (char *) alloca (len + 1);
- strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));
- }
-
- if (INTEGERP (attrs[SOUND_VOLUME]))
- sd.volume = XFASTINT (attrs[SOUND_VOLUME]);
- else if (FLOATP (attrs[SOUND_VOLUME]))
- sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
-
- args[0] = Qplay_sound_functions;
- args[1] = sound;
- Frun_hook_with_args (2, args);
-
- /* There is only one type of device we currently support, the VOX
- sound driver. Set up the device interface functions for that
- device. */
- vox_init (&sd);
-
- /* Open the device. */
- sd.open (&sd);
-
- /* Play the sound. */
- s.play (&s, &sd);
-
- /* Close the input file, if any. */
- if (!STRINGP (s.data))
- {
- emacs_close (s.fd);
- s.fd = -1;
- }
-
- /* Close the device. */
- sd.close (&sd);
-
- /* Clean up. */
- current_sound_device = NULL;
- current_sound = NULL;
- UNGCPRO;
- unbind_to (count, Qnil);
- return Qnil;
-}
-
-\f
/***********************************************************************
Byte-order Conversion
***********************************************************************/
@@ -555,7 +529,6 @@
#endif /* 0 */
-\f
/***********************************************************************
RIFF-WAVE (*.wav)
***********************************************************************/
@@ -645,7 +618,6 @@
}
-\f
/***********************************************************************
Sun Audio (*.au)
***********************************************************************/
@@ -735,7 +707,6 @@
}
-\f
/***********************************************************************
Voxware Driver Interface
***********************************************************************/
@@ -909,7 +880,6 @@
sd->write = vox_write;
}
-
/* Write NBYTES bytes from BUFFER to device SD. */
static void
@@ -923,7 +893,231 @@
sound_perror ("Error writing to sound device");
}
+/* END: Non Windows functions */
+#else /* WINDOWSNT */
+/* BEGIN: Windows specific functions */
+
+static int
+do_play_sound (psz_file, ui_volume)
+ const char * psz_file;
+ unsigned long ui_volume;
+{
+ int i_result=0;
+ MCIERROR mci_error=0;
+ char sz_cmd_buf[520]={0};
+ char sz_ret_buf[520]={0};
+ MMRESULT mm_result=MMSYSERR_NOERROR;
+ unsigned long ui_volume_org=0;
+ BOOL b_reset_volume=FALSE;
+ memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
+ memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
+ sprintf (
+ sz_cmd_buf,
+ "open \"%s\" alias GNUEmacs_PlaySound_Device wait",
+ psz_file);
+ mci_error=mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
+ if (mci_error != 0)
+ {
+ sound_warning (
+ "The open mciSendString command failed to open\n"
+ "the specified sound file");
+ i_result=(int)mci_error;
+ return i_result;
+ }
+ if ((ui_volume > 0) && (ui_volume != UINT_MAX))
+ {
+ mm_result=waveOutGetVolume ((HWAVEOUT)WAVE_MAPPER, &ui_volume_org);
+ if (mm_result == MMSYSERR_NOERROR)
+ {
+ b_reset_volume=TRUE;
+ mm_result=waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, ui_volume);
+ if ( mm_result != MMSYSERR_NOERROR)
+ {
+ sound_warning (
+ "waveOutSetVolume failed to set the volume level\n"
+ "of the WAVE_MAPPER device.\n"
+ "As a result, the user selected volume level will\n"
+ "not be used.");
+ }
+ }
+ else
+ {
+ sound_warning (
+ "waveOutGetVolume failed to obtain the original\n"
+ "volume level of the WAVE_MAPPER device.\n"
+ "As a result, the user selected volume level will\n"
+ "not be used.");
+ }
+ }
+ memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
+ memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
+ strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait");
+ mci_error=mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
+ if (mci_error != 0)
+ {
+ sound_warning (
+ "The play mciSendString command failed to play the\n"
+ "opened sound file.");
+ i_result=(int)mci_error;
+ }
+ memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
+ memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
+ strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait");
+ mci_error=mciSendString ( sz_cmd_buf, sz_ret_buf, 520, NULL);
+ if (b_reset_volume == TRUE)
+ {
+ mm_result=waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, ui_volume_org);
+ if (mm_result != MMSYSERR_NOERROR)
+ {
+ sound_warning (
+ "waveOutSetVolume failed to reset the original volume\n"
+ "level of the WAVE_MAPPER device.");
+ }
+ }
+ return i_result;
+}
+
+/* END: Windows specific functions */
+
+#endif /* WINDOWSNT */
+
+
+DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
+ doc: /* Play sound SOUND.
+
+Internal use only, use `play-sound' instead.\n */)
+ (sound)
+ Lisp_Object sound;
+{
+ Lisp_Object attrs[SOUND_ATTR_SENTINEL];
+ int count = SPECPDL_INDEX ();
+
+#ifndef WINDOWSNT
+ Lisp_Object file;
+ struct gcpro gcpro1, gcpro2;
+ struct sound_device sd;
+ struct sound s;
+ Lisp_Object args[2];
+#else /* WINDOWSNT */
+ int len=0;
+ Lisp_Object lo_file={0};
+ char * psz_file=NULL;
+ unsigned long ui_volume_tmp=UINT_MAX;
+ unsigned long ui_volume=UINT_MAX;
+ int i_result=0;
+#endif /* WINDOWSNT */
+
+ /* Parse the sound specification. Give up if it is invalid. */
+ if (!parse_sound (sound, attrs))
+ error ("Invalid sound specification");
+
+#ifndef WINDOWSNT
+ file = Qnil;
+ GCPRO2 (sound, file);
+ bzero (&sd, sizeof sd);
+ bzero (&s, sizeof s);
+ current_sound_device = &sd;
+ current_sound = &s;
+ record_unwind_protect (sound_cleanup, Qnil);
+ s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
+
+ if (STRINGP (attrs[SOUND_FILE]))
+ {
+ /* Open the sound file. */
+ s.fd = openp (Fcons (Vdata_directory, Qnil),
+ attrs[SOUND_FILE], Qnil, &file, Qnil);
+ if (s.fd < 0)
+ sound_perror ("Could not open sound file");
+
+ /* Read the first bytes from the file. */
+ s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES);
+ if (s.header_size < 0)
+ sound_perror ("Invalid sound file header");
+ }
+ else
+ {
+ s.data = attrs[SOUND_DATA];
+ s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));
+ bcopy (SDATA (s.data), s.header, s.header_size);
+ }
+
+ /* Find out the type of sound. Give up if we can't tell. */
+ find_sound_type (&s);
+
+ /* Set up a device. */
+ if (STRINGP (attrs[SOUND_DEVICE]))
+ {
+ int len = SCHARS (attrs[SOUND_DEVICE]);
+ sd.file = (char *) alloca (len + 1);
+ strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));
+ }
+
+ if (INTEGERP (attrs[SOUND_VOLUME]))
+ sd.volume = XFASTINT (attrs[SOUND_VOLUME]);
+ else if (FLOATP (attrs[SOUND_VOLUME]))
+ sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
+
+ args[0] = Qplay_sound_functions;
+ args[1] = sound;
+ Frun_hook_with_args (2, args);
+
+ /* There is only one type of device we currently support, the VOX
+ sound driver. Set up the device interface functions for that
+ device. */
+ vox_init (&sd);
+
+ /* Open the device. */
+ sd.open (&sd);
+
+ /* Play the sound. */
+ s.play (&s, &sd);
+
+ /* Close the input file, if any. */
+ if (!STRINGP (s.data))
+ {
+ emacs_close (s.fd);
+ s.fd = -1;
+ }
+
+ /* Close the device. */
+ sd.close (&sd);
+
+ /* Clean up. */
+ current_sound_device = NULL;
+ current_sound = NULL;
+ UNGCPRO;
+#else /* WINDOWSNT */
+ lo_file=Fexpand_file_name (attrs[SOUND_FILE], Qnil);
+ len=XSTRING (lo_file)->size;
+ psz_file=(char *)alloca (len+1);
+ strcpy (psz_file, XSTRING (lo_file)->data);
+ if (INTEGERP (attrs[SOUND_VOLUME]))
+ {
+ ui_volume_tmp=XFASTINT (attrs[SOUND_VOLUME]);
+ }
+ else if (FLOATP (attrs[SOUND_VOLUME]))
+ {
+ ui_volume_tmp=(unsigned long)XFLOAT_DATA (attrs[SOUND_VOLUME])*100;
+ }
+ /*
+ Based on some experiments I have conducted, a value of 100 or less
+ for the sound volume is much too low. You cannot even hear it.
+ A value of UINT_MAX indicates that you wish for the sound to played
+ at the maximum possible volume. A value of UINT_MAX/2 plays the
+ sound at 50% maximum volume. Therefore the value passed to do_play_sound
+ (and thus to waveOutSetVolume must be some fraction of UINT_MAX.
+ The following code adjusts the user specified volume level appropriately.
+ */
+ if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100))
+ {
+ ui_volume=ui_volume_tmp * (UINT_MAX / 100);
+ }
+ i_result=do_play_sound (psz_file, ui_volume);
+#endif /* WINDOWSNT */
+ unbind_to (count, Qnil);
+ return Qnil;
+}
\f
/***********************************************************************
Initialization
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2002-11-16 4:04 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-16 4:04 Patches for Gnu Emacs Ben Key
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.