X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/1e952f0a7a1d0cc533438dcad37db08d8af6855f..52b410c60aebeb769ec9580af25ca50df2a44751:/src/sound.c diff --git a/src/sound.c b/src/sound.c index 7046f4e8e3..b49348f125 100644 --- a/src/sound.c +++ b/src/sound.c @@ -86,8 +86,13 @@ along with GNU Emacs. If not, see . */ /* BEGIN: Windows Specific Includes */ #include #include +#include #include #include + +#include "coding.h" +#include "w32common.h" +#include "w32.h" /* END: Windows Specific Includes */ #endif /* WINDOWSNT */ @@ -564,12 +569,11 @@ wav_play (struct sound *s, struct sound_device *sd) SBYTES (s->data) - sizeof *header); else { - char *buffer; ptrdiff_t nbytes = 0; ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048; ptrdiff_t data_left = header->data_length; - - buffer = alloca (blksize); + USE_SAFE_ALLOCA; + char *buffer = SAFE_ALLOCA (blksize); lseek (s->fd, sizeof *header, SEEK_SET); while (data_left > 0 && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0) @@ -582,6 +586,7 @@ wav_play (struct sound *s, struct sound_device *sd) if (nbytes < 0) sound_perror ("Error reading sound file"); + SAFE_FREE (); } } @@ -656,19 +661,20 @@ au_play (struct sound *s, struct sound_device *sd) else { ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048; - char *buffer; ptrdiff_t nbytes; /* Seek */ lseek (s->fd, header->data_offset, SEEK_SET); /* Copy sound data to the device. */ - buffer = alloca (blksize); + USE_SAFE_ALLOCA; + char *buffer = SAFE_ALLOCA (blksize); while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0) sd->write (sd, buffer, nbytes); if (nbytes < 0) sound_perror ("Error reading sound file"); + SAFE_FREE (); } } @@ -1203,38 +1209,83 @@ alsa_init (struct sound_device *sd) /* BEGIN: Windows specific functions */ -#define SOUND_WARNING(fun, error, text) \ - { \ - char buf[1024]; \ - char err_string[MAXERRORLENGTH]; \ - fun (error, err_string, sizeof (err_string)); \ - _snprintf (buf, sizeof (buf), "%s\nError: %s", \ - text, err_string); \ - sound_warning (buf); \ - } +#define SOUND_WARNING(func, error, text) \ + do { \ + char buf[1024]; \ + char err_string[MAXERRORLENGTH]; \ + func (error, err_string, sizeof (err_string)); \ + _snprintf (buf, sizeof (buf), "%s\nMCI Error: %s", \ + text, err_string); \ + message_with_string ("%s", build_string (buf), 1); \ + } while (0) static int do_play_sound (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}; + char sz_cmd_buf_a[520]; + char sz_ret_buf_a[520]; MMRESULT mm_result = MMSYSERR_NOERROR; unsigned long ui_volume_org = 0; BOOL b_reset_volume = FALSE; + char warn_text[560]; + + /* Since UNICOWS.DLL includes only a stub for mciSendStringW, we + need to encode the file in the ANSI codepage on Windows 9X even + if w32_unicode_filenames is non-zero. */ + if (w32_major_version <= 4 || !w32_unicode_filenames) + { + char fname_a[MAX_PATH], shortname[MAX_PATH], *fname_to_use; + + filename_to_ansi (psz_file, fname_a); + fname_to_use = fname_a; + /* If the file name is not encodable in ANSI, try its short 8+3 + alias. This will only work if w32_unicode_filenames is + non-zero. */ + if (_mbspbrk ((const unsigned char *)fname_a, + (const unsigned char *)"?")) + { + if (w32_get_short_filename (psz_file, shortname, MAX_PATH)) + fname_to_use = shortname; + else + mci_error = MCIERR_FILE_NOT_FOUND; + } - 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, sizeof (sz_ret_buf), NULL); + if (!mci_error) + { + memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a)); + memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a)); + sprintf (sz_cmd_buf_a, + "open \"%s\" alias GNUEmacs_PlaySound_Device wait", + fname_to_use); + mci_error = mciSendStringA (sz_cmd_buf_a, + sz_ret_buf_a, sizeof (sz_ret_buf_a), NULL); + } + } + else + { + wchar_t sz_cmd_buf_w[520]; + wchar_t sz_ret_buf_w[520]; + wchar_t fname_w[MAX_PATH]; + + filename_to_utf16 (psz_file, fname_w); + memset (sz_cmd_buf_w, 0, sizeof (sz_cmd_buf_w)); + memset (sz_ret_buf_w, 0, sizeof (sz_ret_buf_w)); + /* _swprintf is not available on Windows 9X, so we construct the + UTF-16 command string by hand. */ + wcscpy (sz_cmd_buf_w, L"open \""); + wcscat (sz_cmd_buf_w, fname_w); + wcscat (sz_cmd_buf_w, L"\" alias GNUEmacs_PlaySound_Device wait"); + mci_error = mciSendStringW (sz_cmd_buf_w, + sz_ret_buf_w, ARRAYELTS (sz_ret_buf_w) , NULL); + } if (mci_error != 0) { - SOUND_WARNING (mciGetErrorString, mci_error, - "The open mciSendString command failed to open " - "the specified sound file."); + strcpy (warn_text, + "mciSendString: 'open' command failed to open sound file "); + strcat (warn_text, psz_file); + SOUND_WARNING (mciGetErrorString, mci_error, warn_text); i_result = (int) mci_error; return i_result; } @@ -1248,44 +1299,47 @@ do_play_sound (const char *psz_file, unsigned long ui_volume) if (mm_result != MMSYSERR_NOERROR) { SOUND_WARNING (waveOutGetErrorText, mm_result, - "waveOutSetVolume failed to set the volume level " - "of the WAVE_MAPPER device.\n" - "As a result, the user selected volume level will " - "not be used."); + "waveOutSetVolume: failed to set the volume level" + " of the WAVE_MAPPER device.\n" + "As a result, the user selected volume level will" + " not be used."); } } else { SOUND_WARNING (waveOutGetErrorText, mm_result, - "waveOutGetVolume failed to obtain the original " - "volume level of the WAVE_MAPPER device.\n" - "As a result, the user selected volume level will " - "not be used."); + "waveOutGetVolume: failed to obtain the original" + " volume level of the WAVE_MAPPER device.\n" + "As a result, the user selected volume level will" + " 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, sizeof (sz_ret_buf), NULL); + memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a)); + memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a)); + strcpy (sz_cmd_buf_a, "play GNUEmacs_PlaySound_Device wait"); + mci_error = mciSendStringA (sz_cmd_buf_a, sz_ret_buf_a, sizeof (sz_ret_buf_a), + NULL); if (mci_error != 0) { - SOUND_WARNING (mciGetErrorString, mci_error, - "The play mciSendString command failed to play the " - "opened sound file."); + strcpy (warn_text, + "mciSendString: 'play' command failed to play sound file "); + strcat (warn_text, psz_file); + SOUND_WARNING (mciGetErrorString, mci_error, warn_text); 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, sizeof (sz_ret_buf), NULL); + memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a)); + memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a)); + strcpy (sz_cmd_buf_a, "close GNUEmacs_PlaySound_Device wait"); + mci_error = mciSendStringA (sz_cmd_buf_a, sz_ret_buf_a, sizeof (sz_ret_buf_a), + NULL); if (b_reset_volume == TRUE) { mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org); if (mm_result != MMSYSERR_NOERROR) { SOUND_WARNING (waveOutGetErrorText, mm_result, - "waveOutSetVolume failed to reset the original volume " - "level of the WAVE_MAPPER device."); + "waveOutSetVolume: failed to reset the original" + " volume level of the WAVE_MAPPER device."); } } return i_result; @@ -1303,15 +1357,11 @@ Internal use only, use `play-sound' instead. */) { Lisp_Object attrs[SOUND_ATTR_SENTINEL]; ptrdiff_t count = SPECPDL_INDEX (); - -#ifndef WINDOWSNT Lisp_Object file; - struct gcpro gcpro1, gcpro2; Lisp_Object args[2]; -#else /* WINDOWSNT */ - int len = 0; - Lisp_Object lo_file = {0}; - char * psz_file = NULL; + struct gcpro gcpro1, gcpro2; + +#ifdef WINDOWSNT unsigned long ui_volume_tmp = UINT_MAX; unsigned long ui_volume = UINT_MAX; #endif /* WINDOWSNT */ @@ -1326,7 +1376,8 @@ Internal use only, use `play-sound' instead. */) current_sound_device = xzalloc (sizeof *current_sound_device); current_sound = xzalloc (sizeof *current_sound); record_unwind_protect_void (sound_cleanup); - current_sound->header = alloca (MAX_SOUND_HEADER_BYTES); + char headerbuf[MAX_SOUND_HEADER_BYTES]; + current_sound->header = headerbuf; if (STRINGP (attrs[SOUND_FILE])) { @@ -1383,10 +1434,8 @@ Internal use only, use `play-sound' instead. */) #else /* WINDOWSNT */ - lo_file = Fexpand_file_name (attrs[SOUND_FILE], Qnil); - len = XSTRING (lo_file)->size; - psz_file = alloca (len + 1); - strcpy (psz_file, XSTRING (lo_file)->data); + file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory); + file = ENCODE_FILE (file); if (INTEGERP (attrs[SOUND_VOLUME])) { ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]); @@ -1395,6 +1444,13 @@ Internal use only, use `play-sound' instead. */) { ui_volume_tmp = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100; } + + GCPRO2 (sound, file); + + args[0] = Qplay_sound_functions; + args[1] = sound; + Frun_hook_with_args (2, args); + /* 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. @@ -1408,7 +1464,9 @@ Internal use only, use `play-sound' instead. */) { ui_volume = ui_volume_tmp * (UINT_MAX / 100); } - do_play_sound (psz_file, ui_volume); + (void)do_play_sound (SSDATA (file), ui_volume); + + UNGCPRO; #endif /* WINDOWSNT */