/** * Pulseaudio stream state callback */ static void stream_state_callback (pa_stream * s, void *userdata) { GNUNET_assert (NULL != s); switch (pa_stream_get_state (s)) { case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX]; char sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stream successfully created.\n")); if (!(a = pa_stream_get_buffer_attr (s))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_get_buffer_attr() failed: %s\n"), pa_strerror (pa_context_errno (pa_stream_get_context (s)))); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Using sample spec '%s', channel map '%s'.\n"), pa_sample_spec_snprint (sst, sizeof (sst), pa_stream_get_sample_spec (s)), pa_channel_map_snprint (cmt, sizeof (cmt), pa_stream_get_channel_map (s))); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connected to device %s (%u, %ssuspended).\n"), pa_stream_get_device_name (s), pa_stream_get_device_index (s), pa_stream_is_suspended (s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Stream error: %s\n"), pa_strerror (pa_context_errno (pa_stream_get_context (s)))); quit (1); } }
void AudioStream::stream_state_callback(pa_stream* s, void* /*user_data*/) { char str[PA_SAMPLE_SPEC_SNPRINT_MAX]; switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: DEBUG("Stream is creating..."); break; case PA_STREAM_TERMINATED: DEBUG("Stream is terminating..."); break; case PA_STREAM_READY: DEBUG("Stream successfully created, connected to %s", pa_stream_get_device_name(s)); DEBUG("maxlength %u", pa_stream_get_buffer_attr(s)->maxlength); DEBUG("tlength %u", pa_stream_get_buffer_attr(s)->tlength); DEBUG("prebuf %u", pa_stream_get_buffer_attr(s)->prebuf); DEBUG("minreq %u", pa_stream_get_buffer_attr(s)->minreq); DEBUG("fragsize %u", pa_stream_get_buffer_attr(s)->fragsize); DEBUG("samplespec %s", pa_sample_spec_snprint(str, sizeof(str), pa_stream_get_sample_spec(s))); break; case PA_STREAM_UNCONNECTED: DEBUG("Stream unconnected"); break; case PA_STREAM_FAILED: default: ERROR("Sink/Source doesn't exists: %s" , pa_strerror(pa_context_errno(pa_stream_get_context(s)))); break; } }
void AudioStream::stateChanged(pa_stream* s) { UNUSED char str[PA_SAMPLE_SPEC_SNPRINT_MAX]; switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: RING_DBG("Stream is creating..."); break; case PA_STREAM_TERMINATED: RING_DBG("Stream is terminating..."); break; case PA_STREAM_READY: RING_DBG("Stream successfully created, connected to %s", pa_stream_get_device_name(s)); //RING_DBG("maxlength %u", pa_stream_get_buffer_attr(s)->maxlength); //RING_DBG("tlength %u", pa_stream_get_buffer_attr(s)->tlength); //RING_DBG("prebuf %u", pa_stream_get_buffer_attr(s)->prebuf); //RING_DBG("minreq %u", pa_stream_get_buffer_attr(s)->minreq); //RING_DBG("fragsize %u", pa_stream_get_buffer_attr(s)->fragsize); //RING_DBG("samplespec %s", pa_sample_spec_snprint(str, sizeof(str), pa_stream_get_sample_spec(s))); break; case PA_STREAM_UNCONNECTED: RING_DBG("Stream unconnected"); break; case PA_STREAM_FAILED: default: RING_ERR("Stream failure: %s" , pa_strerror(pa_context_errno(pa_stream_get_context(s)))); break; } }
/* This routine is called whenever the stream state changes */ void QPulseAudioThread::stream_state_callback ( pa_stream *s, void *userdata ) { assert ( s ); QPulseAudioThread * thread = (QPulseAudioThread *)userdata; switch ( pa_stream_get_state ( s ) ) { case PA_STREAM_UNCONNECTED: qDebug() << "UNCONNECTED"; break; case PA_STREAM_CREATING: qDebug() << "CREATED"; break; case PA_STREAM_TERMINATED: qDebug() << "TERMINATED"; break; case PA_STREAM_READY: qDebug() << "READY"; if ( verbose ) { const pa_buffer_attr *a; fprintf ( stderr, "Stream successfully created.\n" ); if ( ! ( a = pa_stream_get_buffer_attr ( s ) ) ) fprintf ( stderr, "pa_stream_get_buffer_attr() failed: %s\n", pa_strerror ( pa_context_errno ( pa_stream_get_context ( s ) ) ) ); else { fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } } break; case PA_STREAM_FAILED: qDebug() << "FAILED"; default: fprintf ( stderr, "Stream error: %s\n", pa_strerror ( pa_context_errno ( pa_stream_get_context ( s ) ) ) ); pulseQuit ( 1 ); } }
void stream_state_callback(pa_stream *s, void *userdata) { assert(s); switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: break; case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; printf("Stream successfully created.\n"); if (!(a = pa_stream_get_buffer_attr(s))) printf("pa_stream_get_buffer_attr() failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else { printf("Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } /* printf("Using sample spec '%s', channel map '%s'.", pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); */ printf("Connected to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: printf("Stream error: %s", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); exit(1); //quit(1); } }
void PulseAudioSystem::stream_callback(pa_stream *s, void *userdata) { PulseAudioSystem *pas = reinterpret_cast<PulseAudioSystem *>(userdata); switch (pa_stream_get_state(s)) { case PA_STREAM_FAILED: qWarning("PulseAudio: Stream error: %s", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); break; default: break; } pas->wakeup(); }
/*drain stream function*/ void quisk_drain_cork_stream(struct sound_dev *dev) { pa_stream *s = dev->handle; pa_operation *o; if (!(o = pa_stream_drain(s, stream_drain_complete, NULL))) { printf("pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); exit(1); } pa_operation_unref(o); }
/* Stream draining complete */ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { struct sound_dev *dev = userdata; if (!success) { printf("Failed to drain stream: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); quit(1); } if (quisk_sound_state.verbose_pulse) printf("Playback stream %s drained.\n", dev->name); }
// This is called by the play function when the timing structure is updated. static void stream_timing_callback(pa_stream *s, int success, void *userdata) { struct sound_dev *dev = userdata; pa_usec_t l; int negative = 0; assert(s); if (!success || pa_stream_get_latency(s, &l, &negative) < 0) { printf("pa_stream_get_latency() failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); return; } dev->dev_latency = (int)l; if (negative) dev->dev_latency *= -1; pa_threaded_mainloop_signal(pa_ml, 0); }
/* This routine is called whenever the stream state changes */ static void stream_state_callback(pa_stream *s, void *userdata) { pa_assert(s); switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_log(_("Stream successfully created.")); if (!(a = pa_stream_get_buffer_attr(s))) pa_log(_("pa_stream_get_buffer_attr() failed: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else { if (mode == PLAYBACK) pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u"), a->maxlength, a->tlength, a->prebuf, a->minreq); else { pa_assert(mode == RECORD); pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u"), a->maxlength, a->fragsize); } } pa_log(_("Using sample spec '%s', channel map '%s'."), pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); pa_log(_("Connected to device %s (%u, %ssuspended)."), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: pa_log(_("Stream error: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); quit(1); } }
static void stream_state_callback (pa_stream *pa, void *data) { switch (pa_stream_get_state(pa)) { case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: case PA_STREAM_READY: case PA_STREAM_UNCONNECTED: break; case PA_STREAM_FAILED: g_printerr("PA stream failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(pa)))); default: break; } }
//Flush function. Holds mainloop lock until operation is completed. void quisk_flush_pulseaudio(struct sound_dev *dev) { pa_stream *s = dev->handle; pa_operation *o; pa_threaded_mainloop_lock(pa_ml); if (!(o = pa_stream_flush(s, stream_flushed_callback, dev))) { printf("pa_stream_flush(): %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); exit(1); } else { while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) pa_threaded_mainloop_wait(pa_ml); pa_operation_unref(o); } pa_threaded_mainloop_unlock(pa_ml); }
static void outputStreamStateCallback(pa_stream *stream, void *userdata) { Q_UNUSED(userdata) pa_stream_state_t state = pa_stream_get_state(stream); #ifdef DEBUG_PULSE qDebug() << "Stream state: " << QPulseAudioInternal::stateToQString(state); #endif switch (state) { case PA_STREAM_CREATING: case PA_STREAM_READY: case PA_STREAM_TERMINATED: break; case PA_STREAM_FAILED: default: qWarning() << QString("Stream error: %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(stream)))); QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0); break; } }
/* This routine is called whenever the stream state changes */ static void stream_state_callback(pa_stream *s, void *userdata) { fail_unless(s != NULL); switch (pa_stream_get_state(s)) { case PA_STREAM_UNCONNECTED: case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: { int r, i = (int) (long) userdata; fprintf(stderr, "Writing data to stream %i.\n", i); r = pa_stream_write(s, data, sizeof(data), nop_free_cb, (int64_t) sizeof(data) * (int64_t) i, PA_SEEK_ABSOLUTE); fail_unless(r == 0); /* Be notified when this stream is drained */ pa_stream_set_underflow_callback(s, underflow_cb, userdata); /* All streams have been set up, let's go! */ if (++n_streams_ready >= NSTREAMS) { fprintf(stderr, "Uncorking\n"); pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL)); } break; } default: case PA_STREAM_FAILED: fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); fail(); } }
static void inputStreamStateCallback(pa_stream *stream, void *userdata) { Q_UNUSED(userdata); pa_stream_state_t state = pa_stream_get_state(stream); #ifdef DEBUG_PULSE qDebug() << "Stream state: " << QPulseAudioInternal::stateToQString(state); #endif switch (state) { case PA_STREAM_CREATING: break; case PA_STREAM_READY: { #ifdef DEBUG_PULSE QPulseAudioInput *audioInput = static_cast<QPulseAudioInput*>(userdata); const pa_buffer_attr *buffer_attr = pa_stream_get_buffer_attr(stream); qDebug() << "*** maxlength: " << buffer_attr->maxlength; qDebug() << "*** prebuf: " << buffer_attr->prebuf; qDebug() << "*** fragsize: " << buffer_attr->fragsize; qDebug() << "*** minreq: " << buffer_attr->minreq; qDebug() << "*** tlength: " << buffer_attr->tlength; pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(audioInput->format()); qDebug() << "*** bytes_to_usec: " << pa_bytes_to_usec(buffer_attr->fragsize, &spec); #endif } break; case PA_STREAM_TERMINATED: break; case PA_STREAM_FAILED: default: qWarning() << QString("Stream error: %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(stream)))); QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0); break; } }
qint64 QPulseAudioInput::read(char *data, qint64 len) { m_bytesAvailable = checkBytesReady(); setError(QAudio::NoError); setState(QAudio::ActiveState); int readBytes = 0; if (!m_pullMode && !m_tempBuffer.isEmpty()) { readBytes = qMin(static_cast<int>(len), m_tempBuffer.size()); memcpy(data, m_tempBuffer.constData(), readBytes); m_totalTimeValue += readBytes; if (readBytes < m_tempBuffer.size()) { m_tempBuffer.remove(0, readBytes); return readBytes; } m_tempBuffer.clear(); } while (pa_stream_readable_size(m_stream) > 0) { size_t readLength = 0; #ifdef DEBUG_PULSE qDebug() << "QPulseAudioInput::read -- " << pa_stream_readable_size(m_stream) << " bytes available from pulse audio"; #endif QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); pulseEngine->lock(); const void *audioBuffer; // Second and third parameters (audioBuffer and length) to pa_stream_peek are output parameters, // the audioBuffer pointer is set to point to the actual pulse audio data, // and the length is set to the length of this data. if (pa_stream_peek(m_stream, &audioBuffer, &readLength) < 0) { qWarning() << QString("pa_stream_peek() failed: %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(m_stream)))); pulseEngine->unlock(); return 0; } qint64 actualLength = 0; if (m_pullMode) { QByteArray adjusted(readLength, Qt::Uninitialized); applyVolume(audioBuffer, adjusted.data(), readLength); actualLength = m_audioSource->write(adjusted); if (actualLength < qint64(readLength)) { pulseEngine->unlock(); setError(QAudio::UnderrunError); setState(QAudio::IdleState); return actualLength; } } else { actualLength = qMin(static_cast<int>(len - readBytes), static_cast<int>(readLength)); applyVolume(audioBuffer, data + readBytes, actualLength); } #ifdef DEBUG_PULSE qDebug() << "QPulseAudioInput::read -- wrote " << actualLength << " to client"; #endif if (actualLength < qint64(readLength)) { #ifdef DEBUG_PULSE qDebug() << "QPulseAudioInput::read -- appending " << readLength - actualLength << " bytes of data to temp buffer"; #endif int diff = readLength - actualLength; int oldSize = m_tempBuffer.size(); m_tempBuffer.resize(m_tempBuffer.size() + diff); applyVolume(static_cast<const char *>(audioBuffer) + actualLength, m_tempBuffer.data() + oldSize, diff); QMetaObject::invokeMethod(this, "userFeed", Qt::QueuedConnection); } m_totalTimeValue += actualLength; readBytes += actualLength; pa_stream_drop(m_stream); pulseEngine->unlock(); if (!m_pullMode && readBytes >= len) break; if (m_intervalTime && (m_timeStamp.elapsed() + m_elapsedTimeOffset) > m_intervalTime) { emit notify(); m_elapsedTimeOffset = m_timeStamp.elapsed() + m_elapsedTimeOffset - m_intervalTime; m_timeStamp.restart(); } } #ifdef DEBUG_PULSE qDebug() << "QPulseAudioInput::read -- returning after reading " << readBytes << " bytes"; #endif return readBytes; }
void stream_state_callback(pa_stream *s, void *userdata) { struct sound_dev *dev = userdata; assert(s); assert(dev); switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: break; case PA_STREAM_TERMINATED: if (quisk_sound_state.verbose_pulse) printf("stream %s terminated\n", dev->name); streams_ready--; break; case PA_STREAM_READY: streams_ready++; //increment counter to tell other thread that this stream is ready if (quisk_sound_state.verbose_pulse) { const pa_buffer_attr *a; printf("Connected to device %s (%u, %ssuspended). ", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); if (!(a = pa_stream_get_buffer_attr(s))) printf("pa_stream_get_buffer_attr() failed: %s", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else if (!(a->prebuf)) { printf("Buffer metrics %s: maxlength=%u, fragsize=%u\n", dev->name, a->maxlength, a->fragsize); } else { printf("Buffer metrics %s: maxlength=%u, prebuf=%u, tlength=%u minreq=%u\n", dev->name, a->maxlength, a->prebuf, a->tlength, a->minreq); } } break; case PA_STREAM_FAILED: default: printf("Stream error: %s - %s\n", dev->name, pa_strerror(pa_context_errno(pa_stream_get_context(s)))); exit(1); } }
/*! * \Write outgoing samples directly to pulseaudio server. * \param playdev Input. Device to which to play the samples. * \param nSamples Input. Number of samples to play. * \param cSamples Input. Sample buffer to play from. * \param report_latency Input. 1 to update \c quisk_sound_state.latencyPlay, 0 otherwise. * \param volume Input. Ratio in [0,1] by which to scale the played samples. */ void quisk_play_pulseaudio(struct sound_dev *dev, int nSamples, complex double *cSamples, int report_latency, double volume) { pa_stream *s = dev->handle; int i=0, n=0; void *fbuffer; int fbuffer_bytes = 0; if( !dev || nSamples <= 0) return; if (dev->cork_status) return; if (report_latency) { // Report the latency, if requested. pa_operation *o; pa_threaded_mainloop_lock(pa_ml); if (!(o = pa_stream_update_timing_info(s, stream_timing_callback, dev))) { printf("pa_stream_update_timing(): %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); } else { while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) pa_threaded_mainloop_wait(pa_ml); pa_operation_unref(o); } pa_threaded_mainloop_unlock(pa_ml); } fbuffer = pa_xmalloc(nSamples * dev->num_channels * dev->sample_bytes); // Convert from complex data to framebuffer if (dev->sample_bytes == 4) { float fi=0.f, fq=0.f; for(i = 0, n = 0; n < nSamples; i += (dev->num_channels * 4), ++n) { fi = (volume * creal(cSamples[n])) / CLIP32; fq = (volume * cimag(cSamples[n])) / CLIP32; memcpy(fbuffer + i + (dev->channel_I * 4), &fi, 4); memcpy(fbuffer + i + (dev->channel_Q * 4), &fq, 4); } } else if (dev->sample_bytes == 2) { int ii, qq; for(i = 0, n = 0; n < nSamples; i += (dev->num_channels * 2), ++n) { ii = (int)(volume * creal(cSamples[n]) / 65536); qq = (int)(volume * cimag(cSamples[n]) / 65536); memcpy(fbuffer + i + (dev->channel_I * 2), &ii, 2); memcpy(fbuffer + i + (dev->channel_Q * 2), &qq, 2); } } else { printf("Unknown sample size for %s", dev->name); exit(1); } fbuffer_bytes = nSamples * dev->num_channels * dev->sample_bytes; pa_threaded_mainloop_lock(pa_ml); size_t writable = pa_stream_writable_size(s); if (writable > 0) { if ( writable > 1024*1000 ) //sanity check to prevent pa_xmalloc from crashing on monitor streams writable = 1024*1000; if (fbuffer_bytes > writable) { if (quisk_sound_state.verbose_pulse) printf("Truncating write by %u bytes\n", fbuffer_bytes - (int)writable); fbuffer_bytes = writable; } pa_stream_write(dev->handle, fbuffer, (size_t)fbuffer_bytes, NULL, 0, PA_SEEK_RELATIVE); //printf("wrote %d to %s\n", writable, dev->name); } else { if (quisk_sound_state.verbose_pulse) printf("Can't write to stream %s. Dropping %d bytes\n", dev->name, fbuffer_bytes); } pa_threaded_mainloop_unlock(pa_ml); pa_xfree(fbuffer); fbuffer=NULL; }