Commit 5e941d4b51dd0888f4003e838c7e7499aa9e8a62

Authored by bellard
1 parent 50903530

workaround for atexit - buffer size API change


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1635 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 94 additions and 44 deletions
audio/coreaudio.c
@@ -33,17 +33,19 @@ @@ -33,17 +33,19 @@
33 33
34 struct { 34 struct {
35 int buffer_frames; 35 int buffer_frames;
  36 + int isAtexit;
36 } conf = { 37 } conf = {
37 - .buffer_frames = 512 38 + .buffer_frames = 512,
  39 + .isAtexit = 0
38 }; 40 };
39 41
40 typedef struct coreaudioVoiceOut { 42 typedef struct coreaudioVoiceOut {
41 HWVoiceOut hw; 43 HWVoiceOut hw;
42 pthread_mutex_t mutex; 44 pthread_mutex_t mutex;
  45 + int isAtexit;
43 AudioDeviceID outputDeviceID; 46 AudioDeviceID outputDeviceID;
44 - UInt32 audioDevicePropertyBufferSize; 47 + UInt32 audioDevicePropertyBufferFrameSize;
45 AudioStreamBasicDescription outputStreamBasicDescription; 48 AudioStreamBasicDescription outputStreamBasicDescription;
46 - int isPlaying;  
47 int live; 49 int live;
48 int decr; 50 int decr;
49 int rpos; 51 int rpos;
@@ -139,6 +141,26 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 ( @@ -139,6 +141,26 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
139 coreaudio_logstatus (status); 141 coreaudio_logstatus (status);
140 } 142 }
141 143
  144 +static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
  145 +{
  146 + OSStatus status;
  147 + UInt32 result = 0;
  148 + UInt32 propertySize = sizeof(outputDeviceID);
  149 + status = AudioDeviceGetProperty(
  150 + outputDeviceID, 0, 0,
  151 + kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
  152 + if (status != kAudioHardwareNoError) {
  153 + coreaudio_logerr(status,
  154 + "Could not determine whether Device is playing\n");
  155 + }
  156 + return result;
  157 +}
  158 +
  159 +static void coreaudio_atexit (void)
  160 +{
  161 + conf.isAtexit = 1;
  162 +}
  163 +
142 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) 164 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
143 { 165 {
144 int err; 166 int err;
@@ -203,7 +225,7 @@ static OSStatus audioDeviceIOProc( @@ -203,7 +225,7 @@ static OSStatus audioDeviceIOProc(
203 const AudioTimeStamp* inOutputTime, 225 const AudioTimeStamp* inOutputTime,
204 void* hwptr) 226 void* hwptr)
205 { 227 {
206 - unsigned int frame, frameCount; 228 + UInt32 frame, frameCount;
207 float *out = outOutputData->mBuffers[0].mData; 229 float *out = outOutputData->mBuffers[0].mData;
208 HWVoiceOut *hw = hwptr; 230 HWVoiceOut *hw = hwptr;
209 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; 231 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
@@ -222,7 +244,7 @@ static OSStatus audioDeviceIOProc( @@ -222,7 +244,7 @@ static OSStatus audioDeviceIOProc(
222 return 0; 244 return 0;
223 } 245 }
224 246
225 - frameCount = conf.buffer_frames; 247 + frameCount = core->audioDevicePropertyBufferFrameSize;
226 live = core->live; 248 live = core->live;
227 249
228 /* if there are not enough samples, set signal and return */ 250 /* if there are not enough samples, set signal and return */
@@ -254,7 +276,7 @@ static OSStatus audioDeviceIOProc( @@ -254,7 +276,7 @@ static OSStatus audioDeviceIOProc(
254 /* cleanup */ 276 /* cleanup */
255 mixeng_clear (src, frameCount); 277 mixeng_clear (src, frameCount);
256 rpos = (rpos + frameCount) % hw->samples; 278 rpos = (rpos + frameCount) % hw->samples;
257 - core->decr = frameCount; 279 + core->decr += frameCount;
258 core->rpos = rpos; 280 core->rpos = rpos;
259 281
260 coreaudio_unlock (core, "audioDeviceIOProc"); 282 coreaudio_unlock (core, "audioDeviceIOProc");
@@ -274,7 +296,8 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) @@ -274,7 +296,8 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
274 int err; 296 int err;
275 int bits = 8; 297 int bits = 8;
276 int endianess = 0; 298 int endianess = 0;
277 - const char *typ = "DAC"; 299 + const char *typ = "playback";
  300 + AudioValueRange frameRange;
278 301
279 /* create mutex */ 302 /* create mutex */
280 err = pthread_mutex_init(&core->mutex, NULL); 303 err = pthread_mutex_init(&core->mutex, NULL);
@@ -312,40 +335,65 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) @@ -312,40 +335,65 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
312 return -1; 335 return -1;
313 } 336 }
314 337
315 - /* set Buffersize to conf.buffer_frames frames */  
316 - propertySize = sizeof(core->audioDevicePropertyBufferSize);  
317 - core->audioDevicePropertyBufferSize =  
318 - conf.buffer_frames * sizeof(float) << (as->nchannels == 2); 338 + /* get minimum and maximum buffer frame sizes */
  339 + propertySize = sizeof(frameRange);
  340 + status = AudioDeviceGetProperty(
  341 + core->outputDeviceID,
  342 + 0,
  343 + 0,
  344 + kAudioDevicePropertyBufferFrameSizeRange,
  345 + &propertySize,
  346 + &frameRange);
  347 + if (status != kAudioHardwareNoError) {
  348 + coreaudio_logerr2 (status, typ,
  349 + "Could not get device buffer frame range\n");
  350 + return -1;
  351 + }
  352 +
  353 + if (frameRange.mMinimum > conf.buffer_frames) {
  354 + core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
  355 + dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
  356 + }
  357 + else if (frameRange.mMaximum < conf.buffer_frames) {
  358 + core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
  359 + dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
  360 + }
  361 + else {
  362 + core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
  363 + }
  364 +
  365 + /* set Buffer Frame Size */
  366 + propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
319 status = AudioDeviceSetProperty( 367 status = AudioDeviceSetProperty(
320 core->outputDeviceID, 368 core->outputDeviceID,
321 NULL, 369 NULL,
322 0, 370 0,
323 false, 371 false,
324 - kAudioDevicePropertyBufferSize, 372 + kAudioDevicePropertyBufferFrameSize,
325 propertySize, 373 propertySize,
326 - &core->audioDevicePropertyBufferSize); 374 + &core->audioDevicePropertyBufferFrameSize);
327 if (status != kAudioHardwareNoError) { 375 if (status != kAudioHardwareNoError) {
328 coreaudio_logerr2 (status, typ, 376 coreaudio_logerr2 (status, typ,
329 - "Could not set device buffer size %d\n",  
330 - kAudioDevicePropertyBufferSize); 377 + "Could not set device buffer frame size %ld\n",
  378 + core->audioDevicePropertyBufferFrameSize);
331 return -1; 379 return -1;
332 } 380 }
333 381
334 - /* get Buffersize */  
335 - propertySize = sizeof(core->audioDevicePropertyBufferSize); 382 + /* get Buffer Frame Size */
  383 + propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
336 status = AudioDeviceGetProperty( 384 status = AudioDeviceGetProperty(
337 core->outputDeviceID, 385 core->outputDeviceID,
338 0, 386 0,
339 false, 387 false,
340 - kAudioDevicePropertyBufferSize, 388 + kAudioDevicePropertyBufferFrameSize,
341 &propertySize, 389 &propertySize,
342 - &core->audioDevicePropertyBufferSize); 390 + &core->audioDevicePropertyBufferFrameSize);
343 if (status != kAudioHardwareNoError) { 391 if (status != kAudioHardwareNoError) {
344 - coreaudio_logerr2 (status, typ, "Could not get device buffer size\n"); 392 + coreaudio_logerr2 (status, typ,
  393 + "Could not get device buffer frame size\n");
345 return -1; 394 return -1;
346 } 395 }
347 - hw->samples = (core->audioDevicePropertyBufferSize / sizeof (float))  
348 - >> (as->nchannels == 2); 396 + hw->samples = 4 * core->audioDevicePropertyBufferFrameSize;
349 397
350 /* get StreamFormat */ 398 /* get StreamFormat */
351 propertySize = sizeof(core->outputStreamBasicDescription); 399 propertySize = sizeof(core->outputStreamBasicDescription);
@@ -364,7 +412,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) @@ -364,7 +412,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
364 } 412 }
365 413
366 /* set Samplerate */ 414 /* set Samplerate */
367 - core->outputStreamBasicDescription.mSampleRate = (Float64)as->freq; 415 + core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
368 propertySize = sizeof(core->outputStreamBasicDescription); 416 propertySize = sizeof(core->outputStreamBasicDescription);
369 status = AudioDeviceSetProperty( 417 status = AudioDeviceSetProperty(
370 core->outputDeviceID, 418 core->outputDeviceID,
@@ -390,7 +438,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) @@ -390,7 +438,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
390 } 438 }
391 439
392 /* start Playback */ 440 /* start Playback */
393 - if (!core->isPlaying) { 441 + if (!isPlaying(core->outputDeviceID)) {
394 status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); 442 status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
395 if (status != kAudioHardwareNoError) { 443 if (status != kAudioHardwareNoError) {
396 coreaudio_logerr2 (status, typ, "Could not start playback\n"); 444 coreaudio_logerr2 (status, typ, "Could not start playback\n");
@@ -398,7 +446,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) @@ -398,7 +446,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
398 core->outputDeviceID = kAudioDeviceUnknown; 446 core->outputDeviceID = kAudioDeviceUnknown;
399 return -1; 447 return -1;
400 } 448 }
401 - core->isPlaying = 1;  
402 } 449 }
403 450
404 return 0; 451 return 0;
@@ -410,19 +457,21 @@ static void coreaudio_fini_out (HWVoiceOut *hw) @@ -410,19 +457,21 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
410 int err; 457 int err;
411 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; 458 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
412 459
413 - /* stop playback */  
414 - if (core->isPlaying) {  
415 - status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);  
416 - if (status != kAudioHardwareNoError) {  
417 - coreaudio_logerr (status, "Could not stop playback\n"); 460 + if (!conf.isAtexit) {
  461 + /* stop playback */
  462 + if (isPlaying(core->outputDeviceID)) {
  463 + status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
  464 + if (status != kAudioHardwareNoError) {
  465 + coreaudio_logerr (status, "Could not stop playback\n");
  466 + }
418 } 467 }
419 - core->isPlaying = 0;  
420 - }  
421 468
422 - /* remove callback */  
423 - status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);  
424 - if (status != kAudioHardwareNoError) {  
425 - coreaudio_logerr (status, "Could not remove IOProc\n"); 469 + /* remove callback */
  470 + status = AudioDeviceRemoveIOProc(core->outputDeviceID,
  471 + audioDeviceIOProc);
  472 + if (status != kAudioHardwareNoError) {
  473 + coreaudio_logerr (status, "Could not remove IOProc\n");
  474 + }
426 } 475 }
427 core->outputDeviceID = kAudioDeviceUnknown; 476 core->outputDeviceID = kAudioDeviceUnknown;
428 477
@@ -441,23 +490,23 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -441,23 +490,23 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
441 switch (cmd) { 490 switch (cmd) {
442 case VOICE_ENABLE: 491 case VOICE_ENABLE:
443 /* start playback */ 492 /* start playback */
444 - if (!core->isPlaying) { 493 + if (!isPlaying(core->outputDeviceID)) {
445 status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); 494 status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
446 if (status != kAudioHardwareNoError) { 495 if (status != kAudioHardwareNoError) {
447 - coreaudio_logerr (status, "Could not unpause playback\n"); 496 + coreaudio_logerr (status, "Could not resume playback\n");
448 } 497 }
449 - core->isPlaying = 1;  
450 } 498 }
451 break; 499 break;
452 500
453 case VOICE_DISABLE: 501 case VOICE_DISABLE:
454 /* stop playback */ 502 /* stop playback */
455 - if (core->isPlaying) {  
456 - status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);  
457 - if (status != kAudioHardwareNoError) {  
458 - coreaudio_logerr (status, "Could not pause playback\n"); 503 + if (!conf.isAtexit) {
  504 + if (isPlaying(core->outputDeviceID)) {
  505 + status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
  506 + if (status != kAudioHardwareNoError) {
  507 + coreaudio_logerr (status, "Could not pause playback\n");
  508 + }
459 } 509 }
460 - core->isPlaying = 0;  
461 } 510 }
462 break; 511 break;
463 } 512 }
@@ -466,6 +515,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -466,6 +515,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
466 515
467 static void *coreaudio_audio_init (void) 516 static void *coreaudio_audio_init (void)
468 { 517 {
  518 + atexit(coreaudio_atexit);
469 return &coreaudio_audio_init; 519 return &coreaudio_audio_init;
470 } 520 }
471 521