Exemple #1
0
static pa_stream *connect_playback_stream(ALCdevice *device,
    pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec,
    pa_channel_map *chanmap)
{
    pulse_data *data = device->ExtraData;
    pa_stream_state_t state;
    pa_stream *stream;

    stream = pa_stream_new(data->context, "Playback Stream", spec, chanmap);
    if(!stream)
    {
        ERR("pa_stream_new() failed: %s\n",
            pa_strerror(pa_context_errno(data->context)));
        return NULL;
    }

    pa_stream_set_state_callback(stream, stream_state_callback, data->loop);

    AL_PRINT("Attempting flags 0x%x\n", flags);
    if (attr)
    {
        AL_PRINT("maxlength: %d tlegth: %d prebuf: %d minreq: %d fragsize: %d\n",
           attr->maxlength, attr->tlength, attr->prebuf, attr->minreq, attr->fragsize);
    }

    if(pa_stream_connect_playback(stream, data->device_name, attr, flags, NULL, NULL) < 0)
    {
        ERR("Stream did not connect: %s\n",
            pa_strerror(pa_context_errno(data->context)));
        pa_stream_unref(stream);
        return NULL;
    }

    while((state=pa_stream_get_state(stream)) != PA_STREAM_READY)
    {
        if(!PA_STREAM_IS_GOOD(state))
        {
            ERR("Stream did not get ready: %s\n",
                pa_strerror(pa_context_errno(data->context)));
            pa_stream_unref(stream);
            return NULL;
        }

        pa_threaded_mainloop_wait(data->loop);
    }
    pa_stream_set_state_callback(stream, NULL, NULL);

    return stream;
}
/**
 * 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;
}
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 QPulseAudioInput::close()
{
    if (!m_opened)
        return;

    m_timer->stop();

    QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();

    if (m_stream) {
        pulseEngine->lock();

        pa_stream_set_state_callback(m_stream, 0, 0);
        pa_stream_set_read_callback(m_stream, 0, 0);
        pa_stream_set_underflow_callback(m_stream, 0, 0);
        pa_stream_set_overflow_callback(m_stream, 0, 0);

        pa_stream_disconnect(m_stream);
        pa_stream_unref(m_stream);
        m_stream = 0;

        pulseEngine->unlock();
    }

    disconnect(pulseEngine, &QPulseAudioEngine::contextFailed, this, &QPulseAudioInput::onPulseContextFailed);

    if (!m_pullMode && m_audioSource) {
        delete m_audioSource;
        m_audioSource = 0;
    }
    m_opened = false;
}
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);
}
/**
 * Pulseaudio context state callback
 */
static void
context_state_callback (pa_context * c,
			void *userdata)
{
  GNUNET_assert (c);

  switch (pa_context_get_state (c))
  {
  case PA_CONTEXT_CONNECTING:
  case PA_CONTEXT_AUTHORIZING:
  case PA_CONTEXT_SETTING_NAME:
    break;
  case PA_CONTEXT_READY:
  {
    int r;
    pa_buffer_attr na;

    GNUNET_assert (!stream_in);
    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
		_("Connection established.\n"));
    if (! (stream_in =
	   pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL)))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		  _("pa_stream_new() failed: %s\n"),
		  pa_strerror (pa_context_errno (c)));
      goto fail;
    }
    pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL);
    pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL);
    memset (&na, 0, sizeof (na));
    na.maxlength = UINT32_MAX;
    na.fragsize = pcm_length;
    if ((r = pa_stream_connect_record (stream_in, NULL, &na,
				       PA_STREAM_ADJUST_LATENCY)) < 0)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		  _("pa_stream_connect_record() failed: %s\n"),
		  pa_strerror (pa_context_errno (c)));
      goto fail;
    }

    break;
  }
  case PA_CONTEXT_TERMINATED:
    quit (0);
    break;
  case PA_CONTEXT_FAILED:
  default:
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		_("Connection failure: %s\n"),
		pa_strerror (pa_context_errno (c)));
    goto fail;
  }
  return;

