Example #1
0
gboolean xmms_pulse_backend_write (xmms_pulse *p, const char *data,
                                   size_t length, int *rerror)
{
	assert (p);

	if (!data || !length) {
		if (rerror)
			*rerror = PA_ERR_INVALID;
		return FALSE;
	}

	pa_threaded_mainloop_lock (p->mainloop);
	if (!check_pulse_health (p, rerror))
		goto unlock_and_fail;

	while (length > 0) {
		size_t buf_len;
		int ret;

		while (!(buf_len = pa_stream_writable_size (p->stream))) {
			pa_threaded_mainloop_wait (p->mainloop);
			if (!check_pulse_health (p, rerror))
				goto unlock_and_fail;
		}

		if (buf_len == (size_t)-1) {
			if (rerror)
				*rerror = pa_context_errno ((p)->context);
			goto unlock_and_fail;
		}
		if (buf_len > length)
			buf_len = length;

		ret = pa_stream_write (p->stream, data, buf_len, NULL, 0, PA_SEEK_RELATIVE);
		if (ret < 0) {
			if (rerror)
				*rerror = pa_context_errno ((p)->context);
			goto unlock_and_fail;
		}

		data += buf_len;
		length -= buf_len;
	}

	pa_threaded_mainloop_unlock (p->mainloop);
	return TRUE;

 unlock_and_fail:
	pa_threaded_mainloop_unlock (p->mainloop);
	return FALSE;
}
Example #2
0
static void
gst_pulsesrc_reset (GstAudioSrc * asrc)
{
  GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
  pa_operation *o = NULL;

  pa_threaded_mainloop_lock (pulsesrc->mainloop);
  GST_DEBUG_OBJECT (pulsesrc, "reset");

  if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
    goto unlock_and_fail;

  if (!(o =
          pa_stream_flush (pulsesrc->stream, gst_pulsesrc_success_cb,
              pulsesrc))) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
        ("pa_stream_flush() failed: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }

  pulsesrc->paused = TRUE;
  /* Inform anyone waiting in _write() call that it shall wakeup */
  if (pulsesrc->in_read) {
    pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
  }

  pulsesrc->operation_success = FALSE;
  while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {

    if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
      goto unlock_and_fail;

    pa_threaded_mainloop_wait (pulsesrc->mainloop);
  }

  if (!pulsesrc->operation_success) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Flush failed: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }

unlock_and_fail:

  if (o) {
    pa_operation_cancel (o);
    pa_operation_unref (o);
  }

  pa_threaded_mainloop_unlock (pulsesrc->mainloop);
}
Example #3
0
static int
rdpsnd_pulse_connect(rdpsndDevicePlugin * devplugin)
{
	struct pulse_device_data * pulse_data;
	pa_context_state_t state;

	pulse_data = (struct pulse_device_data *) devplugin->device_data;
	if (!pulse_data->context)
		return 1;

	if (pa_context_connect(pulse_data->context, NULL, 0, NULL))
	{
		LLOGLN(0, ("rdpsnd_pulse_connect: pa_context_connect failed (%d)",
			pa_context_errno(pulse_data->context)));
		return 1;
	}
	pa_threaded_mainloop_lock(pulse_data->mainloop);
	if (pa_threaded_mainloop_start(pulse_data->mainloop) < 0)
	{
		pa_threaded_mainloop_unlock(pulse_data->mainloop);
		LLOGLN(0, ("rdpsnd_pulse_connect: pa_threaded_mainloop_start failed (%d)",
			pa_context_errno(pulse_data->context)));
		return 1;
	}
	for (;;)
	{
		state = pa_context_get_state(pulse_data->context);
		if (state == PA_CONTEXT_READY)
			break;
        if (!PA_CONTEXT_IS_GOOD(state))
		{
			LLOGLN(0, ("rdpsnd_pulse_connect: bad context state (%d)",
				pa_context_errno(pulse_data->context)));
			break;
		}
		pa_threaded_mainloop_wait(pulse_data->mainloop);
	}
	pa_threaded_mainloop_unlock(pulse_data->mainloop);
	if (state == PA_CONTEXT_READY)
	{
		LLOGLN(0, ("rdpsnd_pulse_connect: connected"));
		return 0;
	}
	else
	{
		pa_context_disconnect(pulse_data->context);
		return 1;
	}
}
Example #4
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;
}
Example #5
0
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;
      }
