Package: emacs;
Reported by: Alex Schröder <kensanata <at> gmail.com>
Date: Fri, 22 May 2009 13:40:04 UTC
Severity: wishlist
View this message in rfc822 format
From: YAMAMOTO Mitsuharu <mituharu <at> math.s.chiba-u.ac.jp> To: Leo Liu <sdl.web <at> gmail.com> Cc: Alex Schröder <kensanata <at> gmail.com>, 3351 <at> debbugs.gnu.org Subject: bug#3351: 23.0.93; OSX sound support Date: Mon, 18 Mar 2013 11:47:46 +0900
>>>>> On Sun, 17 Mar 2013 17:36:31 +0900, YAMAMOTO Mitsuharu <mituharu <at> 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 <at> 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; } + + + /*********************************************************************** + 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;
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.