fail:
  quit (1);
}
Exemple #7
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;
}
Exemple #8
0
void
eventd_sound_pulseaudio_play_data(EventdSoundPulseaudioContext *context, gpointer data, gsize length, gint format, guint32 rate, guint8 channels)
{
    pa_sample_spec sample_spec;
    pa_stream *stream;
    EventdSoundPulseaudioEventData *event_data;

    if ( data == NULL )
        return;

    if ( ( context == NULL ) || ( pa_context_get_state(context->context) != PA_CONTEXT_READY ) )
    {
        g_free(data);
        return;
    }

    switch ( format )
    {
    case SF_FORMAT_PCM_16:
    case SF_FORMAT_PCM_U8:
    case SF_FORMAT_PCM_S8:
        sample_spec.format = PA_SAMPLE_S16NE;
    break;
    case SF_FORMAT_PCM_24:
        sample_spec.format = PA_SAMPLE_S24NE;
    break;
    case SF_FORMAT_PCM_32:
        sample_spec.format = PA_SAMPLE_S32NE;
    break;
    case SF_FORMAT_FLOAT:
    case SF_FORMAT_DOUBLE:
        sample_spec.format = PA_SAMPLE_FLOAT32NE;
    break;
    default:
        g_warning("Unsupported format");
        return;
    }

    sample_spec.rate = rate;
    sample_spec.channels = channels;

    if ( ! pa_sample_spec_valid(&sample_spec) )
    {
        g_warning("Invalid spec");
        return;
    }

    stream = pa_stream_new(context->context, "sndfile plugin playback", &sample_spec, NULL);

    event_data = g_new0(EventdSoundPulseaudioEventData, 1);
    event_data->data = data;
    event_data->length = length;

    pa_stream_set_state_callback(stream, _eventd_sound_pulseaudio_stream_state_callback, event_data);
    pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL);
}
static pa_stream *connect_playback_stream(ALCdevice *device,
    pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec,
    pa_channel_map *chanmap)
{
    pulse_data *data = device->ExtraData;
    pa_stream_state_t state;
    pa_stream *stream;

    stream = pa_stream_new(data->context, "Playback Stream", spec, chanmap);
    if(!stream)
    {
        ERR("pa_stream_new() failed: %s\n",
            pa_strerror(pa_context_errno(data->context)));
        return NULL;
    }

    pa_stream_set_state_callback(stream, stream_state_callback, data->loop);

    if(pa_stream_connect_playback(stream, data->device_name, attr, flags, NULL, NULL) < 0)
    {
        ERR("Stream did not connect: %s\n",
            pa_strerror(pa_context_errno(data->context)));
        pa_stream_unref(stream);
        return NULL;
    }

    while((state=pa_stream_get_state(stream)) != PA_STREAM_READY)
    {
        if(!PA_STREAM_IS_GOOD(state))
        {
            ERR("Stream did not get ready: %s\n",
                pa_strerror(pa_context_errno(data->context)));
            pa_stream_unref(stream);
            return NULL;
        }

        pa_threaded_mainloop_wait(data->loop);
    }
    pa_stream_set_state_callback(stream, NULL, NULL);

    return stream;
}
JNIEXPORT void JNICALL
Java_org_jitsi_impl_neomedia_pulseaudio_PA_stream_1set_1state_1callback
    (JNIEnv *env, jclass clazz, jlong s, jobject cb)
{
    jweak weakCb = cb ? (*env)->NewWeakGlobalRef(env, cb) : NULL;

    pa_stream_set_state_callback(
            (pa_stream *) (intptr_t) s,
            weakCb ? PulseAudio_streamStateCallback : NULL,
            (void *) weakCb);
}
void QPulseAudioThread::reconnect(SourceContainer::const_iterator pos = s_sourceList.end())
{

    if (s_sourceList.empty())
        return;

    if (pos != s_sourceList.end()) {
        s_sourcePosition = pos;
        qDebug() << "reconnecting with" << *pos;
    } else
        s_sourcePosition = scanForPlaybackMonitor();

    if (s_sourcePosition == s_sourceList.end()) {
        s_sourcePosition = s_sourceList.begin();
    }

    if (stream && (pa_stream_get_state(stream) == PA_STREAM_READY)) {
        //qDebug() << "disconnect";
        pa_stream_disconnect ( stream );
        //	pa_stream_unref(stream);
        //qDebug() << "* return *";

    }

    if ( ! ( stream = pa_stream_new ( context, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL ) ) ) {
        fprintf ( stderr, "pa_stream_new() failed: %s\n", pa_strerror ( pa_context_errno ( context ) ) );
        return;
    }

    pa_stream_set_state_callback
    ( stream, stream_state_callback, &s_sourceList );
    pa_stream_set_read_callback ( stream, stream_read_callback, &s_sourceList );
    pa_stream_set_moved_callback(stream, stream_moved_callback, &s_sourceList );

    switch (pa_stream_get_state(stream)) {
    case PA_STREAM_UNCONNECTED:// 	The stream is not yet connected to any sink or source.
        qDebug() << "unconnected: connecting...";
        connectHelper(s_sourcePosition);
        break;
    case PA_STREAM_CREATING 	://The stream is being created.
        break;
    case PA_STREAM_READY ://	The stream is established, you may pass audio data to it now.
        qDebug() << "stream is still ready, waiting for callback...";
        break;
    case PA_STREAM_FAILED ://	An error occured that made the stream invalid.
        qDebug() << "stream is now invalid. great.";
        break;
    case PA_STREAM_TERMINATED:// 	The stream has been terminated cleanly.
        qDebug() << "terminated...";
        break;

    }
}
/*
 * 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);
}
Exemple #13
0
static pa_stream *connect_record_stream(const char *device_name,
    pa_threaded_mainloop *loop, pa_context *context,
    pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec,
    pa_channel_map *chanmap)
{
    pa_stream_state_t state;
    pa_stream *stream;

    stream = pa_stream_new_with_proplist(context, "Capture Stream", spec, chanmap, prop_filter);
    if(!stream)
    {
        ERR("pa_stream_new_with_proplist() failed: %s\n", pa_strerror(pa_context_errno(context)));
        return NULL;
    }

    pa_stream_set_state_callback(stream, stream_state_callback, loop);

    if(pa_stream_connect_record(stream, device_name, attr, flags) < 0)
    {
        ERR("Stream did not connect: %s\n", pa_strerror(pa_context_errno(context)));
        pa_stream_unref(stream);
        return NULL;
    }

    while((state=pa_stream_get_state(stream)) != PA_STREAM_READY)
    {
        if(!PA_STREAM_IS_GOOD(state))
        {
            ERR("Stream did not get ready: %s\n", pa_strerror(pa_context_errno(context)));
            pa_stream_unref(stream);
            return NULL;
        }

        pa_threaded_mainloop_wait(loop);
    }
    pa_stream_set_state_callback(stream, NULL, NULL);

    return stream;
}
Exemple #14
0
static int instream_open_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
    struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
    struct SoundIoInStream *instream = &is->pub;

    if ((unsigned)instream->layout.channel_count > PA_CHANNELS_MAX)
        return SoundIoErrorIncompatibleBackend;
    if (!instream->name)
        instream->name = "SoundIoInStream";

    struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
    SOUNDIO_ATOMIC_STORE(ispa->stream_ready, false);

    pa_threaded_mainloop_lock(sipa->main_loop);

    pa_sample_spec sample_spec;
    sample_spec.format = to_pulseaudio_format(instream->format);
    sample_spec.rate = instream->sample_rate;
    sample_spec.channels = instream->layout.channel_count;

    pa_channel_map channel_map = to_pulseaudio_channel_map(&instream->layout);

    ispa->stream = pa_stream_new(sipa->pulse_context, instream->name, &sample_spec, &channel_map);
    if (!ispa->stream) {
        pa_threaded_mainloop_unlock(sipa->main_loop);
        instream_destroy_pa(si, is);
        return SoundIoErrorNoMem;
    }

    pa_stream *stream = ispa->stream;

    pa_stream_set_state_callback(stream, recording_stream_state_callback, is);
    pa_stream_set_read_callback(stream, recording_stream_read_callback, is);

    ispa->buffer_attr.maxlength = UINT32_MAX;
    ispa->buffer_attr.tlength = UINT32_MAX;
    ispa->buffer_attr.prebuf = 0;
    ispa->buffer_attr.minreq = UINT32_MAX;
    ispa->buffer_attr.fragsize = UINT32_MAX;

    if (instream->software_latency > 0.0) {
        int bytes_per_second = instream->bytes_per_frame * instream->sample_rate;
        int buffer_length = instream->bytes_per_frame *
            ceil_dbl_to_int(instream->software_latency * bytes_per_second / (double)instream->bytes_per_frame);
        ispa->buffer_attr.fragsize = buffer_length;
    }

    pa_threaded_mainloop_unlock(sipa->main_loop);

    return 0;
}
/* This is called whenever the context status changes */
static void context_state_callback(pa_context *c, void *userdata) {
    fail_unless(c != NULL);

    switch (pa_context_get_state(c)) {
        case PA_CONTEXT_CONNECTING:
        case PA_CONTEXT_AUTHORIZING:
        case PA_CONTEXT_SETTING_NAME:
            break;

        case PA_CONTEXT_READY: {

            int i;
            fprintf(stderr, "Connection established.\n");

            for (i = 0; i < NSTREAMS; i++) {
                char name[64];
                pa_format_info *formats[1];

                formats[0] = pa_format_info_new();
                formats[0]->encoding = PA_ENCODING_PCM;
                pa_format_info_set_sample_format(formats[0], PA_SAMPLE_FLOAT32);
                pa_format_info_set_rate(formats[0], SAMPLE_HZ);
                pa_format_info_set_channels(formats[0], 1);

                fprintf(stderr, "Creating stream %i\n", i);

                snprintf(name, sizeof(name), "stream #%i", i);

                streams[i] = pa_stream_new_extended(c, name, formats, 1, NULL);
                fail_unless(streams[i] != NULL);
                pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i);
                pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]);

                pa_format_info_free(formats[0]);
            }

            break;
        }

        case PA_CONTEXT_TERMINATED:
            mainloop_api->quit(mainloop_api, 0);
            break;

        case PA_CONTEXT_FAILED:
        default:
            fprintf(stderr, "Context error: %s\n", pa_strerror(pa_context_errno(c)));
            fail();
    }
}
Exemple #16
0
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_);
}
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_);
}
Exemple #18
0
static void instream_destroy_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
    struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
    struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
    pa_stream *stream = ispa->stream;
    if (stream) {
        pa_threaded_mainloop_lock(sipa->main_loop);

        pa_stream_set_state_callback(stream, NULL, NULL);
        pa_stream_set_read_callback(stream, NULL, NULL);
        pa_stream_disconnect(stream);
        pa_stream_unref(stream);

        pa_threaded_mainloop_unlock(sipa->main_loop);

        ispa->stream = NULL;
    }
}
Exemple #19
0
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;
}
/**
 * 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;
}
Exemple #21
0
AudioStream::AudioStream(pa_context *c, pa_threaded_mainloop *m, const char *desc, int type, int smplrate, std::string& deviceName)
    : audiostream_(0), mainloop_(m)
{
    static const pa_channel_map channel_map = {
        1,
        { PA_CHANNEL_POSITION_MONO },
    };

    pa_sample_spec sample_spec = {
        PA_SAMPLE_S16LE, // PA_SAMPLE_FLOAT32LE,
        smplrate,
        1
    };

    assert(pa_sample_spec_valid(&sample_spec));
    assert(pa_channel_map_valid(&channel_map));

    audiostream_ = pa_stream_new(c, desc, &sample_spec, &channel_map);

    if (!audiostream_) {
        ERROR("%s: pa_stream_new() failed : %s" , desc, pa_strerror(pa_context_errno(c)));
        throw std::runtime_error("Could not create stream\n");
    }

    pa_buffer_attr attributes;
    attributes.maxlength = pa_usec_to_bytes(160 * PA_USEC_PER_MSEC, &sample_spec);
    attributes.tlength = pa_usec_to_bytes(80 * PA_USEC_PER_MSEC, &sample_spec);
    attributes.prebuf = 0;
    attributes.fragsize = pa_usec_to_bytes(80 * PA_USEC_PER_MSEC, &sample_spec);
    attributes.minreq = (uint32_t) -1;

    pa_threaded_mainloop_lock(mainloop_);

    if (type == PLAYBACK_STREAM || type == RINGTONE_STREAM)
        pa_stream_connect_playback(audiostream_, deviceName == "" ? NULL : deviceName.c_str(), &attributes,
		(pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL);
    else if (type == CAPTURE_STREAM)
        pa_stream_connect_record(audiostream_, deviceName == "" ? NULL : deviceName.c_str(), &attributes,
		(pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE));

    pa_threaded_mainloop_unlock(mainloop_);

    pa_stream_set_state_callback(audiostream_, stream_state_callback, NULL);
}
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;
}
Exemple #23
0
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;
    }
}
Exemple #24
0
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();
}
Exemple #25
0
/* This is called whenever the context status changes */
static void context_state_callback(pa_context *c, void *userdata) {
    fail_unless(c != NULL);

    switch (pa_context_get_state(c)) {
        case PA_CONTEXT_CONNECTING:
        case PA_CONTEXT_AUTHORIZING:
        case PA_CONTEXT_SETTING_NAME:
            break;

        case PA_CONTEXT_READY: {

            int i;
            fprintf(stderr, "Connection established.\n");

            for (i = 0; i < NSTREAMS; i++) {
                char name[64];

                fprintf(stderr, "Creating stream %i\n", i);

                snprintf(name, sizeof(name), "stream #%i", i);

                streams[i] = pa_stream_new(c, name, &sample_spec, NULL);
                fail_unless(streams[i] != NULL);
                pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i);
                pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]);
            }

            break;
        }

        case PA_CONTEXT_TERMINATED:
            mainloop_api->quit(mainloop_api, 0);
            break;

        case PA_CONTEXT_FAILED:
        default:
            fprintf(stderr, "Context error: %s\n", pa_strerror(pa_context_errno(c)));
            fail();
    }
}
Exemple #26
0
static void __context_get_sink_info_callback(pa_context* context,
        const pa_sink_info* info, int is_last, void* data) {

    guac_client* client = (guac_client*) data;
    pa_stream* stream;
    pa_sample_spec spec;
    pa_buffer_attr attr;

    /* Stop if end of list reached */
    if (is_last)
        return;

    guac_client_log_info(client, "Starting streaming from \"%s\"",
            info->description);

    /* Set format */
    spec.format   = PA_SAMPLE_S16LE;
    spec.rate     = GUAC_VNC_AUDIO_RATE;
    spec.channels = GUAC_VNC_AUDIO_CHANNELS;

    attr.maxlength = -1;
    attr.fragsize  = GUAC_VNC_AUDIO_FRAGMENT_SIZE;

    /* Create stream */
    stream = pa_stream_new(context, "Guacamole Audio", &spec, NULL);

    /* Set stream callbacks */
    pa_stream_set_state_callback(stream, __stream_state_callback, client);
    pa_stream_set_read_callback(stream, __stream_read_callback, client);

    /* Start stream */
    pa_stream_connect_record(stream, info->monitor_source_name, &attr,
                PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
              | PA_STREAM_ADJUST_LATENCY);

}
void RageSoundDriver_PulseAudio::m_InitStream(void)
{
	int error;
	pa_sample_spec ss;
	pa_channel_map map;

	/* init sample spec */
	ss.format = PA_SAMPLE_S16LE;
	ss.channels = 2;
	ss.rate = PREFSMAN->m_iSoundPreferredSampleRate;
	if(ss.rate == 0)
	{
		ss.rate = 44100;
	}

	/* init channel map */
	pa_channel_map_init_stereo(&map);

	/* check sample spec */
	if(!pa_sample_spec_valid(&ss))
	{
		if(asprintf(&m_Error, "invalid sample spec!") == -1)
		{
			m_Error = nullptr;
		}
		m_Sem.Post();
		return;
	}

	/* log the used sample spec */
	char specstring[PA_SAMPLE_SPEC_SNPRINT_MAX];
	pa_sample_spec_snprint(specstring, sizeof(specstring), &ss);
	LOG->Trace("Pulse: using sample spec: %s", specstring);

	/* create the stream */
	LOG->Trace("Pulse: pa_stream_new()...");
	m_PulseStream = pa_stream_new(m_PulseCtx, "Stepmania Audio", &ss, &map);
	if(m_PulseStream == nullptr)
	{
		if(asprintf(&m_Error, "pa_stream_new(): %s", pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
		{
			m_Error = nullptr;
		}
		m_Sem.Post();
		return;
	}

	/* set the write callback, it will be called when the sound server
	* needs data */
	pa_stream_set_write_callback(m_PulseStream, StaticStreamWriteCb, this);

	/* set the state callback, it will be called the the stream state will
	* change */
	pa_stream_set_state_callback(m_PulseStream, StaticStreamStateCb, this);

	/* configure attributes of the stream */
	pa_buffer_attr attr;
	memset(&attr, 0x00, sizeof(attr));

	/* tlength: Target length of the buffer.
	*
	* "The server tries to assure that at least tlength bytes are always
	*  available in the per-stream server-side playback buffer. It is
	*  recommended to set this to (uint32_t) -1, which will initialize
	*  this to a value that is deemed sensible by the server. However,
	*  this value will default to something like 2s, i.e. for applications
	*  that have specific latency requirements this value should be set to
	*  the maximum latency that the application can deal with."
	*
	* We don't want the default here, we want a small latency.
	* We use pa_usec_to_bytes() to convert a latency to a buffer size.
	*/
	attr.tlength = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &ss);

	/* maxlength: Maximum length of the buffer
	*
	* "Setting this to (uint32_t) -1 will initialize this to the maximum
	*  value supported by server, which is recommended."
	*
	* (uint32_t)-1 is NOT working here, setting it to tlength*2, like
	* openal-soft-pulseaudio does.
	*/
	attr.maxlength = attr.tlength*2;

	/* minreq: Minimum request
	*
	* "The server does not request less than minreq bytes from the client,
	*  instead waits until the buffer is free enough to request more bytes
	*  at once. It is recommended to set this to (uint32_t) -1, which will
	*  initialize this to a value that is deemed sensible by the server."
	*
	* (uint32_t)-1 is NOT working here, setting it to 0, like
	* openal-soft-pulseaudio does.
	*/
	attr.minreq = 0;

	/* prebuf: Pre-buffering
	*
	* "The server does not start with playback before at least prebuf
	*  bytes are available in the buffer. It is recommended to set this
	*  to (uint32_t) -1, which will initialize this to the same value as
	*  tlength"
	*/
	attr.prebuf = (uint32_t)-1;

	/* log the used target buffer length */
	LOG->Trace("Pulse: using target buffer length of %i bytes", attr.tlength);

	 /* connect the stream for playback */
	LOG->Trace("Pulse: pa_stream_connect_playback()...");
	error = pa_stream_connect_playback(m_PulseStream, nullptr, &attr,
			PA_STREAM_AUTO_TIMING_UPDATE, nullptr, nullptr);
	if(error < 0)
	{
		if(asprintf(&m_Error, "pa_stream_connect_playback(): %s",
				pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
		{
			m_Error = nullptr;
		}
		m_Sem.Post();
		return;
	}

	 m_SampleRate = ss.rate;
}
AudioStream::AudioStream(pa_context *c,
                         pa_threaded_mainloop *m,
                         const char *desc,
                         int type,
                         unsigned samplrate,
                         const PaDeviceInfos* infos,
                         bool ec)
    : audiostream_(0), mainloop_(m)
{
    const pa_channel_map channel_map = infos->channel_map;

    pa_sample_spec sample_spec = {
        PA_SAMPLE_S16LE, // PA_SAMPLE_FLOAT32LE,
        samplrate,
        channel_map.channels
    };

    RING_DBG("%s: trying to create stream with device %s (%dHz, %d channels)", desc, infos->name.c_str(), samplrate, channel_map.channels);

    assert(pa_sample_spec_valid(&sample_spec));
    assert(pa_channel_map_valid(&channel_map));

    std::unique_ptr<pa_proplist, decltype(pa_proplist_free)&> pl (pa_proplist_new(), pa_proplist_free);
    pa_proplist_sets(pl.get(), PA_PROP_FILTER_WANT, "echo-cancel");

    audiostream_ = pa_stream_new_with_proplist(c, desc, &sample_spec, &channel_map, ec ? pl.get() : nullptr);
    if (!audiostream_) {
        RING_ERR("%s: pa_stream_new() failed : %s" , desc, pa_strerror(pa_context_errno(c)));
        throw std::runtime_error("Could not create stream\n");
    }

    pa_buffer_attr attributes;
    attributes.maxlength = pa_usec_to_bytes(160 * PA_USEC_PER_MSEC, &sample_spec);
    attributes.tlength = pa_usec_to_bytes(80 * PA_USEC_PER_MSEC, &sample_spec);
    attributes.prebuf = 0;
    attributes.fragsize = pa_usec_to_bytes(80 * PA_USEC_PER_MSEC, &sample_spec);
    attributes.minreq = (uint32_t) -1;

    {
        PulseMainLoopLock lock(mainloop_);
        const pa_stream_flags_t flags = static_cast<pa_stream_flags_t>(PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE);

        if (type == PLAYBACK_STREAM || type == RINGTONE_STREAM) {
            pa_stream_connect_playback(audiostream_,
                    infos->name.empty() ? NULL : infos->name.c_str(),
                    &attributes,
                    flags,
                    NULL, NULL);
        } else if (type == CAPTURE_STREAM) {
            pa_stream_connect_record(audiostream_,
                    infos->name.empty() ? NULL : infos->name.c_str(),
                    &attributes,
                    flags);
        }
    }

    pa_stream_set_state_callback(audiostream_, [](pa_stream* s, void* user_data){
        static_cast<AudioStream*>(user_data)->stateChanged(s);
    }, this);
    pa_stream_set_moved_callback(audiostream_, [](pa_stream* s, void* user_data){
        static_cast<AudioStream*>(user_data)->moved(s);
    }, this);
}
Exemple #29
0
static void *pulse_init(const char *device, unsigned rate, unsigned latency)
{
   pa_sample_spec spec;
   pa_t *pa;
   pa_buffer_attr buffer_attr = {0};
   const pa_buffer_attr *server_attr = NULL;

   memset(&spec, 0, sizeof(spec));
   
   pa = (pa_t*)calloc(1, sizeof(*pa));
   if (!pa)
      goto error;

   pa->mainloop = pa_threaded_mainloop_new();
   if (!pa->mainloop)
      goto error;

   pa->context = pa_context_new(pa_threaded_mainloop_get_api(pa->mainloop), "RetroArch");
   if (!pa->context)
      goto error;

   pa_context_set_state_callback(pa->context, context_state_cb, pa);

   if (pa_context_connect(pa->context, device, PA_CONTEXT_NOFLAGS, NULL) < 0)
      goto error;

   pa_threaded_mainloop_lock(pa->mainloop);
   if (pa_threaded_mainloop_start(pa->mainloop) < 0)
      goto error;

   pa_threaded_mainloop_wait(pa->mainloop);

   if (pa_context_get_state(pa->context) != PA_CONTEXT_READY)
      goto unlock_error;

   spec.format = is_little_endian() ? PA_SAMPLE_FLOAT32LE : PA_SAMPLE_FLOAT32BE;
   spec.channels = 2;
   spec.rate = rate;

   pa->stream = pa_stream_new(pa->context, "audio", &spec, NULL);
   if (!pa->stream)
      goto unlock_error;

   pa_stream_set_state_callback(pa->stream, stream_state_cb, pa);
   pa_stream_set_write_callback(pa->stream, stream_request_cb, pa);
   pa_stream_set_latency_update_callback(pa->stream, stream_latency_update_cb, pa);
   pa_stream_set_underflow_callback(pa->stream, underrun_update_cb, pa);
   pa_stream_set_buffer_attr_callback(pa->stream, buffer_attr_cb, pa);

   buffer_attr.maxlength = -1;
   buffer_attr.tlength = pa_usec_to_bytes(latency * PA_USEC_PER_MSEC, &spec);
   buffer_attr.prebuf = -1;
   buffer_attr.minreq = -1;
   buffer_attr.fragsize = -1;

   if (pa_stream_connect_playback(pa->stream, NULL, &buffer_attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0)
      goto error;

   pa_threaded_mainloop_wait(pa->mainloop);

   if (pa_stream_get_state(pa->stream) != PA_STREAM_READY)
      goto unlock_error;

   server_attr = pa_stream_get_buffer_attr(pa->stream);
   if (server_attr)
   {
      pa->buffer_size = server_attr->tlength;
      RARCH_LOG("[PulseAudio]: Requested %u bytes buffer, got %u.\n",
            (unsigned)buffer_attr.tlength,
            (unsigned)pa->buffer_size);
   }
   else
      pa->buffer_size = buffer_attr.tlength;

   pa_threaded_mainloop_unlock(pa->mainloop);

   return pa;

unlock_error:
   pa_threaded_mainloop_unlock(pa->mainloop);
error:
   pulse_free(pa); 
   return NULL;
}
Exemple #30
0
bool CPulseAESound::Initialize()
{
  /* we dont re-init the wav loader in PA as PA handles the samplerate */
  if (!m_wavLoader.IsValid())
    return false;

  m_sampleSpec.format   = PA_SAMPLE_FLOAT32NE;
  m_sampleSpec.rate     = m_wavLoader.GetSampleRate();
  m_sampleSpec.channels = m_wavLoader.GetChannelLayout().Count();

  if (!pa_sample_spec_valid(&m_sampleSpec))
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Invalid sample spec");
    return false;
  }

  struct pa_channel_map map;
  map.channels = m_sampleSpec.channels;
  switch (map.channels)
  {
    case 1:
      map.map[0] = PA_CHANNEL_POSITION_MONO;
      break;

    case 2:
      map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
      map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
      break;

    default:
      CLog::Log(LOGERROR, "CPulseAESound::Initialize - We do not yet support multichannel sounds");
      return false;
  }

  m_maxVolume     = CAEFactory::GetEngine()->GetVolume();
  m_volume        = 1.0f;
  pa_volume_t paVolume = pa_sw_volume_from_linear((double)(m_volume * m_maxVolume));
  pa_cvolume_set(&m_chVolume, m_sampleSpec.channels, paVolume);

  pa_threaded_mainloop_lock(m_mainLoop);
  if ((m_stream = pa_stream_new(m_context, m_pulseName.c_str(), &m_sampleSpec, &map)) == NULL)
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Could not create a stream");
    pa_threaded_mainloop_unlock(m_mainLoop);
    return false;
  }

  pa_stream_set_state_callback(m_stream, CPulseAESound::StreamStateCallback, this);
  pa_stream_set_write_callback(m_stream, CPulseAESound::StreamWriteCallback, this);

  if (pa_stream_connect_upload(m_stream, m_wavLoader.GetFrameCount() * pa_frame_size(&m_sampleSpec)) != 0)
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Could not initialize the stream");
    pa_stream_disconnect(m_stream);
    m_stream = NULL;
    pa_threaded_mainloop_unlock(m_mainLoop);
    return false;
  }

  /* check if the stream failed */
  if (pa_stream_get_state(m_stream) == PA_STREAM_FAILED)
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Waited for the stream but it failed");
    pa_stream_disconnect(m_stream);
    m_stream = NULL;
    pa_threaded_mainloop_unlock(m_mainLoop);
    return false;
  }

  pa_threaded_mainloop_unlock(m_mainLoop);
  return true;
}