Implemented volume control for jukebox
This commit is contained in:
@@ -238,6 +238,15 @@ namespace lms::audio::alsa
|
||||
return ::snd_pcm_state(_pcm.get()) == SND_PCM_STATE_PAUSED;
|
||||
}
|
||||
|
||||
void AudioOutputStream::setVolume(float)
|
||||
{
|
||||
}
|
||||
|
||||
float AudioOutputStream::getVolume() const
|
||||
{
|
||||
return 1.F;
|
||||
}
|
||||
|
||||
std::chrono::microseconds AudioOutputStream::getPlaybackTime() const
|
||||
{
|
||||
::snd_pcm_sframes_t delayFrames{};
|
||||
|
||||
@@ -52,15 +52,18 @@ namespace lms::audio::alsa
|
||||
void asyncWrite(std::span<const std::byte> buffer, WriteCompletionCallback cb) override;
|
||||
void asyncDrain(DrainCompletionCallback cb) override;
|
||||
|
||||
void pause() override;
|
||||
void resume() override;
|
||||
bool isPaused() const override;
|
||||
|
||||
std::chrono::microseconds getPlaybackTime() const override;
|
||||
std::chrono::microseconds getLatency() const override;
|
||||
|
||||
void flush() override;
|
||||
|
||||
void pause() override;
|
||||
void resume() override;
|
||||
bool isPaused() const override;
|
||||
|
||||
void setVolume(float volume) override;
|
||||
float getVolume() const override;
|
||||
|
||||
void stop();
|
||||
void setupAllDescriptors();
|
||||
void releaseAllDescriptors();
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
|
||||
#include "AudioOutputStream.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <pulse/context.h>
|
||||
#include <pulse/def.h>
|
||||
#include <pulse/error.h>
|
||||
#include <pulse/introspect.h>
|
||||
#include <pulse/operation.h>
|
||||
#include <pulse/proplist.h>
|
||||
#include <pulse/stream.h>
|
||||
@@ -195,47 +198,6 @@ namespace lms::audio::pulseaudio
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputStream::pause()
|
||||
{
|
||||
LMS_LOG(AUDIO_OUTPUT_STREAM, DEBUG, "Pausing stream");
|
||||
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
pa_operation* op{ ::pa_stream_cork(_stream.get(), 1, nullptr, nullptr) };
|
||||
if (!op)
|
||||
throw PaException("pa_stream_cork (pause) failed", pa_context_errno(_context));
|
||||
|
||||
::pa_operation_unref(op);
|
||||
}
|
||||
|
||||
void AudioOutputStream::resume()
|
||||
{
|
||||
LMS_LOG(AUDIO_OUTPUT_STREAM, DEBUG, "Resuming stream");
|
||||
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
{
|
||||
pa_operation* op{ ::pa_stream_cork(_stream.get(), 0, nullptr, nullptr) };
|
||||
if (!op)
|
||||
throw PaException("pa_stream_cork (resume) failed", pa_context_errno(_context));
|
||||
::pa_operation_unref(op);
|
||||
}
|
||||
|
||||
{
|
||||
pa_operation* op{ ::pa_stream_trigger(_stream.get(), NULL, NULL) };
|
||||
if (!op)
|
||||
throw PaException("pa_stream_trigger failed", pa_context_errno(_context));
|
||||
::pa_operation_unref(op);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioOutputStream::isPaused() const
|
||||
{
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
return pa_stream_is_corked(_stream.get());
|
||||
}
|
||||
|
||||
std::chrono::microseconds AudioOutputStream::getPlaybackTime() const
|
||||
{
|
||||
pa_usec_t duration{};
|
||||
@@ -279,6 +241,78 @@ namespace lms::audio::pulseaudio
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputStream::pause()
|
||||
{
|
||||
LMS_LOG(AUDIO_OUTPUT_STREAM, DEBUG, "Pausing stream");
|
||||
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
pa_operation* op{ ::pa_stream_cork(_stream.get(), 1, nullptr, nullptr) };
|
||||
if (!op)
|
||||
throw PaException("pa_stream_cork (pause) failed", pa_context_errno(_context));
|
||||
|
||||
::pa_operation_unref(op);
|
||||
}
|
||||
|
||||
void AudioOutputStream::resume()
|
||||
{
|
||||
LMS_LOG(AUDIO_OUTPUT_STREAM, DEBUG, "Resuming stream");
|
||||
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
{
|
||||
pa_operation* op{ ::pa_stream_cork(_stream.get(), 0, nullptr, nullptr) };
|
||||
if (!op)
|
||||
throw PaException("pa_stream_cork (resume) failed", pa_context_errno(_context));
|
||||
::pa_operation_unref(op);
|
||||
}
|
||||
|
||||
{
|
||||
pa_operation* op{ ::pa_stream_trigger(_stream.get(), NULL, NULL) };
|
||||
if (!op)
|
||||
throw PaException("pa_stream_trigger failed", pa_context_errno(_context));
|
||||
::pa_operation_unref(op);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioOutputStream::isPaused() const
|
||||
{
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
return pa_stream_is_corked(_stream.get());
|
||||
}
|
||||
|
||||
void AudioOutputStream::setVolume(float volume)
|
||||
{
|
||||
MainLoopScopedLock lock{ _mainLoop };
|
||||
|
||||
if (volume < 0.F || volume > 1.F)
|
||||
throw Exception{ "Volume must be in range 0-1" };
|
||||
|
||||
const pa_volume_t paVol{ pa_sw_volume_from_linear(volume) };
|
||||
|
||||
pa_cvolume paChanVol;
|
||||
pa_cvolume_set(&paChanVol, _outputParameters.channelCount, paVol);
|
||||
|
||||
pa_operation* op{ ::pa_context_set_sink_input_volume(
|
||||
_context,
|
||||
pa_stream_get_index(_stream.get()),
|
||||
&paChanVol,
|
||||
nullptr,
|
||||
nullptr) };
|
||||
if (!op)
|
||||
throw PaException("pa_context_set_sink_input_volume failed", pa_context_errno(_context));
|
||||
|
||||
::pa_operation_unref(op);
|
||||
|
||||
_currentVolume = volume;
|
||||
}
|
||||
|
||||
float AudioOutputStream::getVolume() const
|
||||
{
|
||||
return _currentVolume;
|
||||
}
|
||||
|
||||
void AudioOutputStream::connect()
|
||||
{
|
||||
constexpr pa_stream_flags_t flags{ static_cast<pa_stream_flags_t>(
|
||||
|
||||
@@ -62,15 +62,18 @@ namespace lms::audio::pulseaudio
|
||||
void asyncWrite(std::span<const std::byte> buffer, WriteCompletionCallback cb) override;
|
||||
void asyncDrain(DrainCompletionCallback cb) override;
|
||||
|
||||
void pause() override;
|
||||
void resume() override;
|
||||
bool isPaused() const override;
|
||||
|
||||
std::chrono::microseconds getPlaybackTime() const override;
|
||||
std::chrono::microseconds getLatency() const override;
|
||||
|
||||
void flush() override;
|
||||
|
||||
void pause() override;
|
||||
void resume() override;
|
||||
bool isPaused() const override;
|
||||
|
||||
void setVolume(float volume) override;
|
||||
float getVolume() const override;
|
||||
|
||||
void connect();
|
||||
void onStateChanged();
|
||||
void onWriteRequested(std::size_t writableSize);
|
||||
@@ -83,6 +86,7 @@ namespace lms::audio::pulseaudio
|
||||
pa_threaded_mainloop* _mainLoop;
|
||||
const PcmParameters _outputParameters;
|
||||
PaStreamPtr _stream;
|
||||
float _currentVolume{ 1.F };
|
||||
|
||||
WaitReadyCallback _waitReadyCallback;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user