Example #6
0
static void
gst_pulsemixer_ctrl_timeout_event (pa_mainloop_api * a, pa_time_event * e,
    const struct timeval *tv, void *userdata)
{
  pa_operation *o;
  GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);

  if (c->update_volume) {
    if (c->type == GST_PULSEMIXER_SINK)
      o = pa_context_set_sink_volume_by_index (c->context, c->index, &c->volume,
          NULL, NULL);
    else
      o = pa_context_set_source_volume_by_index (c->context, c->index,
          &c->volume, NULL, NULL);

    if (!o)
      GST_WARNING_OBJECT (c->object, "Failed to set device volume: %s",
          pa_strerror (pa_context_errno (c->context)));
    else
      pa_operation_unref (o);

    c->update_volume = FALSE;
  }

  if (c->update_mute) {
    if (c->type == GST_PULSEMIXER_SINK)
      o = pa_context_set_sink_mute_by_index (c->context, c->index, !!c->muted,
          NULL, NULL);
    else
      o = pa_context_set_source_mute_by_index (c->context, c->index, !!c->muted,
          NULL, NULL);

    if (!o)
      GST_WARNING_OBJECT (c->object, "Failed to set device mute: %s",
          pa_strerror (pa_context_errno (c->context)));
    else
      pa_operation_unref (o);

    c->update_mute = FALSE;
  }

  /* Make sure that all outstanding queries are being ignored */
  c->ignore_queries = c->outstandig_queries;

  g_assert (e == c->time_event);
  a->time_free (e);
  c->time_event = NULL;
}
Example #7
0
bool
pulse_output_set_volume(struct pulse_output *po,
			const struct pa_cvolume *volume, GError **error_r)
{
	pa_operation *o;

	if (po->context == NULL || po->stream == NULL ||
	    pa_stream_get_state(po->stream) != PA_STREAM_READY) {
		g_set_error(error_r, pulse_output_quark(), 0, "disconnected");
		return false;
	}

	o = pa_context_set_sink_input_volume(po->context,
					     pa_stream_get_index(po->stream),
					     volume, NULL, NULL);
	if (o == NULL) {
		g_set_error(error_r, pulse_output_quark(), 0,
			    "failed to set PulseAudio volume: %s",
			    pa_strerror(pa_context_errno(po->context)));
		return false;
	}

	pa_operation_unref(o);
	return true;
}
void PulseAudioPlayer::Stop()
{
	if (!is_playing) return;
	//printf("Stopping PulseAudio\n");

	is_playing = false;

	start_frame = 0;
	cur_frame = 0;
	end_frame = 0;

	// Flush the stream of data
	//printf("Flushing stream\n");
	pa_threaded_mainloop_lock(mainloop);
	pa_operation *op = pa_stream_flush(stream, (pa_stream_success_cb_t)pa_stream_success, this);
	pa_threaded_mainloop_unlock(mainloop);
	stream_success.Wait();
	pa_operation_unref(op);
	if (!stream_success_val) {
		paerror = pa_context_errno(context);
		printf("PulseAudio player: Error flushing stream: %s (%d)\n", pa_strerror(paerror), paerror);
	}

	// And unref it
	//printf("Stopped stream\n\n");
}
Example #9
0
static ALCuint pulse_available_samples(ALCdevice *device) //{{{
{
    pulse_data *data = device->ExtraData;
    size_t samples;

    pa_threaded_mainloop_lock(data->loop);
    /* Capture is done in fragment-sized chunks, so we loop until we get all
     * that's available */
    samples = (device->Connected ? pa_stream_readable_size(data->stream) : 0);
    while(samples > 0)
    {
        const void *buf;
        size_t length;

        if(pa_stream_peek(data->stream, &buf, &length) < 0)
        {
            ERR("pa_stream_peek() failed: %s\n",
                pa_strerror(pa_context_errno(data->context)));
            break;
        }

        WriteRingBuffer(data->ring, buf, length/data->frame_size);
        samples -= length;

        pa_stream_drop(data->stream);
    }
    pa_threaded_mainloop_unlock(data->loop);

    return RingBufferSize(data->ring);
} //}}}
Example #10
0
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;
    }
}
Example #11
0
/* Write some data to the stream */
static void do_stream_write(size_t length) {
    size_t l;
    pa_assert(length);

    if (!buffer || !buffer_length)
        return;

    l = length;
    if (l > buffer_length)
        l = buffer_length;

    if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) {
        pa_log(_("pa_stream_write() failed: %s"), pa_strerror(pa_context_errno(context)));
        quit(1);
        return;
    }

    buffer_length -= l;
    buffer_index += l;

    if (!buffer_length) {
        pa_xfree(buffer);
        buffer = NULL;
        buffer_index = buffer_length = 0;
    }
}
Example #12
0
/* 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 );
    }
}
Example #13
0
/**
 * Check if the stream is (already) connected, and waits if not.  The
 * mainloop must be locked before calling this function.
 *
 * @return true on success, false on error
 */
