Changeset 27105 in vbox
- Timestamp:
- Mar 5, 2010 3:36:32 PM (15 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/pulse_stubs.c
r26783 r27105 181 181 (o)) 182 182 PROXY_STUB (pa_operation_get_state, pa_operation_state_t, 183 (pa_operation *o), 184 (o)) 185 PROXY_STUB_VOID(pa_operation_cancel, 183 186 (pa_operation *o), 184 187 (o)) … … 241 244 ELEMENT(pa_operation_unref), 242 245 ELEMENT(pa_operation_get_state), 246 ELEMENT(pa_operation_cancel), 243 247 ELEMENT(pa_strerror), 244 248 ELEMENT(pa_stream_readable_size) -
trunk/src/VBox/Devices/Audio/pulseaudio.c
r26783 r27105 70 70 size_t cbPeekBuf; 71 71 size_t offPeekBuf; 72 pa_operation *pDrainOp; 72 73 } PulseVoice; 73 74 … … 147 148 } 148 149 149 static void context_state_callback(pa_context *c, void *userdata)150 static void stream_success_callback(pa_stream *pStream, int fSuccess, void *userdata) 150 151 { 151 152 PulseVoice *pPulse = (PulseVoice *)userdata; 152 switch (pa_context_get_state(c)) 153 pPulse->fOpSuccess = fSuccess; 154 if (!fSuccess) 155 { 156 if (pPulse->cErrors < MAX_LOG_REL_ERRORS) 157 { 158 int rc = pa_context_errno(g_pContext); 159 pPulse->cErrors++; 160 LogRel(("Pulse: Failed stream operation: %s\n", pa_strerror(rc))); 161 } 162 } 163 pa_threaded_mainloop_signal(g_pMainLoop, 0); 164 } 165 166 /** 167 * Synchronously wait until an operation completed. 168 */ 169 static int pulse_wait_for_operation (pa_operation *op) 170 { 171 if (op) 172 { 173 while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) 174 pa_threaded_mainloop_wait(g_pMainLoop); 175 pa_operation_unref(op); 176 } 177 178 return 1; 179 } 180 181 /** 182 * Context status changed. 183 */ 184 static void context_state_callback(pa_context *pContext, void *userdata) 185 { 186 PulseVoice *pPulse = (PulseVoice *)userdata; 187 switch (pa_context_get_state(pContext)) 153 188 { 154 189 case PA_CONTEXT_READY: … … 169 204 } 170 205 171 static void stream_state_callback(pa_stream *s, void *userdata) 172 { 173 switch (pa_stream_get_state(s)) 206 /** 207 * Stream status changed. 208 */ 209 static void stream_state_callback(pa_stream *pStream, void *userdata) 210 { 211 switch (pa_stream_get_state(pStream)) 174 212 { 175 213 case PA_STREAM_READY: … … 182 220 break; 183 221 } 222 } 223 224 /** 225 * Callback called when our pa_stream_drain operation was completed. 226 */ 227 static void stream_drain_callback(pa_stream *pStream, int fSuccess, void *userdata) 228 { 229 PulseVoice *pPulse = (PulseVoice *)userdata; 230 pPulse->fOpSuccess = fSuccess; 231 if (!fSuccess) 232 { 233 if (pPulse->cErrors < MAX_LOG_REL_ERRORS) 234 { 235 int rc = pa_context_errno(g_pContext); 236 pPulse->cErrors++; 237 LogRel(("Pulse: Failed stream operation: %s\n", pa_strerror(rc))); 238 } 239 } 240 else 241 pa_operation_unref(pa_stream_cork(pStream, 1, stream_success_callback, userdata)); 242 243 pa_operation_unref(pPulse->pDrainOp); 244 pPulse->pDrainOp = NULL; 184 245 } 185 246 … … 229 290 #endif 230 291 292 /* no input/output right away after the stream was started */ 293 flags |= PA_STREAM_START_CORKED; 294 231 295 if (fIn) 232 296 { … … 246 310 pBufAttr->maxlength, pBufAttr->tlength, pBufAttr->prebuf, pBufAttr->minreq)); 247 311 248 flags |= PA_STREAM_START_CORKED;249 250 312 if (pa_stream_connect_playback(pStream, /*dev=*/NULL, pBufAttr, flags, 251 313 /*cvolume=*/NULL, /*sync_stream=*/NULL) < 0) … … 310 372 audsettings_t obt_as; 311 373 int cbBuf; 374 375 pPulse->pDrainOp = NULL; 312 376 313 377 pPulse->SampleSpec.format = aud_to_pulsefmt (as->fmt); … … 440 504 } 441 505 442 static void stream_success_callback(pa_stream *pStream, int success, void *userdata)443 {444 PulseVoice *pPulse = (PulseVoice *) userdata;445 pPulse->fOpSuccess = success;446 if (!success)447 {448 if (pPulse->cErrors < MAX_LOG_REL_ERRORS)449 {450 int rc = pa_context_errno(g_pContext);451 pPulse->cErrors++;452 LogRel(("Pulse: Failed stream operation: %s\n", pa_strerror(rc)));453 }454 }455 pa_threaded_mainloop_signal(g_pMainLoop, 0);456 }457 458 static int pulse_wait_for_operation (pa_operation *op)459 {460 if (op)461 {462 while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)463 pa_threaded_mainloop_wait(g_pMainLoop);464 pa_operation_unref(op);465 }466 467 return 1;468 }469 470 506 static int pulse_ctl_out (HWVoiceOut *hw, int cmd, ...) 471 507 { … … 477 513 /* Start audio output. */ 478 514 pa_threaded_mainloop_lock(g_pMainLoop); 479 pulse_wait_for_operation(pa_stream_cork(pPulse->pStream, 0, 480 stream_success_callback, pPulse)); 515 if ( pPulse->pDrainOp 516 && pa_operation_get_state(pPulse->pDrainOp) != PA_OPERATION_DONE) 517 { 518 pa_operation_cancel(pPulse->pDrainOp); 519 pa_operation_unref(pPulse->pDrainOp); 520 pPulse->pDrainOp = NULL; 521 } 522 else 523 { 524 /* should return immediately */ 525 pulse_wait_for_operation(pa_stream_cork(pPulse->pStream, 0, 526 stream_success_callback, pPulse)); 527 } 481 528 pa_threaded_mainloop_unlock(g_pMainLoop); 482 529 break; 483 530 484 531 case VOICE_DISABLE: 485 /* Pause audio output. Note that we must return immediately from here 486 * so waiting until the buffers are flushed (trigger+drain) is not an 487 * option! It could be sufficient to cork the audio stream (we are 488 * called if the Pause bit of the AC97 x_CR register is set) but ALSA 489 * uses snd_pcm_drop() dropping all pending frames so we do the same 490 * here. */ 532 /* Pause audio output (the Pause bit of the AC97 x_CR register is set). 533 * Note that we must return immediately from here! */ 491 534 pa_threaded_mainloop_lock(g_pMainLoop); 492 pulse_wait_for_operation(pa_stream_flush(pPulse->pStream, 493 stream_success_callback, pPulse)); 494 pulse_wait_for_operation(pa_stream_cork(pPulse->pStream, 1, 495 stream_success_callback, pPulse)); 535 if (!pPulse->pDrainOp) 536 { 537 /* should return immediately */ 538 pulse_wait_for_operation(pa_stream_trigger(pPulse->pStream, 539 stream_success_callback, pPulse)); 540 pPulse->pDrainOp = pa_stream_drain(pPulse->pStream, 541 stream_drain_callback, pPulse); 542 } 496 543 pa_threaded_mainloop_unlock(g_pMainLoop); 497 544 break; … … 653 700 case VOICE_ENABLE: 654 701 pa_threaded_mainloop_lock(g_pMainLoop); 702 /* should return immediately */ 655 703 pulse_wait_for_operation(pa_stream_cork(pPulse->pStream, 0, 656 704 stream_success_callback, pPulse)); … … 665 713 pPulse->pu8PeekBuf = NULL; 666 714 } 715 /* should return immediately */ 667 716 pulse_wait_for_operation(pa_stream_cork(pPulse->pStream, 1, 668 717 stream_success_callback, pPulse));
Note:
See TracChangeset
for help on using the changeset viewer.