all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
To: Leo Liu <sdl.web@gmail.com>
Cc: "Alex Schröder" <kensanata@gmail.com>, 3351@debbugs.gnu.org
Subject: bug#3351: 23.0.93; OSX sound support
Date: Mon, 18 Mar 2013 11:47:46 +0900	[thread overview]
Message-ID: <wlvc8pmnjh.wl%mituharu@math.s.chiba-u.ac.jp> (raw)
In-Reply-To: <wlwqt6zals.wl%mituharu@math.s.chiba-u.ac.jp>

>>>>> On Sun, 17 Mar 2013 17:36:31 +0900, YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> said:

>> Two conscious abuses (can be fixed):

>> - misuse (signal 'wrong-type-argument (list sound)); it requires the
>> first item of DATA to be a predicate but I decided not to add another
>> function.

>> - async; should probably use call-process to stay close to the C
>> version.

>> BTW, I only remember once in the past years needing the feature.

> Below is a quick hack for the Mac port (*) to have sound support.
> Perhaps one may use this as a hint.

> *: http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00251.html

Oops, I didn't realize that play-sound-internal was supposed to be
synchronous and unquittable.  Below is an updated one.

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp

=== modified file 'configure.ac'
*** configure.ac	2013-03-11 03:49:04 +0000
--- configure.ac	2013-03-18 02:36:18 +0000
***************
*** 2752,2757 ****
--- 2752,2758 ----
  ### Use Mac OS X GUI.
  if test "${HAVE_MACGUI}" = "yes"; then
    AC_DEFINE(HAVE_MACGUI, 1, [Define to 1 if you are using GUI on Mac OS X.])
+   AC_DEFINE(HAVE_SOUND, 1, [Define to 1 if you have sound support.])
    AC_CHECK_HEADERS(AvailabilityMacros.h)
    MAC_CFLAGS="-fconstant-cfstrings"
    ## Specify the install directory

=== modified file 'src/macappkit.h'
*** src/macappkit.h	2013-02-09 07:26:28 +0000
--- src/macappkit.h	2013-03-18 02:36:18 +0000
***************
*** 61,66 ****
--- 61,67 ----
     compiled on Mac OS X 10.5 fails in startup at -[EmacsController
     methodSignatureForSelector:] when executed on Mac OS X 10.6.  */
  @protocol NSApplicationDelegate @end
+ @protocol NSSoundDelegate @end
  @protocol NSWindowDelegate @end
  @protocol NSToolbarDelegate @end
  @protocol NSMenuDelegate @end
***************
*** 691,696 ****
--- 692,700 ----
  
  #endif	/* MAC_OS_X_VERSION_MIN_REQUIRED < 1050 */
  
+ @interface EmacsController (Sound) <NSSoundDelegate>
+ @end
+ 
  /* Some methods that are not declared in older versions.  Should be
     used with some runtime check such as `respondsToSelector:'. */
  
***************
*** 868,870 ****
--- 872,881 ----
  @end
  #endif
  #endif
+ 
+ #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
+ @interface NSSound (AvailableOn1050AndLater)
+ - (void)setVolume:(float)volume;
+ - (void)setPlaybackDeviceIdentifier:(NSString *)deviceUID;
+ @end
+ #endif

=== modified file 'src/macappkit.m'
*** src/macappkit.m	2013-03-05 06:19:19 +0000
--- src/macappkit.m	2013-03-18 02:36:41 +0000
***************
*** 12207,12209 ****
--- 12207,12263 ----
  
    return result;
  }
