Mercurial > sdl-ios-xcode
annotate src/audio/dma/SDL_dmaaudio.c @ 1348:40d0975c1769
Date: Mon, 6 Feb 2006 11:41:04 -0500
From: "mystml@adinet.com.uy"
Subject: [SDL] ALT-F4 using DirectX
My game isn't getting SDL_QUIT when I press ALT-F4 using the DirectX
driver; it does get SDL_QUIT when I press the red X in the window.
I tracked this down to DX5_HandleMessage() in SDL_dx5events.c;
WM_SYSKEYDOWN is being trapped and ignored which causes Windows not to post
a WM_CLOSE, hence no SDL_QUIT is being generated.
The relevant code is this :
/* The keyboard is handled via DirectInput */
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_KEYDOWN: {
/* Ignore windows keyboard messages */;
}
return(0);
If I comment the WM_SYSKEYDOWN case, it falls through DefWindowProc() and
ALT-F4 starts working again.
I'm not sure about the best way to fix this. One option is handling ALT-F4
as a particular case somehow, but doesn't sound good. Another option would
be to handle WM_SYSKEYDOWN separately and breaking instead of returning 0,
so processing falls through and goes to DefWindowProc which does The Right
Thing (TM). This seems to be the minimal change that makes ALT-F4 work and
normal keyboard input continues to work.
Does this sound reasonable? Am I overlooking anything? Do I submit a patch?
--Gabriel
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 08 Feb 2006 17:19:43 +0000 |
parents | d02b552e5304 |
children | c71e05b4dc2e |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
960
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
94
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 /* Allow access to a raw mixing buffer */ | |
24 | |
25 #include <stdio.h> | |
1341
d02b552e5304
Configure dynamically generates SDL_config.h
Sam Lantinga <slouken@libsdl.org>
parents:
1338
diff
changeset
|
26 #include <string.h> /* For strerror() */ |
0 | 27 #include <errno.h> |
28 #include <unistd.h> | |
29 #include <fcntl.h> | |
30 #include <signal.h> | |
31 #include <sys/types.h> | |
32 #include <sys/time.h> | |
33 #include <sys/ioctl.h> | |
34 #include <sys/stat.h> | |
35 #include <sys/mman.h> | |
94
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
92
diff
changeset
|
36 #ifdef OSS_USE_SOUNDCARD_H |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
92
diff
changeset
|
37 /* This is installed on some systems */ |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
92
diff
changeset
|
38 #include <soundcard.h> |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
92
diff
changeset
|
39 #else |
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
92
diff
changeset
|
40 /* This is recommended by OSS */ |
0 | 41 #include <sys/soundcard.h> |
94
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
92
diff
changeset
|
42 #endif |
0 | 43 |
44 #ifndef MAP_FAILED | |
45 #define MAP_FAILED ((Uint8 *)-1) | |
46 #endif | |
47 | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
48 #include "SDL_stdlib.h" |
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
49 #include "SDL_string.h" |
0 | 50 #include "SDL_audio.h" |
51 #include "SDL_error.h" | |
52 #include "SDL_audiomem.h" | |
53 #include "SDL_audio_c.h" | |
54 #include "SDL_timer.h" | |
55 #include "SDL_audiodev_c.h" | |
56 #include "SDL_dmaaudio.h" | |
57 | |
58 /* The tag name used by DMA audio */ | |
59 #define DMA_DRIVER_NAME "dma" | |
60 | |
61 /* Open the audio device for playback, and don't block if busy */ | |
62 #define OPEN_FLAGS (O_RDWR|O_NONBLOCK) | |
63 | |
64 /* Audio driver functions */ | |
65 static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
66 static void DMA_WaitAudio(_THIS); | |
67 static void DMA_PlayAudio(_THIS); | |
68 static Uint8 *DMA_GetAudioBuf(_THIS); | |
69 static void DMA_CloseAudio(_THIS); | |
70 | |
71 /* Audio driver bootstrap functions */ | |
72 | |
73 static int Audio_Available(void) | |
74 { | |
75 int available; | |
76 int fd; | |
77 | |
78 available = 0; | |
79 | |
80 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | |
81 if ( fd >= 0 ) { | |
82 int caps; | |
83 struct audio_buf_info info; | |
84 | |
85 if ( (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) && | |
86 (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) && | |
87 (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0) ) { | |
88 available = 1; | |
89 } | |
90 close(fd); | |
91 } | |
92 return(available); | |
93 } | |
94 | |
95 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
96 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
97 SDL_free(device->hidden); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
98 SDL_free(device); |
0 | 99 } |
100 | |
101 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
102 { | |
103 SDL_AudioDevice *this; | |
104 | |
105 /* Initialize all variables that we clean on shutdown */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
106 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); |
0 | 107 if ( this ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
108 SDL_memset(this, 0, (sizeof *this)); |
0 | 109 this->hidden = (struct SDL_PrivateAudioData *) |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
110 SDL_malloc((sizeof *this->hidden)); |
0 | 111 } |
112 if ( (this == NULL) || (this->hidden == NULL) ) { | |
113 SDL_OutOfMemory(); | |
114 if ( this ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
115 SDL_free(this); |
0 | 116 } |
117 return(0); | |
118 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
119 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
0 | 120 audio_fd = -1; |
121 | |
122 /* Set the function pointers */ | |
123 this->OpenAudio = DMA_OpenAudio; | |
124 this->WaitAudio = DMA_WaitAudio; | |
125 this->PlayAudio = DMA_PlayAudio; | |
126 this->GetAudioBuf = DMA_GetAudioBuf; | |
127 this->CloseAudio = DMA_CloseAudio; | |
128 | |
129 this->free = Audio_DeleteDevice; | |
130 | |
131 return this; | |
132 } | |
133 | |
134 AudioBootStrap DMA_bootstrap = { | |
135 DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", | |
136 Audio_Available, Audio_CreateDevice | |
137 }; | |
138 | |
139 /* This function waits until it is possible to write a full sound buffer */ | |
140 static void DMA_WaitAudio(_THIS) | |
141 { | |
142 fd_set fdset; | |
143 | |
144 /* Check to see if the thread-parent process is still alive */ | |
145 { static int cnt = 0; | |
146 /* Note that this only works with thread implementations | |
147 that use a different process id for each thread. | |
148 */ | |
149 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ | |
150 if ( kill(parent, 0) < 0 ) { | |
151 this->enabled = 0; | |
152 } | |
153 } | |
154 } | |
155 | |
156 /* See if we need to use timed audio synchronization */ | |
157 if ( frame_ticks ) { | |
158 /* Use timer for general audio synchronization */ | |
159 Sint32 ticks; | |
160 | |
161 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; | |
162 if ( ticks > 0 ) { | |
163 SDL_Delay(ticks); | |
164 } | |
165 } else { | |
166 /* Use select() for audio synchronization */ | |
167 struct timeval timeout; | |
168 FD_ZERO(&fdset); | |
169 FD_SET(audio_fd, &fdset); | |
170 timeout.tv_sec = 10; | |
171 timeout.tv_usec = 0; | |
172 #ifdef DEBUG_AUDIO | |
173 fprintf(stderr, "Waiting for audio to get ready\n"); | |
174 #endif | |
175 if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { | |
176 const char *message = | |
177 #ifdef AUDIO_OSPACE_HACK | |
178 "Audio timeout - buggy audio driver? (trying ospace)"; | |
179 #else | |
180 "Audio timeout - buggy audio driver? (disabled)"; | |
181 #endif | |
182 /* In general we should never print to the screen, | |
183 but in this case we have no other way of letting | |
184 the user know what happened. | |
185 */ | |
186 fprintf(stderr, "SDL: %s\n", message); | |
187 #ifdef AUDIO_OSPACE_HACK | |
188 /* We may be able to use GET_OSPACE trick */ | |
189 frame_ticks = (float)(this->spec->samples*1000) / | |
190 this->spec->freq; | |
191 next_frame = SDL_GetTicks()+frame_ticks; | |
192 #else | |
193 this->enabled = 0; | |
194 /* Don't try to close - may hang */ | |
195 audio_fd = -1; | |
196 #ifdef DEBUG_AUDIO | |
197 fprintf(stderr, "Done disabling audio\n"); | |
198 #endif | |
199 #endif /* AUDIO_OSPACE_HACK */ | |
200 } | |
201 #ifdef DEBUG_AUDIO | |
202 fprintf(stderr, "Ready!\n"); | |
203 #endif | |
204 } | |
205 } | |
206 | |
207 static void DMA_PlayAudio(_THIS) | |
208 { | |
209 /* If timer synchronization is enabled, set the next write frame */ | |
210 if ( frame_ticks ) { | |
211 next_frame += frame_ticks; | |
212 } | |
213 return; | |
214 } | |
215 | |
216 static Uint8 *DMA_GetAudioBuf(_THIS) | |
217 { | |
218 count_info info; | |
219 int playing; | |
220 int filling; | |
221 | |
222 /* Get number of blocks, looping if we're not using select() */ | |
223 do { | |
224 if ( ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0 ) { | |
225 /* Uh oh... */ | |
226 this->enabled = 0; | |
227 return(NULL); | |
228 } | |
229 } while ( frame_ticks && (info.blocks < 1) ); | |
230 #ifdef DEBUG_AUDIO | |
231 if ( info.blocks > 1 ) { | |
232 printf("Warning: audio underflow (%d frags)\n", info.blocks-1); | |
233 } | |
234 #endif | |
235 playing = info.ptr / this->spec.size; | |
236 filling = (playing + 1)%num_buffers; | |
237 return (dma_buf + (filling * this->spec.size)); | |
238 } | |
239 | |
240 static void DMA_CloseAudio(_THIS) | |
241 { | |
242 if ( dma_buf != NULL ) { | |
243 munmap(dma_buf, dma_len); | |
244 dma_buf = NULL; | |
245 } | |
246 if ( audio_fd >= 0 ) { | |
247 close(audio_fd); | |
248 audio_fd = -1; | |
249 } | |
250 } | |
251 | |
252 static int DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, | |
253 SDL_AudioSpec *spec) | |
254 { | |
255 int frag_spec; | |
256 int value; | |
257 | |
258 /* Close and then reopen the audio device */ | |
259 close(audio_fd); | |
260 audio_fd = open(audiodev, O_RDWR, 0); | |
261 if ( audio_fd < 0 ) { | |
262 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
263 return(-1); | |
264 } | |
265 | |
266 /* Calculate the final parameters for this audio specification */ | |
267 SDL_CalculateAudioSpec(spec); | |
268 | |
269 /* Determine the power of two of the fragment size */ | |
270 for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); | |
271 if ( (0x01<<frag_spec) != spec->size ) { | |
272 SDL_SetError("Fragment size must be a power of two"); | |
273 return(-1); | |
274 } | |
275 | |
276 /* Set the audio buffering parameters */ | |
277 if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) { | |
278 SDL_SetError("Couldn't set audio fragment spec"); | |
279 return(-1); | |
280 } | |
281 | |
282 /* Set the audio format */ | |
283 value = format; | |
284 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || | |
285 (value != format) ) { | |
286 SDL_SetError("Couldn't set audio format"); | |
287 return(-1); | |
288 } | |
289 | |
290 /* Set mono or stereo audio */ | |
291 value = (spec->channels > 1); | |
292 if ( (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) || | |
293 (value != stereo) ) { | |
294 SDL_SetError("Couldn't set audio channels"); | |
295 return(-1); | |
296 } | |
297 | |
298 /* Set the DSP frequency */ | |
299 value = spec->freq; | |
960
eec28a5278be
Date: Sat, 9 Oct 2004 02:46:18 +0300 (EEST)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
300 if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) { |
0 | 301 SDL_SetError("Couldn't set audio frequency"); |
302 return(-1); | |
303 } | |
304 spec->freq = value; | |
305 | |
306 /* We successfully re-opened the audio */ | |
307 return(0); | |
308 } | |
309 | |
310 static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
311 { | |
312 char audiodev[1024]; | |
313 int format; | |
314 int stereo; | |
315 int value; | |
316 Uint16 test_format; | |
317 struct audio_buf_info info; | |
318 | |
319 /* Reset the timer synchronization flag */ | |
320 frame_ticks = 0.0; | |
321 | |
322 /* Open the audio device */ | |
323 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | |
324 if ( audio_fd < 0 ) { | |
325 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
326 return(-1); | |
327 } | |
328 dma_buf = NULL; | |
329 ioctl(audio_fd, SNDCTL_DSP_RESET, 0); | |
330 | |
331 /* Get a list of supported hardware formats */ | |
332 if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) { | |
333 SDL_SetError("Couldn't get audio format list"); | |
334 return(-1); | |
335 } | |
336 | |
337 /* Try for a closest match on audio format */ | |
338 format = 0; | |
339 for ( test_format = SDL_FirstAudioFormat(spec->format); | |
340 ! format && test_format; ) { | |
341 #ifdef DEBUG_AUDIO | |
342 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); | |
343 #endif | |
344 switch ( test_format ) { | |
345 case AUDIO_U8: | |
346 if ( value & AFMT_U8 ) { | |
347 format = AFMT_U8; | |
348 } | |
349 break; | |
350 case AUDIO_S8: | |
351 if ( value & AFMT_S8 ) { | |
352 format = AFMT_S8; | |
353 } | |
354 break; | |
355 case AUDIO_S16LSB: | |
356 if ( value & AFMT_S16_LE ) { | |
357 format = AFMT_S16_LE; | |
358 } | |
359 break; | |
360 case AUDIO_S16MSB: | |
361 if ( value & AFMT_S16_BE ) { | |
362 format = AFMT_S16_BE; | |
363 } | |
364 break; | |
365 case AUDIO_U16LSB: | |
366 if ( value & AFMT_U16_LE ) { | |
367 format = AFMT_U16_LE; | |
368 } | |
369 break; | |
370 case AUDIO_U16MSB: | |
371 if ( value & AFMT_U16_BE ) { | |
372 format = AFMT_U16_BE; | |
373 } | |
374 break; | |
375 default: | |
354
30935e76acb5
Updated ALSA audio support for ALSA 0.9
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
376 format = 0; |
0 | 377 break; |
378 } | |
379 if ( ! format ) { | |
380 test_format = SDL_NextAudioFormat(); | |
381 } | |
382 } | |
383 if ( format == 0 ) { | |
384 SDL_SetError("Couldn't find any hardware audio formats"); | |
385 return(-1); | |
386 } | |
387 spec->format = test_format; | |
388 | |
389 /* Set the audio format */ | |
390 value = format; | |
391 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || | |
392 (value != format) ) { | |
393 SDL_SetError("Couldn't set audio format"); | |
394 return(-1); | |
395 } | |
396 | |
397 /* Set mono or stereo audio (currently only two channels supported) */ | |
398 stereo = (spec->channels > 1); | |
399 ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo); | |
400 if ( stereo ) { | |
401 spec->channels = 2; | |
402 } else { | |
403 spec->channels = 1; | |
404 } | |
405 | |
406 /* Because some drivers don't allow setting the buffer size | |
407 after setting the format, we must re-open the audio device | |
408 once we know what format and channels are supported | |
409 */ | |
410 if ( DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0 ) { | |
411 /* Error is set by DMA_ReopenAudio() */ | |
412 return(-1); | |
413 } | |
414 | |
415 /* Memory map the audio buffer */ | |
416 if ( ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0 ) { | |
417 SDL_SetError("Couldn't get OSPACE parameters"); | |
418 return(-1); | |
419 } | |
420 spec->size = info.fragsize; | |
421 spec->samples = spec->size / ((spec->format & 0xFF) / 8); | |
422 spec->samples /= spec->channels; | |
423 num_buffers = info.fragstotal; | |
424 dma_len = num_buffers*spec->size; | |
425 dma_buf = (Uint8 *)mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED, | |
426 audio_fd, 0); | |
427 if ( dma_buf == MAP_FAILED ) { | |
428 SDL_SetError("DMA memory map failed"); | |
429 dma_buf = NULL; | |
430 return(-1); | |
431 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
432 SDL_memset(dma_buf, spec->silence, dma_len); |
0 | 433 |
434 /* Check to see if we need to use select() workaround */ | |
435 { char *workaround; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
436 workaround = SDL_getenv("SDL_DSP_NOSELECT"); |
0 | 437 if ( workaround ) { |
438 frame_ticks = (float)(spec->samples*1000)/spec->freq; | |
439 next_frame = SDL_GetTicks()+frame_ticks; | |
440 } | |
441 } | |
442 | |
443 /* Trigger audio playback */ | |
444 value = 0; | |
445 ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value); | |
446 value = PCM_ENABLE_OUTPUT; | |
447 if ( ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0 ) { | |
448 SDL_SetError("Couldn't trigger audio output"); | |
449 return(-1); | |
450 } | |
451 | |
452 /* Get the parent process id (we're the parent of the audio thread) */ | |
453 parent = getpid(); | |
454 | |
455 /* We're ready to rock and roll. :-) */ | |
456 return(0); | |
457 } |