static bool
pulse_output_wait_stream(struct pulse_output *po, GError **error_r)
{
	pa_stream_state_t state = pa_stream_get_state(po->stream);

	switch (state) {
	case PA_STREAM_READY:
		return true;

	case PA_STREAM_FAILED:
	case PA_STREAM_TERMINATED:
	case PA_STREAM_UNCONNECTED:
		g_set_error(error_r, pulse_output_quark(), 0,
			    "disconnected");
		return false;

	case PA_STREAM_CREATING:
		break;
	}

	do {
		state = pulse_output_check_stream(po);
	} while (state == PA_STREAM_CREATING);

	if (state != PA_STREAM_READY) {
		g_set_error(error_r, pulse_output_quark(), 0,
			    "failed to connect the stream: %s",
			    pa_strerror(pa_context_errno(po->context)));
		return false;
	}

	return true;
}
Example #14
0
/**
 * This function does the context initialization.
 */
static gboolean
xvd_connect_to_pulse (XvdInstance *i)
{
  pa_context_flags_t flags = PA_CONTEXT_NOFAIL;

  if (i->pulse_context)
    {
      pa_context_unref (i->pulse_context);
      i->pulse_context = NULL;
    }

  i->pulse_context = pa_context_new (pa_glib_mainloop_get_api (i->pa_main_loop),
                                     XVD_APPNAME);
  g_assert(i->pulse_context);
  pa_context_set_state_callback (i->pulse_context,
                                 xvd_context_state_callback,
                                 i);

  if (pa_context_connect (i->pulse_context,
                          NULL,
                          flags,
                          NULL) < 0)
    {
      g_warning ("xvd_connect_to_pulse: failed to connect context: %s",
                 pa_strerror (pa_context_errno (i->pulse_context)));
      return FALSE;
    }
  return TRUE;
}
Example #15
0
static void pulse_write(void* ptr, int length) {
    int writeoffs, remain, writable;

    CHECK_CONNECTED();

    pa_threaded_mainloop_lock(mainloop);
    CHECK_DEAD_GOTO(fail, 1);

    /* break large fragments into smaller fragments. --nenolod */
    for (writeoffs = 0, remain = length;
         writeoffs < length;
         writeoffs += writable, remain -= writable)
    {
         void * pptr = (char *) ptr + writeoffs;

         writable = length - writeoffs;
         size_t fragsize = pa_stream_writable_size(stream);

         /* don't write more than what PA is willing to handle right now. */
         if (writable > fragsize)
             writable = fragsize;

         if (pa_stream_write(stream, pptr, writable, NULL, PA_SEEK_RELATIVE, 0) < 0) {
             AUDDBG("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context)));
             goto fail;
         }
    }

    do_trigger = 0;
    written += length;

fail:
    pa_threaded_mainloop_unlock(mainloop);
}
int AudioOutputPulseAudio::GetBufferedOnSoundcard(void) const
{
    pa_usec_t latency = 0;
    size_t buffered = 0;

    if (!pcontext || pa_context_get_state(pcontext) != PA_CONTEXT_READY)
        return 0;

    if (!pstream || pa_stream_get_state(pstream) != PA_STREAM_READY)
        return 0;

    const pa_buffer_attr *buf_attr =  pa_stream_get_buffer_attr(pstream);
    size_t bfree = pa_stream_writable_size(pstream);
    buffered = buf_attr->tlength - bfree;

    pa_threaded_mainloop_lock(mainloop);

    while (pa_stream_get_latency(pstream, &latency, NULL) < 0)
    {
        if (pa_context_errno(pcontext) != PA_ERR_NODATA)
        {
            latency = 0;
            break;
        }
        pa_threaded_mainloop_wait(mainloop);
    }

    pa_threaded_mainloop_unlock(mainloop);

    return ((uint64_t)latency * samplerate *
            output_bytes_per_frame / 1000000) + buffered;
}
Example #17
0
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;
    }
}
Example #18
0
static void
gst_pulsemixer_ctrl_subscribe_cb (pa_context * context,
    pa_subscription_event_type_t t, uint32_t idx, void *userdata)
{
  GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);
  pa_operation *o = NULL;

  /* Called from the background thread! */

  if (c->index != idx)
    return;

  if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
    return;

  if (c->type == GST_PULSEMIXER_SINK)
    o = pa_context_get_sink_info_by_index (c->context, c->index,
        gst_pulsemixer_ctrl_sink_info_cb, c);
  else
    o = pa_context_get_source_info_by_index (c->context, c->index,
        gst_pulsemixer_ctrl_source_info_cb, c);

  if (!o) {
    GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
        pa_strerror (pa_context_errno (c->context)));
    return;
  }

  pa_operation_unref (o);

  c->outstandig_queries++;
}
Example #19
0
/**
 * 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;
}
Example #20
0
pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
    pa_usec_t t;
    int negative;

    pa_assert(p);

    pa_threaded_mainloop_lock(p->mainloop);

    for (;;) {
        CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);

        if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
            break;

        CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);

        /* Wait until latency data is available again */
        pa_threaded_mainloop_wait(p->mainloop);
    }

    pa_threaded_mainloop_unlock(p->mainloop);

    return negative ? 0 : t;