+ 
+ \f
+ /***********************************************************************
+ 				Sound
+ ***********************************************************************/
+ @implementation EmacsController (Sound)
+ 
+ - (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finishedPlaying
+ {
+   [NSApp postDummyEvent];
+ }
+ 
+ @end
+ 
+ CFTypeRef
+ mac_sound_create (Lisp_Object file, Lisp_Object data)
+ {
+   NSSound *sound;
+ 
+   if (STRINGP (file))
+     {
+       file = ENCODE_FILE (file);
+       sound = [[NSSound alloc]
+ 		initWithContentsOfFile:[NSString stringWithUTF8LispString:file]
+ 			   byReference:YES];
+     }
+   else if (STRINGP (data))
+     sound = [[NSSound alloc]
+ 	      initWithData:[NSData dataWithBytes:(SDATA (data))
+ 					  length:(SBYTES (data))]];
+   else
+     sound = nil;
+ 
+   return CF_BRIDGING_RETAIN (MRC_AUTORELEASE (sound));
+ }
+ 
+ void
+ mac_sound_play (CFTypeRef mac_sound, Lisp_Object volume, Lisp_Object device)
+ {
+   NSSound *sound = (__bridge NSSound *) mac_sound;
+ 
+   if ((INTEGERP (volume) || FLOATP (volume))
+       && [sound respondsToSelector:@selector(setVolume:)])
+     [sound setVolume:(INTEGERP (volume) ? XFASTINT (volume) * 0.01
+ 		      : XFLOAT_DATA (volume))];
+   if (STRINGP (device)
+       && [sound respondsToSelector:@selector(setPlaybackDeviceIdentifier:)])
+     [sound setPlaybackDeviceIdentifier:[NSString stringWithLispString:device]];
+ 
+   [sound setDelegate:emacsController];
+   [sound play];
+   while ([sound isPlaying])
+     mac_run_loop_run_once (kEventDurationForever);
+ }

=== modified file 'src/macterm.h'
*** src/macterm.h	2013-02-09 07:26:28 +0000
--- src/macterm.h	2013-03-18 02:36:18 +0000
***************
*** 652,657 ****
--- 652,660 ----
  extern void mac_invalidate_frame_cursor_rects (struct frame *f);
  extern int mac_webkit_supports_svg_p (void);
  
+ extern CFTypeRef mac_sound_create (Lisp_Object, Lisp_Object);
+ extern void mac_sound_play (CFTypeRef, Lisp_Object, Lisp_Object);
+ 
  #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc)	\
    CGContextSetFillColorWithColor (context, (gc)->cg_fore_color)
  #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc)	\

=== modified file 'src/sound.c'
*** src/sound.c	2013-01-01 09:11:05 +0000
--- src/sound.c	2013-03-18 02:36:18 +0000
***************
*** 53,59 ****
  
  
  /* BEGIN: Non Windows Includes */
! #ifndef WINDOWSNT
  
  #include <sys/ioctl.h>
  
--- 53,59 ----
  
  
  /* BEGIN: Non Windows Includes */
! #if !defined WINDOWSNT && !defined HAVE_MACGUI
  
  #include <sys/ioctl.h>
  
***************
*** 79,85 ****
  
  /* END: Non Windows Includes */
  
! #else /* WINDOWSNT */
  
  /* BEGIN: Windows Specific Includes */
  #include <stdio.h>
--- 79,85 ----
  
  /* END: Non Windows Includes */
  
! #elif defined WINDOWSNT
  
  /* BEGIN: Windows Specific Includes */
  #include <stdio.h>
***************
*** 88,94 ****
  #include <mmsystem.h>
  /* END: Windows Specific Includes */
  
! #endif /* WINDOWSNT */
  
  /* BEGIN: Common Definitions */
  
--- 88,97 ----
  #include <mmsystem.h>
  /* END: Windows Specific Includes */
  
! #else /* HAVE_MACGUI */
! #include "blockinput.h"
! #include "macterm.h"
! #endif /* HAVE_MACGUI */
  
  /* BEGIN: Common Definitions */
  
***************
*** 112,118 ****
  /* END: Common Definitions */
  
  /* BEGIN: Non Windows Definitions */
! #ifndef WINDOWSNT
  
  /* Structure forward declarations.  */
  
--- 115,121 ----
  /* END: Common Definitions */
  
  /* BEGIN: Non Windows Definitions */
! #if !defined WINDOWSNT && !defined HAVE_MACGUI
  
  /* Structure forward declarations.  */
  
***************
*** 291,297 ****
  #endif
  
  /* END: Non Windows Definitions */
! #else /* WINDOWSNT */
  
  /* BEGIN: Windows Specific Definitions */
  static int do_play_sound (const char *, unsigned long);
--- 294,300 ----
  #endif
  
  /* END: Non Windows Definitions */
! #elif defined WINDOWSNT
  
  /* BEGIN: Windows Specific Definitions */
  static int do_play_sound (const char *, unsigned long);
***************
*** 428,434 ****
  /* 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.  */
--- 431,437 ----
  /* END: Common functions */
  
  /* BEGIN: Non Windows functions */
! #if !defined WINDOWSNT && !defined HAVE_MACGUI
  
  /* Find out the type of the sound file whose file descriptor is FD.
     S is the sound file structure to fill in.  */
***************
*** 1247,1253 ****
  
  
  /* END: Non Windows functions */
! #else /* WINDOWSNT */
  
  /* BEGIN: Windows specific functions */
  
--- 1250,1256 ----
  
  
  /* END: Non Windows functions */
! #elif defined WINDOWSNT
  
  /* BEGIN: Windows specific functions */
  
***************
*** 1356,1361 ****
--- 1359,1367 ----
    Lisp_Object file;
    struct gcpro gcpro1, gcpro2;
    Lisp_Object args[2];
+ #ifdef HAVE_MACGUI
+   CFTypeRef mac_sound;
+ #endif
  #else /* WINDOWSNT */
    int len = 0;
    Lisp_Object lo_file = {0};
***************
*** 1369,1375 ****
    if (!parse_sound (sound, attrs))
      error ("Invalid sound specification");
  
! #ifndef WINDOWSNT
    file = Qnil;
    GCPRO2 (sound, file);
    current_sound_device = xzalloc (sizeof *current_sound_device);
--- 1375,1381 ----
    if (!parse_sound (sound, attrs))
      error ("Invalid sound specification");
  
! #if !defined WINDOWSNT && !defined HAVE_MACGUI
    file = Qnil;
    GCPRO2 (sound, file);
    current_sound_device = xzalloc (sizeof *current_sound_device);
***************
*** 1435,1441 ****
    /* Clean up.  */
    UNGCPRO;
  
! #else /* WINDOWSNT */
  
    lo_file = Fexpand_file_name (attrs[SOUND_FILE], Qnil);
    len = XSTRING (lo_file)->size;
--- 1441,1447 ----
    /* Clean up.  */
    UNGCPRO;
  
! #elif defined WINDOWSNT
  
    lo_file = Fexpand_file_name (attrs[SOUND_FILE], Qnil);
    len = XSTRING (lo_file)->size;
***************
*** 1464,1470 ****
      }
    i_result = do_play_sound (psz_file, ui_volume);
  
