Пример #1
0
void
PortAudioLayer::stopStream()
{
    if (status_ != Status::Started)
        return;

    RING_DBG("Stop PortAudio Streams");

    for (int i = 0; i < Direction::End; i++) {
        auto err = Pa_StopStream(streams[i]);
        if(err != paNoError)
            this->handleError(err);

        err = Pa_CloseStream(streams[i]);
        if (err != paNoError)
            this->handleError(err);
    }

    {
        std::lock_guard<std::mutex> lock(mutex_);
        status_ = Status::Idle;
    }

    /* Flush the ring buffers */
    flushUrgent();
    flushMain();
}
Пример #2
0
/* This thread can lock, do whatever it wants, and read from/write to the jack
 * ring buffers
 * XXX: Access to shared state (i.e. member variables) should be synchronized if needed */
void
JackLayer::ringbuffer_worker()
{
    flushMain();
    flushUrgent();

    while (true) {

        std::unique_lock<std::mutex> lock(ringbuffer_thread_mutex_);

        // may have changed, we don't want to wait for a notification we won't get
        if (status_ != Status::Started)
            return;

        // FIXME this is all kinds of evil
        usleep(20000);

        capture();
        playback();

        // wait until process() signals more data
        // FIXME: this checks for spurious wakes, but the predicate
        // is rather arbitrary. We should wait until ring has/needs data
        // and jack has/needs data.
        data_ready_.wait(lock, [&] {
            // Note: lock is released while waiting, and held when woken
            // up, so this predicate is called while holding the lock
            return status_ != Status::Started
            or ringbuffer_ready_for_read(in_ringbuffers_[0]);
        });
    }
}
Пример #3
0
void
OpenSLLayer::init()
{
    initAudioEngine();
    initAudioPlayback();
    initAudioCapture();

    flushMain();
    flushUrgent();
}
Пример #4
0
void
OpenSLLayer::stopStream()
{
    if (not isStarted_)
        return;

    DEBUG("Stop OpenSL audio layer");

    stopAudioPlayback();
    stopAudioCapture();

    isStarted_ = false;

    flushMain();
    flushUrgent();
}
Пример #5
0
void
AlsaLayer::stopStream()
{
    isStarted_ = false;

    delete audioThread_;
    audioThread_ = NULL;

    closeCaptureStream();
    closePlaybackStream();

    playbackHandle_ = NULL;
    captureHandle_ = NULL;
    ringtoneHandle_ = NULL;

    /* Flush the ring buffers */
    flushUrgent();
    flushMain();
}
Пример #6
0
/**
 * Stop playback and capture.
 */
void
JackLayer::stopStream()
{
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (status_ != Status::Started)
            return;
        status_ = Status::Idle;
    }
    data_ready_.notify_one();

    if (jack_deactivate(playbackClient_) or jack_deactivate(captureClient_)) {
        RING_ERR("JACK client could not deactivate");
    }

    if (ringbuffer_thread_.joinable())
        ringbuffer_thread_.join();

    flushMain();
    flushUrgent();
}
Пример #7
0
void
PortAudioLayer::initStream()
{
    dcblocker_.reset();

    RING_DBG("Open PortAudio Output Stream");
    PaStreamParameters outputParameters;
    outputParameters.device = indexOut_;

    if (outputParameters.device == paNoDevice) {
        RING_ERR("Error: No valid output device. There will be no sound.");
    } else {
        const auto outputDeviceInfo =
            Pa_GetDeviceInfo(outputParameters.device);
        outputParameters.channelCount =
            audioFormat_.nb_channels = outputDeviceInfo->maxOutputChannels;
        outputParameters.sampleFormat = paInt16;
        outputParameters.suggestedLatency = outputDeviceInfo->defaultLowOutputLatency;
        outputParameters.hostApiSpecificStreamInfo = NULL;

        auto err = Pa_OpenStream(
            &streams[Direction::Output],
            NULL,
            &outputParameters,
            outputDeviceInfo->defaultSampleRate,
            paFramesPerBufferUnspecified,
            paNoFlag,
            &PortAudioLayer::paOutputCallback,
            this);
        if(err != paNoError)
            this->handleError(err);
    }

    RING_DBG("Open PortAudio Input Stream");
    PaStreamParameters inputParameters;
    inputParameters.device = indexIn_;
    if (inputParameters.device == paNoDevice) {
        RING_ERR("Error: No valid input device. There will be no mic.");
    } else {
        const auto inputDeviceInfo =
            Pa_GetDeviceInfo(inputParameters.device);
        inputParameters.channelCount =
            audioInputFormat_.nb_channels = inputDeviceInfo->maxInputChannels;
        inputParameters.sampleFormat = paInt16;
        inputParameters.suggestedLatency = inputDeviceInfo->defaultLowInputLatency;
        inputParameters.hostApiSpecificStreamInfo = NULL;

        auto err = Pa_OpenStream(
            &streams[Direction::Input],
            &inputParameters,
            NULL,
            inputDeviceInfo->defaultSampleRate,
            paFramesPerBufferUnspecified,
            paNoFlag,
            &PortAudioLayer::paInputCallback,
            this);
        if(err != paNoError)
            this->handleError(err);
    }

    RING_DBG("Start PortAudio Streams");
    for (int i = 0; i < Direction::End; i++) {
        auto err = Pa_StartStream(streams[i]);
        if (err != paNoError)
            this->handleError(err);
    }

    flushUrgent();
    flushMain();
}