emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] trunk r117886: Support playing on MS-Windows non-ASCII sou


From: Eli Zaretskii
Subject: [Emacs-diffs] trunk r117886: Support playing on MS-Windows non-ASCII sound files using Unicode APIs.
Date: Mon, 15 Sep 2014 15:53:37 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 117886
revision-id: address@hidden
parent: address@hidden
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Mon 2014-09-15 18:51:57 +0300
message:
  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.
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/sound.c                    sound.c-20091113204419-o5vbwnq5f7feedwu-1323
  src/w32.c                      w32.c-20091113204419-o5vbwnq5f7feedwu-808
  src/w32.h                      w32.h-20091113204419-o5vbwnq5f7feedwu-809
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2014-09-15 14:53:23 +0000
+++ b/src/ChangeLog     2014-09-15 15:51:57 +0000
@@ -1,3 +1,23 @@
+2014-09-15  Eli Zaretskii  <address@hidden>
+
+       * 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.
+
+       * w32.c (w32_get_long_filename, w32_get_short_filename): Constify
+       the input file name arguments.
+
+       * w32.h (w32_get_long_filename, w32_get_short_filename): Update
+       prototypes.
+
 2014-09-15  Dmitry Antipov  <address@hidden>
 
        If USE_LOCAL_ALLOCATORS, allocate some Lisp objects on stack.

=== modified file 'src/sound.c'
--- a/src/sound.c       2014-09-15 00:20:21 +0000
+++ b/src/sound.c       2014-09-15 15:51:57 +0000
@@ -86,10 +86,12 @@
 /* BEGIN: Windows Specific Includes */
 #include <stdio.h>
 #include <limits.h>
+#include <mbstring.h>
 #include <windows.h>
 #include <mmsystem.h>
 
 #include "coding.h"
+#include "w32common.h"
 #include "w32.h"
 /* END: Windows Specific Includes */
 
@@ -1207,38 +1209,83 @@
 
 /* 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;
-
-  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);
+  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;
+       }
+
+      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;
     }
@@ -1252,44 +1299,47 @@
           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;
@@ -1307,13 +1357,11 @@
 {
   Lisp_Object attrs[SOUND_ATTR_SENTINEL];
   ptrdiff_t count = SPECPDL_INDEX ();
-
-#ifndef WINDOWSNT
   Lisp_Object file;
+  Lisp_Object args[2];
   struct gcpro gcpro1, gcpro2;
-  Lisp_Object args[2];
-#else /* WINDOWSNT */
-  Lisp_Object lo_file;
+
+#ifdef WINDOWSNT
   unsigned long ui_volume_tmp = UINT_MAX;
   unsigned long ui_volume = UINT_MAX;
 #endif /* WINDOWSNT */
@@ -1386,11 +1434,8 @@
 
 #else /* WINDOWSNT */
 
-  lo_file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory);
-  lo_file = ENCODE_FILE (lo_file);
-  /* Since UNICOWS.DLL includes only a stub for mciSendStringW, we
-     need to encode the file in the ANSI codepage.  */
-  lo_file = ansi_encode_filename (lo_file);
+  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]);
@@ -1399,6 +1444,13 @@
     {
       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.
@@ -1412,7 +1464,9 @@
     {
       ui_volume = ui_volume_tmp * (UINT_MAX / 100);
     }
-  do_play_sound (SDATA (lo_file), ui_volume);
+  (void)do_play_sound (SSDATA (file), ui_volume);
+
+  UNGCPRO;
 
 #endif /* WINDOWSNT */
 

=== modified file 'src/w32.c'
--- a/src/w32.c 2014-09-15 00:20:21 +0000
+++ b/src/w32.c 2014-09-15 15:51:57 +0000
@@ -2294,7 +2294,7 @@
 
 /* Get long name for file, if possible (assumed to be absolute).  */
 BOOL
-w32_get_long_filename (char * name, char * buf, int size)
+w32_get_long_filename (const char * name, char * buf, int size)
 {
   char * o = buf;
   char * p;
@@ -2345,7 +2345,7 @@
 }
 
 unsigned int
-w32_get_short_filename (char * name, char * buf, int size)
+w32_get_short_filename (const char * name, char * buf, int size)
 {
   if (w32_unicode_filenames)
     {

=== modified file 'src/w32.h'
--- a/src/w32.h 2014-08-29 19:18:06 +0000
+++ b/src/w32.h 2014-09-15 15:51:57 +0000
@@ -144,10 +144,10 @@
 extern int w32_valid_pointer_p (void *, int);
 
 /* Get long (aka "true") form of file name, if it exists.  */
-extern BOOL w32_get_long_filename (char * name, char * buf, int size);
+extern BOOL w32_get_long_filename (const char * name, char * buf, int size);
 
 /* Get the short (a.k.a. "8+3") form of a file name.  */
-extern unsigned int w32_get_short_filename (char *, char *, int);
+extern unsigned int w32_get_short_filename (const char *, char *, int);
 
 /* Prepare our standard handles for proper inheritance by child processes.  */
 extern void prepare_standard_handles (int in, int out,


reply via email to

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