updated to use portaudio v19.

on startup creates a daemon using NSTask.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@21640 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
esersale 2005-08-16 17:36:44 +00:00
parent 5cd54d4415
commit 134aac6c8a

View file

@ -251,6 +251,8 @@ gsnd_log (int prio)
- (void)checkIsPlaying; - (void)checkIsPlaying;
- (void)closeStream;
- (Snd *)cachedSoundWithName:(NSString *)aName; - (Snd *)cachedSoundWithName:(NSString *)aName;
- (void)checkCachedSounds; - (void)checkCachedSounds;
@ -270,7 +272,7 @@ gsnd_log (int prio)
SoundServer *gsnd = nil; SoundServer *gsnd = nil;
PortAudioStream *pStream = NULL; PaStream *pStream = NULL;
struct SoundServer_t { struct SoundServer_t {
@defs(SoundServer) @defs(SoundServer)
@ -291,21 +293,20 @@ struct SoundServer_t {
{ {
self = [super init]; self = [super init];
if (self) if (self) {
{ ASSIGN (name, [anobject name]);
ASSIGN (name, [anobject name]); ASSIGN (identifier, [anobject identifier]);
ASSIGN (identifier, [anobject identifier]); data = [[anobject data] mutableCopy];
data = [[anobject data] mutableCopy]; frameCount = [anobject frameCount];
frameCount = [anobject frameCount]; rate = [anobject samplingRate];
rate = [anobject samplingRate]; startPos = 0;
startPos = 0; endPos = 0;
endPos = 0; posInBytes = 0;
posInBytes = 0; playing = NO;
playing = NO; paused = NO;
paused = NO;
[self resampleWithFactor: (PLAY_RATE / rate)];
[self resampleWithFactor: (PLAY_RATE / rate)]; }
}
return self; return self;
} }
@ -463,14 +464,14 @@ struct SoundServer_t {
@end @end
@implementation SoundServer
static int paCallback(void *inputBuffer, static int paCallback(void *inputBuffer,
void *outputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, unsigned long framesPerBuffer,
PaTimestamp outTime, const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData) void *userData)
{ {
NSAutoreleasePool *pool;
NSData *data; NSData *data;
long length; long length;
int chunkLength; int chunkLength;
@ -479,8 +480,12 @@ static int paCallback(void *inputBuffer,
gss16 *in; gss16 *in;
int i; int i;
CREATE_AUTORELEASE_POOL(pool); #ifdef GNUSTEP
GSRegisterCurrentThread();
#endif
pool = [[NSAutoreleasePool alloc] init];
data = serverPtr->soundData; data = serverPtr->soundData;
length = [data length]; length = [data length];
@ -502,19 +507,8 @@ static int paCallback(void *inputBuffer,
} }
if (retvalue == 1) { if (retvalue == 1) {
PaError err; [(SoundServer *)serverPtr performSelectorOnMainThread: @selector(closeStream)
withObject: (SoundServer *)serverPtr waitUntilDone: NO];
err = Pa_CloseStream(pStream);
if (err != paNoError) {
NSLog(@"PortAudio Pa_CloseStream error: %s", Pa_GetErrorText(err));
}
err = Pa_Terminate();
if (err != paNoError) {
NSLog(@"PortAudio Pa_Terminate error: %s", Pa_GetErrorText(err));
}
[(SoundServer *)serverPtr stopAll];
} }
serverPtr->isPlaying = !retvalue; serverPtr->isPlaying = !retvalue;
@ -524,6 +518,9 @@ static int paCallback(void *inputBuffer,
return retvalue; return retvalue;
} }
@implementation SoundServer
- (void)dealloc - (void)dealloc
{ {
[nc removeObserver: self]; [nc removeObserver: self];
@ -539,7 +536,7 @@ static int paCallback(void *inputBuffer,
if (self) { if (self) {
NSString *hostname; NSString *hostname;
NSNumber *csize; NSNumber *csize;
serverPtr = (struct SoundServer_t *)self; serverPtr = (struct SoundServer_t *)self;
nc = [NSNotificationCenter defaultCenter]; nc = [NSNotificationCenter defaultCenter];
@ -557,15 +554,17 @@ static int paCallback(void *inputBuffer,
[conn setRootObject: self]; [conn setRootObject: self];
[conn setDelegate: self]; [conn setDelegate: self];
[nc addObserver: self [nc addObserver: self
selector: @selector(connectionBecameInvalid:) selector: @selector(connectionBecameInvalid:)
name: NSConnectionDidDieNotification object: (id)conn]; name: NSConnectionDidDieNotification
object: (id)conn];
hostname = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"]; hostname = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"];
if ([hostname length] == 0 if ([hostname length] == 0
|| [[NSHost hostWithName: hostname] isEqual: [NSHost currentHost]] == YES) { || [[NSHost hostWithName: hostname] isEqual: [NSHost currentHost]]) {
if ([conn registerName: GSNDNAME] == NO) { if ([conn registerName: GSNDNAME] == NO) {
NSLog(@"Unable to register with name server.\n"); NSLog(@"Unable to register with name server.\n");
exit(1); exit(1);
} }
} else { } else {
NSHost *host = [NSHost hostWithName: hostname]; NSHost *host = [NSHost hostWithName: hostname];
@ -575,30 +574,30 @@ static int paCallback(void *inputBuffer,
unsigned c; unsigned c;
if (host == nil) { if (host == nil) {
NSLog(@"gsnd - unknown NSHost argument ... %@ - quiting.", hostname); NSLog(@"gsnd - unknown NSHost argument ... %@ - quiting.", hostname);
exit(1); exit(1);
} }
a = [host names]; a = [host names];
c = [a count]; c = [a count];
while (c-- > 0) { while (c-- > 0) {
NSString *name = [a objectAtIndex: c]; NSString *name = [a objectAtIndex: c];
name = [GSNDNAME stringByAppendingFormat: @"-%@", name]; name = [GSNDNAME stringByAppendingFormat: @"-%@", name];
if ([ns registerPort: port forName: name] == NO) { if ([ns registerPort: port forName: name] == NO) {
} }
} }
a = [host addresses]; a = [host addresses];
c = [a count]; c = [a count];
while (c-- > 0) { while (c-- > 0) {
NSString *name = [a objectAtIndex: c]; NSString *name = [a objectAtIndex: c];
name = [GSNDNAME stringByAppendingFormat: @"-%@", name]; name = [GSNDNAME stringByAppendingFormat: @"-%@", name];
if ([ns registerPort: port forName: name] == NO) { if ([ns registerPort: port forName: name] == NO) {
} }
} }
} }
} }
return self; return self;
@ -637,9 +636,9 @@ static int paCallback(void *inputBuffer,
RELEASE (snd); RELEASE (snd);
} else { } else {
if ([snd isPlaying] || [snd isPaused]) { if ([snd isPlaying] || [snd isPaused]) {
snd = [snd copy]; snd = [snd copy];
[sounds addObject: snd]; [sounds addObject: snd];
RELEASE (snd); RELEASE (snd);
} }
[snd reset]; [snd reset];
[snd setIdentifier: idendstr]; [snd setIdentifier: idendstr];
@ -744,39 +743,38 @@ static int paCallback(void *inputBuffer,
{ {
PaError err; PaError err;
int d = 0; int d = 0;
err = Pa_Initialize(); err = Pa_Initialize();
if(err != paNoError) {
NSLog(@"PortAudio error: %s", Pa_GetErrorText(err));
} else {
NSLog(@"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, err = Pa_OpenDefaultStream(&pStream, 0, DEFAULT_CHANNELS, paInt16,
PLAY_RATE, BUFFER_SIZE_IN_FRAMES, 0, paCallback, &d); PLAY_RATE, BUFFER_SIZE_IN_FRAMES, (PaStreamCallback *)paCallback, &d);
if(err != paNoError) { 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)); NSLog(@"PortAudio Pa_OpenDefaultStream error: %s", Pa_GetErrorText(err));
} else {
NSLog(@"Pa_OpenDefaultStream");
} }
err = Pa_StartStream(pStream);
if(err != paNoError) {
NSLog(@"PortAudio Pa_StartStream error: %s", Pa_GetErrorText(err));
} else {
NSLog(@"Pa_StartStream");
}
Pa_Sleep(2);
} }
- (void)mixWithSound:(Snd *)snd - (void)mixWithSound:(Snd *)snd
{ {
if (isPlaying == NO) { if (isPlaying) {
return;
} else {
NSData *snddata = [snd remainingData]; NSData *snddata = [snd remainingData];
long inFrameCount = (long)([snddata length] / FRAME_SIZE); long inFrameCount = (long)([snddata length] / FRAME_SIZE);
gss16 *in = (gss16 *)[snddata bytes]; gss16 *in = (gss16 *)[snddata bytes];
@ -790,6 +788,7 @@ static int paCallback(void *inputBuffer,
[snd setEndPos: posInBytes + (long)([snddata length] / FRAME_SIZE)]; [snd setEndPos: posInBytes + (long)([snddata length] / FRAME_SIZE)];
j = 0; j = 0;
for (i = posInBytes; i < frameCount; i++) { for (i = posInBytes; i < frameCount; i++) {
sum_l = out[i * 2] + in[j * 2]; sum_l = out[i * 2] + in[j * 2];
sum_r = out[i * 2 + 1] + in[j * 2 + 1]; sum_r = out[i * 2 + 1] + in[j * 2 + 1];
@ -799,11 +798,12 @@ static int paCallback(void *inputBuffer,
j++; j++;
if (j == inFrameCount) { if (j == inFrameCount) {
break; break;
} }
} }
inPos = (j * FRAME_SIZE); inPos = (j * FRAME_SIZE);
if (inPos < ([snddata length] - 1)) { if (inPos < ([snddata length] - 1)) {
long remLength = [snddata length] - inPos; long remLength = [snddata length] - inPos;
NSRange range = NSMakeRange(inPos, remLength); NSRange range = NSMakeRange(inPos, remLength);
@ -818,10 +818,7 @@ static int paCallback(void *inputBuffer,
- (void)unMixSound:(Snd *)snd - (void)unMixSound:(Snd *)snd
{ {
if (isPlaying == NO) { if (isPlaying) {
return;
} else {
int *in = (int *)[[snd data] bytes]; int *in = (int *)[[snd data] bytes];
int *out = (int *)[soundData mutableBytes]; int *out = (int *)[soundData mutableBytes];
long deleteFrom = [snd startPos] + [snd posInBytes]; long deleteFrom = [snd startPos] + [snd posInBytes];
@ -833,10 +830,10 @@ static int paCallback(void *inputBuffer,
out[i] -= in[j]; out[i] -= in[j];
j++; j++;
if (j == deleteTo) { if (j == deleteTo) {
break; break;
} }
} }
} }
} }
- (void)updatePosition - (void)updatePosition
@ -853,7 +850,7 @@ static int paCallback(void *inputBuffer,
[snd posInBytesAdd]; [snd posInBytesAdd];
if (posInBytes == [snd endPos]) { if (posInBytes == [snd endPos]) {
[snd reset]; [snd reset];
} }
} }
} }
@ -903,12 +900,41 @@ static int paCallback(void *inputBuffer,
} }
} }
- (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 - (Snd *)cachedSoundWithName:(NSString *)aName
{ {
int i; int i;
for (i = 0; i < [sounds count]; i++) { for (i = 0; i < [sounds count]; i++) {
Snd *snd = [sounds objectAtIndex: i]; Snd *snd = [sounds objectAtIndex: i];
if ([[snd name] isEqual: aName]) { if ([[snd name] isEqual: aName]) {
return snd; return snd;
} }
@ -932,12 +958,12 @@ static int paCallback(void *inputBuffer,
Snd *snd1 = [sounds objectAtIndex: j]; Snd *snd1 = [sounds objectAtIndex: j];
if (([[snd1 name] isEqual: name]) && (snd0 != snd1)) { if (([[snd1 name] isEqual: name]) && (snd0 != snd1)) {
if (([snd1 isPaused] == NO) && ([snd1 isPlaying] == NO)) { if (([snd1 isPaused] == NO) && ([snd1 isPlaying] == NO)) {
[sounds removeObject: snd1]; [sounds removeObject: snd1];
count--; count--;
i--; i--;
j--; j--;
} }
} }
} }
} }
@ -953,13 +979,13 @@ static int paCallback(void *inputBuffer,
Snd *snd = [sounds objectAtIndex: i]; Snd *snd = [sounds objectAtIndex: i];
if (([snd isPlaying] == NO) && ([snd isPaused] == NO)) { if (([snd isPlaying] == NO) && ([snd isPaused] == NO)) {
csize -= [[snd data] length]; csize -= [[snd data] length];
[sounds removeObject: snd]; [sounds removeObject: snd];
count--; count--;
i--; i--;
} }
if (csize <= maxCacheSize) { if (csize <= maxCacheSize) {
break; break;
} }
} }
} }
@ -991,7 +1017,7 @@ static int paCallback(void *inputBuffer,
NSString *sname = [snd name]; NSString *sname = [snd name];
if ([sname isEqual: aName]) { if ([sname isEqual: aName]) {
return snd; return snd;
} }
} }
} }
@ -1008,12 +1034,12 @@ static int paCallback(void *inputBuffer,
} }
- (BOOL)connection:(NSConnection*)ancestor - (BOOL)connection:(NSConnection*)ancestor
shouldMakeNewConnection:(NSConnection*)newConn; shouldMakeNewConnection:(NSConnection*)newConn;
{ {
[nc addObserver: self [nc addObserver: self
selector: @selector(connectionBecameInvalid:) selector: @selector(connectionBecameInvalid:)
name: NSConnectionDidDieNotification name: NSConnectionDidDieNotification
object: newConn]; object: newConn];
[newConn setDelegate: self]; [newConn setDelegate: self];
@ -1034,95 +1060,80 @@ shouldMakeNewConnection:(NSConnection*)newConn;
@end @end
int int main(int argc, char** argv, char **env)
main(int argc, char** argv, char **env)
{ {
int c;
CREATE_AUTORELEASE_POOL(pool); CREATE_AUTORELEASE_POOL(pool);
BOOL subtask = YES;
NSProcessInfo *pInfo;
NSMutableArray *args;
#ifdef GS_PASS_ARGUMENTS #ifdef GS_PASS_ARGUMENTS
[NSProcessInfo initializeWithArguments: argv count: argc environment: env]; [NSProcessInfo initializeWithArguments: argv count: argc environment: env];
#endif #endif
#ifdef __MINGW__ pInfo = [NSProcessInfo processInfo];
{ args = AUTORELEASE ([[pInfo arguments] mutableCopy]);
char **a = malloc((argc+2) * sizeof(char*));
memcpy(a, argv, argc * sizeof(char*)); if ([[pInfo arguments] containsObject: @"--daemon"]) {
a[argc] = "--no-fork"; subtask = NO;
a[argc+1] = 0; is_daemon = YES;
if (_spawnv(_P_NOWAIT, argv[0], a) == -1) {
fprintf(stderr, "gsnd - spawn failed - bye.\n");
exit(1);
}
exit(0);
}
#else
is_daemon = 1;
switch (fork()) {
case -1:
NSLog(@"gsnd - fork failed - bye.\n");
exit(1);
case 0:
#ifdef NeXT
setpgrp(0, getpid());
#else
setsid();
#endif
break;
default:
exit(0);
} }
/* if (subtask) {
* Ensure we don't have any open file descriptors which may refer NSFileHandle *null;
* to sockets bound to ports we may try to use. NSTask *t;
*
* Use '/dev/null' for stdin and stdout. Assume stderr is ok.
*/
for (c = 0; c < FD_SETSIZE; c++)
{
if (is_daemon || (c != 2))
{
(void)close(c);
}
}
if (open("/dev/null", O_RDONLY) != 0)
{
sprintf(ebuf, "failed to open stdin from /dev/null (%s)\n",
strerror(errno));
gsnd_log(LOG_CRIT);
exit(EXIT_FAILURE);
}
if (open("/dev/null", O_WRONLY) != 1)
{
sprintf(ebuf, "failed to open stdout from /dev/null (%s)\n",
strerror(errno));
gsnd_log(LOG_CRIT);
exit(EXIT_FAILURE);
}
if (is_daemon && open("/dev/null", O_WRONLY) != 2)
{
sprintf(ebuf, "failed to open stderr from /dev/null (%s)\n",
strerror(errno));
gsnd_log(LOG_CRIT);
exit(EXIT_FAILURE);
}
#endif
gsnd = [[SoundServer alloc] init]; 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);
}
if (gsnd == nil)
{
NSLog(@"Unable to create gsnd object.\n");
exit(1);
}
[[NSRunLoop currentRunLoop] run];
RELEASE(pool); RELEASE(pool);
exit(0);
{
#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);
} }