Esempio n. 1
0
static void stream_request_cb(pa_stream *s, size_t length, void *data) {
    M6502 *mpu = (M6502 *) data;
	int max = 0;

    redraw = 0;

    pa_stream_begin_write(s, (void**) &sndbuf, &length);

   	memset(sndbuf, 128, length);

    max = length * 6250 / 539;
    if (max > 20454)
		fprintf(stderr, "Cycles = %u!\n", (unsigned int) max);

    cycles = 0;
    while (cycles < max) {
        if (trace)
            M6502_disassemble(mpu);

        cycles += M6502_run(mpu);
    }

   	pa_stream_write(s, sndbuf, length, NULL, 0, PA_SEEK_RELATIVE);

    redraw = 1;
}
Esempio n. 2
0
void PulseAudioDriver::stream_write_callback(pa_stream* stream, size_t bytes, void* udata)
{
	PulseAudioDriver* self = (PulseAudioDriver*)udata;

	void* vdata;
	pa_stream_begin_write(stream, &vdata, &bytes);
	if (!vdata) return;

	short* out = (short*)vdata;

	unsigned num_samples = bytes / 4;

	while (num_samples)
	{
		int n = std::min(self->m_buffer_size, num_samples);
		self->m_callback(n, 0);
		for (int i = 0; i < n; ++i)
		{
			*out++ = FLOAT_TO_SHORT(self->m_outL[i]);
			*out++ = FLOAT_TO_SHORT(self->m_outR[i]);
		}

		num_samples -= n;
	}

	pa_stream_write(stream, vdata, (bytes / 4) * 4, 0, 0, PA_SEEK_RELATIVE);
}
Esempio n. 3
0
/* This is called whenever new data may be written to the stream */
static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
    pa_assert(s);
    pa_assert(length > 0);

    if (raw) {
        pa_assert(!sndfile);

        if (stdio_event)
            mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT);

        if (!buffer)
            return;

        do_stream_write(length);

    } else {
        sf_count_t bytes;
        void *data;

        pa_assert(sndfile);

        for (;;) {
            size_t data_length = length;

            if (pa_stream_begin_write(s, &data, &data_length) < 0) {
                pa_log(_("pa_stream_begin_write() failed: %s"), pa_strerror(pa_context_errno(context)));
                quit(1);
                return;
            }

            if (readf_function) {
                size_t k = pa_frame_size(&sample_spec);

                if ((bytes = readf_function(sndfile, data, (sf_count_t) (data_length/k))) > 0)
                    bytes *= (sf_count_t) k;

            } else
                bytes = sf_read_raw(sndfile, data, (sf_count_t) data_length);

            if (bytes > 0)
                pa_stream_write(s, data, (size_t) bytes, NULL, 0, PA_SEEK_RELATIVE);
            else
                pa_stream_cancel_write(s);

            /* EOF? */
            if (bytes < (sf_count_t) data_length) {
                start_drain();
                break;
            }

            /* Request fulfilled */
            if ((size_t) bytes >= length)
                break;

            length -= bytes;
        }
    }
}
Esempio n. 4
0
void PulseAudio::WriteCallback(pa_stream* s, size_t length)
{
	// fetch dst buffer directly from pulseaudio, so no memcpy is needed
	void* buffer;
	m_pa_error = pa_stream_begin_write(s, &buffer, &length);

	if (!buffer || m_pa_error < 0)
		return; // error will be printed from main loop

	m_mixer->Mix((s16*) buffer, length / sizeof(s16) / CHANNEL_COUNT);
	m_pa_error = pa_stream_write(s, buffer, length, nullptr, 0, PA_SEEK_RELATIVE);
}
JNIEXPORT jint JNICALL
Java_org_jitsi_impl_neomedia_pulseaudio_PA_stream_1write
    (JNIEnv *env, jclass clazz, jlong s, jbyteArray data, jint dataOffset,
        jint dataLength, jobject freeCb, jlong offset, jint seek)
{
    pa_stream *stream = (pa_stream *) (intptr_t) s;
    jbyte *bytes = NULL;
    size_t nbytes = dataLength;
    int ret;

    pa_stream_begin_write(stream, (void **) &bytes, &nbytes);
    if (bytes && nbytes)
    {
        if (nbytes < dataLength)
            dataLength = nbytes;
        (*env)->GetByteArrayRegion(env, data, dataOffset, dataLength, bytes);
        if ((*env)->ExceptionCheck(env))
            ret = 0;
        else
        {
            pa_stream_write(
                    stream,
                    bytes,
                    (size_t) dataLength,
                    NULL,
                    (int64_t) offset,
                    (pa_seek_mode_t) seek);
            ret = dataLength;
        }
    }
    else
    {
        bytes = (*env)->GetByteArrayElements(env, data, NULL);
        if ((*env)->ExceptionCheck(env))
            ret = 0;
        else
        {
            pa_stream_write(
                    stream,
                    bytes + dataOffset,
                    (size_t) dataLength,
                    NULL,
                    (int64_t) offset,
                    (pa_seek_mode_t) seek);
            (*env)->ReleaseByteArrayElements(env, data, bytes, JNI_ABORT);
            ret = dataLength;
        }
    }
    return ret;
}
Esempio n. 6
0
static void
stream_request_callback(pa_stream * s, size_t nbytes, void * u)
{
  cubeb_stream * stm;
  void * buffer;
  size_t size;
  int r;
  long got;
  size_t towrite;
  size_t frame_size;

  stm = u;

  if (stm->shutdown)
    return;

  frame_size = pa_frame_size(&stm->sample_spec);

  assert(nbytes % frame_size == 0);

  towrite = nbytes;

  while (towrite) {
    size = towrite;
    r = pa_stream_begin_write(s, &buffer, &size);
    assert(r == 0);
    assert(size > 0);
    assert(size % frame_size == 0);

    got = stm->data_callback(stm, stm->user_ptr, buffer, size / frame_size);
    if (got < 0) {
      pa_stream_cancel_write(s);
      stm->shutdown = 1;
      return;
    }

    r = pa_stream_write(s, buffer, got * frame_size, NULL, 0, PA_SEEK_RELATIVE);
    assert(r == 0);

    if ((size_t) got < size / frame_size) {
      stm->draining = pa_stream_drain(s, stream_drain_success_callback, stm);
      stm->shutdown = 1;
      return;
    }

    towrite -= size;
  }

  assert(towrite == 0);
}
Esempio n. 7
0
static void stream_write_cb(pa_stream *p, size_t nbytes, void *userdata) {
    /* Just some silence */

    for (;;) {
        void *data;

        fail_unless((nbytes = pa_stream_writable_size(p)) != (size_t) -1);

        if (nbytes <= 0)
            break;

        fail_unless(pa_stream_begin_write(p, &data, &nbytes) == 0);
        pa_memzero(data, nbytes);
        fail_unless(pa_stream_write(p, data, nbytes, NULL, 0, PA_SEEK_RELATIVE) == 0);
    }
}
Esempio n. 8
0
static ALuint PulseProc(ALvoid *param)
{
    ALCdevice *Device = param;
    pulse_data *data = Device->ExtraData;
    ssize_t len;

    SetRTPriority();

    pa_threaded_mainloop_lock(data->loop);
    do {
        len = (Device->Connected ? pa_stream_writable_size(data->stream) : 0);
        len -= len%(Device->UpdateSize*data->frame_size);
        if(len == 0)
        {
            pa_threaded_mainloop_wait(data->loop);
            continue;
        }

        while(len > 0)
        {
            size_t newlen = len;
            void *buf;
            pa_free_cb_t free_func = NULL;

#if PA_CHECK_VERSION(0,9,16)
            if(!pa_stream_begin_write ||
               pa_stream_begin_write(data->stream, &buf, &newlen) < 0)
#endif
            {
                buf = pa_xmalloc(newlen);
                free_func = pa_xfree;
            }
            pa_threaded_mainloop_unlock(data->loop);

            aluMixData(Device, buf, newlen/data->frame_size);

            pa_threaded_mainloop_lock(data->loop);
            pa_stream_write(data->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
            len -= newlen;
        }
    } while(Device->Connected && !data->killNow);
    pa_threaded_mainloop_unlock(data->loop);

    return 0;
}
Esempio n. 9
0
static int outstream_begin_write_pa(struct SoundIoPrivate *si,
        struct SoundIoOutStreamPrivate *os, struct SoundIoChannelArea **out_areas, int *frame_count)
{
    struct SoundIoOutStream *outstream = &os->pub;
    struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
    pa_stream *stream = ospa->stream;

    ospa->write_byte_count = *frame_count * outstream->bytes_per_frame;
    if (pa_stream_begin_write(stream, (void**)&ospa->write_ptr, &ospa->write_byte_count))
        return SoundIoErrorStreaming;

    for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
        ospa->areas[ch].ptr = ospa->write_ptr + outstream->bytes_per_sample * ch;
        ospa->areas[ch].step = outstream->bytes_per_frame;
    }

    *frame_count = ospa->write_byte_count / outstream->bytes_per_frame;
    *out_areas = ospa->areas;

    return 0;
}
Esempio n. 10
0
/******************************************************************************
 * stream_write_cb()
 * This will be called by PulseAudio when we need to provide audio data
 * for playback.
 *****************************************************************************/
