static void streamRequestCallback(pa_stream *p, size_t nbytes, FileReader *h) { switch (h->writeToStream(p, nbytes)) { case FileReader::StatusOk: break; case FileReader::StatusEof: pa_stream_set_write_callback(p, NULL, NULL); pa_stream_finish_upload(p); break; case FileReader::StatusError: pa_stream_set_write_callback(p, NULL, NULL); pa_stream_disconnect(p); break; } }
/***************************************************************************** * Close: close the audio device *****************************************************************************/ static void Close ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; msg_Dbg(p_aout, "Pulse Close"); if(p_sys->stream) { pa_threaded_mainloop_lock(p_sys->mainloop); pa_stream_set_write_callback(p_sys->stream, NULL, NULL); pa_operation *o; o = pa_stream_flush(p_sys->stream, success_cb, p_aout); while( pa_operation_get_state(o) == PA_OPERATION_RUNNING ) pa_threaded_mainloop_wait(p_sys->mainloop); pa_operation_unref(o); o = pa_stream_drain(p_sys->stream, success_cb, p_aout); while( pa_operation_get_state(o) == PA_OPERATION_RUNNING ) pa_threaded_mainloop_wait(p_sys->mainloop); pa_operation_unref(o); pa_threaded_mainloop_unlock(p_sys->mainloop); } uninit(p_aout); }
static void __pulseaudio_stream_write_cb(pa_stream *stream, size_t length, void *user_data) { sf_count_t read_length; short *data; SOUND_INFO *info = NULL; mmf_return_if_fail(user_data); info = (SOUND_INFO *)user_data; _mmcam_dbg_log("START"); data = pa_xmalloc(length); read_length = (sf_count_t)(length/pa_frame_size(&(info->sample_spec))); if ((sf_readf_short(info->infile, data, read_length)) != read_length) { pa_xfree(data); return; } pa_stream_write(stream, data, length, pa_xfree, 0, PA_SEEK_RELATIVE); info->sample_length -= length; if (info->sample_length <= 0) { pa_stream_set_write_callback(info->sample_stream, NULL, NULL); pa_stream_finish_upload(info->sample_stream); pa_threaded_mainloop_signal(info->pulse_mainloop, 0); _mmcam_dbg_log("send signal DONE"); } _mmcam_dbg_log("DONE read_length %d", read_length); }
int PulseAudioDriver::thread_body() { m_main_loop = pa_mainloop_new(); pa_mainloop_api* api = pa_mainloop_get_api(m_main_loop); pa_io_event* ioev = api->io_new(api, m_pipe[0], PA_IO_EVENT_INPUT, pipe_callback, this); m_ctx = pa_context_new(api, "Hydrogen"); pa_context_set_state_callback(m_ctx, ctx_state_callback, this); pa_context_connect(m_ctx, 0, pa_context_flags_t(0), 0); int retval; pa_mainloop_run(m_main_loop, &retval); if (m_stream) { pa_stream_set_state_callback(m_stream, 0, 0); pa_stream_set_write_callback(m_stream, 0, 0); pa_stream_unref(m_stream); m_stream = 0; } api->io_free(ioev); pa_context_unref(m_ctx); pa_mainloop_free(m_main_loop); return retval; }
void PulseAudioDriver::ctx_state_callback(pa_context* ctx, void* udata) { PulseAudioDriver* self = (PulseAudioDriver*)udata; pa_context_state s = pa_context_get_state(ctx); if (s == PA_CONTEXT_READY) { pa_sample_spec spec; spec.format = PA_SAMPLE_S16LE; spec.rate = self->m_sample_rate; spec.channels = 2; self->m_stream = pa_stream_new(ctx, "Hydrogen", &spec, 0); pa_stream_set_state_callback(self->m_stream, stream_state_callback, self); pa_stream_set_write_callback(self->m_stream, stream_write_callback, self); pa_buffer_attr bufattr; bufattr.fragsize = (uint32_t)-1; bufattr.maxlength = self->m_buffer_size * 4; bufattr.minreq = 0; bufattr.prebuf = (uint32_t)-1; bufattr.tlength = self->m_buffer_size * 4; pa_stream_connect_playback(self->m_stream, 0, &bufattr, pa_stream_flags_t(0), 0, 0); } else if (s == PA_CONTEXT_FAILED) pa_mainloop_quit(self->m_main_loop, 1); }
/***************************************************************************** * Close: close the audio device *****************************************************************************/ static void Close ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; msg_Dbg(p_aout, "Pulse Close"); if(p_sys->stream){ pa_operation *o; pa_threaded_mainloop_lock(p_sys->mainloop); pa_stream_set_write_callback(p_sys->stream, NULL, NULL); if((o = pa_stream_drain(p_sys->stream, success_cb, p_aout))){ while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail); pa_threaded_mainloop_wait(p_sys->mainloop); } fail: pa_operation_unref(o); } pa_threaded_mainloop_unlock(p_sys->mainloop); } uninit(p_aout); }
static void pulse_stop_playback(ALCdevice *device) //{{{ { pulse_data *data = device->ExtraData; if(!data->stream) return; data->killNow = AL_TRUE; if(data->thread) { pa_threaded_mainloop_signal(data->loop, 0); StopThread(data->thread); data->thread = NULL; } data->killNow = AL_FALSE; pa_threaded_mainloop_lock(data->loop); #if PA_CHECK_VERSION(0,9,15) if(pa_stream_set_buffer_attr_callback) pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL); #endif pa_stream_set_moved_callback(data->stream, NULL, NULL); pa_stream_set_write_callback(data->stream, NULL, NULL); pa_stream_set_underflow_callback(data->stream, NULL, NULL); pa_stream_disconnect(data->stream); pa_stream_unref(data->stream); data->stream = NULL; pa_threaded_mainloop_unlock(data->loop); } //}}}
/** * Create, set up and connect a context. * * Caller must lock the main loop. * * @return true on success, false on error */ static bool pulse_output_setup_stream(struct pulse_output *po, const pa_sample_spec *ss, GError **error_r) { assert(po != NULL); assert(po->context != NULL); po->stream = pa_stream_new(po->context, po->name, ss, NULL); if (po->stream == NULL) { g_set_error(error_r, pulse_output_quark(), 0, "pa_stream_new() has failed: %s", pa_strerror(pa_context_errno(po->context))); return false; } #if PA_CHECK_VERSION(0,9,8) pa_stream_set_suspended_callback(po->stream, pulse_output_stream_suspended_cb, po); #endif pa_stream_set_state_callback(po->stream, pulse_output_stream_state_cb, po); pa_stream_set_write_callback(po->stream, pulse_output_stream_write_cb, po); return true; }
static int outstream_start_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) { struct SoundIoOutStream *outstream = &os->pub; struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; pa_threaded_mainloop_lock(sipa->main_loop); ospa->write_byte_count = pa_stream_writable_size(ospa->stream); int frame_count = ospa->write_byte_count / outstream->bytes_per_frame; outstream->write_callback(outstream, 0, frame_count); pa_operation *op = pa_stream_cork(ospa->stream, false, NULL, NULL); if (!op) { pa_threaded_mainloop_unlock(sipa->main_loop); return SoundIoErrorStreaming; } pa_operation_unref(op); pa_stream_set_write_callback(ospa->stream, playback_stream_write_callback, os); pa_stream_set_underflow_callback(ospa->stream, playback_stream_underflow_callback, outstream); pa_stream_set_overflow_callback(ospa->stream, playback_stream_underflow_callback, outstream); pa_threaded_mainloop_unlock(sipa->main_loop); return 0; }
static pa_stream *qpa_simple_new ( paaudio *g, const char *name, pa_stream_direction_t dir, const char *dev, const pa_sample_spec *ss, const pa_channel_map *map, const pa_buffer_attr *attr, int *rerror) { int r; pa_stream *stream; pa_threaded_mainloop_lock (g->mainloop); stream = pa_stream_new (g->context, name, ss, map); if (!stream) { goto fail; } pa_stream_set_state_callback (stream, stream_state_cb, g); pa_stream_set_read_callback (stream, stream_request_cb, g); pa_stream_set_write_callback (stream, stream_request_cb, g); if (dir == PA_STREAM_PLAYBACK) { r = pa_stream_connect_playback (stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING #ifdef PA_STREAM_ADJUST_LATENCY |PA_STREAM_ADJUST_LATENCY #endif |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); } else { r = pa_stream_connect_record (stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING #ifdef PA_STREAM_ADJUST_LATENCY |PA_STREAM_ADJUST_LATENCY #endif |PA_STREAM_AUTO_TIMING_UPDATE); } if (r < 0) { goto fail; } pa_threaded_mainloop_unlock (g->mainloop); return stream; fail: pa_threaded_mainloop_unlock (g->mainloop); if (stream) { pa_stream_unref (stream); } *rerror = pa_context_errno (g->context); return NULL; }
/* When we shutdown, or in case of error, we must make sure that pulseaudio * quits calling callbacks with the defunct audio_output. * This method sets all callbacks NULL. * --- * TODO: The name of this function is misleading: Actually, we just unset * the callbacks needed for playback, but we keep the callbacks needed during * shutdown */ static void unset_all_callbacks(_mbx_out out) { if ( out->pa_ctx != NULL ) { pa_context_set_state_callback(out->pa_ctx, NULL, NULL); } if ( out->stream != NULL ) { pa_stream_set_write_callback(out->stream, NULL, NULL); pa_stream_set_underflow_callback(out->stream, NULL, NULL); } }
bool PulseAudio::init(bool) { pa_ml = pa_mainloop_new(); pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml); pa_context* pa_ctx = pa_context_new(pa_mlapi, "MuseScore"); if (pa_context_connect(pa_ctx, NULL, pa_context_flags_t(0), NULL) != 0) qDebug("PulseAudio Context Connect Failed with Error: %s", pa_strerror(pa_context_errno(pa_ctx))); int pa_ready = 0; pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); while (pa_ready == 0) pa_mainloop_iterate(pa_ml, 1, NULL); if (pa_ready == 2) return false; ss.rate = _sampleRate; ss.channels = 2; ss.format = PA_SAMPLE_FLOAT32LE; pa_stream* playstream = pa_stream_new(pa_ctx, "Playback", &ss, NULL); if (!playstream) { qDebug("pa_stream_new failed"); return false; } pa_stream_set_write_callback(playstream, paCallback, this); bufattr.fragsize = (uint32_t)-1; bufattr.maxlength = FRAMES * 2 * sizeof(float); bufattr.minreq = FRAMES * 1 * sizeof(float); // pa_usec_to_bytes(0, &ss); bufattr.prebuf = (uint32_t)-1; bufattr.tlength = bufattr.maxlength; int r = pa_stream_connect_playback(playstream, NULL, &bufattr, pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); if (r < 0) { // Old pulse audio servers don't like the ADJUST_LATENCY flag, so retry without that r = pa_stream_connect_playback(playstream, NULL, &bufattr, pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); } if (r < 0) { qDebug("pa_stream_connect_playback failed"); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); pa_ml = 0; return false; } return true; }
JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_pulseaudio_PA_stream_1set_1write_1callback (JNIEnv *env, jclass clazz, jlong s, jobject cb) { jweak weakCb = cb ? (*env)->NewWeakGlobalRef(env, cb) : NULL; pa_stream_set_write_callback( (pa_stream *) (intptr_t) s, weakCb ? PulseAudio_streamRequestCallback : NULL, (void *) weakCb); }
/* * Context state callbacks * * A 'context' represents the connection handle between a PulseAudio * client and its server. It multiplexes everything in that connection * including data streams , bi-directional commands, and events. */ static void context_state_callback(pa_context *context, void *userdata) { struct context *ctx = userdata; struct audio_file *file; pa_stream *stream; int ret; assert(ctx); assert((file = ctx->file)); switch (pa_context_get_state(context)) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_CONNECTING: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: out("Connection established with PulseAudio sound server"); for (int i = 0; i < 256; i++) { stream = pa_stream_new(context, "playback stream", &file->spec, NULL); if (!stream) goto fail; pa_stream_set_state_callback(stream, stream_state_callback, userdata); pa_stream_set_write_callback(stream, stream_write_callback, userdata); /* Connect this stream with a sink chosen by PulseAudio */ ret = pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL); if (ret < 0) { error("pa_stream_connect_playback() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } } break; case PA_CONTEXT_TERMINATED: exit(EXIT_SUCCESS); break; case PA_CONTEXT_FAILED: default: error("PulseAudio context connection failure: %s", pa_strerror(pa_context_errno(context))); goto fail; } return; fail: quit(ctx, EXIT_FAILURE); }
bool PulseAudio::PulseInit() { m_pa_error = 0; m_pa_connected = 0; // create pulseaudio main loop and context // also register the async state callback which is called when the connection to the pa server has changed m_pa_ml = pa_mainloop_new(); m_pa_mlapi = pa_mainloop_get_api(m_pa_ml); m_pa_ctx = pa_context_new(m_pa_mlapi, "dolphin-emu"); m_pa_error = pa_context_connect(m_pa_ctx, nullptr, PA_CONTEXT_NOFLAGS, nullptr); pa_context_set_state_callback(m_pa_ctx, StateCallback, this); // wait until we're connected to the pulseaudio server while (m_pa_connected == 0 && m_pa_error >= 0) m_pa_error = pa_mainloop_iterate(m_pa_ml, 1, nullptr); if (m_pa_connected == 2 || m_pa_error < 0) { ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", pa_strerror(m_pa_error)); return false; } // create a new audio stream with our sample format // also connect the callbacks for this stream pa_sample_spec ss; ss.format = PA_SAMPLE_S16LE; ss.channels = 2; ss.rate = m_mixer->GetSampleRate(); m_pa_s = pa_stream_new(m_pa_ctx, "Playback", &ss, nullptr); pa_stream_set_write_callback(m_pa_s, WriteCallback, this); pa_stream_set_underflow_callback(m_pa_s, UnderflowCallback, this); // connect this audio stream to the default audio playback // limit buffersize to reduce latency m_pa_ba.fragsize = -1; m_pa_ba.maxlength = -1; // max buffer, so also max latency m_pa_ba.minreq = -1; // don't read every byte, try to group them _a bit_ m_pa_ba.prebuf = -1; // start as early as possible m_pa_ba.tlength = BUFFER_SIZE; // designed latency, only change this flag for low latency output pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); m_pa_error = pa_stream_connect_playback(m_pa_s, nullptr, &m_pa_ba, flags, nullptr, nullptr); if (m_pa_error < 0) { ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", pa_strerror(m_pa_error)); return false; } INFO_LOG(AUDIO, "Pulse successfully initialized"); return true; }
static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice *pulse) { if(!pulse->context || !pulse->stream) return FALSE; DEBUG_TSMF(""); pa_threaded_mainloop_lock(pulse->mainloop); pa_stream_set_write_callback(pulse->stream, NULL, NULL); tsmf_pulse_wait_for_operation(pulse, pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse)); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); return TRUE; }
bool PulseAudio::init(bool) { pa_ml = pa_mainloop_new(); pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml); pa_context* pa_ctx = pa_context_new(pa_mlapi, "MuseScore"); if (pa_context_connect(pa_ctx, NULL, pa_context_flags_t(0), NULL) != 0) { qDebug("PulseAudio Context Connect Failed with Error: %s", pa_strerror(pa_context_errno(pa_ctx))); return false; } int pa_ready = 0; pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); while (pa_ready == 0) pa_mainloop_iterate(pa_ml, 1, NULL); if (pa_ready == 2) return false; ss.rate = _sampleRate; ss.channels = 2; ss.format = PA_SAMPLE_FLOAT32LE; pa_stream* playstream = pa_stream_new(pa_ctx, "Playback", &ss, NULL); if (!playstream) { qDebug("pa_stream_new failed: %s", pa_strerror(pa_context_errno(pa_ctx))); return false; } pa_stream_set_write_callback(playstream, paCallback, this); bufattr.fragsize = (uint32_t)-1; bufattr.maxlength = FRAMES * 2 * sizeof(float); bufattr.minreq = FRAMES * 1 * sizeof(float); // pa_usec_to_bytes(0, &ss); bufattr.prebuf = (uint32_t)-1; bufattr.tlength = bufattr.maxlength; int r = pa_stream_connect_playback(playstream, nullptr, &bufattr, PA_STREAM_NOFLAGS, nullptr, nullptr); if (r < 0) { qDebug("pa_stream_connect_playback failed"); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); pa_ml = 0; return false; } return true; }
AudioStream::~AudioStream() { PulseMainLoopLock lock(mainloop_); pa_stream_disconnect(audiostream_); // make sure we don't get any further callback pa_stream_set_state_callback(audiostream_, NULL, NULL); pa_stream_set_write_callback(audiostream_, NULL, NULL); pa_stream_set_read_callback(audiostream_, NULL, NULL); pa_stream_set_moved_callback(audiostream_, NULL, NULL); pa_stream_set_underflow_callback(audiostream_, NULL, NULL); pa_stream_set_overflow_callback(audiostream_, NULL, NULL); pa_stream_unref(audiostream_); }
AudioStream::~AudioStream() { pa_threaded_mainloop_lock(mainloop_); pa_stream_disconnect(audiostream_); // make sure we don't get any further callback pa_stream_set_state_callback(audiostream_, NULL, NULL); pa_stream_set_write_callback(audiostream_, NULL, NULL); pa_stream_set_underflow_callback(audiostream_, NULL, NULL); pa_stream_set_overflow_callback(audiostream_, NULL, NULL); pa_stream_unref(audiostream_); pa_threaded_mainloop_unlock(mainloop_); }
static int tsmf_pulse_close_stream(TSMFPulseAudioDevice * pulse) { if (!pulse->context || !pulse->stream) return 1; LLOGLN(0, ("tsmf_pulse_close_stream:")); pa_threaded_mainloop_lock(pulse->mainloop); pa_stream_set_write_callback(pulse->stream, NULL, NULL); tsmf_pulse_wait_for_operation(pulse, pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse)); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); return 0; }
/* Start draining */ static void start_drain(void) { if (stream) { pa_operation *o; pa_stream_set_write_callback(stream, NULL, NULL); if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { pa_log(_("pa_stream_drain(): %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_operation_unref(o); } else quit(0); }
/** * Frees and clears the stream. */ static void pulse_output_delete_stream(struct pulse_output *po) { assert(po != NULL); assert(po->stream != NULL); #if PA_CHECK_VERSION(0,9,8) pa_stream_set_suspended_callback(po->stream, NULL, NULL); #endif pa_stream_set_state_callback(po->stream, NULL, NULL); pa_stream_set_write_callback(po->stream, NULL, NULL); pa_stream_disconnect(po->stream); pa_stream_unref(po->stream); po->stream = NULL; }
static bool preload_sample(struct audio_service *service, struct play_feedback_data *pfd) { bool result = false; struct stat st; pa_sample_spec spec; char *sample_path; if (!pfd || !pfd->name) return false; if (g_slist_find(sample_list, pfd->name)) { play_feedback_sample(pfd); play_feedback_data_free(pfd); return true; } sample_path = g_strdup_printf("%s/%s.pcm", SAMPLE_PATH, pfd->name); if (stat(sample_path, &st) != 0) goto cleanup; pfd->sample_length = st.st_size; spec.format = PA_SAMPLE_S16LE; spec.rate = 44100; spec.channels = 1; pfd->fd = open(sample_path, O_RDONLY); if (pfd->fd < 0) goto cleanup; pfd->sample_stream = pa_stream_new(service->context, pfd->name, &spec, NULL); if (!pfd->sample_stream) goto cleanup; pa_stream_set_state_callback(pfd->sample_stream, preload_stream_state_cb, pfd); pa_stream_set_write_callback(pfd->sample_stream, preload_stream_write_cb, pfd); pa_stream_connect_upload(pfd->sample_stream, pfd->sample_length); result = true; cleanup: g_free(sample_path); return result; }
/* Start draining */ static void start_drain(void) { printf("Draining\n"); if (stream) { pa_operation *o; pa_stream_set_write_callback(stream, NULL, NULL); if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { //printf("pa_stream_drain(): %s", pa_strerror(pa_context_errno(context))); exit(1); return; } pa_operation_unref(o); } else exit(0); }
void QSoundEffectPrivate::uploadSample() { daemon()->lock(); size_t bufferSize = qMin(pa_stream_writable_size(m_pulseStream), size_t(m_waveDecoder->bytesAvailable())); char buffer[bufferSize]; size_t len = 0; while (len < (m_waveDecoder->size())) { qint64 read = m_waveDecoder->read(buffer, qMin((int)bufferSize, (int)(m_waveDecoder->size()-len))); if (read > 0) { if (pa_stream_write(m_pulseStream, buffer, size_t(read), 0, 0, PA_SEEK_RELATIVE) == 0) len += size_t(read); else break; } } m_dataUploaded += len; pa_stream_set_write_callback(m_pulseStream, NULL, NULL); if (m_waveDecoder->size() == m_dataUploaded) { int err = pa_stream_finish_upload(m_pulseStream); if(err != 0) { qWarning("pa_stream_finish_upload() err=%d",err); pa_stream_disconnect(m_pulseStream); m_retry = true; m_playQueued = false; QMetaObject::invokeMethod(this, "play"); daemon()->unlock(); return; } m_duration = m_waveDecoder->duration(); m_waveDecoder->deleteLater(); m_stream->deleteLater(); m_sampleLoaded = true; if (m_playQueued) { m_playQueued = false; QMetaObject::invokeMethod(this, "play"); } } daemon()->unlock(); }
static void preload_stream_write_cb(pa_stream *stream, size_t length, void *user_data) { struct play_feedback_data *pfd = user_data; void *buffer; ssize_t bread; buffer = pa_xmalloc(pfd->sample_length); bread = read(pfd->fd, buffer, pfd->sample_length); pfd->stream_written += bread; pa_stream_write(stream, buffer, bread, pa_xfree, 0, PA_SEEK_RELATIVE); if (pfd->stream_written == pfd->sample_length) { pa_stream_set_write_callback(stream, NULL, NULL); pa_stream_finish_upload(stream); } }
int sa_stream_open(sa_stream_t *s) { if (s == NULL) { return SA_ERROR_NO_INIT; } if (s->stream != NULL) { return SA_ERROR_INVALID; } pa_threaded_mainloop_lock(s->m); if (!(s->stream = pa_stream_new(s->context, s->client_name, &s->sample_spec, NULL))) { fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(s->context))); goto unlock_and_fail; } pa_stream_set_state_callback(s->stream, stream_state_callback, s); pa_stream_set_write_callback(s->stream, stream_write_callback, s); pa_stream_set_latency_update_callback(s->stream, stream_latency_update_callback, s); if (pa_stream_connect_playback(s->stream, NULL, NULL, 0, NULL, NULL) < 0) { fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(s->context))); goto unlock_and_fail; } /* Wait until the stream is ready */ pa_threaded_mainloop_wait(s->m); if (pa_stream_get_state(s->stream) != PA_STREAM_READY) { fprintf(stderr, "Failed to connect stream: %s", pa_strerror(pa_context_errno(s->context))); goto unlock_and_fail; } pa_threaded_mainloop_unlock(s->m); if (!s->stream) return SA_ERROR_NO_DEVICE; return SA_SUCCESS; unlock_and_fail: pa_threaded_mainloop_unlock(s->m); return SA_ERROR_NO_DEVICE; }
void QSoundEffectPrivate::decoderReady() { if (m_waveDecoder->size() >= PA_SCACHE_ENTRY_SIZE_MAX) { m_waveDecoder->deleteLater(); qWarning("QSoundEffect(pulseaudio): Attempting to load to large a sample"); return; } if (m_name.isNull()) m_name = QString(QLatin1String("QtPulseSample-%1-%2")).arg(::getpid()).arg(quintptr(this)).toUtf8(); pa_sample_spec spec = audioFormatToSampleSpec(m_waveDecoder->audioFormat()); daemon()->lock(); pa_stream *stream = pa_stream_new(daemon()->context(), m_name.constData(), &spec, 0); pa_stream_set_state_callback(stream, stream_state_callback, this); pa_stream_set_write_callback(stream, stream_write_callback, this); pa_stream_connect_upload(stream, (size_t)m_waveDecoder->size()); m_pulseStream = stream; daemon()->unlock(); }
static void outstream_destroy_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) { struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_stream *stream = ospa->stream; if (stream) { pa_threaded_mainloop_lock(sipa->main_loop); pa_stream_set_write_callback(stream, NULL, NULL); pa_stream_set_state_callback(stream, NULL, NULL); pa_stream_set_underflow_callback(stream, NULL, NULL); pa_stream_set_overflow_callback(stream, NULL, NULL); pa_stream_disconnect(stream); pa_stream_unref(stream); pa_threaded_mainloop_unlock(sipa->main_loop); ospa->stream = NULL; } }
void audio_init() { pa_threaded_mainloop *pa_ml=pa_threaded_mainloop_new(); pa_mainloop_api *pa_mlapi=pa_threaded_mainloop_get_api(pa_ml); pa_context *pa_ctx=pa_context_new(pa_mlapi, "te"); pa_context_connect(pa_ctx, NULL, 0, NULL); int pa_ready = 0; pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); pa_threaded_mainloop_start(pa_ml); while(pa_ready==0) { ; } printf("audio ready\n"); if (pa_ready == 2) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_threaded_mainloop_free(pa_ml); } pa_sample_spec ss; ss.rate=96000; ss.channels=1; ss.format=PA_SAMPLE_S24_32LE; ps=pa_stream_new(pa_ctx,"Playback",&ss,NULL); pa_stream_set_write_callback(ps,audio_request_cb,NULL); pa_stream_set_underflow_callback(ps,audio_underflow_cb,NULL); pa_buffer_attr bufattr; bufattr.fragsize = (uint32_t)-1; bufattr.maxlength = pa_usec_to_bytes(20000,&ss); bufattr.minreq = pa_usec_to_bytes(0,&ss); bufattr.prebuf = 0; bufattr.tlength = pa_usec_to_bytes(20000,&ss); pa_stream_connect_playback(ps,NULL,&bufattr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_START_CORKED,NULL,NULL); }