M changelog.md => changelog.md +1 -0
@@ 6,6 6,7 @@
* `[calendar]` Add notifications from database handling.
* `[cellular]``[call app]` Added DTMF tone generation
+* `[audio]` Enabled sounds priorities
### Changed
M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +6 -4
@@ 59,7 59,8 @@ namespace app
assert(callWindow != nullptr);
LOG_INFO("---------------------------------CallAborted");
- AudioServiceAPI::Stop(this);
+ AudioServiceAPI::Stop(this, routingAudioHandle);
+ AudioServiceAPI::Stop(this, callringAudioHandle);
callDelayedStopTime = utils::time::Timestamp() + delayToSwitchToPreviousApp;
callWindow->setState(gui::CallWindow::State::CALL_ENDED);
if (getState() == State::ACTIVE_FORGROUND && getCurrentWindow() != callWindow) {
@@ 80,7 81,7 @@ namespace app
gui::CallWindow *callWindow = dynamic_cast<gui::CallWindow *>(windows.find(window::name_call)->second);
assert(callWindow != nullptr);
- AudioServiceAPI::RoutingStart(this);
+ routingAudioHandle = AudioServiceAPI::RoutingStart(this);
runCallTimer();
LOG_INFO("---------------------------------CallActive");
@@ 98,7 99,8 @@ namespace app
LOG_INFO("ignoring call incoming");
}
else {
- AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::CallRingtone, ringtone_path);
+ callringAudioHandle =
+ AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::CallRingtone, ringtone_path);
runCallTimer();
std::unique_ptr<gui::SwitchData> data = std::make_unique<app::IncomingCallData>(msg->number);
// send to itself message to switch (run) call application
@@ 121,7 123,7 @@ namespace app
assert(callWindow != nullptr);
LOG_INFO("---------------------------------Ringing");
- AudioServiceAPI::RoutingStart(this);
+ routingAudioHandle = AudioServiceAPI::RoutingStart(this);
runCallTimer();
std::unique_ptr<gui::SwitchData> data = std::make_unique<app::ExecuteCallData>(msg->number);
M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +2 -0
@@ 31,6 31,8 @@ namespace app
void RingingHandler(const CellularCallMessage *const msg);
protected:
+ audio::Handle routingAudioHandle;
+ audio::Handle callringAudioHandle;
AppTimer timerCall;
utils::time::Timestamp callStartTime = 0;
utils::time::Duration callDuration;
M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +3 -3
@@ 92,9 92,9 @@ namespace app
bool ApplicationMusicPlayer::play(const std::string &fileName)
{
- auto ret = AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::Multimedia, fileName);
- if (ret != audio::RetCode::Success) {
- LOG_ERROR("play failed with %s", audio::c_str(ret));
+ auto handle = AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::Multimedia, fileName);
+ if (handle.GetLastRetCode() != audio::RetCode::Success) {
+ LOG_ERROR("play failed with %s", audio::c_str(handle.GetLastRetCode()));
return false;
}
return true;
M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +6 -4
@@ 6,8 6,7 @@
namespace audio
{
- Audio::Audio(std::function<int32_t(AudioEvents event)> asyncCallback,
- std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback)
+ Audio::Audio(AsyncCallback asyncCallback, DbCallback dbCallback)
: currentOperation(), asyncCallback(asyncCallback), dbCallback(dbCallback)
{
@@ 74,7 73,10 @@ namespace audio
return currentOperation->SetInputGain(gainToSet);
}
- audio::RetCode Audio::Start(Operation::Type op, const char *fileName, const audio::PlaybackType &playbackType)
+ audio::RetCode Audio::Start(Operation::Type op,
+ audio::Token token,
+ const char *fileName,
+ const audio::PlaybackType &playbackType)
{
auto ret = Operation::Create(op, fileName, playbackType, dbCallback);
@@ 107,7 109,7 @@ namespace audio
return RetCode::OperationCreateFailed;
}
- return currentOperation->Start(asyncCallback);
+ return currentOperation->Start(asyncCallback, token);
}
audio::RetCode Audio::Stop()
M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +4 -4
@@ 22,8 22,7 @@ namespace audio
Routing,
};
- Audio(std::function<int32_t(AudioEvents event)> asyncCallback,
- std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback);
+ Audio(AsyncCallback asyncCallback, DbCallback dbCallback);
// Events
audio::RetCode SendEvent(const Operation::Event evt, const EventData *data = nullptr);
@@ 66,6 65,7 @@ namespace audio
// Operations
audio::RetCode Start(Operation::Type op,
+ audio::Token token = audio::Token::MakeBadToken(),
const char *fileName = "",
const audio::PlaybackType &playbackType = audio::PlaybackType::None);
@@ 82,8 82,8 @@ namespace audio
State currentState = State::Idle;
std::unique_ptr<Operation> currentOperation;
- std::function<int32_t(AudioEvents event)> asyncCallback = nullptr;
- std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback = nullptr;
+ AsyncCallback asyncCallback;
+ DbCallback dbCallback;
};
} // namespace audio
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +120 -2
@@ 7,6 7,11 @@
namespace audio
{
+ class AudioMux;
+}
+
+namespace audio
+{
using Position = float;
using Volume = uint32_t;
using Gain = uint32_t;
@@ 37,7 42,17 @@ namespace audio
Notifications,
KeypadSound,
CallRingtone,
- TextMessageRingtone
+ TextMessageRingtone,
+ Last = TextMessageRingtone,
+ };
+
+ const static std::map<PlaybackType, uint8_t> PlaybackTypePriority = {
+ {PlaybackType::CallRingtone, 2},
+ {PlaybackType::TextMessageRingtone, 3},
+ {PlaybackType::Notifications, 3},
+ {PlaybackType::Multimedia, 4},
+ {PlaybackType::KeypadSound, 5},
+ {PlaybackType::None, static_cast<uint8_t>(PlaybackType::Last)},
};
[[nodiscard]] const std::string str(const PlaybackType &playbackType) noexcept;
@@ 68,13 83,116 @@ namespace audio
Failed
};
- enum class AudioEvents
+ class Token
{
+ using TokenType = int16_t;
+
+ public:
+ explicit Token(TokenType initValue = tokenUninitialized) : t(initValue)
+ {}
+
+ bool operator==(const Token &other) const noexcept
+ {
+ return other.t == t;
+ }
+
+ bool operator!=(const Token &other) const noexcept
+ {
+ return !(other.t == t);
+ }
+
+ /**
+ * Valid token is one connected with existing sequence of operations
+ * @return True if valid, false otherwise
+ */
+ bool IsValid() const
+ {
+ return t > tokenUninitialized;
+ }
+ /**
+ * Bad token cannot be used anymore
+ * @return True if token is flagged bad
+ */
+ bool IsBad() const
+ {
+ return t == tokenBad;
+ }
+ /**
+ * Uninitialized token can be used but it is not connected to any sequence of operations
+ * @return True if token is flagged uninitialized
+ */
+ bool IsUninitialized() const
+ {
+ return t == tokenUninitialized;
+ }
+ /**
+ * Helper - returns bad Token
+ * @return Unusable bad Token
+ */
+ static inline Token MakeBadToken()
+ {
+ return Token(tokenBad);
+ }
+
+ private:
+ static constexpr auto maxToken = std::numeric_limits<TokenType>::max();
+ Token IncrementToken()
+ {
+ t = (t == maxToken) ? 0 : t + 1;
+ return *this;
+ }
+
+ constexpr static TokenType tokenUninitialized = -1;
+ constexpr static TokenType tokenBad = -2;
+
+ TokenType t;
+ friend class ::audio::AudioMux;
+ };
+
+ class Handle
+ {
+ public:
+ Handle(const RetCode &retCode = RetCode::Failed, const Token &token = Token())
+ : lastRetCode(retCode), token(token)
+ {}
+ auto GetLastRetCode() -> RetCode
+ {
+ return lastRetCode;
+ }
+ auto GetToken() const -> const Token &
+ {
+ return token;
+ }
+
+ private:
+ RetCode lastRetCode;
+ Token token;
+ };
+
+ enum class PlaybackEventType
+ {
+ Empty,
EndOfFile,
FileSystemNoSpace
};
+ struct PlaybackEvent
+ {
+ PlaybackEventType event = PlaybackEventType::Empty;
+ audio::Token token = audio::Token::MakeBadToken();
+ };
+
+ typedef std::function<int32_t(PlaybackEvent e)> AsyncCallback;
+ typedef std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> DbCallback;
+
RetCode GetDeviceError(bsp::AudioDevice::RetCode retCode);
const char *c_str(RetCode retcode);
[[nodiscard]] auto GetVolumeText(const audio::Volume &volume) -> const std::string;
} // namespace audio
+
+namespace audio::notifications
+{
+ const std::vector<audio::PlaybackType> typesToMute = {audio::PlaybackType::Notifications,
+ audio::PlaybackType::CallRingtone,
+ audio::PlaybackType::TextMessageRingtone};
+} // namespace audio::notifications
A module-audio/Audio/AudioMux.cpp => module-audio/Audio/AudioMux.cpp +150 -0
@@ 0,0 1,150 @@
+
+#include "AudioMux.hpp"
+#include "Audio.hpp"
+
+namespace audio
+{
+ AudioMux::AudioMux(audio::AsyncCallback asyncClbk, audio::DbCallback dbClbk, size_t audioInputsCount)
+ {
+ audioInputsCount = audioInputsCount > 0 ? audioInputsCount : 1;
+ audioInputs.reserve(audioInputsCount);
+ for (size_t i = 0; i < audioInputsCount; i++) {
+ audioInputs.emplace_back(Input(Audio(asyncClbk, dbClbk), refToken.IncrementToken()));
+ }
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetRoutingInput(bool force)
+ {
+ if (auto input = GetInput({Audio::State::Routing})) {
+ return input;
+ }
+
+ if (force) {
+ auto *lowInput = &audioInputs.front();
+ for (auto &audioInput : audioInputs) {
+ auto lowestPrio = GetPlaybackPriority(lowInput->audio.GetCurrentOperation()->GetPlaybackType());
+ auto currentPrio = GetPlaybackPriority(audioInput.audio.GetCurrentOperation()->GetPlaybackType());
+
+ if (currentPrio > lowestPrio) {
+ lowInput = &audioInput;
+ }
+ }
+ LOG_DEBUG("Routing took over audio input.");
+ return lowInput;
+ }
+ return std::nullopt;
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetRecordingInput()
+ {
+ if (auto input = GetInput({Audio::State::Recording, Audio::State::Routing})) {
+ return input;
+ }
+ return std::nullopt;
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetPlaybackInput(const Token &token,
+ const audio::PlaybackType &playbackType)
+ {
+ // if routing or recording we cannot continue
+ if (GetInput({Audio::State::Routing, Audio::State::Recording})) {
+ return std::nullopt;
+ }
+ // try get with token
+ if (auto input = GetInput(token)) {
+ return input;
+ }
+ // try get with priority
+ if (auto input = GetInput(playbackType)) {
+ return input;
+ }
+ return std::nullopt;
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetIdleInput()
+ {
+ return GetInput({Audio::State::Idle});
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetActiveInput()
+ {
+ for (auto &audioInput : audioInputs) {
+ if (!audioInput.audio.GetCurrentOperation()) {
+ continue;
+ }
+ if (audioInput.audio.GetCurrentState() != Audio::State::Idle &&
+ audioInput.audio.GetCurrentOperation()->GetState() == audio::Operation::State::Active) {
+ return &audioInput;
+ }
+ }
+ return std::nullopt;
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetInput(const std::vector<Audio::State> &states)
+ {
+ for (auto &audioInput : audioInputs) {
+ if (std::find(states.begin(), states.end(), audioInput.audio.GetCurrentState()) != std::end(states)) {
+ return &audioInput;
+ }
+ }
+ return std::nullopt;
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetInput(const Token &token)
+ {
+ if (!token.IsValid()) {
+ return std::nullopt;
+ }
+
+ for (auto &audioInput : audioInputs) {
+ // if has token - match or reject
+ if (token == audioInput.token) {
+ return &audioInput;
+ }
+ }
+ return std::nullopt;
+ }
+
+ std::optional<AudioMux::Input *> AudioMux::GetInput(const audio::PlaybackType &playbackType)
+ {
+ std::optional<AudioMux::Input *> idleInput;
+ std::optional<AudioMux::Input *> overridableInput;
+
+ for (auto &audioInput : audioInputs) {
+ auto currentInputPrior = GetPlaybackPriority(audioInput.audio.GetCurrentOperation()->GetPlaybackType());
+
+ // check busy input
+ if (audioInput.audio.GetCurrentState() != Audio::State::Idle) {
+ // handle priorities
+ if (GetPlaybackPriority(playbackType) > currentInputPrior) {
+ return std::nullopt;
+ }
+ else if (GetPlaybackPriority(playbackType) <= currentInputPrior) {
+ overridableInput = &audioInput;
+ }
+ }
+ else {
+ idleInput = &audioInput;
+ }
+ }
+
+ return idleInput ? idleInput : overridableInput;
+ }
+
+ Token AudioMux::IncrementToken(std::optional<AudioMux::Input *> input)
+ {
+ if (input) {
+ return (*input)->token = refToken.IncrementToken();
+ }
+ return Token::MakeBadToken();
+ }
+
+ uint8_t AudioMux::GetPlaybackPriority(const audio::PlaybackType &type)
+ {
+ const auto &pmap = audio::PlaybackTypePriority;
+ if (pmap.find(type) != pmap.end()) {
+ return pmap.at(type);
+ }
+ return static_cast<uint8_t>(PlaybackType::Last);
+ }
+} // namespace audio
A module-audio/Audio/AudioMux.hpp => module-audio/Audio/AudioMux.hpp +90 -0
@@ 0,0 1,90 @@
+#pragma once
+
+#include "AudioCommon.hpp"
+#include "Audio.hpp"
+
+namespace audio
+{
+ /**
+ * Container for audio::Audio instances, handles the logic for choosing right input, but does not perform
+ * operations on those inputs
+ */
+ class AudioMux
+ {
+ public:
+ struct Input
+ {
+ Input(audio::Audio &&a, audio::Token handle) : audio(std::move(a)), token(handle)
+ {}
+ audio::Audio audio;
+ audio::Token token;
+ };
+ /**
+ * Constructs class with fixed number of managed inputs
+ * @param asyncClbk Callback for async control events from of managed audio::Audio() instances
+ * @param dbClbk Callback for async DB change events from of managed audio::Audio() instances
+ * @param audioInputsCount Number of inputs managed and internal audio::Audio() classes created
+ */
+ AudioMux(audio::AsyncCallback asyncClbk, audio::DbCallback dbClbk, size_t audioInputsCount = 1);
+ /**
+ * Gets input related to given token
+ * @param token Token to compare
+ * @return nullopt if input not found
+ */
+ auto GetInput(const Token &token) -> std::optional<Input *>;
+ /**
+ * Gets first input which is in given state
+ * @param states State to compare
+ * @return nullopt if input not found
+ */
+ auto GetInput(const std::vector<Audio::State> &states) -> std::optional<Input *>;
+ /**
+ * Gets available input respecting priority
+ * @param playbackType Playback type to compare to compare
+ * @return Idle input if found, otherwise one of inputs that can be overridden.
+ * nullopt if none of the inputs is not available (higher priority operation is active)
+ */
+ auto GetInput(const audio::PlaybackType &playbackType = audio::PlaybackType::None) -> std::optional<Input *>;
+ /**
+ * Gets first Idle input
+ * @return nullopt if input not found
+ */
+ auto GetIdleInput() -> std::optional<Input *>;
+ /**
+ * Gets first Active input
+ * @return nullopt if input not found
+ */
+ auto GetActiveInput() -> std::optional<Input *>;
+ /**
+ * Gets input for routing
+ * @param force If set upon failure returns one of busy inputs
+ * @return nullopt if input not found
+ */
+ auto GetRoutingInput(bool force = false) -> std::optional<Input *>;
+ /**
+ * Gets input for recording
+ * @return nullopt if input not found
+ */
+ auto GetRecordingInput() -> std::optional<Input *>;
+ /**
+ * Gets input for playback
+ * @param token Token to compare
+ * @param playbackType Playback type to compare
+ * @return nullopt if input not found
+ */
+ auto GetPlaybackInput(const Token &token, const audio::PlaybackType &playbackType)
+ -> std::optional<AudioMux::Input *>;
+
+ auto GetAllInputs() -> std::vector<Input> &
+ {
+ return audioInputs;
+ };
+ auto IncrementToken(std::optional<AudioMux::Input *> input) -> Token;
+
+ private:
+ auto GetPlaybackPriority(const audio::PlaybackType &type) -> uint8_t;
+ std::vector<Input> audioInputs;
+ audio::Token refToken;
+ };
+
+} // namespace audio
M module-audio/Audio/Operation/IdleOperation.hpp => module-audio/Audio/Operation/IdleOperation.hpp +1 -1
@@ 26,7 26,7 @@ namespace audio
~IdleOperation() = default;
- audio::RetCode Start([[maybe_unused]] std::function<int32_t(AudioEvents event)> callback) override final
+ audio::RetCode Start([[maybe_unused]] audio::AsyncCallback callback, audio::Token token) override final
{
return audio::RetCode::Success;
}
M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +3 -2
@@ 80,7 80,7 @@ namespace audio
const audio::PlaybackType &operations = audio::PlaybackType::None,
std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback = nullptr);
- virtual audio::RetCode Start(std::function<int32_t(AudioEvents event)> callback) = 0;
+ virtual audio::RetCode Start(audio::AsyncCallback callback, audio::Token token) = 0;
virtual audio::RetCode Stop() = 0;
@@ 125,7 125,8 @@ namespace audio
Profile *currentProfile = nullptr;
std::vector<std::unique_ptr<Profile>> availableProfiles;
State state = State::Idle;
- std::function<int32_t(AudioEvents event)> eventCallback = nullptr;
+ audio::AsyncCallback eventCallback = nullptr;
+ audio::Token operationToken;
bool isInitialized = false;
audio::PlaybackType playbackType = audio::PlaybackType::None;
M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +4 -4
@@ 36,7 36,7 @@ namespace audio
#endif
if (ret == 0) {
state = State::Idle;
- eventCallback(AudioEvents::EndOfFile); // TODO:M.P pass proper err code
+ eventCallback({PlaybackEventType::EndOfFile, audio::Token::MakeBadToken()});
}
return ret;
};
@@ 71,13 71,13 @@ namespace audio
isInitialized = true;
}
- audio::RetCode PlaybackOperation::Start(std::function<int32_t(AudioEvents event)> callback)
+ audio::RetCode PlaybackOperation::Start(audio::AsyncCallback callback, audio::Token token)
{
if (state == State::Active || state == State::Paused) {
return RetCode::InvokedInIncorrectState;
}
-
+ operationToken = token;
auto tags = dec->fetchTags();
eventCallback = callback;
@@ 194,7 194,7 @@ namespace audio
case State::Active:
state = State::Idle;
- Start(eventCallback);
+ Start(eventCallback, operationToken);
break;
}
M module-audio/Audio/Operation/PlaybackOperation.hpp => module-audio/Audio/Operation/PlaybackOperation.hpp +1 -1
@@ 22,7 22,7 @@ namespace audio
const audio::PlaybackType &playbackType,
std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback = nullptr);
- audio::RetCode Start(std::function<int32_t(AudioEvents event)> callback) override final;
+ audio::RetCode Start(audio::AsyncCallback callback, audio::Token token) override final;
audio::RetCode Stop() override final;
M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +4 -4
@@ 43,7 43,7 @@ namespace audio
#endif
if (ret == 0) {
state = State::Idle;
- eventCallback(AudioEvents::FileSystemNoSpace);
+ eventCallback({PlaybackEventType::FileSystemNoSpace, audio::Token::MakeBadToken()});
}
return ret;
};
@@ 89,13 89,13 @@ namespace audio
isInitialized = true;
}
- audio::RetCode RecorderOperation::Start(std::function<int32_t(AudioEvents event)> callback)
+ audio::RetCode RecorderOperation::Start(audio::AsyncCallback callback, audio::Token token)
{
if (state == State::Paused || state == State::Active) {
return RetCode::InvokedInIncorrectState;
}
-
+ operationToken = token;
eventCallback = callback;
state = State::Active;
@@ 186,7 186,7 @@ namespace audio
case State::Active:
state = State::Idle;
- Start(eventCallback);
+ Start(eventCallback, operationToken);
break;
}
M module-audio/Audio/Operation/RecorderOperation.hpp => module-audio/Audio/Operation/RecorderOperation.hpp +1 -1
@@ 23,7 23,7 @@ namespace audio
RecorderOperation(const char *file,
std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback);
- audio::RetCode Start(std::function<int32_t(AudioEvents event)> callback) override final;
+ audio::RetCode Start(audio::AsyncCallback callback, audio::Token token) override final;
audio::RetCode Stop() override final;
M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +3 -3
@@ 152,12 152,12 @@ namespace audio
return GetDeviceError(ret);
}
- audio::RetCode RouterOperation::Start(std::function<int32_t(audio::AudioEvents)> callback)
+ audio::RetCode RouterOperation::Start(audio::AsyncCallback callback, audio::Token token)
{
if (state == State::Paused || state == State::Active) {
return RetCode::InvokedInIncorrectState;
}
-
+ operationToken = token;
eventCallback = callback;
state = State::Active;
@@ 282,7 282,7 @@ namespace audio
case State::Active:
state = State::Idle;
- Start(eventCallback);
+ Start(eventCallback, operationToken);
break;
}
M module-audio/Audio/Operation/RouterOperation.hpp => module-audio/Audio/Operation/RouterOperation.hpp +1 -1
@@ 38,7 38,7 @@ namespace audio
~RouterOperation();
- audio::RetCode Start([[maybe_unused]] std::function<int32_t(AudioEvents event)> callback) override final;
+ audio::RetCode Start([[maybe_unused]] audio::AsyncCallback callback, audio::Token token) override final;
audio::RetCode Stop() override final;
M module-audio/CMakeLists.txt => module-audio/CMakeLists.txt +1 -0
@@ 22,6 22,7 @@ set(SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/encoder/EncoderWAV.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Audio.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioMux.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioCommon.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/Operation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/PlaybackOperation.cpp"
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +240 -103
@@ 16,30 16,12 @@ const char *ServiceAudio::serviceName = "ServiceAudio";
using namespace audio;
-
ServiceAudio::ServiceAudio()
: sys::Service(serviceName, "", 4096 * 2, sys::ServicePriority::Idle),
- audio(
- [this](AudioEvents event) -> int32_t {
- switch (event) {
- case AudioEvents::EndOfFile: {
- auto msg = std::make_shared<AudioNotificationMessage>(
- static_cast<AudioNotificationMessage::Type>(AudioNotificationMessage::Type::EndOfFile));
- sys::Bus::SendMulticast(msg, sys::BusChannels::ServiceAudioNotifications, this);
- } break;
- case AudioEvents::FileSystemNoSpace:
- break;
- }
- return 0;
- },
- [this](const std::string &path, const uint32_t &defaultValue) -> uint32_t {
- this->addOrIgnoreEntry(path, defaultValue);
- return this->fetchAudioSettingFromDb(path, defaultValue);
- })
+ audioMux([this](auto... params) { return this->AsyncCallback(params...); },
+ [this](auto... params) { return this->DbCallback(params...); })
{
-
busChannels.push_back(sys::BusChannels::ServiceAudioNotifications);
-
LOG_INFO("[ServiceAudio] Initializing");
}
@@ 58,6 40,27 @@ sys::ReturnCodes ServiceAudio::DeinitHandler()
return sys::ReturnCodes::Success;
}
+int32_t ServiceAudio::AsyncCallback(PlaybackEvent e)
+{
+ switch (e.event) {
+ case audio::PlaybackEventType::EndOfFile: {
+ auto msg = std::make_shared<AudioNotificationMessage>(
+ static_cast<AudioNotificationMessage::Type>(AudioNotificationMessage::Type::EndOfFile), e.token);
+ sys::Bus::SendMulticast(msg, sys::BusChannels::ServiceAudioNotifications, this);
+ } break;
+ case audio::PlaybackEventType::FileSystemNoSpace:
+ case audio::PlaybackEventType::Empty:
+ break;
+ }
+ return 0;
+};
+
+uint32_t ServiceAudio::DbCallback(const std::string &path, const uint32_t &defaultValue)
+{
+ this->addOrIgnoreEntry(path, defaultValue);
+ return this->fetchAudioSettingFromDb(path, defaultValue);
+};
+
sys::ReturnCodes ServiceAudio::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
{
LOG_FATAL("[ServiceAudio] PowerModeHandler: %s", c_str(mode));
@@ 67,6 70,144 @@ sys::ReturnCodes ServiceAudio::SwitchPowerModeHandler(const sys::ServicePowerMod
void ServiceAudio::TickHandler(uint32_t id)
{}
+bool ServiceAudio::IsResumable(const audio::PlaybackType &type)
+{
+ switch (type) {
+ case audio::PlaybackType::Multimedia:
+ return true;
+ case audio::PlaybackType::None:
+ case audio::PlaybackType::TextMessageRingtone:
+ case audio::PlaybackType::Notifications:
+ case audio::PlaybackType::KeypadSound:
+ case audio::PlaybackType::CallRingtone:
+ return false;
+ }
+ return false;
+}
+
+bool ServiceAudio::IsMergable(const audio::PlaybackType &type)
+{
+ switch (type) {
+ case audio::PlaybackType::KeypadSound:
+ case audio::PlaybackType::Notifications:
+ case audio::PlaybackType::TextMessageRingtone:
+ return true;
+ case audio::PlaybackType::None:
+ case audio::PlaybackType::Multimedia:
+ case audio::PlaybackType::CallRingtone:
+ return false;
+ }
+ return false;
+}
+
+std::unique_ptr<AudioResponseMessage> ServiceAudio::HandlePause(std::optional<AudioRequestMessage *> msg)
+{
+
+ audio::RetCode retCode = audio::RetCode::Failed;
+ audio::Token retToken = Token::MakeBadToken();
+
+ auto pauseInput = [this](AudioMux::Input &audioInput) {
+ if (IsResumable(audioInput.audio.GetCurrentOperation()->GetPlaybackType())) {
+ audioInput.audio.Pause();
+ return audioInput.token;
+ }
+ else {
+ audioInput.audio.Stop();
+ auto broadMsg = std::make_shared<AudioNotificationMessage>(
+ static_cast<AudioNotificationMessage::Type>(AudioNotificationMessage::Type::Stop), audioInput.token);
+ sys::Bus::SendMulticast(broadMsg, sys::BusChannels::ServiceAudioNotifications, this);
+ audioMux.IncrementToken(&audioInput);
+ return Token::MakeBadToken();
+ }
+ };
+
+ if (msg) {
+ std::optional<AudioMux::Input *> input = audioMux.GetInput((*msg)->token);
+ if (!input) {
+ retToken = pauseInput(**input);
+ }
+ }
+ else {
+ for (auto &audioInput : audioMux.GetAllInputs()) {
+ if (audioInput.audio.GetCurrentOperation()->GetState() == Operation::State::Active) {
+ pauseInput(audioInput);
+ }
+ }
+ return std::make_unique<AudioResponseMessage>(audio::RetCode::Success, Tags(), retToken);
+ }
+
+ return std::make_unique<AudioResponseMessage>(retCode, Tags(), retToken);
+}
+
+template <typename... Args>
+std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(std::optional<AudioMux::Input *> input,
+ AudioRequestMessage *msg,
+ Operation::Type opType,
+ Args... args)
+{
+ audio::RetCode retCode = audio::RetCode::Failed;
+ audio::Token retToken = Token::MakeBadToken();
+
+ if (input) {
+
+ HandlePause();
+ retToken = audioMux.IncrementToken(input);
+ retCode = (*input)->audio.Start(opType, retToken, args...);
+ }
+ if (retCode != audio::RetCode::Success) {
+ retToken = Token::MakeBadToken();
+ }
+ return std::make_unique<AudioResponseMessage>(retCode, Tags(), retToken);
+}
+
+std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStop(AudioStopMessage *msg)
+{
+ const auto playbackTypesToStop = msg->stopVec;
+ std::vector<audio::RetCode> retCodes = {audio::RetCode::Success};
+
+ auto stopInput = [this](auto inp) {
+ if (inp->audio.GetCurrentState() == Audio::State::Idle) {
+ return audio::RetCode::Success;
+ }
+ auto rCode = inp->audio.Stop();
+ // Send notification that audio file was stopped
+ auto msgStop = std::make_shared<AudioNotificationMessage>(
+ static_cast<AudioNotificationMessage::Type>(AudioNotificationMessage::Type::Stop), inp->token);
+ sys::Bus::SendMulticast(msgStop, sys::BusChannels::ServiceAudioNotifications, this);
+ audioMux.IncrementToken(inp);
+ return rCode;
+ };
+
+ // stop by token
+ if (auto tokenInput = audioMux.GetInput(msg->token)) {
+ retCodes.emplace_back(stopInput(tokenInput.value()));
+ }
+ // stop with vector of playback types
+ else if (!playbackTypesToStop.empty()) {
+ for (auto &input : audioMux.GetAllInputs()) {
+ const auto currentOperation = input.audio.GetCurrentOperation();
+ if (currentOperation && (std::find(playbackTypesToStop.begin(),
+ playbackTypesToStop.end(),
+ currentOperation->GetPlaybackType()) != playbackTypesToStop.end())) {
+ retCodes.emplace_back(stopInput(&input));
+ }
+ }
+ }
+ // stop all audio
+ else if (!msg->token.IsUninitialized()) {
+ for (auto &input : audioMux.GetAllInputs()) {
+ retCodes.emplace_back(stopInput(&input));
+ }
+ }
+
+ // on failure return first false code
+ auto it = std::find_if_not(retCodes.begin(), retCodes.end(), [](auto p) { return p == audio::RetCode::Success; });
+ if (it != retCodes.end()) {
+ return std::make_unique<AudioResponseMessage>(*it);
+ }
+ return std::make_unique<AudioResponseMessage>(audio::RetCode::Success);
+}
+
sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
{
std::shared_ptr<sys::ResponseMessage> responseMsg;
@@ 78,8 219,9 @@ sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::Re
switch (msg->type) {
case AudioNotificationMessage::Type::EndOfFile: {
- std::shared_ptr<AudioRequestMessage> msg = std::make_shared<AudioRequestMessage>(MessageType::AudioStop);
- sys::Bus::SendUnicast(msg, ServiceAudio::serviceName, this);
+ std::shared_ptr<AudioRequestMessage> newMsg =
+ std::make_shared<AudioRequestMessage>(MessageType::AudioStop, msg->token);
+ sys::Bus::SendUnicast(newMsg, ServiceAudio::serviceName, this);
} break;
case AudioNotificationMessage::Type::Stop: {
@@ 99,74 241,79 @@ sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::Re
responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success);
}
else if (auto *msg = dynamic_cast<AudioStopMessage *>(msgl)) {
- const auto currentOperation = audio.GetCurrentOperation();
- const auto stopVec = msg->stopVec;
- if (currentOperation &&
- (std::find(stopVec.begin(), stopVec.end(), currentOperation->GetPlaybackType()) == stopVec.end())) {
- responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success);
- }
- else {
- responseMsg = std::make_shared<AudioResponseMessage>(audio.Stop());
-
- // Send notification that audio file was stopped
- auto retMsg = std::make_shared<AudioNotificationMessage>(
- static_cast<AudioNotificationMessage::Type>(AudioNotificationMessage::Type::Stop));
- sys::Bus::SendMulticast(retMsg, sys::BusChannels::ServiceAudioNotifications, this);
- }
+ responseMsg = HandleStop(msg);
}
else if (auto *msg = dynamic_cast<AudioRequestMessage *>(msgl)) {
switch (msg->type) {
case MessageType::AudioPlaybackStart: {
- responseMsg = std::make_shared<AudioResponseMessage>(
- audio.Start(Operation::Type::Playback, msg->fileName.c_str(), msg->playbackType));
+ if (auto input = audioMux.GetPlaybackInput(msg->token, msg->playbackType)) {
+ responseMsg =
+ HandleStart(input, msg, Operation::Type::Playback, msg->fileName.c_str(), msg->playbackType);
+ }
} break;
case MessageType::AudioRecorderStart: {
- responseMsg =
- std::make_shared<AudioResponseMessage>(audio.Start(Operation::Type::Recorder, msg->fileName.c_str()));
+ if (auto input = audioMux.GetRecordingInput()) {
+ responseMsg = std::make_shared<AudioResponseMessage>(
+ (*input)->audio.Start(Operation::Type::Recorder, (*input)->token, msg->fileName.c_str()));
+ }
} break;
case MessageType::AudioRoutingStart: {
LOG_DEBUG("AudioRoutingStart");
- responseMsg = std::make_shared<AudioResponseMessage>(audio.Start(Operation::Type::Router));
+ if (auto input = audioMux.GetRoutingInput(true)) {
+ responseMsg = HandleStart(input, msg, Operation::Type::Router);
+ }
} break;
case MessageType::AudioPause: {
- responseMsg = std::make_shared<AudioResponseMessage>(audio.Pause());
+ responseMsg = HandlePause(msg);
} break;
case MessageType::AudioResume: {
- responseMsg = std::make_shared<AudioResponseMessage>(audio.Resume());
+ if (auto input = audioMux.GetInput(msg->token)) {
+ responseMsg = std::make_shared<AudioResponseMessage>((*input)->audio.Resume());
+ }
} break;
case MessageType::AudioGetFileTags: {
- auto tag = audio.GetFileTags(msg->fileName.c_str());
- if (tag) {
- responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success, tag.value());
- }
- else {
- responseMsg = std::make_shared<AudioResponseMessage>(RetCode::FileDoesntExist);
+ if (auto input = audioMux.GetInput()) {
+ auto tag = (*input)->audio.GetFileTags(msg->fileName.c_str());
+ if (tag) {
+ responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success, tag.value());
+ }
+ else {
+ responseMsg = std::make_shared<AudioResponseMessage>(RetCode::FileDoesntExist);
+ }
}
} break;
case MessageType::AudioRoutingRecordCtrl: {
- responseMsg = std::make_shared<AudioResponseMessage>(audio.SendEvent(
- msg->enable ? Operation::Event::StartCallRecording : Operation::Event::StopCallRecording));
+ if (auto input = audioMux.GetRecordingInput()) {
+ responseMsg = std::make_shared<AudioResponseMessage>((*input)->audio.SendEvent(
+ msg->enable ? Operation::Event::StartCallRecording : Operation::Event::StopCallRecording));
+ }
} break;
case MessageType::AudioRoutingMute: {
- responseMsg = std::make_shared<AudioResponseMessage>(
- audio.SendEvent(msg->enable ? Operation::Event::CallMute : Operation::Event::CallUnmute));
+ if (auto input = audioMux.GetRecordingInput()) {
+ responseMsg = std::make_shared<AudioResponseMessage>(
+ (*input)->audio.SendEvent(msg->enable ? Operation::Event::CallMute : Operation::Event::CallUnmute));
+ }
} break;
case MessageType::AudioRoutingSpeakerhone: {
- responseMsg = std::make_shared<AudioResponseMessage>(audio.SendEvent(
- msg->enable ? Operation::Event::CallSpeakerphoneOn : Operation::Event::CallSpeakerphoneOff));
+ if (auto input = audioMux.GetRecordingInput()) {
+ responseMsg = std::make_shared<AudioResponseMessage>((*input)->audio.SendEvent(
+ msg->enable ? Operation::Event::CallSpeakerphoneOn : Operation::Event::CallSpeakerphoneOff));
+ }
} break;
case MessageType::AudioRoutingHeadset: {
- responseMsg = std::make_shared<AudioResponseMessage>(
- audio.SendEvent(msg->enable ? Operation::Event::HeadphonesPlugin : Operation::Event::HeadphonesUnplug));
+ if (auto input = audioMux.GetRecordingInput()) {
+ responseMsg = std::make_shared<AudioResponseMessage>((*input)->audio.SendEvent(
+ msg->enable ? Operation::Event::HeadphonesPlugin : Operation::Event::HeadphonesUnplug));
+ }
} break;
default:
@@ 179,7 326,12 @@ sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::Re
LOG_DEBUG("Unhandled message");
}
- return responseMsg;
+ if (responseMsg) {
+ return responseMsg;
+ }
+ else {
+ return std::make_shared<AudioResponseMessage>(RetCode::Failed, Tags{}, Token::MakeBadToken());
+ }
}
void ServiceAudio::updateDbValue(const std::string &path, const audio::Setting &setting, const uint32_t &value)
@@ 235,20 387,19 @@ uint32_t ServiceAudio::getSetting(const audio::Setting &setting,
std::optional<uint32_t> ServiceAudio::getCurrentSetting(const audio::Setting &setting)
{
- const auto currentOperation = audio.GetCurrentOperation();
- const auto noOngoingOperation = [¤tOperation]() -> bool {
- return currentOperation == nullptr || currentOperation->GetState() == audio::Operation::State::Idle;
- };
+ const auto activeInput = audioMux.GetActiveInput();
- if (noOngoingOperation()) {
- if (setting == audio::Setting::Volume) {
- const auto path =
- audio::str(audio::PlaybackType::CallRingtone, audio::Setting::Volume, audio.GetHeadphonesInserted());
+ if (!activeInput.has_value()) {
+ const auto idleInput = audioMux.GetIdleInput();
+ if (idleInput.has_value() && setting == audio::Setting::Volume) {
+ const auto path = audio::str(
+ audio::PlaybackType::CallRingtone, audio::Setting::Volume, (*idleInput)->audio.GetHeadphonesInserted());
return fetchAudioSettingFromDb<audio::Volume>(path, 0);
}
return {};
}
+ const auto currentOperation = (*activeInput)->audio.GetCurrentOperation();
const auto path =
audio::str(currentOperation->GetProfile()->GetType(), setting, currentOperation->GetPlaybackType());
return (setting == audio::Setting::Volume) ? fetchAudioSettingFromDb<audio::Volume>(path, 0)
@@ 257,46 408,32 @@ std::optional<uint32_t> ServiceAudio::getCurrentSetting(const audio::Setting &se
void ServiceAudio::setCurrentSetting(const audio::Setting &setting, const uint32_t &value)
{
- const auto currentOperation = audio.GetCurrentOperation();
- const auto valueToSet = [&value, &setting]() -> std::optional<uint32_t> {
- switch (setting) {
- case audio::Setting::Volume: {
- return std::clamp(value, minVolume, maxVolume);
- }
- case audio::Setting::Gain: {
- return std::clamp(value, minGain, maxGain);
- }
- }
- return {};
- }();
- if (!valueToSet.has_value()) {
- return;
- }
- auto idleOperation = dynamic_cast<const IdleOperation *>(currentOperation);
-
- const auto noOngoingOperation = [¤tOperation, &idleOperation]() -> bool {
- return currentOperation == nullptr || idleOperation != nullptr ||
- currentOperation->GetState() == audio::Operation::State::Idle;
- };
+ const auto activeInput = audioMux.GetActiveInput();
- if (noOngoingOperation()) {
- if (setting == audio::Setting::Volume) {
- const auto path =
- audio::str(audio::PlaybackType::CallRingtone, audio::Setting::Volume, audio.GetHeadphonesInserted());
+ if (!activeInput.has_value()) {
+ const auto idleInput = audioMux.GetIdleInput();
+ if (idleInput.has_value() && setting == audio::Setting::Volume) {
+ const auto path = audio::str(
+ audio::PlaybackType::CallRingtone, audio::Setting::Volume, (*idleInput)->audio.GetHeadphonesInserted());
addOrIgnoreEntry(path, audio::playbackDefaults::defaultLoudspeakerVolume);
- updateDbValue(path, Setting::Volume, valueToSet.value());
+ const auto valueToSet = std::clamp(value, minVolume, maxVolume);
+ updateDbValue(path, Setting::Volume, valueToSet);
}
+ return;
}
- else {
- switch (setting) {
- case audio::Setting::Volume: {
- audio.SetOutputVolume(valueToSet.value());
- updateDbValue(currentOperation, audio::Setting::Volume, valueToSet.value());
- } break;
- case audio::Setting::Gain: {
- audio.SetInputGain(valueToSet.value());
- updateDbValue(currentOperation, audio::Setting::Gain, valueToSet.value());
- } break;
- }
+
+ auto &audio = (*activeInput)->audio;
+ const auto currentOperation = audio.GetCurrentOperation();
+ switch (setting) {
+ case audio::Setting::Volume: {
+ const auto valueToSet = std::clamp(value, minVolume, maxVolume);
+ audio.SetOutputVolume(valueToSet);
+ updateDbValue(currentOperation, audio::Setting::Volume, valueToSet);
+ } break;
+ case audio::Setting::Gain: {
+ const auto valueToSet = std::clamp(value, minGain, maxGain);
+ audio.SetInputGain(valueToSet);
+ updateDbValue(currentOperation, audio::Setting::Gain, valueToSet);
+ } break;
}
}
M module-services/service-audio/ServiceAudio.hpp => module-services/service-audio/ServiceAudio.hpp +16 -2
@@ 13,7 13,9 @@
#include "Service/Service.hpp"
#include <functional>
#include "Audio/Audio.hpp"
+#include "Audio/AudioMux.hpp"
#include "MessageType.hpp"
+#include "messages/AudioMessage.hpp"
#include <service-db/api/DBServiceAPI.hpp>
#include <queries/settings/QuerySettingsGet_v2.hpp>
@@ 45,8 47,20 @@ class ServiceAudio : public sys::Service
static const char *serviceName;
private:
- audio::Audio audio;
- std::function<uint32_t(audio::AudioEvents event)> audioCallback = nullptr;
+ audio::AudioMux audioMux;
+ auto AsyncCallback(audio::PlaybackEvent e) -> int32_t;
+ auto DbCallback(const std::string &path, const uint32_t &defaultValue) -> uint32_t;
+
+ template <typename... Args>
+ std::unique_ptr<AudioResponseMessage> HandleStart(std::optional<audio::AudioMux::Input *> input,
+ AudioRequestMessage *msg,
+ audio::Operation::Type opType,
+ Args... args);
+ std::unique_ptr<AudioResponseMessage> HandlePause(std::optional<AudioRequestMessage *> msg = std::nullopt);
+ std::unique_ptr<AudioResponseMessage> HandleStop(AudioStopMessage *msg);
+
+ auto IsResumable(const audio::PlaybackType &type) -> bool;
+ auto IsMergable(const audio::PlaybackType &type) -> bool;
template <typename T> void addOrIgnoreEntry(const std::string &profilePath, const T &defaultValue)
{
M module-services/service-audio/api/AudioServiceAPI.cpp => module-services/service-audio/api/AudioServiceAPI.cpp +22 -15
@@ 34,28 34,29 @@ namespace AudioServiceAPI
}
} // namespace
- RetCode PlaybackStart(sys::Service *serv, const audio::PlaybackType &playbackType, const std::string &fileName)
+ Handle PlaybackStart(sys::Service *serv, const audio::PlaybackType &playbackType, const std::string &fileName)
{
auto msg = std::make_shared<AudioRequestMessage>(MessageType::AudioPlaybackStart);
msg->fileName = fileName;
msg->playbackType = playbackType;
-
- return SendAudioRequest(serv, msg)->retCode;
+ auto ret = SendAudioRequest(serv, msg);
+ return Handle(ret->retCode, ret->token);
}
- RetCode RecordingStart(sys::Service *serv, const std::string &fileName)
+ Handle RecordingStart(sys::Service *serv, const std::string &fileName)
{
auto msg = std::make_shared<AudioRequestMessage>(MessageType::AudioRecorderStart);
msg->fileName = fileName;
-
- return SendAudioRequest(serv, msg)->retCode;
+ auto ret = SendAudioRequest(serv, msg);
+ return Handle(ret->retCode, ret->token);
}
- audio::RetCode RoutingStart(sys::Service *serv)
+ Handle RoutingStart(sys::Service *serv)
{
- auto msg = std::make_shared<AudioRequestMessage>(MessageType::AudioRoutingStart);
-
- return SendAudioRequest(serv, msg)->retCode;
+ std::shared_ptr<AudioRequestMessage> msg =
+ std::make_shared<AudioRequestMessage>(MessageType::AudioRoutingStart);
+ auto ret = SendAudioRequest(serv, msg);
+ return Handle(ret->retCode, ret->token);
}
audio::RetCode RoutingRecordCtrl(sys::Service *serv, bool enable)
@@ 97,17 98,23 @@ namespace AudioServiceAPI
return SendAudioRequest(serv, msg)->retCode;
}
- RetCode Pause(sys::Service *serv)
+ RetCode Stop(sys::Service *serv, const audio::Handle &handle)
{
- auto msg = std::make_shared<AudioRequestMessage>(MessageType::AudioPause);
-
+ auto msg = std::make_shared<AudioStopMessage>(handle.GetToken());
return SendAudioRequest(serv, msg)->retCode;
}
- RetCode Resume(sys::Service *serv)
+ RetCode Pause(sys::Service *serv, const audio::Handle &handle)
{
- auto msg = std::make_shared<AudioRequestMessage>(MessageType::AudioResume);
+ std::shared_ptr<AudioRequestMessage> msg =
+ std::make_shared<AudioRequestMessage>(MessageType::AudioPause, handle.GetToken());
+ return SendAudioRequest(serv, msg)->retCode;
+ }
+ RetCode Resume(sys::Service *serv, const audio::Handle &handle)
+ {
+ std::shared_ptr<AudioRequestMessage> msg =
+ std::make_shared<AudioRequestMessage>(MessageType::AudioResume, handle.GetToken());
return SendAudioRequest(serv, msg)->retCode;
}
M module-services/service-audio/api/AudioServiceAPI.hpp => module-services/service-audio/api/AudioServiceAPI.hpp +34 -21
@@ 11,34 11,47 @@ namespace AudioServiceAPI
{
/*! @brief Starts playback operation.
*
- * @param serv - requesting service.
- * @param playbackType - type of playback.
- * If none, request would still be valid and default volume would be used.
- * @param fileName - name of the file.
- * @return Standard service-api return code. Success if suitable.
+ * @param serv Requesting service.
+ * @param playbackType Type of playback.
+ * @param fileName Name of the file.
+ * @return audio::Handle Handle to operation to be used in subsequent operation.
*/
- audio::RetCode PlaybackStart(sys::Service *serv,
- const audio::PlaybackType &playbackType,
- const std::string &fileName);
- audio::RetCode RecordingStart(sys::Service *serv, const std::string &fileName);
- audio::RetCode RoutingStart(sys::Service *serv);
+ audio::Handle PlaybackStart(sys::Service *serv,
+ const audio::PlaybackType &playbackType,
+ const std::string &fileName);
+ audio::Handle RecordingStart(sys::Service *serv, const std::string &fileName);
+ audio::Handle RoutingStart(sys::Service *serv);
audio::RetCode RoutingRecordCtrl(sys::Service *serv, bool enable);
audio::RetCode RoutingMute(sys::Service *serv, bool enable);
audio::RetCode RoutingSpeakerPhone(sys::Service *serv, bool enable);
audio::RetCode RoutingHeadset(sys::Service *serv, bool enable);
- /// Stops current audio operation.
- ///
- /// Stops current audio operation when it's valid and not idle.
- /// @param serv requesting service
- /// @param stopVec vector that contains playback types to be stopped.
- /// When no vector is passed it stops current operation.
- /// When stop vector is passed it stops current operation only if it's type is contained in the vector.
- /// @return Standard service-api return code. Success if suitable.
audio::RetCode Stop(sys::Service *serv, const std::vector<audio::PlaybackType> &stopVec = {});
- audio::RetCode Pause(sys::Service *serv);
- audio::RetCode Resume(sys::Service *serv);
+ /*!
+ * @brief Stops playback operation.
+ *
+ * @param serv Requesting service
+ * @param handle Handle to controlled operation
+ * @return audio::RetCode standard service-api return code
+ */
+ audio::RetCode Stop(sys::Service *serv, const audio::Handle &handle);
+ /*!
+ * @brief Pauses playback operation. Can be resumed by Resume()
+ *
+ * @param serv Requesting service
+ * @param handle Handle to controlled operation
+ * @return audio::RetCode standard service-api return code
+ */
+ audio::RetCode Pause(sys::Service *serv, const audio::Handle &handle);
+ /*!
+ * @brief Resumes paused operation.
+ *
+ * @param serv Requesting service
+ * @param handle Handle to controlled operation
+ * @return audio::RetCode standard service-api return code
+ */
+ audio::RetCode Resume(sys::Service *serv, const audio::Handle &handle);
+
std::optional<audio::Tags> GetFileTags(sys::Service *serv, const std::string &fileName);
- // audio::RetCode AdjustVolume(sys::Service *serv, const int &step = 0);
/*! @brief Gets settings. Current profile is taken by default.
*
* @param serv - requesting service.
M module-services/service-audio/messages/AudioMessage.hpp => module-services/service-audio/messages/AudioMessage.hpp +24 -9
@@ 20,15 20,19 @@
class AudioMessage : public sys::DataMessage
{
public:
- AudioMessage(MessageType messageType) : sys::DataMessage(messageType), type(messageType)
+ AudioMessage() : sys::DataMessage(MessageType::MessageTypeUninitialized)
{}
- AudioMessage() : sys::DataMessage(MessageType::MessageTypeUninitialized)
+ AudioMessage(MessageType messageType,
+ audio::PlaybackType playbackType = audio::PlaybackType::None,
+ audio::Token token = audio::Token())
+ : sys::DataMessage(messageType), type(messageType), playbackType(playbackType), token(token)
{}
virtual ~AudioMessage() = default;
-
MessageType type = MessageType::MessageTypeUninitialized;
+ audio::PlaybackType playbackType = audio::PlaybackType::None;
+ audio::Token token;
};
class AudioNotificationMessage : public AudioMessage
@@ 41,7 45,8 @@ class AudioNotificationMessage : public AudioMessage
Stop
};
- AudioNotificationMessage(Type type) : AudioMessage(MessageType::AudioNotification), type(type)
+ AudioNotificationMessage(Type type, audio::Token token)
+ : AudioMessage(MessageType::AudioNotification, audio::PlaybackType::None, token), type(type)
{}
~AudioNotificationMessage()
@@ 96,24 101,29 @@ class AudioSetSetting : public AudioSettingsMessage
class AudioRequestMessage : public AudioMessage
{
public:
- AudioRequestMessage(MessageType messageType) : AudioMessage(messageType)
+ AudioRequestMessage(MessageType messageType, audio::Token token = audio::Token())
+ : AudioMessage(messageType, audio::PlaybackType::None, token)
{}
+
~AudioRequestMessage()
{}
std::string fileName;
float val;
bool enable;
- audio::PlaybackType playbackType = audio::PlaybackType::None;
};
class AudioStopMessage : public AudioMessage
{
public:
- AudioStopMessage(const std::vector<audio::PlaybackType> &stopVec = {}) : AudioMessage{}, stopVec{stopVec}
+ AudioStopMessage(const std::vector<audio::PlaybackType> &stopVec = {}) : AudioMessage(), stopVec(stopVec)
+ {}
+
+ AudioStopMessage(const audio::Token &token) : AudioMessage(), token(token)
{}
const std::vector<audio::PlaybackType> stopVec;
+ const audio::Token token;
};
class AudioResponseMessage : public sys::ResponseMessage
@@ 121,17 131,22 @@ class AudioResponseMessage : public sys::ResponseMessage
public:
AudioResponseMessage(audio::RetCode retCode = audio::RetCode::Success,
const audio::Tags &tags = {},
+ audio::Token token = audio::Token(),
const float val = 0.0)
- : sys::ResponseMessage(), tags(tags), val(val)
+ : sys::ResponseMessage(), tags(tags), val(val), token(token)
{}
- AudioResponseMessage(audio::RetCode retCode, const float val) : AudioResponseMessage(retCode, {}, val)
+
+ AudioResponseMessage(audio::RetCode retCode, const float val)
+ : AudioResponseMessage(retCode, {}, audio::Token(), val)
{}
+
virtual ~AudioResponseMessage()
{}
audio::RetCode retCode = audio::RetCode::Success;
audio::Tags tags = {};
float val = 0.0;
+ audio::Token token;
};
#endif // PUREPHONE_AUDIOMESSAGE_HPP