~aleteoryx/muditaos

7ccc52c04cb4cc1cbc8e43d6d5ba33f81da4fec3 — Hubert Chrzaniuk 5 years ago 7f89f41
[EGD-4357] Improve error handling in audio (#990)

 - error code can be now returned also during
   initialization
 - fixed crash when user requested to playback
   file that does not exist
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;
                }
            }
        }