workaround for atexit - buffer size API change

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1635 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2005-11-20 16:24:09 +00:00
parent 509035303d
commit 5e941d4b51
1 changed files with 94 additions and 44 deletions

View File

@ -33,17 +33,19 @@
struct { struct {
int buffer_frames; int buffer_frames;
int isAtexit;
} conf = { } conf = {
.buffer_frames = 512 .buffer_frames = 512,
.isAtexit = 0
}; };
typedef struct coreaudioVoiceOut { typedef struct coreaudioVoiceOut {
HWVoiceOut hw; HWVoiceOut hw;
pthread_mutex_t mutex; pthread_mutex_t mutex;
int isAtexit;
AudioDeviceID outputDeviceID; AudioDeviceID outputDeviceID;
UInt32 audioDevicePropertyBufferSize; UInt32 audioDevicePropertyBufferFrameSize;
AudioStreamBasicDescription outputStreamBasicDescription; AudioStreamBasicDescription outputStreamBasicDescription;
int isPlaying;
int live; int live;
int decr; int decr;
int rpos; int rpos;
@ -139,6 +141,26 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
coreaudio_logstatus (status); coreaudio_logstatus (status);
} }
static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
{
OSStatus status;
UInt32 result = 0;
UInt32 propertySize = sizeof(outputDeviceID);
status = AudioDeviceGetProperty(
outputDeviceID, 0, 0,
kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
if (status != kAudioHardwareNoError) {
coreaudio_logerr(status,
"Could not determine whether Device is playing\n");
}
return result;
}
static void coreaudio_atexit (void)
{
conf.isAtexit = 1;
}
static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
{ {
int err; int err;
@ -203,7 +225,7 @@ static OSStatus audioDeviceIOProc(
const AudioTimeStamp* inOutputTime, const AudioTimeStamp* inOutputTime,
void* hwptr) void* hwptr)
{ {
unsigned int frame, frameCount; UInt32 frame, frameCount;
float *out = outOutputData->mBuffers[0].mData; float *out = outOutputData->mBuffers[0].mData;
HWVoiceOut *hw = hwptr; HWVoiceOut *hw = hwptr;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
@ -222,7 +244,7 @@ static OSStatus audioDeviceIOProc(
return 0; return 0;
} }
frameCount = conf.buffer_frames; frameCount = core->audioDevicePropertyBufferFrameSize;
live = core->live; live = core->live;
/* if there are not enough samples, set signal and return */ /* if there are not enough samples, set signal and return */
@ -254,7 +276,7 @@ static OSStatus audioDeviceIOProc(
/* cleanup */ /* cleanup */
mixeng_clear (src, frameCount); mixeng_clear (src, frameCount);
rpos = (rpos + frameCount) % hw->samples; rpos = (rpos + frameCount) % hw->samples;
core->decr = frameCount; core->decr += frameCount;
core->rpos = rpos; core->rpos = rpos;
coreaudio_unlock (core, "audioDeviceIOProc"); coreaudio_unlock (core, "audioDeviceIOProc");
@ -274,7 +296,8 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
int err; int err;
int bits = 8; int bits = 8;
int endianess = 0; int endianess = 0;
const char *typ = "DAC"; const char *typ = "playback";
AudioValueRange frameRange;
/* create mutex */ /* create mutex */
err = pthread_mutex_init(&core->mutex, NULL); err = pthread_mutex_init(&core->mutex, NULL);
@ -312,40 +335,65 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
return -1; return -1;
} }
/* set Buffersize to conf.buffer_frames frames */ /* get minimum and maximum buffer frame sizes */
propertySize = sizeof(core->audioDevicePropertyBufferSize); propertySize = sizeof(frameRange);
core->audioDevicePropertyBufferSize = status = AudioDeviceGetProperty(
conf.buffer_frames * sizeof(float) << (as->nchannels == 2); core->outputDeviceID,
0,
0,
kAudioDevicePropertyBufferFrameSizeRange,
&propertySize,
&frameRange);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get device buffer frame range\n");
return -1;
}
if (frameRange.mMinimum > conf.buffer_frames) {
core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
}
else if (frameRange.mMaximum < conf.buffer_frames) {
core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
}
else {
core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
}
/* set Buffer Frame Size */
propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
status = AudioDeviceSetProperty( status = AudioDeviceSetProperty(
core->outputDeviceID, core->outputDeviceID,
NULL, NULL,
0, 0,
false, false,
kAudioDevicePropertyBufferSize, kAudioDevicePropertyBufferFrameSize,
propertySize, propertySize,
&core->audioDevicePropertyBufferSize); &core->audioDevicePropertyBufferFrameSize);
if (status != kAudioHardwareNoError) { if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, coreaudio_logerr2 (status, typ,
"Could not set device buffer size %d\n", "Could not set device buffer frame size %ld\n",
kAudioDevicePropertyBufferSize); core->audioDevicePropertyBufferFrameSize);
return -1; return -1;
} }
/* get Buffersize */ /* get Buffer Frame Size */
propertySize = sizeof(core->audioDevicePropertyBufferSize); propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
status = AudioDeviceGetProperty( status = AudioDeviceGetProperty(
core->outputDeviceID, core->outputDeviceID,
0, 0,
false, false,
kAudioDevicePropertyBufferSize, kAudioDevicePropertyBufferFrameSize,
&propertySize, &propertySize,
&core->audioDevicePropertyBufferSize); &core->audioDevicePropertyBufferFrameSize);
if (status != kAudioHardwareNoError) { if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not get device buffer size\n"); coreaudio_logerr2 (status, typ,
"Could not get device buffer frame size\n");
return -1; return -1;
} }
hw->samples = (core->audioDevicePropertyBufferSize / sizeof (float)) hw->samples = 4 * core->audioDevicePropertyBufferFrameSize;
>> (as->nchannels == 2);
/* get StreamFormat */ /* get StreamFormat */
propertySize = sizeof(core->outputStreamBasicDescription); propertySize = sizeof(core->outputStreamBasicDescription);
@ -364,7 +412,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
} }
/* set Samplerate */ /* set Samplerate */
core->outputStreamBasicDescription.mSampleRate = (Float64)as->freq; core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
propertySize = sizeof(core->outputStreamBasicDescription); propertySize = sizeof(core->outputStreamBasicDescription);
status = AudioDeviceSetProperty( status = AudioDeviceSetProperty(
core->outputDeviceID, core->outputDeviceID,
@ -390,7 +438,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
} }
/* start Playback */ /* start Playback */
if (!core->isPlaying) { if (!isPlaying(core->outputDeviceID)) {
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) { if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not start playback\n"); coreaudio_logerr2 (status, typ, "Could not start playback\n");
@ -398,7 +446,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
core->outputDeviceID = kAudioDeviceUnknown; core->outputDeviceID = kAudioDeviceUnknown;
return -1; return -1;
} }
core->isPlaying = 1;
} }
return 0; return 0;
@ -410,19 +457,21 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
int err; int err;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
/* stop playback */ if (!conf.isAtexit) {
if (core->isPlaying) { /* stop playback */
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); if (isPlaying(core->outputDeviceID)) {
if (status != kAudioHardwareNoError) { status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
coreaudio_logerr (status, "Could not stop playback\n"); if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not stop playback\n");
}
} }
core->isPlaying = 0;
}
/* remove callback */ /* remove callback */
status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); status = AudioDeviceRemoveIOProc(core->outputDeviceID,
if (status != kAudioHardwareNoError) { audioDeviceIOProc);
coreaudio_logerr (status, "Could not remove IOProc\n"); if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not remove IOProc\n");
}
} }
core->outputDeviceID = kAudioDeviceUnknown; core->outputDeviceID = kAudioDeviceUnknown;
@ -441,23 +490,23 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
switch (cmd) { switch (cmd) {
case VOICE_ENABLE: case VOICE_ENABLE:
/* start playback */ /* start playback */
if (!core->isPlaying) { if (!isPlaying(core->outputDeviceID)) {
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) { if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not unpause playback\n"); coreaudio_logerr (status, "Could not resume playback\n");
} }
core->isPlaying = 1;
} }
break; break;
case VOICE_DISABLE: case VOICE_DISABLE:
/* stop playback */ /* stop playback */
if (core->isPlaying) { if (!conf.isAtexit) {
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); if (isPlaying(core->outputDeviceID)) {
if (status != kAudioHardwareNoError) { status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
coreaudio_logerr (status, "Could not pause playback\n"); if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not pause playback\n");
}
} }
core->isPlaying = 0;
} }
break; break;
} }
@ -466,6 +515,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
static void *coreaudio_audio_init (void) static void *coreaudio_audio_init (void)
{ {
atexit(coreaudio_atexit);
return &coreaudio_audio_init; return &coreaudio_audio_init;
} }