unlock_and_fail:

    pa_threaded_mainloop_unlock(p->mainloop);
    return (pa_usec_t) -1;
}
Example #21
0
static void
pulse_output_close(struct audio_output *ao)
{
	struct pulse_output *po = (struct pulse_output *)ao;
	pa_operation *o;

	assert(po->mainloop != NULL);

	pa_threaded_mainloop_lock(po->mainloop);

	if (pa_stream_get_state(po->stream) == PA_STREAM_READY) {
		o = pa_stream_drain(po->stream,
				    pulse_output_stream_success_cb, po);
		if (o == NULL) {
			g_warning("pa_stream_drain() has failed: %s",
				  pa_strerror(pa_context_errno(po->context)));
		} else
			pulse_wait_for_operation(po->mainloop, o);
	}

	pulse_output_delete_stream(po);

	if (po->context != NULL &&
	    pa_context_get_state(po->context) != PA_CONTEXT_READY)
		pulse_output_delete_context(po);

	pa_threaded_mainloop_unlock(po->mainloop);
}
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;
    }
}
Example #23
0
static void
pulse_output_cancel(struct audio_output *ao)
{
	struct pulse_output *po = (struct pulse_output *)ao;
	pa_operation *o;

	assert(po->mainloop != NULL);
	assert(po->stream != NULL);

	pa_threaded_mainloop_lock(po->mainloop);

	if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {
		/* no need to flush when the stream isn't connected
		   yet */
		pa_threaded_mainloop_unlock(po->mainloop);
		return;
	}

	assert(po->context != NULL);

	o = pa_stream_flush(po->stream, pulse_output_stream_success_cb, po);
	if (o == NULL) {
		g_warning("pa_stream_flush() has failed: %s",
			  pa_strerror(pa_context_errno(po->context)));
		pa_threaded_mainloop_unlock(po->mainloop);
		return;
	}

	pulse_wait_for_operation(po->mainloop, o);
	pa_threaded_mainloop_unlock(po->mainloop);
}
/*
 * Stream state callbacks
 *
 * A 'stream' represents a data path between the client and server.
 * Sample streams include a playback stream, a recording stream, or
 * a file upload stream.
 *
 * A single client-server connection ('context') can have multiple
 * streams. Each stream can have its own latency and time fragment
 * requirements through PulseAudio buffer attributes. A stream can
 * be moved to a different sink during its lifetime.
 */