! #endif /* WINDOWSNT */
  
    unbind_to (count, Qnil);
    return Qnil;
--- 1470,1515 ----
      }
    i_result = do_play_sound (psz_file, ui_volume);
  
! #else /* HAVE_MACGUI */
!   if (inhibit_window_system || noninteractive)
!     error ("Sound support on Mac requires a window system");
! 
!   file = Qnil;
!   GCPRO2 (sound, file);
! 
!   if (STRINGP (attrs[SOUND_FILE]))
!     {
!       /* Open the sound file.  */
!       int fd = openp (Fcons (Vdata_directory, Qnil),
! 		      attrs[SOUND_FILE], Qnil, &file, Qnil);
! 
!       if (fd < 0)
! 	{
! 	  if (errno == 0)
! 	    error ("Could not open sound file");
! 	  else
! 	    error ("Could not open sound file: %s", strerror (errno));
! 	}
!       emacs_close (fd);
!     }
! 
!   block_input ();
!   mac_sound = mac_sound_create (file, attrs[SOUND_DATA]);
!   unblock_input ();
!   if (mac_sound == NULL)
!     error ("Unknown sound format");
! 
!   args[0] = Qplay_sound_functions;
!   args[1] = sound;
!   Frun_hook_with_args (2, args);
! 
!   block_input ();
!   mac_sound_play (mac_sound, attrs[SOUND_VOLUME], attrs[SOUND_DEVICE]);
!   CFRelease (mac_sound);
!   unblock_input ();
! 
!   UNGCPRO;
! #endif /* HAVE_MACGUI */
  
    unbind_to (count, Qnil);
    return Qnil;






  reply	other threads:[~2013-03-18  2:47 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-22 13:31 bug#3351: 23.0.93; OSX sound support Alex Schröder
2013-03-15 10:25 ` Leo Liu
2013-03-17  8:36   ` YAMAMOTO Mitsuharu
2013-03-18  2:47     ` YAMAMOTO Mitsuharu [this message]
2013-03-18  6:47       ` Jan Djärv

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=wlvc8pmnjh.wl%mituharu@math.s.chiba-u.ac.jp \
    --to=mituharu@math.s.chiba-u.ac.jp \
    --cc=3351@debbugs.gnu.org \
    --cc=kensanata@gmail.com \
    --cc=sdl.web@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.