)
+ // 2 - read lock (NSConditionLock *)
+ // 3 - playback lock (NSLock *)
+ void *_private[4];
+ BOOL _shouldStop;
+ BOOL _shouldLoop;
}
//
// Creating an NSSound
//
+/**
+ * Initalizes the receiver object with the contents of file located at path.
+ * If byRef is set to YES only the name of the NSSound is encoded with
+ * -encodeWithCoder:; if set to NO the data is encoded.
+ * See Also:
+ *
+ * - -initWithContentsOfURL:byReference:
+ * - -initWithData:
+ *
+ */
- (id)initWithContentsOfFile:(NSString *)path byReference:(BOOL)byRef;
+/**
+ * Initializes the receiver object with the contents of the data located in
+ * url. If byRef is set to YES only the name of the NSSound is encoded with
+ * -encodeWithCoder:; if set to NO the data is encoded.
+ * See Also:
+ *
+ * - -initWithContentsOfFile:byReference:
+ * - -initWithData:
+ *
+ */
- (id)initWithContentsOfURL:(NSURL *)url byReference:(BOOL)byRef;
+/**
+ * Initializes the receiver object with the contents of data with a
+ * valid magic number.
+ * See Also:
+ *
+ * - -initWithContentsOfFile:byReference:
+ * - -initWithContentsOfURL:byReference:
+ *
+ */
- (id)initWithData:(NSData *)data;
- (id)initWithPasteboard:(NSPasteboard *)pasteboard;
//
// Playing
//
+/** Pauses audio playback.
+ * Returns NO if receiver could not be paused or is already paused,
+ * and YES if receiver was successfully paused.
+ */
- (BOOL)pause;
-- (BOOL)play;
+/** Start audio playback. Playback is done asynchronously.
+ * Returns NO if receiver is already playing or if an error occurred, and
+ * YES if receiver was started successfully.
+ */
+- (BOOL)play;
+/** Resume audio playback after a -pause.
+ * Returns NO if receiver is already playing or if an error occurred, and
+ * YES if receiver was successfully restarted/resumed.
+ */
- (BOOL)resume;
+/** Stop audio playback.
+ * Return YES if receiver was successfully stopped.
+ * This method will close the playback device.
+ */
- (BOOL)stop;
+/* Returns YES if receiver is playing and NO otherwise.
+ */
- (BOOL)isPlaying;
//
@@ -84,17 +143,69 @@
//
// Working with delegates
//
+/** Returns the receiver's delegate
+ */
- (id)delegate;
+/** Sets the receiver's delegate
+ */
- (void)setDelegate:(id)aDelegate;
//
-// Naming Sounds
+// Sound Information
//
+ (id)soundNamed:(NSString *)name;
+/** Provides an array of file types that NSSound can understand. The returning
+ * array may be directly passed to [NSOpenPanel -runModalForTypes:].
+ * Built with libsndfile:
+ * wav, aiff, aifc, aif, au, snd, mat, mat4, mat5, paf, sf, voc, w64,
+ * xi, caf, sd2, flac, ogg, oga
+ * Built without libsndfile:
+ * wav, aiff, aifc, aif, au, snd
+ */
+ (NSArray *)soundUnfilteredFileTypes;
+/** Returns the name of the receiver. Use -setName: to set the name.
+ */
- (NSString *)name;
+/** Sets the receiver's name. Method -name will return aName.
+ */
- (BOOL)setName:(NSString *)aName;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
++ (NSArray *)soundUnfilteredTypes;
+/** Returns the length, in seconds, of the receiver.
+ */
+- (NSTimeInterval)duration;
+/** Returns the volume of the receiver.
+ * Volume will be between 0.0 and 1.0.
+ */
+- (float)volume;
+/** Sets the volume of the receiver.
+ * Volume must be between 0.0 and 1.0.
+ */
+- (void)setVolume: (float)volume;
+/** Returns the current position of the audio playback.
+ */
+- (NSTimeInterval)currentTime;
+/** Sets the current time of the audio playback.
+ */
+- (void)setCurrentTime: (NSTimeInterval)currentTime;
+/** Returns the current loop property of the receiver.
+ * YES indicates this NSSound will restart once it reaches the end,
+ * otherwise NO.
+ */
+- (BOOL)loops;
+/** Sets the loop property of the receiver.
+ * YES indicates this NSSound will restart once it reaches the end,
+ * otherwise NO.
+ */
+- (void)setLoops: (BOOL)loops;
+
+- (NSString *)playbackDeviceIdentifier;
+- (void)setPlaybackDeviceIdentifier: (NSString *)playbackDeviceIdentifier;
+- (NSArray *)channelMapping;
+- (void)setChannelMapping: (NSArray *)channelMapping;
+#endif
+
@end
//
@@ -102,6 +213,9 @@
//
@interface NSObject (NSSoundDelegate)
+/** Method called when sound has finished playing. Currently this method
+ * is not called.
+ */
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)aBool;
@end
Index: Headers/Additions/GNUstepGUI/GSSoundSource.h
===================================================================
--- Headers/Additions/GNUstepGUI/GSSoundSource.h (revision 0)
+++ Headers/Additions/GNUstepGUI/GSSoundSource.h (revision 0)
@@ -0,0 +1,96 @@
+/*
+ GSSoundSource.h
+
+ Load and read sound data.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: Jun 2009
+
+ This file is part of the GNUstep GUI Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _GNUstep_H_GSSoundSource
+#define _GNUstep_H_GSSoundSource
+
address@hidden NSArray;
+
+enum
+{
+ GSSoundFormatUnknown = 0x0000,
+ GSSoundFormatPCMS8 = 0x0001,
+ GSSoundFormatPCM16 = 0x0002,
+ GSSoundFormatPCM24 = 0x0003,
+ GSSoundFormatPCM32 = 0x0004,
+ GSSoundFormatPCMU8 = 0x0005,
+ GSSoundFormatFloat32 = 0x0006,
+ GSSoundFormatFloat64 = 0x0007,
+
+ GSSoundFormatULaw = 0x0010,
+ GSSoundFormatALaw = 0x0011
+};
+
address@hidden GSSoundSource
+
+/** Returns an array of the file types supported by the class.
+ */
++ (NSArray *)soundUnfilteredFileTypes;
+/** Returns an array of UTIs identifying the file types the class understands.
+ */
++ (NSArray *)soundUnfilteredTypes;
+/** Returns YES if the class can understand data and NO otherwise.
+ */
++ (BOOL)canInitWithData: (NSData *)data;
+
+/**
+ * Initilizes the reciever for output.
+ */
+- (id)initWithData: (NSData *)data;
+/** Reads data provided in -initWithData:. Parameter bytes must be big enough
+ * to hold length bytes.
+ */
+- (NSUInteger)readBytes: (void *)bytes length: (NSUInteger)length;
+
+/** Returns the duration, in seconds. Equivalent to [NSSound-duration].
+ */
+- (NSTimeInterval)duration;
+/** Called by [NSSound-setCurrentTime:].
+ */
+- (void)setCurrentTime: (NSTimeInterval)currentTime;
+/** Called by [NSSound-currentTime].
+ */
+- (NSTimeInterval)currentTime;
+
+/** Returns encoding of the audio data.
+ */
+- (int)encoding;
+/** Returns the number of channels.
+ */
+- (NSUInteger)channelCount;
+/** Returns the receiver's sample rate (ie 44100, 8000, etc).
+ */
+- (NSUInteger)sampleRate;
+/** Returns the byte order of the audio data.
+ */
+- (NSByteOrder)byteOrder;
+
address@hidden
+
+#endif // _GNUstep_H_GSSoundSource
Index: Headers/Additions/GNUstepGUI/GSSoundSink.h
===================================================================
--- Headers/Additions/GNUstepGUI/GSSoundSink.h (revision 0)
+++ Headers/Additions/GNUstepGUI/GSSoundSink.h (revision 0)
@@ -0,0 +1,83 @@
+/*
+ GSSoundSink.h
+
+ Sink audio data.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: Jun 2009
+
+ This file is part of the GNUstep GUI Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _GNUstep_H_GSSoundSink
+#define _GNUstep_H_GSSoundSink
+
address@hidden GSSoundSink
+
+/** Returns YES if class has the ability of playing audio data
+ * through a playback device playbackDevice, NO otherwise.
+ */
++ (BOOL)canInitWithPlaybackDevice: (NSString *)playbackDevice;
+
+/**
+ * Initializes the receiver for output using the defined parameters.
+ * WARNING: This method does not open the device, see -open.
+ */
+- (id)initWithEncoding: (int)encoding
+ channels: (NSUInteger)channelCount
+ sampleRate: (NSUInteger)sampleRate
+ byteOrder: (NSByteOrder)byteOrder;
+/** Opens the device for output, called by [NSSound-play].
+ */
+- (BOOL)open;
+/** Closes the device, called by [NSSound-stop].
+ */
+- (void)close;
+/** Writes/Plays the data in bytes to the device. Data must be in
+ * the same format as specified in
+ * -initWithEncoding:channels:sampleRate:byteOrder:.
+ */
+- (BOOL)writeBytes: (void *)bytes length: (NSUInteger)length;
+
+/** Called by [NSSound-setVolume:], and corresponds to it. Parameter volume
+ * is between the values 0.0 and 1.0.
+ */
+- (void)setVolume: (float)volume;
+/** Called by [NSSound-volume].
+ */
+- (float)volume;
+/** Called by [NSSound-setPlaybackDeviceIdentifier:].
+ */
+- (void)setPlaybackDeviceIdentifier: (NSString *)playbackDeviceIdentifier;
+/** Called by [NSSound-playbackDeviceIdentifier].
+ */
+- (NSString *)playbackDeviceIdentifier;
+/** Called by [NSSound-setChannelMapping:].
+ */
+- (void)setChannelMapping: (NSArray *)channelMapping;
+/** Called by [NSSound-channelMapping].
+ */
+- (NSArray *)channelMapping;
+
address@hidden
+
+#endif // _GNUstep_H_GSSoundSink
+
Index: Headers/Additions/GNUstepGUI/config.h.in
===================================================================
--- Headers/Additions/GNUstepGUI/config.h.in (revision 28389)
+++ Headers/Additions/GNUstepGUI/config.h.in (working copy)
@@ -6,9 +6,6 @@
/* Define to 1 if you have the header file. */
#undef HAVE_ASPELL_H
-/* Define to 1 if you have the header file. */
-#undef HAVE_AUDIOFILE_H
-
/* Define to 1 if you have the header file. */
#undef HAVE_CUPS_CUPS_H
@@ -24,9 +21,6 @@
/* Define to 1 if you have the `aspell' library (-laspell). */
#undef HAVE_LIBASPELL
-/* Define to 1 if you have the `audiofile' library (-laudiofile). */
-#undef HAVE_LIBAUDIOFILE
-
/* Define to 1 if you have the `gif' library (-lgif). */
#undef HAVE_LIBGIF
@@ -60,9 +54,6 @@
/* Define to 1 if you have the header file. */
#undef HAVE_MNTENT_H
-/* Define to 1 if you have the header file. */
-#undef HAVE_PORTAUDIO_H
-
/* Define to 1 if you have the `rint' function. */
#undef HAVE_RINT
Index: Sound/SndfileSource.m
===================================================================
--- Sound/SndfileSource.m (revision 0)
+++ Sound/SndfileSource.m (revision 0)
@@ -0,0 +1,237 @@
+/*
+ SndfileSource.m
+
+ Load and read sound data using libsndfile.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: Jun 2009
+
+ This file is part of the GNUstep GUI Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include
+#include
+#include
+
address@hidden SndfileSource : NSObject
+{
+ NSData *_data;
+ SNDFILE *_snd;
+ SF_INFO _info;
+
+ NSUInteger _curPos;
+ NSTimeInterval _dur;
+ int _encoding;
+}
+
+- (NSData *)data;
+- (NSUInteger)currentPosition;
+- (void)setCurrentPosition: (NSUInteger)curPos;
address@hidden
+
+/**********************************/
+/* Sndfile virtual I/O functions. */
+/**********************************/
+static inline sf_count_t dataLength (void *user_data)
+{
+ SndfileSource *snd = (SndfileSource *)user_data;
+
+ return (sf_count_t)[[snd data] length];
+}
+
+static inline sf_count_t dataSeek (sf_count_t offset, int whence,
+ void *user_data)
+{
+ SndfileSource *snd = (SndfileSource *)user_data;
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+ case SEEK_END:
+ offset = (sf_count_t)[[snd data] length] + offset;
+ break;
+ case SEEK_CUR:
+ offset = (sf_count_t)[snd currentPosition] + offset;
+ break;
+ default:
+ return 0;
+ }
+ [snd setCurrentPosition: (NSUInteger)offset];
+ return (sf_count_t)[snd currentPosition];
+}
+
+static inline sf_count_t dataRead (void *ptr, sf_count_t count,
+ void *user_data)
+{
+ NSUInteger newPos;
+ NSRange range;
+ SndfileSource *snd = (SndfileSource *)user_data;
+
+ // Can't read more data that we have available...
+ if (([snd currentPosition] + (NSUInteger)count) > [[snd data] length])
+ {
+ count = (sf_count_t)([[snd data] length] - [snd currentPosition]);
+ }
+
+ newPos = [snd currentPosition] + (NSUInteger)count;
+ range = NSMakeRange ([snd currentPosition], (NSUInteger)count);
+ [[snd data] getBytes: ptr range: range];
+ [snd setCurrentPosition: newPos];
+
+ return count;
+}
+
+static inline sf_count_t dataWrite (const void *ptr, sf_count_t count,
+ void *user_data)
+{
+ /* FIXME: No write support... do we even need it? */
+ return 0;
+}
+
+static inline sf_count_t dataTell (void *user_data)
+{
+ SndfileSource *snd = (SndfileSource *)user_data;
+ return (sf_count_t)[snd currentPosition];
+}
+
+// The libsndfile virtual I/O function structure
+static SF_VIRTUAL_IO dataIO = { (sf_vio_get_filelen)dataLength,
+ (sf_vio_seek)dataSeek,
+ (sf_vio_read)dataRead,
+ (sf_vio_write)dataWrite,
+ (sf_vio_tell)dataTell };
+/**********************************/
+
address@hidden SndfileSource
+
++ (NSArray *)soundUnfilteredFileTypes
+{
+ return [NSArray arrayWithObjects: @"wav", @"au", @"snd", @"aif", @"aiff",
+ @"aifc", @"paf", @"sf", @"voc", @"w64", @"mat", @"mat4", @"mat5",
+ @"pcf", @"xi", @"caf", @"sd2", @"iff", @"flac", @"ogg", @"oga",
+ nil];
+}
++ (NSArray *)soundUnfilteredTypes
+{
+ /* FIXME: I'm not sure what the UTI for all the types above are. */
+ return [NSArray arrayWithObjects: @"com.microsoft.waveform-audio",
+ @"public.ulaw-audio", @"public.aiff-audio", @"public.aifc-audio",
+ @"com.apple.coreaudio-format", @"com.digidesign.sd2-audio",
+ /* FIXME: are these right? */
+ @"org.xiph.flac-audio", @"org.xiph.vorbis-audio", nil];
+}
++ (BOOL)canInitWithData: (NSData *)data
+{
+ return YES;
+}
+
+- (void)dealloc
+{
+ TEST_RELEASE (_data);
+ sf_close (_snd);
+
+ [super dealloc];
+}
+
+- (id)initWithData: (NSData *)data
+{
+ [self init];
+
+ _data = data;
+ RETAIN(_data);
+
+ _info.format = 0;
+ _snd = sf_open_virtual (&dataIO, SFM_READ, &_info, self);
+ if (_snd == NULL)
+ {
+ DESTROY(self);
+ return nil;
+ }
+
+ // Setup immutable values...
+ /* FIXME: support multiple types */
+ _encoding = GSSoundFormatPCM16;
+ _dur = (double)_info.frames / (double)_info.samplerate;
+
+ return self;
+}
+
+- (NSUInteger)readBytes: (void *)bytes length: (NSUInteger)length
+{
+ return (NSUInteger) (sf_read_short (_snd, bytes, (length>>1))<<1);
+}
+
+- (NSTimeInterval)duration
+{
+ return _dur;
+}
+
+- (void)setCurrentTime: (NSTimeInterval)currentTime
+{
+ sf_count_t frames = (sf_count_t)((double)_info.samplerate * currentTime);
+ sf_seek (_snd, frames, SEEK_SET);
+}
+- (NSTimeInterval)currentTime
+{
+ sf_count_t frames;
+ frames = sf_seek (_snd, 0, SEEK_CUR);
+ return (NSTimeInterval)((double)frames / (double)_info.samplerate);
+}
+
+- (int)encoding
+{
+ return _encoding;
+}
+
+- (NSUInteger)channelCount
+{
+ return (NSUInteger)_info.channels;
+}
+
+- (NSUInteger)sampleRate;
+{
+ return (NSUInteger)_info.samplerate;
+}
+
+- (NSByteOrder)byteOrder
+{
+ // Equivalent to sending native byte order...
+ // Sndfile always reads as native format.
+ return NS_UnknownByteOrder;
+}
+
+- (NSData *)data
+{
+ return _data;
+}
+
+- (NSUInteger)currentPosition
+{
+ return _curPos;
+}
+
+- (void)setCurrentPosition: (NSUInteger)curPos
+{
+ _curPos = curPos;
+}
+
address@hidden
Index: Sound/AudioOutputSink.m
===================================================================
--- Sound/AudioOutputSink.m (revision 0)
+++ Sound/AudioOutputSink.m (revision 0)
@@ -0,0 +1,163 @@
+/*
+ AudioOutputSink.m
+
+ Sink audio data to libao.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: Jun 2009
+
+ This file is part of the GNUstep GUI Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include
+#include
+#include
+#include
+
address@hidden AudioOutputSink : NSObject
+{
+ ao_device *_dev;
+ int _driver;
+ ao_sample_format _format;
+}
address@hidden
+
address@hidden AudioOutputSink
+
++ (BOOL)canInitWithPlaybackDevice: (NSString *)playbackDevice
+{
+ // This is currently the only sink in NSSound, just say
+ // YES to everything.
+ /* FIXME: What is OS X's identifier for the main sound? */
+ return (playbackDevice == nil ? YES : NO);
+}
+
+- (void)dealloc
+{
+ ao_shutdown();
+
+ [super dealloc];
+}
+
+- (id)initWithEncoding: (int)encoding
+ channels: (NSUInteger)channelCount
+ sampleRate: (NSUInteger)sampleRate
+ byteOrder: (NSByteOrder)byteOrder
+{
+ self = [super init];
+
+ ao_initialize();
+ _driver = ao_default_driver_id();
+
+ _format.channels = (int)channelCount;
+ _format.rate = (int)sampleRate;
+
+ switch (encoding)
+ {
+ case GSSoundFormatPCMS8:
+ _format.bits = 8;
+ break;
+
+ case GSSoundFormatPCM16:
+ _format.bits = 16;
+ break;
+
+ case GSSoundFormatPCM24:
+ _format.bits = 24;
+ break;
+
+ case GSSoundFormatPCM32:
+ _format.bits = 32;
+ break;
+
+ case GSSoundFormatFloat32: // Float and double not supported by libao.
+ case GSSoundFormatFloat64:
+ default:
+ DESTROY(self);
+ return nil;
+ }
+
+ if (byteOrder == NS_LittleEndian)
+ {
+ _format.byte_format = AO_FMT_LITTLE;
+ }
+ else if (byteOrder == NS_BigEndian)
+ {
+ _format.byte_format = AO_FMT_BIG;
+ }
+ else
+ {
+ _format.byte_format = AO_FMT_NATIVE;
+ }
+
+ return self;
+}
+
+- (BOOL)open
+{
+ _dev = ao_open_live(_driver, &_format, NULL);
+ return ((_dev == NULL) ? NO : YES);
+}
+
+- (void)close
+{
+ ao_close(_dev);
+}
+
+- (BOOL)writeBytes: (void *)bytes length: (NSUInteger)length
+{
+ int ret = ao_play(_dev, bytes, (uint_32)length);
+ return (ret == 0 ? NO : YES);
+}
+
+/* Functionality not supported by libao */
+- (void)setVolume: (float)volume
+{
+ return;
+}
+
+- (float)volume
+{
+ return 1.0;
+}
+
+- (void)setPlaybackDeviceIdentifier: (NSString *)playbackDeviceIdentifier
+{
+ return;
+}
+
+- (NSString *)playbackDeviceIdentifier
+{
+ return nil;
+}
+
+- (void)setChannelMapping: (NSArray *)channelMapping
+{
+ return;
+}
+
+- (NSArray *)channelMapping
+{
+ return nil;
+}
+
address@hidden
+
Index: Sound/GNUmakefile
===================================================================
--- Sound/GNUmakefile (revision 0)
+++ Sound/GNUmakefile (revision 0)
@@ -0,0 +1,22 @@
+PACKAGE_NAME = gnustep-gui
+include $(GNUSTEP_MAKEFILES)/common.make
+
+BUNDLE_NAME = Sndfile AudioOutput
+BUNDLE_EXTENSION = .nssound
+
+OBJCFLAGS += -Wall
+
+Sndfile_OBJC_FILES = SndfileSource.m
+AudioOutput_OBJC_FILES = AudioOutputSink.m
+
+Sndfile_PRINCIPAL_CLASS = SndfileSource
+AudioOutput_PRINCIPAL_CLASS = AudioOutputSink
+
+Sndfile_BUNDLE_LIBS = -lsndfile
+AudioOutput_BUNDLE_LIBS = -lao
+
+-include GNUmakefile.preamble
+
+include $(GNUSTEP_MAKEFILES)/bundle.make
+
+-include GNUmakefile.postamble
Index: Tools/gsnd/gsnd.m
===================================================================
--- Tools/gsnd/gsnd.m (revision 28389)
+++ Tools/gsnd/gsnd.m (working copy)
@@ -1,1424 +0,0 @@
-/* gsnd
-
- GNUstep sound server
-
- Copyright (C) 2002 Free Software Foundation, Inc.
-
- Author: Enrico Sersale
- Date: August 2002
-
- This file is part of the GNUstep Project
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 3
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with this library; see the file COPYING.
- If not, see or write to the
- Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include
-#include
-#include
-#include
-#include
-
-#ifdef __MINGW__
-#include "process.h"
-#endif
-
-#ifdef HAVE_SYSLOG_H
-#include
-#endif
-
-#define GSNDNAME @"GNUstepGSSoundServer"
-#define FRAME_SIZE 4
-#define BUFFER_SIZE_IN_FRAMES (1024 * FRAME_SIZE)
-#define CHUNK_LENGTH (BUFFER_SIZE_IN_FRAMES * 4)
-#define DEFAULT_CHANNELS 2
-#define PLAY_RATE (44100)
-#define CACHE_SIZE 4194304
-
-/* Conversion constants */
-#define Nhc 8
-#define Na 7
-#define Np (Nhc + Na)
-#define Npc (1 << Nhc)
-#define Amask ((1 << Na) - 1)
-#define Pmask ((1 << Np) - 1)
-#define Nh 16
-#define Nb 16
-#define Nhxn 14
-#define Nhg (Nh - Nhxn)
-#define NLpScl 13
-
-#ifndef INT16_MAX
- #define INT16_MAX (32767)
- #define INT16_MIN (-32767-1)
-#endif
-
-#define IBUFFSIZE 4096
-
-#define CLAMP(x, low, high) \
-(((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
-
-static int is_daemon = 0; /* Currently running as daemon. */
-
-static short **sX;
-static short **sY;
-static unsigned int sTime;
-static double sfactor;
-static BOOL sinitial;
-
-void clearResamplerMemory();
-void initializeResampler(double fac);
-int resample(int inCount, int outCount, short inArray[], short outArray[]);
-int resampleFast(int inCount, int outCount, short inArray[], short outArray[]);
-int SrcLinear(short X[], short Y[], double factor, unsigned int *Time,
- unsigned short Nx, unsigned short Nout);
-inline short WordToHword(int v, int scl);
-int resamplerReadData(int inCount, short inArray[], short *outPtr[],
- int dataArraySize, int Xoff, BOOL init_count);
-int resampleError(char *s);
-
-static char ebuf[2048];
-
-#ifdef HAVE_SYSLOG
-
-static int log_priority;
-
-static void
-gsnd_log (int prio)
-{
- if (is_daemon)
- {
- syslog (log_priority | prio, ebuf);
- }
- else if (prio == LOG_INFO)
- {
- write (1, ebuf, strlen (ebuf));
- write (1, "\n", 1);
- }
- else
- {
- write (2, ebuf, strlen (ebuf));
- write (2, "\n", 1);
- }
-
- if (prio == LOG_CRIT)
- {
- if (is_daemon)
- {
- syslog (LOG_CRIT, "exiting.");
- }
- else
- {
- fprintf (stderr, "exiting.\n");
- fflush (stderr);
- }
- exit(EXIT_FAILURE);
- }
-}
-#else
-
-#define LOG_CRIT 2
-#define LOG_DEBUG 0
-#define LOG_ERR 1
-#define LOG_INFO 0
-#define LOG_WARNING 0
-void
-gsnd_log (int prio)
-{
- write (2, ebuf, strlen (ebuf));
- write (2, "\n", 1);
- if (prio == LOG_CRIT)
- {
- fprintf (stderr, "exiting.\n");
- fflush (stderr);
- exit(EXIT_FAILURE);
- }
-}
-#endif
-
address@hidden GSSndObj
-
-- (void)setIdentifier:(NSString *)identifier;
-- (NSString *)identifier;
-- (NSString *)name;
-- (float)samplingRate;
-- (long)frameCount;
-- (NSData *)data;
-
address@hidden
-
address@hidden Snd : NSObject
-{
- NSString *name;
- NSString *identifier;
- long frameCount;
- float rate;
-
- long startPos;
- long endPos;
- long posInBytes;
-
- BOOL playing;
- BOOL paused;
-
- NSMutableData *data;
-}
-
-- (id)initWithNSSoundObject:(id)anobject;
-
-- (void)setIdentifier:(NSString *)identstr;
-
-- (void)resampleWithFactor:(float)factor;
-
-- (void)reset;
-
-- (NSData *)data;
-
-- (NSData *)remainingData;
-
-- (void)setStartPos:(long)p;
-
-- (void)setEndPos:(long)p;
-
-- (void)setPlaying:(BOOL)value;
-
-- (void)setPaused:(BOOL)value;
-
-- (NSString *)name;
-
-- (NSString *)identifier;
-
-- (long)frameCount;
-
-- (float)rate;
-
-- (long)startPos;
-
-- (long)endPos;
-
-- (long)posInBytes;
-
-- (void)posInBytesAdd;
-
-- (BOOL)isPlaying;
-
-- (BOOL)isPaused;
-
address@hidden
-
address@hidden SoundServer : NSObject
-{
- NSMutableData *soundData;
- NSMutableArray *sounds;
- long maxCacheSize;
- long frameCount;
-
- long position;
- long posInBytes;
-
- BOOL isPlaying;
-
- NSConnection *conn;
- NSNotificationCenter *nc;
-}
-
-- (BOOL)playSound:(id)aSound;
-
-- (BOOL)stopSoundWithIdentifier:(NSString *)identifier;
-
-- (BOOL)pauseSoundWithIdentifier:(NSString *)identifier;
-
-- (BOOL)resumeSoundWithIdentifier:(NSString *)identifier;
-
-- (BOOL)isPlayingSoundWithIdentifier:(NSString *)identifier;
-
-- (void)play;
-
-- (void)mixWithSound:(Snd *)snd;
-
-- (void)unMixSound:(Snd *)snd;
-
-- (void)updatePosition;
-
-- (void)stopAll;
-
-- (void)checkIsPlaying;
-
-- (void)closeStream;
-
-- (Snd *)cachedSoundWithName:(NSString *)aName;
-
-- (void)checkCachedSounds;
-
-- (Snd *)soundWithIdentifier:(NSString *)identifier;
-
-- (Snd *)soundWithName:(NSString *)aName identifier:(NSString *)ident;
-
-- (NSString *)uniqueSoundIdentifier;
-
-- (BOOL)connection:(NSConnection*)ancestor
- shouldMakeNewConnection:(NSConnection*)newConn;
-
-- (id)connectionBecameInvalid:(NSNotification*)notification;
-
address@hidden
-
-
-SoundServer *gsnd = nil;
-PaStream *pStream = NULL;
-
-struct SoundServer_t {
- @defs(SoundServer)
-} *serverPtr;
-
-
address@hidden Snd
-
-- (void)dealloc
-{
- RELEASE (name);
- TEST_RELEASE (identifier);
- RELEASE (data);
- [super dealloc];
-}
-
-- (id)initWithNSSoundObject:(id)anobject
-{
- self = [super init];
-
- if (self) {
- ASSIGN (name, [anobject name]);
- ASSIGN (identifier, [anobject identifier]);
- data = [[anobject data] mutableCopy];
- frameCount = [anobject frameCount];
- rate = [anobject samplingRate];
- startPos = 0;
- endPos = 0;
- posInBytes = 0;
- playing = NO;
- paused = NO;
-
- [self resampleWithFactor: (PLAY_RATE / rate)];
- }
-
- return self;
-}
-
-- (void)setIdentifier:(NSString *)identstr
-{
- ASSIGN (identifier, identstr);
-}
-
-- (void)resampleWithFactor:(float)factor
-{
- gss16 *outbuff;
- int extra_sample;
- long out_count;
- float out_length;
-
- rate *= factor;
-
- if (factor <= 1.0) {
- extra_sample = 50;
- } else {
- extra_sample = (int)factor + 50;
- }
-
- out_count = (long)ceil((frameCount) * factor) + extra_sample;
- out_length = out_count * FRAME_SIZE;
-
- outbuff = NSZoneMalloc(NSDefaultMallocZone(), GS_SIZEOF_SHORT * out_length);
-
- initializeResampler(factor);
- resample(frameCount, out_count, (gss16 *)[data bytes], outbuff);
-
- TEST_RELEASE (data);
- data = [[NSMutableData alloc] initWithCapacity: 1];
-
- [data appendBytes: (const void *)outbuff
- length: out_length];
-
- NSZoneFree(NSDefaultMallocZone(), outbuff);
- clearResamplerMemory();
-
- frameCount = (long)([data length] / FRAME_SIZE);
-}
-
-- (void)reset
-{
- startPos = 0;
- endPos = 0;
- posInBytes = 0;
- playing = NO;
- paused = NO;
- DESTROY (identifier);
-}
-
-- (NSData *)data
-{
- return data;
-}
-
-- (NSData *)remainingData
-{
- long start = (long)(posInBytes * FRAME_SIZE);
- long length = (long)([data length] - start);
- return [data subdataWithRange: NSMakeRange(start, length)];
-}
-
-- (void)setStartPos:(long)p
-{
- startPos = p;
-}
-
-- (void)setEndPos:(long)p
-{
- endPos = p;
-}
-
-- (void)setPlaying:(BOOL)value
-{
- playing = value;
-}
-
-- (void)setPaused:(BOOL)value
-{
- paused = value;
-}
-
-- (NSString *)name
-{
- return name;
-}
-
-- (NSString *)identifier
-{
- return identifier;
-}
-
-- (long)frameCount
-{
- return frameCount;
-}
-
-- (float)rate
-{
- return rate;
-}
-
-- (long)startPos
-{
- return startPos;
-}
-
-- (long)endPos
-{
- return endPos;
-}
-
-- (long)posInBytes
-{
- return posInBytes;
-}
-
-- (void)posInBytesAdd
-{
- posInBytes++;
-}
-
-- (BOOL)isPlaying
-{
- return playing;
-}
-
-- (BOOL)isPaused
-{
- return paused;
-}
-
-- (id)copyWithZone:(NSZone *)zone
-{
- Snd *snd = (Snd *)NSCopyObject(self, 0, zone);
-
- snd->name = [name copy];
- snd->identifier = nil;
- snd->frameCount = frameCount;
- snd->rate = rate;
- snd->startPos = 0;
- snd->endPos = 0;
- snd->posInBytes = 0;
- snd->playing = NO;
- snd->paused = NO;
- snd->data = [data mutableCopy];
-
- return snd;
-}
-
address@hidden
-
-
-static int paCallback(void *inputBuffer,
- void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo *timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData)
-{
- NSAutoreleasePool *pool;
- NSData *data;
- long length;
- int chunkLength;
- int retvalue;
- void *buffer[CHUNK_LENGTH];
- gss16 *in;
- int i;
-
-#ifdef GNUSTEP
- GSRegisterCurrentThread();
-#endif
-
- pool = [[NSAutoreleasePool alloc] init];
-
- data = serverPtr->soundData;
- length = [data length];
-
- if ((serverPtr->position + CHUNK_LENGTH) < length) {
- chunkLength = CHUNK_LENGTH;
- retvalue = 0;
- } else {
- chunkLength = length - serverPtr->position;
- retvalue = 1;
- }
-
- [data getBytes: &buffer range: NSMakeRange(serverPtr->position, chunkLength)];
- in = (gss16 *)buffer;
-
- for(i = 0; i < framesPerBuffer; i++) {
- ((gss16 *)outputBuffer)[i * 2] = in[i * 2];
- ((gss16 *)outputBuffer)[i * 2 + 1] = in[i * 2 + 1];
- [(SoundServer *)serverPtr updatePosition];
- }
-
- if (retvalue == 1) {
- [(SoundServer *)serverPtr performSelectorOnMainThread: @selector(closeStream)
- withObject: (SoundServer *)serverPtr waitUntilDone: NO];
- }
-
- serverPtr->isPlaying = !retvalue;
-
- RELEASE (pool);
-
- return retvalue;
-}
-
-
address@hidden SoundServer
-
-- (void)dealloc
-{
- [nc removeObserver: self];
- RELEASE (sounds);
- RELEASE (soundData);
- [super dealloc];
-}
-
-- (id)init
-{
- self = [super init];
-
- if (self) {
- NSString *hostname;
- NSNumber *csize;
-
- serverPtr = (struct SoundServer_t *)self;
- nc = [NSNotificationCenter defaultCenter];
-
- csize = [[NSUserDefaults standardUserDefaults] objectForKey: @"cachesize"];
- maxCacheSize = csize ? [csize longValue] : CACHE_SIZE;
-
- sounds = [[NSMutableArray alloc] initWithCapacity: 1];
- soundData = [[NSMutableData alloc] initWithCapacity: 1];
- frameCount = 0;
- position = 0;
- posInBytes = 0;
- isPlaying = NO;
-
- conn = [NSConnection defaultConnection];
- [conn setRootObject: self];
- [conn setDelegate: self];
- [nc addObserver: self
- selector: @selector(connectionBecameInvalid:)
- name: NSConnectionDidDieNotification
- object: (id)conn];
-
- hostname = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"];
-
- if ([hostname length] == 0
- || [[NSHost hostWithName: hostname] isEqual: [NSHost currentHost]]) {
- if ([conn registerName: GSNDNAME] == NO) {
- NSLog(@"Unable to register with name server.\n");
- exit(1);
- }
- } else {
- NSHost *host = [NSHost hostWithName: hostname];
- NSPort *port = [conn receivePort];
- NSPortNameServer *ns = [NSPortNameServer systemDefaultPortNameServer];
- NSArray *a;
- unsigned c;
-
- if (host == nil) {
- NSLog(@"gsnd - unknown NSHost argument ... %@ - quiting.", hostname);
- exit(1);
- }
-
- a = [host names];
- c = [a count];
- while (c-- > 0) {
- NSString *name = [a objectAtIndex: c];
-
- name = [GSNDNAME stringByAppendingFormat: @"-%@", name];
- if ([ns registerPort: port forName: name] == NO) {
- }
- }
-
- a = [host addresses];
- c = [a count];
- while (c-- > 0) {
- NSString *name = [a objectAtIndex: c];
-
- name = [GSNDNAME stringByAppendingFormat: @"-%@", name];
- if ([ns registerPort: port forName: name] == NO) {
- }
- }
- }
- }
-
- return self;
-}
-
-- (BOOL)playSound:(id)aSound
-{
- id obj;
- NSString *soundName;
- NSString *idendstr;
- Snd *snd = nil;
-
- [self checkCachedSounds];
-
- obj = (id)aSound;
- soundName = [obj name];
- idendstr = [obj identifier];
-
- if (idendstr == nil) {
- idendstr = [self uniqueSoundIdentifier];
- [obj setIdentifier: idendstr];
- } else {
- snd = [self soundWithIdentifier: idendstr];
-
- if ((snd != nil) && (([snd isPlaying]) || ([snd isPaused]))) {
- return NO;
- }
- }
-
- if (snd == nil) {
- snd = [self cachedSoundWithName: soundName];
-
- if (snd == nil) {
- snd = [[Snd alloc] initWithNSSoundObject: obj];
- [sounds addObject: snd];
- RELEASE (snd);
- } else {
- if ([snd isPlaying] || [snd isPaused]) {
- snd = [snd copy];
- [sounds addObject: snd];
- RELEASE (snd);
- }
- [snd reset];
- [snd setIdentifier: idendstr];
- }
- }
-
- if (isPlaying == NO) {
- frameCount = [snd frameCount];
- TEST_RELEASE (soundData);
- soundData = [[snd data] mutableCopy];
- isPlaying = YES;
-
- [snd setStartPos: 0];
- [snd setEndPos: (long)([soundData length] / FRAME_SIZE)];
- [snd setPlaying: YES];
-
- [self play];
-
- } else {
- [self mixWithSound: snd];
- }
-
- return YES;
-}
-
-- (BOOL)stopSoundWithIdentifier:(NSString *)identifier
-{
- Snd *snd = [self soundWithIdentifier: identifier];
-
- if (snd && [snd isPlaying]) {
- [self unMixSound: snd];
- [snd reset];
- [self checkIsPlaying];
- return YES;
- }
-
- return NO;
-}
-
-- (BOOL)pauseSoundWithIdentifier:(NSString *)identifier
-{
- Snd *snd = [self soundWithIdentifier: identifier];
-
- if (snd && [snd isPlaying]) {
- [self unMixSound: snd];
-
- [snd setPlaying: NO];
- [snd setPaused: YES];
- [snd setStartPos: 0];
- [snd setEndPos: 0];
-
- [self checkIsPlaying];
- return YES;
- }
-
- return NO;
-}
-
-- (BOOL)resumeSoundWithIdentifier:(NSString *)identifier
-{
- Snd *snd = [self soundWithIdentifier: identifier];
-
- if (snd && [snd isPaused]) {
- if (isPlaying == NO) {
- TEST_RELEASE (soundData);
- soundData = [[snd remainingData] mutableCopy];
-
- frameCount = (long)([soundData length] / FRAME_SIZE);
-
- [snd setStartPos: 0];
- [snd setEndPos: (long)([soundData length] / FRAME_SIZE)];
- [snd setPaused: NO];
- [snd setPlaying: YES];
-
- isPlaying = YES;
- [self play];
-
- } else {
- [snd setPlaying: YES];
- [snd setPaused: NO];
- [self mixWithSound: snd];
- }
-
- return YES;
- }
-
- return NO;
-}
-
-- (BOOL)isPlayingSoundWithIdentifier:(NSString *)identifier
-{
- Snd *snd = [self soundWithIdentifier: identifier];
-
- if (snd) {
- return [snd isPlaying];
- }
-
- return NO;
-}
-
-- (void)play
-{
- PaError err;
- int d = 0;
-
- err = Pa_Initialize();
-
- if (err != paNoError) {
- fprintf(stderr, "An error occured while using the portaudio stream\n");
- fprintf(stderr, "Error number: %d\n", err );
- fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
-
- Pa_Terminate();
- return;
- }
-
- err = Pa_OpenDefaultStream(&pStream, 0, DEFAULT_CHANNELS, paInt16,
- PLAY_RATE, BUFFER_SIZE_IN_FRAMES, (PaStreamCallback *)paCallback, &d);
-
- if (err == paNoError) {
- err = Pa_StartStream(pStream);
-
- if (err == paNoError) {
- Pa_Sleep(2);
- } else {
- NSLog(@"PortAudio Pa_StartStream error: %s", Pa_GetErrorText(err));
- }
-
- } else {
- NSLog(@"PortAudio Pa_OpenDefaultStream error: %s", Pa_GetErrorText(err));
- }
-}
-
-- (void)mixWithSound:(Snd *)snd
-{
- if (isPlaying) {
- NSData *snddata = [snd remainingData];
- long inFrameCount = (long)([snddata length] / FRAME_SIZE);
- gss16 *in = (gss16 *)[snddata bytes];
- gss16 *out = (gss16 *)[soundData mutableBytes];
- gss32 sum_l;
- gss32 sum_r;
- long inPos;
- int i, j;
-
- [snd setStartPos: posInBytes + [snd posInBytes]];
- [snd setEndPos: posInBytes + (long)([snddata length] / FRAME_SIZE)];
-
- j = 0;
-
- for (i = posInBytes; i < frameCount; i++) {
- sum_l = out[i * 2] + in[j * 2];
- sum_r = out[i * 2 + 1] + in[j * 2 + 1];
-
- out[i * 2] = CLAMP (sum_l, INT16_MIN, INT16_MAX);
- out[i * 2 + 1] = CLAMP (sum_r, INT16_MIN, INT16_MAX);
-
- j++;
- if (j == inFrameCount) {
- break;
- }
- }
-
- inPos = (j * FRAME_SIZE);
-
- if (inPos < ([snddata length] - 1)) {
- long remLength = [snddata length] - inPos;
- NSRange range = NSMakeRange(inPos, remLength);
-
- [soundData appendData: [snddata subdataWithRange: range]];
- frameCount = (long)([soundData length] / FRAME_SIZE);
- }
-
- [snd setPlaying: YES];
- }
-}
-
-- (void)unMixSound:(Snd *)snd
-{
- if (isPlaying) {
- int *in = (int *)[[snd data] bytes];
- int *out = (int *)[soundData mutableBytes];
- long deleteFrom = [snd startPos] + [snd posInBytes];
- long deleteTo = [snd endPos];
- int i, j;
-
- j = [snd posInBytes];
- for (i = deleteFrom; i < frameCount; i++) {
- out[i] -= in[j];
- j++;
- if (j == deleteTo) {
- break;
- }
- }
- }
-}
-
-- (void)updatePosition
-{
- int i;
-
- posInBytes++;
- position = (long)(posInBytes * FRAME_SIZE);
-
- for (i = 0; i < [sounds count]; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if ([snd isPlaying]) {
- [snd posInBytesAdd];
-
- if (posInBytes == [snd endPos]) {
- [snd reset];
- }
- }
- }
-}
-
-- (void)stopAll
-{
- int i;
-
- [self checkCachedSounds];
-
- for (i = 0; i < [sounds count]; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if ([snd isPaused]) {
- [snd setStartPos: 0];
- [snd setEndPos: 0];
- } else {
- [snd reset];
- }
- }
-
- TEST_RELEASE (soundData);
- soundData = [[NSMutableData alloc] initWithCapacity: 1];
- frameCount = 0;
- position = 0;
- posInBytes = 0;
- isPlaying = NO;
-}
-
-- (void)checkIsPlaying
-{
- int i;
- BOOL found = NO;
-
- for (i = 0; i < [sounds count]; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if ([snd isPlaying]) {
- found = YES;
- break;
- }
- }
-
- if (found == NO) {
- [self stopAll];
- }
-}
-
-- (void)closeStream
-{
- PaError err;
-
- err = Pa_StopStream(pStream);
-
- if (err != paNoError) {
- NSLog(@"PortAudio Pa_StopStream error: %s", Pa_GetErrorText(err));
- return;
- }
-
- err = Pa_CloseStream(pStream);
-
- if (err != paNoError) {
- NSLog(@"PortAudio Pa_CloseStream error: %s", Pa_GetErrorText(err));
- return;
- }
-
- err = Pa_Terminate();
-
- if (err != paNoError) {
- NSLog(@"PortAudio Pa_Terminate error: %s", Pa_GetErrorText(err));
- return;
- }
-
- [self stopAll];
-}
-
-- (Snd *)cachedSoundWithName:(NSString *)aName
-{
- int i;
-
- for (i = 0; i < [sounds count]; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if ([[snd name] isEqual: aName]) {
- return snd;
- }
- }
-
- return nil;
-}
-
-- (void)checkCachedSounds
-{
- int i, j, count;
- long csize = 0;
-
- count = [sounds count];
-
- for (i = 0; i < count; i++) {
- Snd *snd0 = [sounds objectAtIndex: i];
- NSString *name = [snd0 name];
-
- for (j = 0; j < count; j++) {
- Snd *snd1 = [sounds objectAtIndex: j];
-
- if (([[snd1 name] isEqual: name]) && (snd0 != snd1)) {
- if (([snd1 isPaused] == NO) && ([snd1 isPlaying] == NO)) {
- [sounds removeObject: snd1];
- count--;
- i--;
- j--;
- }
- }
- }
- }
-
- count = [sounds count];
-
- for (i = 0; i < count; i++) {
- csize += [[[sounds objectAtIndex: i] data] length];
- }
-
- if (csize > maxCacheSize) {
- for (i = 0; i < count; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if (([snd isPlaying] == NO) && ([snd isPaused] == NO)) {
- csize -= [[snd data] length];
- [sounds removeObject: snd];
- count--;
- i--;
- }
- if (csize <= maxCacheSize) {
- break;
- }
- }
- }
-}
-
-- (Snd *)soundWithIdentifier:(NSString *)identifier
-{
- int i;
-
- for (i = 0; i < [sounds count]; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if ([[snd identifier] isEqual: identifier]) {
- return snd;
- }
- }
-
- return nil;
-}
-
-- (Snd *)soundWithName:(NSString *)aName identifier:(NSString *)ident
-{
- int i;
-
- for (i = 0; i < [sounds count]; i++) {
- Snd *snd = [sounds objectAtIndex: i];
-
- if ([[snd identifier] isEqual: ident]) {
- NSString *sname = [snd name];
-
- if ([sname isEqual: aName]) {
- return snd;
- }
- }
- }
-
- return nil;
-}
-
-- (NSString *)uniqueSoundIdentifier
-{
- int identifier = [[NSProcessInfo processInfo] processIdentifier];
- NSString *identstr = [NSString stringWithFormat: @"sound_%i_%i", identifier, random()];
-
- return identstr;
-}
-
-- (BOOL)connection:(NSConnection*)ancestor
- shouldMakeNewConnection:(NSConnection*)newConn;
-{
- [nc addObserver: self
- selector: @selector(connectionBecameInvalid:)
- name: NSConnectionDidDieNotification
- object: newConn];
-
- [newConn setDelegate: self];
-
- return YES;
-}
-
-- (id)connectionBecameInvalid:(NSNotification*)notification
-{
- id connection = [notification object];
-
- if (connection == conn) {
- NSLog(@"Help - sound server connection has died!\n");
- exit(1);
- }
-
- return self;
-}
-
address@hidden
-
-int main(int argc, char** argv, char **env)
-{
- CREATE_AUTORELEASE_POOL(pool);
- BOOL subtask = YES;
- NSProcessInfo *pInfo;
- NSMutableArray *args;
-
-#ifdef GS_PASS_ARGUMENTS
- [NSProcessInfo initializeWithArguments: argv count: argc environment: env];
-#endif
-
- pInfo = [NSProcessInfo processInfo];
- args = AUTORELEASE ([[pInfo arguments] mutableCopy]);
-
- if ([[pInfo arguments] containsObject: @"--daemon"]) {
- subtask = NO;
- is_daemon = YES;
- }
-
- if (subtask) {
- NSFileHandle *null;
- NSTask *t;
-
- t = [NSTask new];
-
- NS_DURING
- {
- [args removeObjectAtIndex: 0];
- [args addObject: @"--daemon"];
- [t setLaunchPath: [[NSBundle mainBundle] executablePath]];
- [t setArguments: args];
- [t setEnvironment: [pInfo environment]];
- null = [NSFileHandle fileHandleWithNullDevice];
- [t setStandardInput: null];
- [t setStandardOutput: null];
- [t setStandardError: null];
- [t launch];
- DESTROY(t);
- }
- NS_HANDLER
- {
- gsnd_log(LOG_CRIT);
- DESTROY(t);
- }
- NS_ENDHANDLER
-
- exit(EXIT_FAILURE);
- }
-
- RELEASE(pool);
-
- {
-#if GS_WITH_GC == 0
- CREATE_AUTORELEASE_POOL(pool);
-#endif
-
- gsnd = [[SoundServer alloc] init];
-
- [[NSFileHandle fileHandleWithStandardInput] closeFile];
- [[NSFileHandle fileHandleWithStandardOutput] closeFile];
- #ifndef __MINGW__
- [[NSFileHandle fileHandleWithStandardError] closeFile];
- #endif
-
- RELEASE (pool);
- }
-
- if (gsnd != nil) {
- CREATE_AUTORELEASE_POOL(pool);
- [[NSRunLoop currentRunLoop] run];
- RELEASE(pool);
- }
-
- exit(EXIT_SUCCESS);
-}
-
-
-
-//
-// Resampler Functions
-//
-
-void
-clearResamplerMemory()
-{
- int i;
-
- if (sX != NULL)
- {
- for (i = 0; i < DEFAULT_CHANNELS; i++)
- {
- NSZoneFree(NSDefaultMallocZone(), sX[i]);
- sX[i] = NULL;
- NSZoneFree(NSDefaultMallocZone(), sY[i]);
- sY[i] = NULL;
- }
- NSZoneFree(NSDefaultMallocZone(), sX);
- sX = NULL;
- NSZoneFree(NSDefaultMallocZone(), sY);
- sY = NULL;
- }
-}
-
-void
-initializeResampler(double fac)
-{
- int i;
-
- clearResamplerMemory();
-
- sfactor = fac;
- sinitial = YES;
-
- // Allocate all new memory
- sX = NSZoneMalloc(NSDefaultMallocZone(), GS_SIZEOF_SHORT * DEFAULT_CHANNELS);
- sY = NSZoneMalloc(NSDefaultMallocZone(), GS_SIZEOF_SHORT * DEFAULT_CHANNELS);
-
- for (i = 0; i < DEFAULT_CHANNELS; i++)
- {
- // Add extra to allow of offset of input data (Xoff in main routine)
- sX[i] = NSZoneMalloc(NSDefaultMallocZone(), GS_SIZEOF_SHORT * (IBUFFSIZE + 256));
- sY[i] = NSZoneMalloc(NSDefaultMallocZone(), GS_SIZEOF_SHORT * (int)(((double)IBUFFSIZE) * sfactor));
- memset(sX[i], 0, GS_SIZEOF_SHORT * (IBUFFSIZE + 256));
- }
-}
-
-int
-resample(int inCount, int outCount, short inArray[], short outArray[])
-{
- int Ycount = resampleFast(inCount, outCount, inArray, outArray);
- sinitial = NO;
- return Ycount;
-}
-
-int resampleFast(int inCount, int outCount, short inArray[], short outArray[])
-{
- unsigned int Time2; /* Current time/pos in input sample */
- unsigned short Xp, Xread;
- int OBUFFSIZE = (int)(((double)IBUFFSIZE) * sfactor);
- unsigned short Nout = 0, Nx, orig_Nx;
- unsigned short maxOutput;
- int total_inCount = 0;
- int c, i, Ycount, last;
- BOOL first_pass = YES;
- unsigned short Xoff = 10;
-
- Nx = IBUFFSIZE - 2 * Xoff; /* # of samples to process each iteration */
- last = 0; /* Have not read last input sample yet */
- Ycount = 0; /* Current sample and length of output file */
-
- Xp = Xoff; /* Current "now"-sample pointer for input */
- Xread = Xoff; /* Position in input array to read into */
-
- if (sinitial == YES)
- {
- sTime = (Xoff << Np); /* Current-time pointer for converter */
- }
-
- do
- {
- if (!last)
- { /* If haven't read last sample yet */
- last = resamplerReadData(inCount, inArray, sX, IBUFFSIZE, (int)Xread, first_pass);
- first_pass = NO;
-
- if (last && ((last - Xoff) < Nx))
- { /* If last sample has been read... */
- Nx = last - Xoff; /* ...calc last sample affected by filter */
- if (Nx <= 0)
- {
- break;
- }
- }
- }
-
- if ((outCount-Ycount) > (OBUFFSIZE - (2 * Xoff * sfactor)))
- {
- maxOutput = OBUFFSIZE - (unsigned short)(2 * Xoff * sfactor);
- }
- else
- {
- maxOutput = outCount-Ycount;
- }
-
- for (c = 0; c < DEFAULT_CHANNELS; c++)
- {
- orig_Nx = Nx;
- Time2 = sTime;
-
- /* Resample stuff in input buffer */
- Nout = SrcLinear(sX[c], sY[c], sfactor, &Time2, orig_Nx, maxOutput);
- }
-
- Nx = orig_Nx;
- sTime = Time2;
-
- sTime -= (Nx << Np); /* Move converter Nx samples back in time */
- Xp += Nx; /* Advance by number of samples processed */
-
- for (c = 0; c < DEFAULT_CHANNELS; c++)
- {
- for (i = 0; i < (IBUFFSIZE - Xp + Xoff); i++)
- { /* Copy part of input signal */
- sX[c][i] = sX[c][i + Xp - Xoff]; /* that must be re-used */
- }
- }
-
- if (last)
- { /* If near end of sample... */
- last -= Xp; /* ...keep track were it ends */
-
- if (!last)
- { /* Lengthen input by 1 sample if... */
- last++;
- } /* ...needed to keep flag YES */
- }
-
- Xread = IBUFFSIZE - Nx; /* Pos in input buff to read new data into */
- Xp = Xoff;
-
- Ycount += Nout;
- if (Ycount > outCount)
- {
- Nout -= (Ycount - outCount);
- Ycount = outCount;
- }
-
- if (Nout > OBUFFSIZE)
- { /* Check to see if output buff overflowed */
- return resampleError("Output array overflow");
- }
-
- for (c = 0; c < DEFAULT_CHANNELS; c++)
- {
- for (i = 0; i < Nout; i++)
- {
- outArray[c * outCount + i + Ycount - Nout] = sY[c][i];
- }
- }
-
- total_inCount += Nx;
-
- } while (Ycount < outCount); /* Continue until done */
-
- inCount = total_inCount;
-
- return(Ycount); /* Return # of samples in output file */
-}
-
-int
-SrcLinear(short X[], short Y[], double factor, unsigned int *Time,
- unsigned short Nx, unsigned short Nout)
-{
- short iconst;
- short *Xp, *Ystart;
- int v, x1, x2;
-
- double dt; /* Step through input signal */
- unsigned int dtb; /* Fixed-point version of Dt */
- unsigned int start_sample, end_sample;
-
- dt = 1.0 / factor; /* Output sampling period */
- dtb = (unsigned int)(dt * (1 << Np) + 0.5); /* Fixed-point representation */
-
- start_sample = *Time >> Np;
- Ystart = Y;
-
- while (Y - Ystart != Nout)
- {
- iconst = *Time & Pmask;
- Xp = &X[*Time >> Np]; /* Ptr to current input sample */
- x1 = *Xp++;
- x2 = *Xp;
- x1 *= (1 << Np) - iconst;
- x2 *= iconst;
- v = x1 + x2;
- *Y++ = WordToHword(v, Np); /* Deposit output */
- *Time += dtb; /* Move to next sample by time increment */
- }
-
- end_sample = *Time >> Np;
- Nx = end_sample - start_sample;
- return (Y - Ystart); /* Return number of output samples */
-}
-
-inline short
-WordToHword(int v, int scl)
-{
- short out;
- int llsb;
-
- llsb = (1 << (scl - 1));
- v += llsb; /* round */
- v >>= scl;
- if (v > INT16_MAX)
- {
- v = INT16_MAX;
- }
- else if (v < INT16_MIN)
- {
- v = INT16_MIN;
- }
- out = (short)v;
-
- return out;
-}
-
-int
-resamplerReadData(int inCount, short inArray[], short *outPtr[],
- int dataArraySize, int Xoff, BOOL init_count)
-{
- int i, Nsamps, c;
- static unsigned int framecount; /* frames previously read */
- short *ptr;
-
- if (init_count == YES)
- {
- framecount = 0; /* init this too */
- }
-
- Nsamps = dataArraySize - Xoff; /* Calculate number of samples to get */
-
- // Don't overrun input buffers
- if (Nsamps > (inCount - (int)framecount))
- {
- Nsamps = inCount - framecount;
- }
-
- for (c = 0; c < DEFAULT_CHANNELS; c++)
- {
- ptr = outPtr[c];
- ptr += Xoff; /* Start at designated sample number */
-
- for (i = 0; i < Nsamps; i++)
- {
- *ptr++ = (short) inArray[c * inCount + i + framecount];
- }
- }
-
- framecount += Nsamps;
-
- if ((int)framecount >= inCount)
- { /* return index of last samp */
- return (((Nsamps - (framecount - inCount)) - 1) + Xoff);
- }
-
- return 0;
-}
-
-int
-resampleError(char *s)
-{
- NSLog([NSString stringWithCString: s]);
- return -1;
-}
-
Index: Tools/gsnd/GNUmakefile
===================================================================
--- Tools/gsnd/GNUmakefile (revision 28389)
+++ Tools/gsnd/GNUmakefile (working copy)
@@ -1,41 +0,0 @@
-#
-# Tools level makefile for gsnd
-#
-# Copyright (C) 2002 Free Software Foundation, Inc.
-#
-# This file is part of the GNUstep GUI Library.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; see the file COPYING.LIB.
-# If not, see or write to the
-# Free Software Foundation, 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-
-PACKAGE_NAME = gnustep-gui
-include $(GNUSTEP_MAKEFILES)/common.make
-
-# The applications to be compiled
-TOOL_NAME = gnustep_sndd
-
-# The source files to be compiled
-gnustep_sndd_OBJC_FILES = gsnd.m
-
-gnustep_sndd_TOOL_LIBS = -lportaudio
-
--include GNUmakefile.preamble
-
--include GNUmakefile.local
-
-include $(GNUSTEP_MAKEFILES)/tool.make
-
--include GNUmakefile.postamble
Index: Tools/gsnd/GNUmakefile.postamble
===================================================================
--- Tools/gsnd/GNUmakefile.postamble (revision 28389)
+++ Tools/gsnd/GNUmakefile.postamble (working copy)
@@ -1,47 +0,0 @@
-#
-# Makefile.postamble
-#
-# Project specific makefile rules
-#
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# Uncomment the targets you want.
-# The double colons (::) are important, do not make them single colons
-# otherwise the normal makefile rules will not be performed.
-#
-
-# Things to do before compiling
-#before-all::
-
-# Things to do after compiling
-# after-all::
-
-# Things to do before installing
-#before-install::
-
-# Things to do after installing
-# after-install::
-
-# Things to do before uninstalling
-# before-uninstall::
-
-# Things to do after uninstalling
-# after-uninstall::
-
-# Things to do before cleaning
-# before-clean::
-
-# Things to do after cleaning
-# after-clean::
-
-# Things to do before distcleaning
-# before-distclean::
-
-# Things to do after distcleaning
-#after-distclean::
-
-# Things to do before checking
-# before-check::
-
-# Things to do after checking
-# after-check::
Index: Tools/gsnd/GNUmakefile.preamble
===================================================================
--- Tools/gsnd/GNUmakefile.preamble (revision 28389)
+++ Tools/gsnd/GNUmakefile.preamble (working copy)
@@ -1,42 +0,0 @@
-#
-# Makefile.preamble
-#
-# Project specific makefile variables, and additional
-#
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# Do not put any Makefile rules in this file, instead they should
-# be put into Makefile.postamble.
-#
-
-#
-# Flags dealing with compiling and linking
-#
-
-# Additional flags to pass to the preprocessor
-#ADDITIONAL_CPPFLAGS +=
-
-# Additional flags to pass to the Objective-C compiler
-#ADDITIONAL_OBJCFLAGS +=
-
-# Additional flags to pass to the C compiler
-#ADDITIONAL_CFLAGS +=
-
-# Additional include directories the compiler should search
-#ADDITIONAL_INCLUDE_DIRS +=
-
-# Additional LDFLAGS to pass to the linker
-#ADDITIONAL_LDFLAGS +=
-
-# Additional library directories the linker should search
-# ADDITIONAL_LIB_DIRS += -L../Source/$(GNUSTEP_OBJ_DIR)
-
-# Additional libraries when linking applications
-#ADDITIONAL_TOOL_LIBS +=
-
-#
-# Flags dealing with installing and uninstalling
-#
-
-# Additional directories to be created during installation
-#ADDITIONAL_INSTALL_DIRS +=