static void stream_write_cb(pa_stream *s, size_t n_requested_bytes,
        void *userdata) {
    _mbx_out out = (_mbx_out ) userdata;
    sample_t *data_to_write = NULL;
    size_t n_bytes_written = 0;
    assert ( out != NULL && out->stream == s);
    if ( out->trigger_shutdown ) {
        do_shutdown(out);
        return;
    }
    while ( n_bytes_written < n_requested_bytes ) {
        int r;
        size_t n_bytes_to_write = n_requested_bytes - n_bytes_written;
        r = pa_stream_begin_write(s, (void**)&data_to_write, &n_bytes_to_write);
        assert(n_bytes_to_write % (2*sizeof(sample_t)) == 0);
        if ( r < 0 ) {
            mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "Prepare writing data to the pulseaudio server"
                " failed: %s", pa_msg(out));
            pa_stream_cancel_write(s);
            return;
        }
        if ( n_bytes_to_write > 0 ) {
            int i;
            assert ( n_bytes_to_write / sizeof(sample_t) < 44100L*2*8 );
            sample_t left[44100L*2*8];
            sample_t right[44100L*2*8];
            out->cb(left, right, n_bytes_to_write / (2*sizeof(sample_t)), out->output_cb_userdata);
            for ( i=0; i<n_bytes_to_write/(2*sizeof(sample_t)); i++ ) {
                data_to_write[2*i] = left[i];
                data_to_write[2*i+1] = right[i];
            }
            pa_stream_write(s, data_to_write, n_bytes_to_write, NULL, 0,
                PA_SEEK_RELATIVE);
            n_bytes_written += n_bytes_to_write;
        }
    }
}
Esempio n. 11
0
/*! Starts up audio streaming to the host. */
void HostAudio::open()
{
	m_mainloop = pa_threaded_mainloop_new();
	if (!m_mainloop) {
		qDebug("Could not acquire PulseAudio main loop");
		return;
	}
	m_api = pa_threaded_mainloop_get_api(m_mainloop);
	m_context = pa_context_new(m_api, "emumaster");
	pa_context_set_state_callback(m_context, contextStreamCallback, this);

	if (!m_context) {
		qDebug("Could not acquire PulseAudio device context");
		return;
	}
#if defined(MEEGO_EDITION_HARMATTAN)
	if (pa_context_connect(m_context, 0, PA_CONTEXT_NOFLAGS, 0) < 0) {
#elif defined(Q_WS_MAEMO_5)
	if (pa_context_connect(m_context, 0, (pa_context_flags_t)0, 0) < 0) {
#endif
		int error = pa_context_errno(m_context);
		qDebug("Could not connect to PulseAudio server: %s", pa_strerror(error));
		return;
	}
	pa_threaded_mainloop_lock(m_mainloop);
	if (pa_threaded_mainloop_start(m_mainloop) < 0) {
		qDebug("Could not start mainloop");
		return;
	}

	waitForStreamReady();

	pa_sample_spec fmt;
	fmt.channels = 2;
	fmt.format = PA_SAMPLE_S16LE;
	fmt.rate = 44100;

	pa_buffer_attr buffer_attributes;
	buffer_attributes.tlength = pa_bytes_per_second(&fmt) / 5;
	buffer_attributes.maxlength = buffer_attributes.tlength * 3;
	buffer_attributes.minreq = buffer_attributes.tlength / 3;
	buffer_attributes.prebuf = buffer_attributes.tlength;

	m_stream = pa_stream_new(m_context, "emumaster", &fmt, 0);
	if (!m_stream) {
		int error = pa_context_errno(m_context);
		qDebug("Could not acquire new PulseAudio stream: %s", pa_strerror(error));
		return;
	}
	pa_stream_flags_t flags = (pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE);
//	pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS);
	if (pa_stream_connect_playback(m_stream, 0, &buffer_attributes, flags, 0, 0) < 0) {
		m_stream = 0;
		int error = pa_context_errno(m_context);
		qDebug("Could not connect for playback: %s", pa_strerror(error));
		return;
	}

	waitForStreamReady();

	pa_threaded_mainloop_unlock(m_mainloop);
}

/*! Stops audio streaming. */
void HostAudio::close()
{
	if (m_mainloop)
		pa_threaded_mainloop_stop(m_mainloop);
	if (m_stream) {
		pa_stream_unref(m_stream);
		m_stream = 0;
	}
	if (m_context) {
		pa_context_disconnect(m_context);
		pa_context_unref(m_context);
		m_context = 0;
	}
	if (m_mainloop) {
		pa_threaded_mainloop_free(m_mainloop);
		m_mainloop = 0;
	}
}

/*! Streams a frame of audio from emulated system to the host. */
void HostAudio::sendFrame()
{
	if (!m_stream)
		return;
	pa_threaded_mainloop_lock(m_mainloop);
	void *data;
#if defined(MEEGO_EDITION_HARMATTAN)
	size_t size = -1;
	pa_stream_begin_write(m_stream, &data, &size);
#elif defined(Q_WS_MAEMO_5)
	size_t size = 4096;
	static char buf[4096];
	data = buf;
#endif
	size = qMin(size, pa_stream_writable_size(m_stream));
	if (size)
		size = m_emu->fillAudioBuffer(reinterpret_cast<char *>(data), size);
	if (size)
		pa_stream_write(m_stream, data, size, 0, 0, PA_SEEK_RELATIVE);
#if defined(MEEGO_EDITION_HARMATTAN)
	else
		pa_stream_cancel_write(m_stream);
#endif
	pa_threaded_mainloop_unlock(m_mainloop);
}

/*! \internal */
void HostAudio::waitForStreamReady()
{
	pa_context_state_t context_state = pa_context_get_state(m_context);
	while (context_state != PA_CONTEXT_READY) {
		context_state = pa_context_get_state(m_context);
		if (!PA_CONTEXT_IS_GOOD(context_state)) {
			int error = pa_context_errno(m_context);
			qDebug("Context state is not good: %s", pa_strerror(error));
			return;
		} else if (context_state == PA_CONTEXT_READY) {
			break;
		} else {
			//qDebug("PulseAudio context state is %d", context_state);
		}
		pa_threaded_mainloop_wait(m_mainloop);
	}
}
Esempio n. 12
0
static ALuint PulseProc(ALvoid *param)
{
    ALCdevice *Device = param;
    pulse_data *data = Device->ExtraData;
    ALuint buffer_size;
    ALint update_size;
    size_t frame_size;
    ssize_t len;

    SetRTPriority();

    pa_threaded_mainloop_lock(data->loop);
    frame_size = pa_frame_size(&data->spec);
    update_size = Device->UpdateSize * frame_size;

    /* Sanitize buffer metrics, in case we actually have less than what we
     * asked for. */
    buffer_size = minu(update_size*Device->NumUpdates, data->attr.tlength);
    update_size = minu(update_size, buffer_size/2);
    do {
        len = pa_stream_writable_size(data->stream) - data->attr.tlength +
              buffer_size;
        if(len < update_size)
        {
            if(pa_stream_is_corked(data->stream) == 1)
            {
                pa_operation *o;
                o = pa_stream_cork(data->stream, 0, NULL, NULL);
                if(o) pa_operation_unref(o);
            }
            pa_threaded_mainloop_unlock(data->loop);
            Sleep(1);
            pa_threaded_mainloop_lock(data->loop);
            continue;
        }
        len -= len%update_size;

        while(len > 0)
        {
            size_t newlen = len;
            void *buf;
            pa_free_cb_t free_func = NULL;

#if PA_CHECK_VERSION(0,9,16)
            if(!pa_stream_begin_write ||
               pa_stream_begin_write(data->stream, &buf, &newlen) < 0)
#endif
            {
                buf = pa_xmalloc(newlen);
                free_func = pa_xfree;
            }
            pa_threaded_mainloop_unlock(data->loop);

            aluMixData(Device, buf, newlen/frame_size);

            pa_threaded_mainloop_lock(data->loop);
            pa_stream_write(data->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
            len -= newlen;
        }
    } while(!data->killNow && Device->Connected);
    pa_threaded_mainloop_unlock(data->loop);

    return 0;
}
Esempio n. 13
0
static int
pulseaudio_audio_deliver(audio_decoder_t *ad, int samples,
			 int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  size_t bytes;

  if(ad->ad_spdif_muxer != NULL) {
    bytes = ad->ad_spdif_frame_size;
  } else {
    bytes = samples * d->framesize;
  }

  void *buf;
  assert(d->s != NULL);

  pa_threaded_mainloop_lock(mainloop);

  int writable = pa_stream_writable_size(d->s);
  if(writable == 0) {
    d->blocked = 1;
    pa_threaded_mainloop_unlock(mainloop);
    return 1; 
  }

  pa_stream_begin_write(d->s, &buf, &bytes);
  assert(bytes > 0);

  if(ad->ad_spdif_muxer != NULL) {
    memcpy(buf, ad->ad_spdif_frame, ad->ad_spdif_frame_size);
  } else {
    int rsamples = bytes / d->framesize;
    uint8_t *data[8] = {0};
    data[0] = (uint8_t *)buf;
    assert(rsamples <= samples);
    avresample_read(ad->ad_avr, data, rsamples);
  }

  if(pts != AV_NOPTS_VALUE) {

    media_pipe_t *mp = ad->ad_mp;
    hts_mutex_lock(&mp->mp_clock_mutex);

    const pa_timing_info *ti = pa_stream_get_timing_info(d->s);
    if(ti != NULL) {
      mp->mp_audio_clock_avtime = 
	ti->timestamp.tv_sec * 1000000LL + ti->timestamp.tv_usec;

      int64_t busec = pa_bytes_to_usec(ti->write_index - ti->read_index,
				       &d->ss);

      int64_t delay = ti->sink_usec + busec + ti->transport_usec;
      mp->mp_audio_clock = pts - delay;
      mp->mp_audio_clock_epoch = epoch;
    }
    hts_mutex_unlock(&mp->mp_clock_mutex);
  }

  pa_stream_write(d->s, buf, bytes, NULL, 0LL, PA_SEEK_RELATIVE);
  ad->ad_spdif_frame_size = 0;

  pa_threaded_mainloop_unlock(mainloop);
  return 0;
}
Esempio n. 14
0
RTC::ReturnCode_t PulseAudioOutput::WriteBuffer(void)
{
  // get writable length from audio library
  simple_recast *psimple = (simple_recast *)m_simple;
  pa_threaded_mainloop_lock(psimple->mainloop);
  RTC_DEBUG(("pa_threaded_mainloop_lock()"));

  size_t len = pa_stream_writable_size(psimple->stream);
  if (len == 0) {
    RTC_DEBUG(("WriteBufer: no writable buffer."));
    pa_threaded_mainloop_unlock(psimple->mainloop);
    RTC_DEBUG(("pa_threaded_mainloop_unlock()"));
    return RTC::RTC_OK;
  }

  //  now we copy the data from component buffer to audio device buffer
  m_mutex.lock();
  RTC_DEBUG(("WriteBuffer: mutex lock"));

  RTC_DEBUG(("WriteBuffer: data buffer size: %i", m_data.size()));
  RTC_DEBUG(("WriteBuffer: device writable length: %i", len));
  
  size_t nbytes = len;
  if (nbytes > m_data.size()) nbytes = m_data.size();

  if (m_data.size() == 0) {
    if (len > m_bufferattr.tlength / 2) {
      RTC_DEBUG(("WriteBuffer: data buffer size is zero and device buffer size is low >> write zeros <<"));
      m_writezero = true;
    }
    if (m_writezero == false) {
      RTC_DEBUG(("WriteBufer: no writable data."));
      pa_threaded_mainloop_unlock(psimple->mainloop);
      RTC_DEBUG(("pa_threaded_mainloop_unlock()"));
      m_mutex.unlock();
      RTC_DEBUG(("WriteBuffer: mutex unlock"));
      return RTC::RTC_OK;
    }
  } else {
    m_writezero = false;
  }

  if (m_writezero == true)
      nbytes = len;

  if (nbytes > len)
    nbytes = len;

  // get a data buffer from the audio device
  void *data;
  RTC_DEBUG(("WriteBuffer: prepare to write %i bytes", nbytes));
  if ( pa_stream_begin_write(psimple->stream, &data, &nbytes) < 0 ) {
    RTC_WARN(("pa_stream_begin_write() failed.", nbytes));
    pa_threaded_mainloop_unlock(psimple->mainloop);
    RTC_DEBUG(("pa_threaded_mainloop_unlock()"));
    m_mutex.unlock();
    RTC_DEBUG(("WriteBuffer: mutex unlock"));
    //return RTC::RTC_ERROR;  // this sometimes happen (should retry)
    return RTC::RTC_OK;
  }

  // copy the data to the audio buffer
  RTC_DEBUG(("WriteBuffer: audio buffer dequeue start."));
  unsigned char *buff = (unsigned char *)data;
  if (m_writezero == true) {
    for (unsigned long i = 0; i < (unsigned long)nbytes; i++) {
      *buff++ = 0;
    }
  } else {
    for (unsigned long i = 0; i < (unsigned long)nbytes; i++) {
      *buff++ = m_data.front();
      m_data.pop_front();
    }
  }
  RTC_DEBUG(("WriteBuffer: audio buffer dequeue finish."));

  // set the data to the outport
  m_out_data.data.length(nbytes);  //!< set outport data length
  memcpy((void *)&(m_out_data.data[0]), data, nbytes);
  RTC_DEBUG(("WriteBuffer: audio buffer copy complete."));

  m_mutex.unlock();
  RTC_DEBUG(("WriteBuffer: mutex unlock"));

  // send the data to the audio device
  if (pa_stream_write( psimple->stream, data, nbytes, NULL, 0, PA_SEEK_RELATIVE) < 0) {
    RTC_WARN(("pa_stream_write() failed."));
    return RTC::RTC_ERROR;
  }
  pa_threaded_mainloop_unlock(psimple->mainloop);
  RTC_DEBUG(("pa_threaded_mainloop_unlock()"));

  // send the data to the outport
  setTimestamp( m_out_data );
  m_out_dataOut.write();
  RTC_DEBUG(("wrote stream data to AudioDataOut port"));

  return RTC::RTC_OK;
}