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:
parent
509035303d
commit
5e941d4b51
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue