mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-06-02 10:21:00 +00:00
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:
parent
5cd54d4415
commit
134aac6c8a
1 changed files with 189 additions and 178 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue