// SPDX-License-Identifier: MPL-2.0 // Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/) #pragma once #include #include #include #include namespace skyline::service::am { /** * @brief The base class all Applets have to inherit from */ class IApplet : public BaseService { private: std::shared_ptr onNormalDataPushFromApplet; std::shared_ptr onInteractiveDataPushFromApplet; std::mutex outputDataMutex; std::queue> normalOutputData; //!< Stores data sent by the applet so the guest can read it when it needs to std::mutex interactiveOutputDataMutex; std::queue> interactiveOutputData; //!< Stores interactive data sent by the applet so the guest can read it when it needs to protected: std::shared_ptr onAppletStateChanged; /** * @brief Utility to send data to the guest and trigger the onNormalDataPushFromApplet event */ void PushNormalDataAndSignal(std::shared_ptr data); /** * @brief Utility to send data to the guest and trigger the onInteractiveDataPushFromApplet event */ void PushInteractiveDataAndSignal(std::shared_ptr data); public: IApplet(const DeviceState &state, ServiceManager &manager, std::shared_ptr onAppletStateChanged, std::shared_ptr onNormalDataPushFromApplet, std::shared_ptr onInteractiveDataPushFromApplet, applet::LibraryAppletMode appletMode); virtual ~IApplet(); /** * @brief Called when the applet is started */ virtual Result Start() = 0; /** * @brief Called when the applet is stopped */ virtual Result GetResult() = 0; /** * @brief Called when data is pushed to the applet by the guest through the normal queue */ virtual void PushNormalDataToApplet(std::shared_ptr data) = 0; /** * @brief Called when data is pushed to the applet by the guest through the interactive queue */ virtual void PushInteractiveDataToApplet(std::shared_ptr data) = 0; /** * @brief Used by ILibraryAppletAccessor to pop data from the normal queue and reset the corresponding event */ std::shared_ptr PopNormalAndClear(); /** * @brief Used by ILibraryAppletAccessor to pop data from the interactive queue and reset the corresponding event */ std::shared_ptr PopInteractiveAndClear(); }; /** * @brief Utility class for applets that need to queue the normal data sent to them */ class EnableNormalQueue { protected: std::mutex normalInputDataMutex; std::queue> normalInputData; std::shared_ptr PopNormalInput() { std::scoped_lock lock{normalInputDataMutex}; auto data{normalInputData.front()}; normalInputData.pop(); return data; } template T PopNormalInput() { std::scoped_lock lock{normalInputDataMutex}; auto data{normalInputData.front()->GetSpan().as()}; normalInputData.pop(); return data; } void PushNormalInput(std::shared_ptr data) { normalInputData.emplace(data); } }; /** * @brief Utility class for applets that need to queue the interactive data sent to them */ class EnableInteractiveQueue { protected: std::mutex interactiveInputDataMutex; std::queue> interactiveInputData; std::shared_ptr PopInteractiveInput() { std::scoped_lock lock{interactiveInputDataMutex}; auto data{interactiveInputData.front()}; interactiveInputData.pop(); return data; } template T PopInteractiveInput() { std::scoped_lock lock{interactiveInputDataMutex}; auto data{interactiveInputData.front()->GetSpan().as()}; interactiveInputData.pop(); return data; } void PushInteractiveInput(std::shared_ptr data) { interactiveInputData.emplace(data); } }; }