static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{ { ALCdevice *Device = pdata; pulse_data *data = Device->ExtraData; SuspendContext(NULL); data->attr = *(ppa_stream_get_buffer_attr(stream)); Device->UpdateSize = 20 * Device->Frequency / 1000; Device->NumUpdates = data->attr.tlength/data->frame_size / Device->UpdateSize; if(Device->NumUpdates == 0) Device->NumUpdates = 1; ProcessContext(NULL); }//}}}
static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{ { ALCdevice *Device = pdata; pulse_data *data = Device->ExtraData; SuspendContext(NULL); data->attr = *(ppa_stream_get_buffer_attr(stream)); if((data->attr.tlength%data->attr.minreq) != 0) AL_PRINT("new tlength (%d) is not a multiple of minreq (%d)!\n", data->attr.tlength, data->attr.minreq); Device->UpdateSize = data->attr.minreq; Device->NumUpdates = data->attr.tlength/data->attr.minreq; ProcessContext(NULL); }//}}}
static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{ { pulse_data *data = device->ExtraData; pa_stream_state_t state; ppa_threaded_mainloop_lock(data->loop); data->frame_size = aluBytesFromFormat(device->Format) * aluChannelsFromFormat(device->Format); data->attr.minreq = data->frame_size * device->UpdateSize; data->attr.prebuf = -1; data->attr.maxlength = -1; data->attr.fragsize = -1; data->attr.tlength = data->attr.minreq * device->NumUpdates; data->stream_name = "Playback Stream"; switch(aluBytesFromFormat(device->Format)) { case 1: data->spec.format = PA_SAMPLE_U8; break; case 2: data->spec.format = PA_SAMPLE_S16NE; break; case 4: data->spec.format = PA_SAMPLE_FLOAT32NE; break; default: AL_PRINT("Unknown format: 0x%x\n", device->Format); ppa_threaded_mainloop_unlock(data->loop); return ALC_FALSE; } data->spec.rate = device->Frequency; data->spec.channels = aluChannelsFromFormat(device->Format); if(ppa_sample_spec_valid(&data->spec) == 0) { AL_PRINT("Invalid sample format\n"); ppa_threaded_mainloop_unlock(data->loop); return ALC_FALSE; } data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, NULL); if(!data->stream) { AL_PRINT("pa_stream_new() failed: %s\n", ppa_strerror(ppa_context_errno(data->context))); ppa_threaded_mainloop_unlock(data->loop); return ALC_FALSE; } if(ppa_stream_connect_playback(data->stream, NULL, &data->attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0) { AL_PRINT("Stream did not connect: %s\n", ppa_strerror(ppa_context_errno(data->context))); ppa_stream_unref(data->stream); data->stream = NULL; ppa_threaded_mainloop_unlock(data->loop); return ALC_FALSE; } while((state=ppa_stream_get_state(data->stream)) != PA_STREAM_READY) { if(!PA_STREAM_IS_GOOD(state)) { AL_PRINT("Stream did not get ready: %s\n", ppa_strerror(ppa_context_errno(data->context))); ppa_stream_unref(data->stream); data->stream = NULL; ppa_threaded_mainloop_unlock(data->loop); return ALC_FALSE; } ppa_threaded_mainloop_unlock(data->loop); Sleep(1); ppa_threaded_mainloop_lock(data->loop); } data->attr = *(ppa_stream_get_buffer_attr(data->stream)); if((data->attr.tlength%data->attr.minreq) != 0) AL_PRINT("tlength (%d) is not a multiple of minreq (%d)!\n", data->attr.tlength, data->attr.minreq); device->UpdateSize = data->attr.minreq; device->NumUpdates = data->attr.tlength/data->attr.minreq; ppa_stream_set_write_callback(data->stream, stream_write_callback, device); ppa_threaded_mainloop_unlock(data->loop); return ALC_TRUE; } //}}}