예제 #1
0
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;
  }
}
예제 #2
0
/*****************************************************************************
 * 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);
}
예제 #4
0
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;
}
예제 #5
0
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);
}
예제 #6
0
파일: pulse.c 프로젝트: Kafay/vlc
/*****************************************************************************
 * 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);
}
예제 #7
0
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);
} //}}}
예제 #8
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;
}
예제 #9
0
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;
}
예제 #10
0
파일: paaudio.c 프로젝트: juanquintela/qemu
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;
}
예제 #11
0
/* 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);
    }
}
예제 #12
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)));

      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);
}
예제 #15
0
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;
}
예제 #16
0
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;
}
예제 #17
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;
      }
예제 #18
0
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_);
}
예제 #19
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_);
}
예제 #20
0
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;
}
예제 #21
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);
}
예제 #22
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;
}
예제 #23
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;
}
예제 #24
0
/* 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);
}
예제 #25
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();
}
예제 #26
0
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;
}
예제 #28
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();
}
예제 #29
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;
    }
}
예제 #30
0
파일: te.c 프로젝트: ITikhonov/tem
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);
}