static void stream_state_callback(pa_stream *stream, void *userdata) {
    struct context *ctx = userdata;

    assert(ctx);
    assert(ctx->context);

    switch (pa_stream_get_state(stream)) {
    case PA_STREAM_CREATING:
    case PA_STREAM_TERMINATED:
        break;

    case PA_STREAM_READY:
        out("Playback stream succesfully created");
        break;

    case PA_STREAM_FAILED:
    default:
        error("Playback stream error: %s",
              pa_strerror(pa_context_errno(ctx->context)));
        goto fail;
    }

    return;

fail:
    quit(ctx, EXIT_FAILURE);
}
Example #25
0
int xmms_pulse_backend_get_latency (xmms_pulse *p, int *rerror)
{
	pa_usec_t t;
	int negative, r;
	assert (p);

	pa_threaded_mainloop_lock (p->mainloop);

	while (1) {
		if (!check_pulse_health (p, rerror))
			goto unlock_and_fail;

		if (pa_stream_get_latency (p->stream, &t, &negative) >= 0)
			break;

		r = pa_context_errno (p->context);
		if (r != PA_ERR_NODATA) {
			if (rerror)
				*rerror = r;
			goto unlock_and_fail;
		}
		/* Wait until latency data is available again */
		pa_threaded_mainloop_wait (p->mainloop);
	}

	pa_threaded_mainloop_unlock (p->mainloop);

	return negative ? 0 : t;

 unlock_and_fail:
	pa_threaded_mainloop_unlock (p->mainloop);
	return -1;
}
Example #26
0
void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)
{
    QString fn_log_tag = "SetVolumeChannel, ";

    if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)
    {
        VBERROR(fn_log_tag + QString("bad volume params, channel %1, volume %2")
                .arg(channel).arg(volume));
        return;
    }

    volume_control.values[channel] =
        (float)volume / 100.0f * (float)PA_VOLUME_NORM;

    volume = min(100, volume);
    volume = max(0, volume);

    uint32_t sink_index = pa_stream_get_device_index(pstream);
    pa_threaded_mainloop_lock(mainloop);
    pa_operation *op =
        pa_context_set_sink_volume_by_index(pcontext, sink_index,
                                            &volume_control,
                                            OpCompletionCallback, this);
    pa_threaded_mainloop_unlock(mainloop);
    if (op)
        pa_operation_unref(op);
    else
        VBERROR(fn_log_tag +
                QString("set sink volume operation failed, sink %1, error %2 ")
                .arg(sink_index).arg(pa_strerror(pa_context_errno(pcontext))));
}
Example #27
0
static void on_pulse_context_state_change(pa_context *pa_context, AudioListContext *context)
{
    gint error;
    error = pa_context_errno(pa_context);
    if (error) {
        g_warning("PulseAudio: error: %s", pa_strerror(error));
    }
    switch (pa_context_get_state(pa_context)) {
    case PA_CONTEXT_READY:
        pa_context_get_source_info_list(pa_context, (pa_source_info_cb_t) source_info_iterator, context);
        break;
    case PA_CONTEXT_FAILED:
        g_warning("PulseAudio: failed to connect to daemon");
        finish_pa_list(context);
        break;
    case PA_CONTEXT_TERMINATED:
        break;
    case PA_CONTEXT_UNCONNECTED:
        break;
    case PA_CONTEXT_CONNECTING:
        break;
    case PA_CONTEXT_AUTHORIZING:
        break;
    case PA_CONTEXT_SETTING_NAME:
        break;
    default:
        break;
    }
}
Example #28
0
static void simple_callback(pa_context *c, int success, void *userdata)
{
	if (!success) {
		fprintf(stderr, "Failure: %s\n",
			pa_strerror(pa_context_errno(c)));
	}
}
void RageSoundDriver_PulseAudio::CtxStateCb(pa_context *c)
{
	switch (pa_context_get_state(m_PulseCtx))
	{
	case PA_CONTEXT_CONNECTING:
		LOG->Trace("Pulse: Context connecting...");
		break;
	case PA_CONTEXT_AUTHORIZING:
		LOG->Trace("Pulse: Context authorizing...");
		break;
	case PA_CONTEXT_SETTING_NAME:
		LOG->Trace("Pulse: Context setting name...");
		break;
	case PA_CONTEXT_READY:
		LOG->Trace("Pulse: Context ready now.");
		m_InitStream();
		break;
	case PA_CONTEXT_TERMINATED:
	case PA_CONTEXT_FAILED:
		if(asprintf(&m_Error, "context connection failed: %s", pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
		{
			m_Error = nullptr;
		}
		m_Sem.Post();
		return;
		break;
	}
}
static void pulse_write_preprocess(MSFilter *f){
	PulseWriteState *s=(PulseWriteState*)f->data;
	int err;
	pa_sample_spec pss;
	pa_buffer_attr attr;

	if (context==NULL) return;
	
	pss.format=PA_SAMPLE_S16LE;
	pss.channels=s->channels;
	pss.rate=s->rate;

	s->fragsize=latency_req*(float)s->channels*(float)s->rate*2;
	
	attr.maxlength=-1;
	attr.tlength=s->fragsize;
	attr.prebuf=-1;
	attr.minreq=-1;
	attr.fragsize=-1;
	
	s->stream=pa_stream_new(context,"phone",&pss,NULL);
	if (s->stream==NULL){
		ms_error("pa_stream_new() failed: %s",pa_strerror(pa_context_errno(context)));
		return;
	}
	pa_threaded_mainloop_lock(pa_loop);
	err=pa_stream_connect_playback(s->stream,NULL,&attr, PA_STREAM_ADJUST_LATENCY,NULL,NULL);
	pa_threaded_mainloop_unlock(pa_loop);
	if (err!=0){
		ms_error("pa_stream_connect_playback() failed");
	}
}