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(); }
/* 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]); }); } }
void OpenSLLayer::init() { initAudioEngine(); initAudioPlayback(); initAudioCapture(); flushMain(); flushUrgent(); }
void OpenSLLayer::stopStream() { if (not isStarted_) return; DEBUG("Stop OpenSL audio layer"); stopAudioPlayback(); stopAudioCapture(); isStarted_ = false; flushMain(); flushUrgent(); }
void AlsaLayer::stopStream() { isStarted_ = false; delete audioThread_; audioThread_ = NULL; closeCaptureStream(); closePlaybackStream(); playbackHandle_ = NULL; captureHandle_ = NULL; ringtoneHandle_ = NULL; /* Flush the ring buffers */ flushUrgent(); flushMain(); }
/** * 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(); }
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(); }