M changelog.md => changelog.md +1 -0
@@ 20,6 20,7 @@
* `[messages]` In new message window fixed clearing text on options/recipient choice
* `[Text]` Newline handling fix.
* `[appmgr]` Fix for closing applications.
+* `[audio]` Crash on attempt to open non-existent file
## [0.45.1 2020-11-06]
M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +6 -6
@@ 75,9 75,8 @@ namespace audio
const audio::PlaybackType &playbackType)
{
- auto ret = Operation::Create(op, fileName, playbackType, dbCallback);
- if (ret) {
-
+ try {
+ auto ret = Operation::Create(op, fileName, playbackType, dbCallback);
switch (op) {
case Operation::Type::Playback:
currentState = State::Playback;
@@ 98,12 97,13 @@ namespace audio
currentOperation->SetBluetoothStreamData(btData);
}
}
- else {
+ catch (const AudioInitException &audioException) {
// If creating operation failed fallback to IdleOperation which is guaranteed to work
- LOG_ERROR("Failed to create operation type %s", Operation::c_str(op));
+ LOG_ERROR(
+ "Failed to create operation type %s, error message:\n%s", Operation::c_str(op), audioException.what());
currentOperation = Operation::Create(Operation::Type::Idle);
currentState = State ::Idle;
- return RetCode::OperationCreateFailed;
+ return audioException.getErrorCode();
}
return currentOperation->Start(asyncCallback, token);
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +15 -0
@@ 169,6 169,21 @@ namespace audio
Failed
};
+ struct AudioInitException : public std::runtime_error
+ {
+ protected:
+ audio::RetCode errorCode = audio::RetCode::Failed;
+
+ public:
+ AudioInitException(const char *message, audio::RetCode errorCode) : runtime_error(message)
+ {}
+
+ audio::RetCode getErrorCode() const noexcept
+ {
+ return errorCode;
+ }
+ };
+
class Token
{
using TokenType = int16_t;
M module-audio/Audio/Operation/IdleOperation.cpp => module-audio/Audio/Operation/IdleOperation.cpp +1 -1
@@ 8,7 8,7 @@
namespace audio
{
- IdleOperation::IdleOperation([[maybe_unused]] const char *file) : Operation{true}
+ IdleOperation::IdleOperation([[maybe_unused]] const char *file)
{
supportedProfiles.emplace_back(Profile::Create(Profile::Type::Idle, nullptr), true);
currentProfile = supportedProfiles[0].profile;
M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +4 -9
@@ 40,14 40,9 @@ namespace audio
break;
}
- if (inst->isInitialized) {
- inst->opType = t;
- inst->filePath = fileName;
- return inst;
- }
- else {
- return {};
- }
+ inst->opType = t;
+ inst->filePath = fileName;
+ return inst;
}
std::shared_ptr<Profile> Operation::GetProfile(const Profile::Type type)
@@ 80,7 75,7 @@ namespace audio
return SwitchProfile(p.profile->GetType());
}
}
- return audio::RetCode::Failed;
+ return audio::RetCode::ProfileNotSet;
}
void Operation::SetProfileAvailability(std::vector<Profile::Type> profiles, bool available)
M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +7 -10
@@ 18,9 18,7 @@ namespace audio
class Operation
{
public:
- Operation(const bool &isInitialized = false,
- const audio::PlaybackType &playbackType = audio::PlaybackType::None)
- : isInitialized{isInitialized}, playbackType{playbackType}
+ Operation(const audio::PlaybackType &playbackType = audio::PlaybackType::None) : playbackType{playbackType}
{}
enum class State
@@ 62,12 60,12 @@ namespace audio
std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback = nullptr);
virtual audio::RetCode Start(audio::AsyncCallback callback, audio::Token token) = 0;
- virtual audio::RetCode Stop() = 0;
- virtual audio::RetCode Pause() = 0;
- virtual audio::RetCode Resume() = 0;
- virtual audio::RetCode SendEvent(std::shared_ptr<Event> evt) = 0;
- virtual audio::RetCode SetOutputVolume(float vol) = 0;
- virtual audio::RetCode SetInputGain(float gain) = 0;
+ virtual audio::RetCode Stop() = 0;
+ virtual audio::RetCode Pause() = 0;
+ virtual audio::RetCode Resume() = 0;
+ virtual audio::RetCode SendEvent(std::shared_ptr<Event> evt) = 0;
+ virtual audio::RetCode SetOutputVolume(float vol) = 0;
+ virtual audio::RetCode SetInputGain(float gain) = 0;
virtual Position GetPosition() = 0;
virtual void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data);
@@ 140,7 138,6 @@ namespace audio
Type opType = Type::Idle;
std::string filePath;
- bool isInitialized = false;
audio::PlaybackType playbackType = audio::PlaybackType::None;
virtual audio::RetCode SwitchProfile(const Profile::Type type) = 0;
M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +9 -10
@@ 20,7 20,7 @@ namespace audio
const char *file,
const audio::PlaybackType &playbackType,
std::function<uint32_t(const std::string &path, const uint32_t &defaultValue)> dbCallback)
- : Operation(false, playbackType), dec(nullptr)
+ : Operation(playbackType), dec(nullptr)
{
audioCallback = [this](const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer) -> int32_t {
@@ 61,22 61,19 @@ namespace audio
auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
if (!defaultProfile) {
- LOG_ERROR("Error during initializing profile");
- return;
+ throw AudioInitException("Error during initializing profile", RetCode::ProfileNotSet);
}
currentProfile = defaultProfile;
dec = decoder::Create(file);
if (dec == nullptr) {
- LOG_ERROR("Error during initializing decoder");
- return;
+ throw AudioInitException("Error during initializing decoder", RetCode::FileDoesntExist);
}
- if (SwitchToPriorityProfile() != audio::RetCode::Success) {
- return;
+ auto retCode = SwitchToPriorityProfile();
+ if (retCode != RetCode::Success) {
+ throw AudioInitException("Failed to switch audio profile", retCode);
}
-
- isInitialized = true;
}
audio::RetCode PlaybackOperation::Start(audio::AsyncCallback callback, audio::Token token)
@@ 96,7 93,6 @@ namespace audio
currentProfile->SetInOutFlags(tags->num_channel == 2
? static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputStereo)
: static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono));
-
currentProfile->SetSampleRate(tags->sample_rate);
auto ret = audioDevice->Start(currentProfile->GetAudioFormat());
@@ 106,6 102,9 @@ namespace audio
audio::RetCode PlaybackOperation::Stop()
{
state = State::Idle;
+ if (!audioDevice) {
+ return audio::RetCode::DeviceFailure;
+ }
return GetDeviceError(audioDevice->Stop());
}
M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +5 -8
@@ 63,8 63,7 @@ namespace audio
auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
if (!defaultProfile) {
- LOG_ERROR("Error during initializing profile");
- return;
+ throw AudioInitException("Error during initializing profile", RetCode::ProfileNotSet);
}
currentProfile = defaultProfile;
@@ 79,15 78,13 @@ namespace audio
enc = Encoder::Create(file, Encoder::Format{.chanNr = channels, .sampleRate = currentProfile->GetSampleRate()});
if (enc == nullptr) {
- LOG_ERROR("Error during initializing encoder");
- return;
+ throw AudioInitException("Error during initializing encoder", RetCode::InvalidFormat);
}
- if (SwitchToPriorityProfile() != audio::RetCode::Success) {
- return;
+ auto retCode = SwitchToPriorityProfile();
+ if (retCode != RetCode::Success) {
+ throw AudioInitException("Failed to switch audio profile", retCode);
}
-
- isInitialized = true;
}
audio::RetCode RecorderOperation::Start(audio::AsyncCallback callback, audio::Token token)
M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +4 -6
@@ 145,16 145,14 @@ namespace audio
auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
if (!defaultProfile) {
- LOG_ERROR("Error during initializing profile");
- return;
+ throw AudioInitException("Error during initializing profile", RetCode::ProfileNotSet);
}
currentProfile = defaultProfile;
- if (SwitchToPriorityProfile() != audio::RetCode::Success) {
- return;
+ auto retCode = SwitchToPriorityProfile();
+ if (retCode != RetCode::Success) {
+ throw AudioInitException("Failed to switch audio profile", retCode);
}
-
- isInitialized = true;
}
audio::RetCode RouterOperation::SetOutputVolume(float vol)
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +6 -1
@@ 294,7 294,12 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
retToken = audioMux.ResetInput(input);
if (IsOperationEnabled(playbackType, opType)) {
- retCode = (*input)->audio->Start(opType, retToken, fileName.c_str(), playbackType);
+ try {
+ retCode = (*input)->audio->Start(opType, retToken, fileName.c_str(), playbackType);
+ }
+ catch (const AudioInitException &audioException) {
+ retCode = audio::RetCode::FailedToAllocateMemory;
+ }
}
}