38 , indexIn_(
pref.getAlsaCardin())
39 , indexOut_(
pref.getAlsaCardout())
40 , indexRing_(
pref.getAlsaCardRingtone())
41 , audioPlugin_(
pref.getAlsaPlugin())
54 closePlaybackStream();
55 closeRingtoneStream();
85 static const int MAX_RETRIES = 10;
93 std::this_thread::sleep_for(std::chrono::milliseconds(100));
98 JAMI_ERR(
"Alsa: Unable to open %s device %s : %s",
107 if (!alsa_set_params(*
pcm, format)) {
125 is_playback_open_ = openDevice(&playbackHandle_,
129 if (
not is_playback_open_)
133 startPlaybackStream();
137 if (!openDevice(&ringtoneHandle_,
145 is_capture_open_ = openDevice(&captureHandle_,
150 if (
not is_capture_open_)
152 prepareCaptureStream();
153 startCaptureStream();
167 closeCaptureStream();
171 closePlaybackStream();
177 closeRingtoneStream();
180 if (is_capture_open_
or is_playback_open_
or ringtoneHandle_) {
188AlsaLayer::startThread()
195AlsaLayer::stopThread()
198 if (audioThread_.joinable())
210#define ALSA_CALL(call, error) \
212 int err_code = call; \
214 JAMI_ERR(error ": %s", snd_strerror(err_code)); \
219AlsaLayer::stopCaptureStream()
222 is_capture_running_ =
false;
223 is_capture_prepared_ =
false;
228AlsaLayer::closeCaptureStream()
230 if (is_capture_prepared_
and is_capture_running_)
233 JAMI_DBG(
"Alsa: Closing capture stream");
235 is_capture_open_ =
false;
236 captureHandle_ =
nullptr;
241AlsaLayer::startCaptureStream()
243 if (captureHandle_
and not is_capture_running_)
245 is_capture_running_ =
true;
249AlsaLayer::stopPlaybackStream()
251 if (playbackHandle_
and is_playback_running_) {
253 is_playback_running_ =
false;
259AlsaLayer::closePlaybackStream()
261 if (is_playback_running_)
262 stopPlaybackStream();
264 if (is_playback_open_) {
265 JAMI_DBG(
"Alsa: Closing playback stream");
267 is_playback_open_ =
false;
268 playbackHandle_ =
nullptr;
273AlsaLayer::closeRingtoneStream()
275 if (ringtoneHandle_) {
278 ringtoneHandle_ =
nullptr;
283AlsaLayer::startPlaybackStream()
285 is_playback_running_ =
true;
289AlsaLayer::prepareCaptureStream()
291 if (is_capture_open_
and not is_capture_prepared_)
293 is_capture_prepared_ =
true;
299#define TRY(call, error) \
301 if (ALSA_CALL(call, error) < 0) \
321#define HW pcm_handle, hwparams
340 JAMI_WARN(
"Unable to query hardware channel number, defaulting to 2");
345 if (format.nb_channels == 0)
346 format.nb_channels = 2;
374 JAMI_ERR(
"buffer to small, unable to use");
387#define SW pcm_handle, swparams
420 stopPlaybackStream();
421 startPlaybackStream();
425 "XRUN handling failed");
435 JAMI_ERR(
"Writing in state SND_PCM_STATE_SETUP, should be "
436 "SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING");
441 stopPlaybackStream();
451 stopPlaybackStream();
456std::unique_ptr<AudioFrame>
457AlsaLayer::read(
unsigned frames)
460 prepareCaptureStream();
461 startCaptureStream();
468 ret->pointer()->nb_samples =
err;
482 prepareCaptureStream();
483 startCaptureStream();
492 prepareCaptureStream();
493 startCaptureStream();
526static std::vector<std::string>
538std::vector<std::string>
541 return getValues(getAudioDeviceIndexMap(
true));
544std::vector<std::string>
547 return getValues(getAudioDeviceIndexMap(
false));
551AlsaLayer::getAudioDeviceIndexMap(
bool getCapture)
const
567 std::string name = fmt::format(
"hw:{}",
numCard);
576 JAMI_WARN(
"Unable to get info for %s %s: %s",
577 getCapture ?
"capture device" :
"playback device",
586 description.append(
" - ");
604 std::string name = fmt::format(
"hw:{}",
card);
624 for (
const auto&
dev : devices)
625 if (
dev.second == description)
655 if (!captureHandle_
or !is_capture_running_)
671 JAMI_ERR(
"ALSA MIC : Unable to read!");
677 if (!playbackHandle_)
687 write(*
toPlay, playbackHandle_);
694 if (!ringtoneHandle_)
702 write(*
toRing, ringtoneHandle_);
#define ALSA_CALL(call, error)
#define ALSA_CAPTURE_DEVICE
#define ALSA_PLAYBACK_DEVICE
virtual int getIndexPlayback() const
Get the index of the audio card for playback.
std::string getAudioDeviceName(int index, AudioDeviceType type) const
AlsaLayer(const AudioPreference &pref)
Constructor.
std::string buildDeviceTopo(const std::string &plugin, int card)
Concatenate two strings.
int getAudioDeviceIndex(const std::string &description, AudioDeviceType type) const
An index is associated with its string description.
virtual std::vector< std::string > getCaptureDeviceList() const
Scan the sound card available on the system.
virtual std::vector< std::string > getPlaybackDeviceList() const
virtual int getIndexRingtone() const
Get the index of the audio card for ringtone (could be differnet from playback)
void run()
Reimplementation of run()
static bool soundCardIndexExists(int card, AudioDeviceType stream)
Check if the given index corresponds to an existing sound card and supports the specified streaming m...
virtual void stopStream(AudioDeviceType stream=AudioDeviceType::ALL)
Stop the playback and capture streams.
virtual void startStream(AudioDeviceType stream)
Start the capture stream and prepare the playback stream.
std::mutex mutex_
Lock for the entire audio layer.
std::atomic< Status > status_
Whether or not the audio layer's playback stream is started.
void playbackChanged(bool started)
void setHasNativeNS(bool hasNS)
void hardwareFormatAvailable(AudioFormat playback, size_t bufSize=0)
Callback to be called by derived classes when the audio output is opened.
std::shared_ptr< AudioFrame > getToRing(AudioFormat format, size_t writableSamples)
void flushUrgent()
Flush urgent buffer.
void setHasNativeAEC(bool hasEAC)
std::shared_ptr< AudioFrame > getToPlay(AudioFormat format, size_t writableSamples)
void recordChanged(bool started)
AudioFormat audioFormat_
Sample Rate that should be sent to the sound card.
void flushMain()
Flush main buffer.
AudioFormat audioInputFormat_
Sample Rate for input.
void putRecorded(std::shared_ptr< AudioFrame > &&frame)
AudioFormat getFormat() const
Get the audio format of the layer (sample rate & channel number).
static constexpr std::string_view toString(AuthDecodingState state)
void emitSignal(Args... args)
static bool safeUpdate(snd_pcm_t *handle, long &samples)
libjami::AudioFrame AudioFrame
static std::vector< std::string > getValues(const std::vector< HwIDPair > &deviceMap)
Simple macro to hide class' copy constructor and assignment operator.