aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-09-15 18:51:57 +0300
committerEli Zaretskii2014-09-15 18:51:57 +0300
commita7fc3ab8f1e7061a468eaff0c0b47abd12c99003 (patch)
tree5cccc74a0ca4ede4cbeaf82f0c876465a1c0ee69 /src
parentedb0288b83b45d295df52ce7644e897613358971 (diff)
downloademacs-a7fc3ab8f1e7061a468eaff0c0b47abd12c99003.tar.gz
emacs-a7fc3ab8f1e7061a468eaff0c0b47abd12c99003.zip
Support playing on MS-Windows non-ASCII sound files using Unicode APIs.
src/sound.c [WINDOWSNT]: Include w32common.h and mbstring.h. (SOUND_WARNING) [WINDOWSNT]: Include in do..while and improve the error message format. Use message_with_string to have non-ASCII file names properly displayed. (do_play_sound) [WINDOWSNT]: Use Unicode APIs to play sound files when w32-unicode-filenames is non-nil, but not on Windows 9X, where these APIs are not available even in UNICOWS.DLL. Improve the format of error messages and include the file name in them where appropriate. (Fplay_sound_internal) [WINDOWSNT]: Make the MS-Windows branch call play-sound-functions, per documentation. src/w32.c (w32_get_long_filename, w32_get_short_filename): Constify the input file name arguments. src/w32.h (w32_get_long_filename, w32_get_short_filename): Update prototypes.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog20
-rw-r--r--src/sound.c158
-rw-r--r--src/w32.c4
-rw-r--r--src/w32.h4
4 files changed, 130 insertions, 56 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 185a6c4bd40..2258f58299e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,23 @@
12014-09-15 Eli Zaretskii <eliz@gnu.org>
2
3 * sound.c [WINDOWSNT]: Include w32common.h and mbstring.h.
4 (SOUND_WARNING) [WINDOWSNT]: Include in do..while and improve the
5 error message format. Use message_with_string to have non-ASCII
6 file names properly displayed.
7 (do_play_sound) [WINDOWSNT]: Use Unicode APIs to play sound files
8 when w32-unicode-filenames is non-nil, but not on Windows 9X,
9 where these APIs are not available even in UNICOWS.DLL. Improve
10 the format of error messages and include the file name in them
11 where appropriate.
12 (Fplay_sound_internal) [WINDOWSNT]: Make the MS-Windows branch
13 call play-sound-functions, per documentation.
14
15 * w32.c (w32_get_long_filename, w32_get_short_filename): Constify
16 the input file name arguments.
17
18 * w32.h (w32_get_long_filename, w32_get_short_filename): Update
19 prototypes.
20
12014-09-15 Dmitry Antipov <dmantipov@yandex.ru> 212014-09-15 Dmitry Antipov <dmantipov@yandex.ru>
2 22
3 If USE_LOCAL_ALLOCATORS, allocate some Lisp objects on stack. 23 If USE_LOCAL_ALLOCATORS, allocate some Lisp objects on stack.
diff --git a/src/sound.c b/src/sound.c
index 7ba14b36f33..b49348f1256 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -86,10 +86,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
86/* BEGIN: Windows Specific Includes */ 86/* BEGIN: Windows Specific Includes */
87#include <stdio.h> 87#include <stdio.h>
88#include <limits.h> 88#include <limits.h>
89#include <mbstring.h>
89#include <windows.h> 90#include <windows.h>
90#include <mmsystem.h> 91#include <mmsystem.h>
91 92
92#include "coding.h" 93#include "coding.h"
94#include "w32common.h"
93#include "w32.h" 95#include "w32.h"
94/* END: Windows Specific Includes */ 96/* END: Windows Specific Includes */
95 97
@@ -1207,38 +1209,83 @@ alsa_init (struct sound_device *sd)
1207 1209
1208/* BEGIN: Windows specific functions */ 1210/* BEGIN: Windows specific functions */
1209 1211
1210#define SOUND_WARNING(fun, error, text) \ 1212#define SOUND_WARNING(func, error, text) \
1211 { \ 1213 do { \
1212 char buf[1024]; \ 1214 char buf[1024]; \
1213 char err_string[MAXERRORLENGTH]; \ 1215 char err_string[MAXERRORLENGTH]; \
1214 fun (error, err_string, sizeof (err_string)); \ 1216 func (error, err_string, sizeof (err_string)); \
1215 _snprintf (buf, sizeof (buf), "%s\nError: %s", \ 1217 _snprintf (buf, sizeof (buf), "%s\nMCI Error: %s", \
1216 text, err_string); \ 1218 text, err_string); \
1217 sound_warning (buf); \ 1219 message_with_string ("%s", build_string (buf), 1); \
1218 } 1220 } while (0)
1219 1221
1220static int 1222static int
1221do_play_sound (const char *psz_file, unsigned long ui_volume) 1223do_play_sound (const char *psz_file, unsigned long ui_volume)
1222{ 1224{
1223 int i_result = 0; 1225 int i_result = 0;
1224 MCIERROR mci_error = 0; 1226 MCIERROR mci_error = 0;
1225 char sz_cmd_buf[520] = {0}; 1227 char sz_cmd_buf_a[520];
1226 char sz_ret_buf[520] = {0}; 1228 char sz_ret_buf_a[520];
1227 MMRESULT mm_result = MMSYSERR_NOERROR; 1229 MMRESULT mm_result = MMSYSERR_NOERROR;
1228 unsigned long ui_volume_org = 0; 1230 unsigned long ui_volume_org = 0;
1229 BOOL b_reset_volume = FALSE; 1231 BOOL b_reset_volume = FALSE;
1232 char warn_text[560];
1230 1233
1231 memset (sz_cmd_buf, 0, sizeof (sz_cmd_buf)); 1234 /* Since UNICOWS.DLL includes only a stub for mciSendStringW, we
1232 memset (sz_ret_buf, 0, sizeof (sz_ret_buf)); 1235 need to encode the file in the ANSI codepage on Windows 9X even
1233 sprintf (sz_cmd_buf, 1236 if w32_unicode_filenames is non-zero. */
1234 "open \"%s\" alias GNUEmacs_PlaySound_Device wait", 1237 if (w32_major_version <= 4 || !w32_unicode_filenames)
1235 psz_file); 1238 {
1236 mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, sizeof (sz_ret_buf), NULL); 1239 char fname_a[MAX_PATH], shortname[MAX_PATH], *fname_to_use;
1240
1241 filename_to_ansi (psz_file, fname_a);
1242 fname_to_use = fname_a;
1243 /* If the file name is not encodable in ANSI, try its short 8+3
1244 alias. This will only work if w32_unicode_filenames is
1245 non-zero. */
1246 if (_mbspbrk ((const unsigned char *)fname_a,
1247 (const unsigned char *)"?"))
1248 {
1249 if (w32_get_short_filename (psz_file, shortname, MAX_PATH))
1250 fname_to_use = shortname;
1251 else
1252 mci_error = MCIERR_FILE_NOT_FOUND;
1253 }
1254
1255 if (!mci_error)
1256 {
1257 memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a));
1258 memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a));
1259 sprintf (sz_cmd_buf_a,
1260 "open \"%s\" alias GNUEmacs_PlaySound_Device wait",
1261 fname_to_use);
1262 mci_error = mciSendStringA (sz_cmd_buf_a,
1263 sz_ret_buf_a, sizeof (sz_ret_buf_a), NULL);
1264 }
1265 }
1266 else
1267 {
1268 wchar_t sz_cmd_buf_w[520];
1269 wchar_t sz_ret_buf_w[520];
1270 wchar_t fname_w[MAX_PATH];
1271
1272 filename_to_utf16 (psz_file, fname_w);
1273 memset (sz_cmd_buf_w, 0, sizeof (sz_cmd_buf_w));
1274 memset (sz_ret_buf_w, 0, sizeof (sz_ret_buf_w));
1275 /* _swprintf is not available on Windows 9X, so we construct the
1276 UTF-16 command string by hand. */
1277 wcscpy (sz_cmd_buf_w, L"open \"");
1278 wcscat (sz_cmd_buf_w, fname_w);
1279 wcscat (sz_cmd_buf_w, L"\" alias GNUEmacs_PlaySound_Device wait");
1280 mci_error = mciSendStringW (sz_cmd_buf_w,
1281 sz_ret_buf_w, ARRAYELTS (sz_ret_buf_w) , NULL);
1282 }
1237 if (mci_error != 0) 1283 if (mci_error != 0)
1238 { 1284 {
1239 SOUND_WARNING (mciGetErrorString, mci_error, 1285 strcpy (warn_text,
1240 "The open mciSendString command failed to open " 1286 "mciSendString: 'open' command failed to open sound file ");
1241 "the specified sound file."); 1287 strcat (warn_text, psz_file);
1288 SOUND_WARNING (mciGetErrorString, mci_error, warn_text);
1242 i_result = (int) mci_error; 1289 i_result = (int) mci_error;
1243 return i_result; 1290 return i_result;
1244 } 1291 }
@@ -1252,44 +1299,47 @@ do_play_sound (const char *psz_file, unsigned long ui_volume)
1252 if (mm_result != MMSYSERR_NOERROR) 1299 if (mm_result != MMSYSERR_NOERROR)
1253 { 1300 {
1254 SOUND_WARNING (waveOutGetErrorText, mm_result, 1301 SOUND_WARNING (waveOutGetErrorText, mm_result,
1255 "waveOutSetVolume failed to set the volume level " 1302 "waveOutSetVolume: failed to set the volume level"
1256 "of the WAVE_MAPPER device.\n" 1303 " of the WAVE_MAPPER device.\n"
1257 "As a result, the user selected volume level will " 1304 "As a result, the user selected volume level will"
1258 "not be used."); 1305 " not be used.");
1259 } 1306 }
1260 } 1307 }
1261 else 1308 else
1262 { 1309 {
1263 SOUND_WARNING (waveOutGetErrorText, mm_result, 1310 SOUND_WARNING (waveOutGetErrorText, mm_result,
1264 "waveOutGetVolume failed to obtain the original " 1311 "waveOutGetVolume: failed to obtain the original"
1265 "volume level of the WAVE_MAPPER device.\n" 1312 " volume level of the WAVE_MAPPER device.\n"
1266 "As a result, the user selected volume level will " 1313 "As a result, the user selected volume level will"
1267 "not be used."); 1314 " not be used.");
1268 } 1315 }
1269 } 1316 }
1270 memset (sz_cmd_buf, 0, sizeof (sz_cmd_buf)); 1317 memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a));
1271 memset (sz_ret_buf, 0, sizeof (sz_ret_buf)); 1318 memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a));
1272 strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait"); 1319 strcpy (sz_cmd_buf_a, "play GNUEmacs_PlaySound_Device wait");
1273 mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, sizeof (sz_ret_buf), NULL); 1320 mci_error = mciSendStringA (sz_cmd_buf_a, sz_ret_buf_a, sizeof (sz_ret_buf_a),
1321 NULL);
1274 if (mci_error != 0) 1322 if (mci_error != 0)
1275 { 1323 {
1276 SOUND_WARNING (mciGetErrorString, mci_error, 1324 strcpy (warn_text,
1277 "The play mciSendString command failed to play the " 1325 "mciSendString: 'play' command failed to play sound file ");
1278 "opened sound file."); 1326 strcat (warn_text, psz_file);
1327 SOUND_WARNING (mciGetErrorString, mci_error, warn_text);
1279 i_result = (int) mci_error; 1328 i_result = (int) mci_error;
1280 } 1329 }
1281 memset (sz_cmd_buf, 0, sizeof (sz_cmd_buf)); 1330 memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a));
1282 memset (sz_ret_buf, 0, sizeof (sz_ret_buf)); 1331 memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a));
1283 strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait"); 1332 strcpy (sz_cmd_buf_a, "close GNUEmacs_PlaySound_Device wait");
1284 mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, sizeof (sz_ret_buf), NULL); 1333 mci_error = mciSendStringA (sz_cmd_buf_a, sz_ret_buf_a, sizeof (sz_ret_buf_a),
1334 NULL);
1285 if (b_reset_volume == TRUE) 1335 if (b_reset_volume == TRUE)
1286 { 1336 {
1287 mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org); 1337 mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org);
1288 if (mm_result != MMSYSERR_NOERROR) 1338 if (mm_result != MMSYSERR_NOERROR)
1289 { 1339 {
1290 SOUND_WARNING (waveOutGetErrorText, mm_result, 1340 SOUND_WARNING (waveOutGetErrorText, mm_result,
1291 "waveOutSetVolume failed to reset the original volume " 1341 "waveOutSetVolume: failed to reset the original"
1292 "level of the WAVE_MAPPER device."); 1342 " volume level of the WAVE_MAPPER device.");
1293 } 1343 }
1294 } 1344 }
1295 return i_result; 1345 return i_result;
@@ -1307,13 +1357,11 @@ Internal use only, use `play-sound' instead. */)
1307{ 1357{
1308 Lisp_Object attrs[SOUND_ATTR_SENTINEL]; 1358 Lisp_Object attrs[SOUND_ATTR_SENTINEL];
1309 ptrdiff_t count = SPECPDL_INDEX (); 1359 ptrdiff_t count = SPECPDL_INDEX ();
1310
1311#ifndef WINDOWSNT
1312 Lisp_Object file; 1360 Lisp_Object file;
1313 struct gcpro gcpro1, gcpro2;
1314 Lisp_Object args[2]; 1361 Lisp_Object args[2];
1315#else /* WINDOWSNT */ 1362 struct gcpro gcpro1, gcpro2;
1316 Lisp_Object lo_file; 1363
1364#ifdef WINDOWSNT
1317 unsigned long ui_volume_tmp = UINT_MAX; 1365 unsigned long ui_volume_tmp = UINT_MAX;
1318 unsigned long ui_volume = UINT_MAX; 1366 unsigned long ui_volume = UINT_MAX;
1319#endif /* WINDOWSNT */ 1367#endif /* WINDOWSNT */
@@ -1386,11 +1434,8 @@ Internal use only, use `play-sound' instead. */)
1386 1434
1387#else /* WINDOWSNT */ 1435#else /* WINDOWSNT */
1388 1436
1389 lo_file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory); 1437 file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory);
1390 lo_file = ENCODE_FILE (lo_file); 1438 file = ENCODE_FILE (file);
1391 /* Since UNICOWS.DLL includes only a stub for mciSendStringW, we
1392 need to encode the file in the ANSI codepage. */
1393 lo_file = ansi_encode_filename (lo_file);
1394 if (INTEGERP (attrs[SOUND_VOLUME])) 1439 if (INTEGERP (attrs[SOUND_VOLUME]))
1395 { 1440 {
1396 ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]); 1441 ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]);
@@ -1399,6 +1444,13 @@ Internal use only, use `play-sound' instead. */)
1399 { 1444 {
1400 ui_volume_tmp = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100; 1445 ui_volume_tmp = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
1401 } 1446 }
1447
1448 GCPRO2 (sound, file);
1449
1450 args[0] = Qplay_sound_functions;
1451 args[1] = sound;
1452 Frun_hook_with_args (2, args);
1453
1402 /* 1454 /*
1403 Based on some experiments I have conducted, a value of 100 or less 1455 Based on some experiments I have conducted, a value of 100 or less
1404 for the sound volume is much too low. You cannot even hear it. 1456 for the sound volume is much too low. You cannot even hear it.
@@ -1412,7 +1464,9 @@ Internal use only, use `play-sound' instead. */)
1412 { 1464 {
1413 ui_volume = ui_volume_tmp * (UINT_MAX / 100); 1465 ui_volume = ui_volume_tmp * (UINT_MAX / 100);
1414 } 1466 }
1415 do_play_sound (SDATA (lo_file), ui_volume); 1467 (void)do_play_sound (SSDATA (file), ui_volume);
1468
1469 UNGCPRO;
1416 1470
1417#endif /* WINDOWSNT */ 1471#endif /* WINDOWSNT */
1418 1472
diff --git a/src/w32.c b/src/w32.c
index 95e6d394ee0..f014cd73a76 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -2294,7 +2294,7 @@ get_long_basename (char * name, char * buf, int size)
2294 2294
2295/* Get long name for file, if possible (assumed to be absolute). */ 2295/* Get long name for file, if possible (assumed to be absolute). */
2296BOOL 2296BOOL
2297w32_get_long_filename (char * name, char * buf, int size) 2297w32_get_long_filename (const char * name, char * buf, int size)
2298{ 2298{
2299 char * o = buf; 2299 char * o = buf;
2300 char * p; 2300 char * p;
@@ -2345,7 +2345,7 @@ w32_get_long_filename (char * name, char * buf, int size)
2345} 2345}
2346 2346
2347unsigned int 2347unsigned int
2348w32_get_short_filename (char * name, char * buf, int size) 2348w32_get_short_filename (const char * name, char * buf, int size)
2349{ 2349{
2350 if (w32_unicode_filenames) 2350 if (w32_unicode_filenames)
2351 { 2351 {
diff --git a/src/w32.h b/src/w32.h
index 2cc179a0c36..e0aedcbffa2 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -144,10 +144,10 @@ extern char * w32_strerror (int error_no);
144extern int w32_valid_pointer_p (void *, int); 144extern int w32_valid_pointer_p (void *, int);
145 145
146/* Get long (aka "true") form of file name, if it exists. */ 146/* Get long (aka "true") form of file name, if it exists. */
147extern BOOL w32_get_long_filename (char * name, char * buf, int size); 147extern BOOL w32_get_long_filename (const char * name, char * buf, int size);
148 148
149/* Get the short (a.k.a. "8+3") form of a file name. */ 149/* Get the short (a.k.a. "8+3") form of a file name. */
150extern unsigned int w32_get_short_filename (char *, char *, int); 150extern unsigned int w32_get_short_filename (const char *, char *, int);
151 151
152/* Prepare our standard handles for proper inheritance by child processes. */ 152/* Prepare our standard handles for proper inheritance by child processes. */
153extern void prepare_standard_handles (int in, int out, 153extern void prepare_standard_handles (int in, int out,