diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..f4eefa9 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,13 @@ +Checks: > + -*, + bugprone-*, + modernize-*, + readability-*, + performance-*, + -modernize-use-trailing-return-type, + -readability-magic-numbers, + -readability-identifier-length, + -bugprone-easily-swappable-parameters + +HeaderFilterRegex: '(include|src)/.*\.h$' +WarningsAsErrors: '' diff --git a/README.md b/README.md index 085c0dc..2a388b7 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,17 @@ Before running it, export `DEVICE_SSH_USER`, `DEVICE_SSH_HOST`, and `DEVICE_SSH_ ## Lint -Use `lint.sh` to run local static analysis for C/C++ sources. +Use `lint.sh` to run the same clang-format lint that CI enforces. +It checks tracked `*.cpp` and `*.h` files using: + +- `git ls-files -- '*.cpp' '*.h' | xargs clang-format --dry-run --Werror` Examples: - `./lint.sh` -- `./lint.sh --tidy-only` -- `./lint.sh --tidy-only --fix` -- `./lint.sh --cppcheck-only` +- `./lint.sh --fix` +- `./lint.sh --local` +- `SKIP_DOCKER=1 ./lint.sh` ## Coverity diff --git a/include/firebolt/accessibility.h b/include/firebolt/accessibility.h index 810151e..8417591 100644 --- a/include/firebolt/accessibility.h +++ b/include/firebolt/accessibility.h @@ -49,7 +49,7 @@ class IAccessibility * * @retval The audio description setting state or error */ - virtual Result audioDescription() const = 0; + [[nodiscard]] virtual Result audioDescription() const = 0; /** * @brief Subscribe to audio description setting changes @@ -63,7 +63,7 @@ class IAccessibility * * @retval ClosedCaptionsSettings or error */ - virtual Result closedCaptionsSettings() const = 0; + [[nodiscard]] virtual Result closedCaptionsSettings() const = 0; virtual Result subscribeOnClosedCaptionsSettingsChanged(std::function&& notification) = 0; @@ -73,7 +73,7 @@ class IAccessibility * * @retval The high contrast UI setting or error */ - virtual Result highContrastUI() const = 0; + [[nodiscard]] virtual Result highContrastUI() const = 0; virtual Result subscribeOnHighContrastUIChanged(std::function&& notification) = 0; @@ -81,7 +81,7 @@ class IAccessibility * @brief Returns voice guidance settings: enabled, rate, and verbosity * @retval VoiceGuidanceSettings or error */ - virtual Result voiceGuidanceSettings() const = 0; + [[nodiscard]] virtual Result voiceGuidanceSettings() const = 0; virtual Result subscribeOnVoiceGuidanceSettingsChanged(std::function&& notification) = 0; diff --git a/include/firebolt/actions.h b/include/firebolt/actions.h index 7d28222..543320c 100644 --- a/include/firebolt/actions.h +++ b/include/firebolt/actions.h @@ -53,7 +53,7 @@ class IActions public: virtual ~IActions() = default; - virtual Result intent() const = 0; + [[nodiscard]] virtual Result intent() const = 0; virtual Result subscribeOnIntent(std::function&& notification) = 0; virtual Result subscribeOnIntentChanged(std::function&& notification) @@ -64,7 +64,8 @@ class IActions virtual Result unsubscribe(SubscriptionId id) = 0; virtual void unsubscribeAll() = 0; - virtual Result start(const IntentData& intent, std::optional handlerAppId = std::nullopt) const = 0; + [[nodiscard]] virtual Result start(const IntentData& intent, + std::optional handlerAppId = std::nullopt) const = 0; }; // class IActions diff --git a/include/firebolt/advertising.h b/include/firebolt/advertising.h index 1a986a9..4a4ab54 100644 --- a/include/firebolt/advertising.h +++ b/include/firebolt/advertising.h @@ -56,6 +56,6 @@ class IAdvertising * @return Ifa struct or error * */ - virtual Result advertisingId() const = 0; + [[nodiscard]] virtual Result advertisingId() const = 0; }; } // namespace Firebolt::Advertising diff --git a/include/firebolt/device.h b/include/firebolt/device.h index 37ba5d1..458d951 100644 --- a/include/firebolt/device.h +++ b/include/firebolt/device.h @@ -58,42 +58,42 @@ class IDevice * * @retval The chipset id string or error */ - virtual Result chipsetId() const = 0; + [[nodiscard]] virtual Result chipsetId() const = 0; /** * @brief Get the class of the device * * @retval The class property or error */ - virtual Result deviceClass() const = 0; + [[nodiscard]] virtual Result deviceClass() const = 0; /** * @brief Returns the HDR standards that are supported by the attached TV or the integral display * * @retval The HDR format capabilities or error */ - virtual Result hdr() const = 0; + [[nodiscard]] virtual Result hdr() const = 0; /** * @brief Returns number of seconds since most recent device boot, including any time spent during deep sleep * * @retval The uptime in seconds or error */ - virtual Result timeInActiveState() const = 0; + [[nodiscard]] virtual Result timeInActiveState() const = 0; /** * @brief Returns a persistent unique UUID for the current app and device. The UUID is reset when the app or device is reset * * @retval The uid string or error */ - virtual Result uid() const = 0; + [[nodiscard]] virtual Result uid() const = 0; /** * @brief Returns number of seconds since most recent device boot, including any time spent during deep sleep * * @retval The uptime in seconds or error */ - virtual Result uptime() const = 0; + [[nodiscard]] virtual Result uptime() const = 0; /** * @brief Subscribe to HDR format changes @@ -122,7 +122,7 @@ class IDevice * * @retval True if Dolby Atmos experience is available, or error */ - virtual Result dolbyAtmosExperienceAvailable() const = 0; + [[nodiscard]] virtual Result dolbyAtmosExperienceAvailable() const = 0; /** * @brief Subscribe to Dolby Atmos experience availability changes diff --git a/include/firebolt/discovery.h b/include/firebolt/discovery.h index f17bedc..aced324 100644 --- a/include/firebolt/discovery.h +++ b/include/firebolt/discovery.h @@ -45,9 +45,9 @@ class IDiscovery * Prefer watchedV2() for new integrations, which returns Result and omits the * redundant boolean payload. */ - virtual Result watched(const std::string& entityId, std::optional progress, - std::optional completed, std::optional watchedOn, - std::optional agePolicy) const = 0; + [[nodiscard]] virtual Result watched(const std::string& entityId, std::optional progress, + std::optional completed, std::optional watchedOn, + std::optional agePolicy) const = 0; /** * @brief Notify the platform that content was partially or completely watched @@ -62,8 +62,8 @@ class IDiscovery * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result watchedV2(const std::string& entityId, std::optional progress, - std::optional completed, std::optional watchedOn, - std::optional agePolicy) const = 0; + [[nodiscard]] virtual Result watchedV2(const std::string& entityId, std::optional progress, + std::optional completed, std::optional watchedOn, + std::optional agePolicy) const = 0; }; } // namespace Firebolt::Discovery diff --git a/include/firebolt/display.h b/include/firebolt/display.h index ac723fe..ac4719d 100644 --- a/include/firebolt/display.h +++ b/include/firebolt/display.h @@ -41,7 +41,7 @@ class IDisplay * * @retval The class property or error */ - virtual Result edid() const = 0; + [[nodiscard]] virtual Result edid() const = 0; /** * @brief Returns the physical/native resolution of the connected or integral display, in pixels @@ -56,7 +56,7 @@ class IDisplay * * @retval The display resolution (width and height in pixels) or error */ - virtual Result maxResolution() const = 0; + [[nodiscard]] virtual Result maxResolution() const = 0; /** * @brief Returns the physical dimensions of the connected or integral display, in centimeters @@ -71,7 +71,7 @@ class IDisplay * * @retval The class property or error */ - virtual Result size() const = 0; + [[nodiscard]] virtual Result size() const = 0; }; } // namespace Firebolt::Display diff --git a/include/firebolt/firebolt.h b/include/firebolt/firebolt.h index d889ec0..1d1568d 100644 --- a/include/firebolt/firebolt.h +++ b/include/firebolt/firebolt.h @@ -32,6 +32,7 @@ #include "firebolt/presentation.h" #include "firebolt/stats.h" #include "firebolt/texttospeech.h" +#include "firebolt/videooutput.h" #include #include #include @@ -169,5 +170,7 @@ class FIREBOLTCLIENT_EXPORT IFireboltAccessor * @return Reference to Actions interface */ virtual Actions::IActions& ActionsInterface() = 0; + + virtual VideoOutput::IVideoOutput& VideoOutputInterface() = 0; }; } // namespace Firebolt diff --git a/include/firebolt/lifecycle.h b/include/firebolt/lifecycle.h index 94ed93e..3581cda 100644 --- a/include/firebolt/lifecycle.h +++ b/include/firebolt/lifecycle.h @@ -68,14 +68,14 @@ class ILifecycle * * @param[in] type The type of the close app is requesting */ - virtual Result close(const CloseType& type) const = 0; + [[nodiscard]] virtual Result close(const CloseType& type) const = 0; /** * @brief Get the current lifecycle state of the app * * @retval The current lifecycle state or error */ - virtual Result state() const = 0; + [[nodiscard]] virtual Result state() const = 0; /** * @brief Subscribe to lifecycle state changes diff --git a/include/firebolt/localization.h b/include/firebolt/localization.h index 5131a3e..6e33374 100644 --- a/include/firebolt/localization.h +++ b/include/firebolt/localization.h @@ -35,7 +35,7 @@ class ILocalization * * @retval The device country code or error */ - virtual Result country() const = 0; + [[nodiscard]] virtual Result country() const = 0; /** * @brief A list of zero or more languages in order of decreasing preference. Typically two languages are present. @@ -43,21 +43,21 @@ class ILocalization * * @retval The preferred audio languages or error */ - virtual Result> preferredAudioLanguages() const = 0; + [[nodiscard]] virtual Result> preferredAudioLanguages() const = 0; /** * @brief The presentation language of the device, in BCP 47, e.g. en-US * * @retval The preferred audio languages or error */ - virtual Result presentationLanguage() const = 0; + [[nodiscard]] virtual Result presentationLanguage() const = 0; /** * @brief Get the IANA timezone of the device. * * @retval The device timezone or error */ - virtual Result timeZone() const = 0; + [[nodiscard]] virtual Result timeZone() const = 0; /** * @brief Subscribe on the change of CountryChanged property diff --git a/include/firebolt/metrics.h b/include/firebolt/metrics.h index 6927674..23b8673 100644 --- a/include/firebolt/metrics.h +++ b/include/firebolt/metrics.h @@ -45,21 +45,21 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result ready() const = 0; + [[nodiscard]] virtual Result ready() const = 0; /** * @brief Logs a sign in event * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result signIn() const = 0; + [[nodiscard]] virtual Result signIn() const = 0; /** * @brief Logs a sign out event * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result signOut() const = 0; + [[nodiscard]] virtual Result signOut() const = 0; /** * @brief Informs the platform that your user has started content @@ -70,8 +70,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result startContent(const std::optional& entityId, - const std::optional agePolicy) const = 0; + [[nodiscard]] virtual Result startContent(const std::optional& entityId, + std::optional agePolicy) const = 0; /** * @brief Informs the platform that your user has stopped content @@ -82,8 +82,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result stopContent(const std::optional& entityId, - const std::optional agePolicy) const = 0; + [[nodiscard]] virtual Result stopContent(const std::optional& entityId, + std::optional agePolicy) const = 0; /** * @brief Informs the platform that your user has navigated to a page or view @@ -94,7 +94,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result page(const std::string& pageId, const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result page(const std::string& pageId, + const std::optional& agePolicy) const = 0; /** * @brief Informs the platform of an error that has occurred in your app @@ -109,9 +110,10 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result error(const ErrorType type, const std::string& code, const std::string& description, - const bool visible, const std::optional>& parameters, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result error(ErrorType type, const std::string& code, const std::string& description, + bool visible, + const std::optional>& parameters, + const std::optional& agePolicy) const = 0; /** * @brief Called when setting the URL of a media asset to play, in order to infer load time @@ -122,8 +124,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaLoadStart(const std::string& entityId, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaLoadStart(const std::string& entityId, + const std::optional& agePolicy) const = 0; /** * @brief Called when media playback actually starts due to autoplay, user-initiated play, unpausing, or recovering @@ -135,8 +137,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaPlaying(const std::string& entityId, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaPlaying(const std::string& entityId, + const std::optional& agePolicy) const = 0; /** * @brief Called when media playback should start due to autoplay, user-initiated play, or unpausing @@ -147,8 +149,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaPlay(const std::string& entityId, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaPlay(const std::string& entityId, + const std::optional& agePolicy) const = 0; /** * @brief Called when media playback will pause due to an intentional pause operation @@ -159,8 +161,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaPause(const std::string& entityId, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaPause(const std::string& entityId, + const std::optional& agePolicy) const = 0; /** * @brief Called when media playback will halt due to a network, buffer, or other unintentional constraint @@ -171,8 +173,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaWaiting(const std::string& entityId, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaWaiting(const std::string& entityId, + const std::optional& agePolicy) const = 0; /** * @brief Called when a seek is initiated during media playback @@ -185,8 +187,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaSeeking(const std::string& entityId, const double target, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaSeeking(const std::string& entityId, double target, + const std::optional& agePolicy) const = 0; /** * @brief Called when a seek is completed during media playback @@ -200,8 +202,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaSeeked(const std::string& entityId, const double position, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaSeeked(const std::string& entityId, double position, + const std::optional& agePolicy) const = 0; /** * @brief Called when the playback rate of media is changed @@ -213,8 +215,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaRateChanged(const std::string& entityId, const double rate, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaRateChanged(const std::string& entityId, double rate, + const std::optional& agePolicy) const = 0; /** * @brief Called when the rendition of media is changed, such as bitrate, dimensions, or profile @@ -229,9 +231,10 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaRenditionChanged(const std::string& entityId, const unsigned bitrate, const unsigned width, - const unsigned height, const std::optional& profile, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result + mediaRenditionChanged(const std::string& entityId, unsigned bitrate, unsigned width, unsigned height, + const std::optional& profile, + const std::optional& agePolicy) const = 0; /** * @brief Called when playback has stopped because the end of the media was reached @@ -242,8 +245,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result mediaEnded(const std::string& entityId, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result mediaEnded(const std::string& entityId, + const std::optional& agePolicy) const = 0; /** * @brief Called to inform the platform of 1st party distributor metrics @@ -255,8 +258,8 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result event(const std::string& schema, const std::string& data, - const std::optional& agePolicy) const = 0; + [[nodiscard]] virtual Result event(const std::string& schema, const std::string& data, + const std::optional& agePolicy) const = 0; /** * @brief Inform the platform about an app's build info @@ -265,7 +268,7 @@ class IMetrics * * @retval An ok Result on success, or an error; no value is returned */ - virtual Result appInfo(const std::string& build) const = 0; + [[nodiscard]] virtual Result appInfo(const std::string& build) const = 0; }; } // namespace Firebolt::Metrics diff --git a/include/firebolt/network.h b/include/firebolt/network.h index 0a0bc33..8732cf7 100644 --- a/include/firebolt/network.h +++ b/include/firebolt/network.h @@ -34,7 +34,7 @@ class INetwork * * @retval The connection state or error */ - virtual Result connected() const = 0; + [[nodiscard]] virtual Result connected() const = 0; /** * @brief Subscribe to connection changes diff --git a/include/firebolt/presentation.h b/include/firebolt/presentation.h index e7bcf85..687e3a4 100644 --- a/include/firebolt/presentation.h +++ b/include/firebolt/presentation.h @@ -33,7 +33,7 @@ class IPresentation * * @retval The focus state or error */ - virtual Result focused() const = 0; + [[nodiscard]] virtual Result focused() const = 0; /** * @brief Subscribe to focus change notifications diff --git a/include/firebolt/stats.h b/include/firebolt/stats.h index ed4e1e6..8e5dd03 100644 --- a/include/firebolt/stats.h +++ b/include/firebolt/stats.h @@ -40,7 +40,7 @@ class IStats * * @retval MemoryInfo struct or error */ - virtual Result memoryUsage() const = 0; + [[nodiscard]] virtual Result memoryUsage() const = 0; }; } // namespace Firebolt::Stats diff --git a/include/firebolt/texttospeech.h b/include/firebolt/texttospeech.h index 6650498..eaf41e2 100644 --- a/include/firebolt/texttospeech.h +++ b/include/firebolt/texttospeech.h @@ -91,7 +91,7 @@ class ITextToSpeech * * @retval The list of voices supported for the language */ - virtual Result listVoices(const std::string& language) const = 0; + [[nodiscard]] virtual Result listVoices(const std::string& language) const = 0; /** * @brief Speak the uttered text using the TTS engine @@ -100,7 +100,7 @@ class ITextToSpeech * * @retval Result for Speak */ - virtual Result speak(const std::string& text) const = 0; + [[nodiscard]] virtual Result speak(const std::string& text) const = 0; /** * @brief Pauses the speech for given speech id @@ -109,7 +109,7 @@ class ITextToSpeech * * @retval Result for Pause */ - virtual Result pause(SpeechId speechId) const = 0; + [[nodiscard]] virtual Result pause(SpeechId speechId) const = 0; /** * @brief Resumes the speech for given speech id @@ -118,7 +118,7 @@ class ITextToSpeech * * @retval Result for Resume */ - virtual Result resume(SpeechId speechId) const = 0; + [[nodiscard]] virtual Result resume(SpeechId speechId) const = 0; /** * @brief Cancels the speech for given speech id @@ -127,7 +127,7 @@ class ITextToSpeech * * @retval Result for cancel */ - virtual Result cancel(SpeechId speechId) const = 0; + [[nodiscard]] virtual Result cancel(SpeechId speechId) const = 0; /** * @brief Returns the current state of the speech request. @@ -136,7 +136,7 @@ class ITextToSpeech * * @retval Result for speech state */ - virtual Result getSpeechState(SpeechId speechId) const = 0; + [[nodiscard]] virtual Result getSpeechState(SpeechId speechId) const = 0; /** * @brief Triggered when the text to speech conversion is about to start. It diff --git a/include/firebolt/videooutput.h b/include/firebolt/videooutput.h new file mode 100644 index 0000000..4833e74 --- /dev/null +++ b/include/firebolt/videooutput.h @@ -0,0 +1,188 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +// +// ============================================================================ +// AUTO-GENERATED by firebolt-sdk-gen v0.1.0 — DO NOT EDIT +// ============================================================================ +#ifndef FIREBOLT_VIDEOOUTPUT_H +#define FIREBOLT_VIDEOOUTPUT_H + +#include +#include +#include +#include +#include + +namespace Firebolt::VideoOutput +{ +enum class CecStateValue +{ + Active, + Inactive, + Unsupported, +}; + +enum class ColorDepthValue +{ + D0, + D10, + D12, + D8, +}; + +enum class ColorFormatValue +{ + None, + Rgb444, + Ycbcr420, + Ycbcr422, + Ycbcr444, +}; + +enum class DynamicRangeValue +{ + DolbyVision, + Hdr10, + Hdr10plus, + Hlg, + None, + Sdr, +}; + +enum class HdcpState +{ + Direct, + Hdcp14, + Hdcp22, + None, +}; + +enum class OutputColorimetry +{ + Bt2020rgb, + Bt2020ycc, + Bt709, + None, + Oprgb, +}; + +enum class QuantizationRangeValue +{ + Full, + Limited, + None, +}; + +enum class RefreshRateValue +{ + R0, + R23976, + R24, + R25, + R2997, + R30, + R50, + R5994, + R60, +}; + +struct VideoOutputResolution +{ + uint32_t height; + uint32_t width; +}; + +class IVideoOutput +{ +public: + virtual ~IVideoOutput() = default; + + [[nodiscard]] virtual Result cecState() const = 0; + virtual Result subscribeOnCecStateChanged(std::function&& notification) = 0; + + [[nodiscard]] virtual Result colorDepth() const = 0; + + [[nodiscard]] virtual Result colorFormat() const = 0; + + [[nodiscard]] virtual Result colorimetry() const = 0; + + [[nodiscard]] virtual Result dynamicRange() const = 0; + + [[nodiscard]] virtual Result hdcp() const = 0; + virtual Result subscribeOnHdcpChanged(std::function&& notification) = 0; + + [[nodiscard]] virtual Result quantizationRange() const = 0; + + [[nodiscard]] virtual Result refreshRate() const = 0; + virtual Result + subscribeOnRefreshRateChanged(std::function&& notification) = 0; + + [[nodiscard]] virtual Result resolution() const = 0; + virtual Result + subscribeOnResolutionChanged(std::function&& notification) = 0; + + virtual Result unsubscribe(SubscriptionId id) = 0; + virtual void unsubscribeAll() = 0; + +}; // class IVideoOutput + +#ifndef FIREBOLT_NO_METHOD_AVAILABILITY + +/// Enum of available methods in this module for runtime capability queries. +enum class MethodId +{ + resolution = 0, + hdcp = 1, + cecState = 2, + refreshRate = 3, + colorDepth = 4, + colorFormat = 5, + colorimetry = 6, + dynamicRange = 7, + quantizationRange = 8, +}; + +/// Check if a method is available in this SDK build. +/// Returns true if the method is compiled in, false otherwise. +/// All methods in this build are currently available (true). +inline bool isMethodAvailable(MethodId method) noexcept +{ + static constexpr bool kMethodAvailable[] = { + true, true, true, true, true, true, true, true, true, + }; + const int idx = static_cast(method); + if (idx < 0 || idx >= static_cast(sizeof(kMethodAvailable) / sizeof(kMethodAvailable[0]))) + { + return false; + } + return kMethodAvailable[idx]; +} + +/// Static array containing all available methods in this module. +/// Use for convenient enumeration: for (auto m : allMethods) { ... } +static constexpr std::array allMethods = { + MethodId::resolution, MethodId::hdcp, MethodId::cecState, + MethodId::refreshRate, MethodId::colorDepth, MethodId::colorFormat, + MethodId::colorimetry, MethodId::dynamicRange, MethodId::quantizationRange, +}; + +#endif // FIREBOLT_NO_METHOD_AVAILABILITY + +} // namespace Firebolt::VideoOutput + +#endif // FIREBOLT_VIDEOOUTPUT_H diff --git a/lint.sh b/lint.sh index a7dc561..17a1ced 100755 --- a/lint.sh +++ b/lint.sh @@ -19,78 +19,61 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -BUILD_DIR="build-dev" -NO_BUILD=false -CLEAN=false -RUN_CLANG_TIDY=true -RUN_CPPCHECK=true -APPLY_FIXES=false -CLANG_TIDY_PATHS=(src include test/unit test/component) +MODE="check" +USE_DOCKER="auto" +IMAGE="${LINT_DOCKER_IMAGE:-firebolt-cpp-client-fmt:local}" usage() { cat < Build directory containing compile_commands.json (default: build-dev) - --tidy-path

Add path for clang-tidy scan (repeatable) - --fix Apply clang-tidy fix-its (clang-tidy only) - --tidy-only Run clang-tidy only - --cppcheck-only Run cppcheck only - --help Show this help + --fix Reformat files in place (same file set as CI) + --check Explicitly run check mode (default) + --docker Force Docker execution + --local Force local clang-format execution + --image Docker image name (default: firebolt-cpp-client-fmt:local) + --help Show this help + +Environment: + SKIP_DOCKER=1 Same as --local Examples: ./lint.sh - ./lint.sh --tidy-only - ./lint.sh --tidy-only --fix - ./lint.sh --tidy-path test/api_test_app - ./lint.sh --no-build --build-dir build-dev + ./lint.sh --fix + ./lint.sh --docker + SKIP_DOCKER=1 ./lint.sh EOF } while [[ $# -gt 0 ]]; do case "$1" in - --clean) - CLEAN=true + --fix) + MODE="fix" ;; - --no-build) - NO_BUILD=true + --check) + MODE="check" ;; - --build-dir) - if [[ $# -lt 2 || -z "${2:-}" || "$2" == --* ]]; then - echo "Missing value for --build-dir" >&2 - usage - exit 1 - fi - BUILD_DIR="${2:-}" - shift + --docker) + USE_DOCKER="true" + ;; + --local) + USE_DOCKER="false" ;; - --tidy-path) + --image) if [[ $# -lt 2 || -z "${2:-}" || "$2" == --* ]]; then - echo "Missing value for --tidy-path" >&2 + echo "Missing value for --image" >&2 usage exit 1 fi - CLANG_TIDY_PATHS+=("${2:-}") + IMAGE="$2" shift ;; - --fix) - APPLY_FIXES=true - ;; - --tidy-only) - RUN_CLANG_TIDY=true - RUN_CPPCHECK=false - ;; - --cppcheck-only) - RUN_CLANG_TIDY=false - RUN_CPPCHECK=true - ;; --help|-h) usage exit 0 @@ -104,107 +87,55 @@ while [[ $# -gt 0 ]]; do shift done -cd "$ROOT_DIR" - -if [[ "$RUN_CLANG_TIDY" == true && "$NO_BUILD" == false && "$BUILD_DIR" != "build-dev" ]]; then - echo "--build-dir is only supported with --no-build (build step always uses build-dev)." >&2 - exit 1 -fi - -if [[ "$RUN_CLANG_TIDY" == false && "$RUN_CPPCHECK" == false ]]; then - echo "Nothing to run: clang-tidy and cppcheck are both disabled." >&2 - exit 1 -fi - -if [[ "$APPLY_FIXES" == true && "$RUN_CLANG_TIDY" == false ]]; then - echo "--fix requires clang-tidy to be enabled (remove --cppcheck-only)." >&2 - exit 1 -fi - -if [[ "$RUN_CLANG_TIDY" == true ]] && ! command -v clang-tidy >/dev/null 2>&1; then - echo "clang-tidy not found. Install it (e.g. apt install clang-tidy)." >&2 - exit 1 -fi - -if [[ "$RUN_CPPCHECK" == true ]] && ! command -v cppcheck >/dev/null 2>&1; then - echo "cppcheck not found. Install it (e.g. apt install cppcheck)." >&2 - exit 1 -fi - -if [[ "$CLEAN" == true ]]; then - rm -rf "$BUILD_DIR" -fi - -if [[ "$NO_BUILD" == false && "$RUN_CLANG_TIDY" == true ]]; then - ./build.sh +tests -fi - -if [[ "$RUN_CLANG_TIDY" == true && ! -f "$BUILD_DIR/compile_commands.json" ]]; then - echo "Missing $BUILD_DIR/compile_commands.json. Run ./build.sh +tests first." >&2 - exit 1 -fi - -if [[ "$RUN_CLANG_TIDY" == true ]]; then - if [[ "$APPLY_FIXES" == true ]]; then - echo "[lint] Running clang-tidy with fixes enabled" +if [[ "${SKIP_DOCKER:-0}" == "1" ]]; then + USE_DOCKER="false" +elif [[ "$USE_DOCKER" == "auto" ]]; then + if command -v docker >/dev/null 2>&1; then + USE_DOCKER="true" else - echo "[lint] Running clang-tidy" + USE_DOCKER="false" fi +fi - existing_paths=() - for p in "${CLANG_TIDY_PATHS[@]}"; do - if [[ -e "$p" ]]; then - existing_paths+=("$p") - fi - done +cd "$ROOT_DIR" - if [[ ${#existing_paths[@]} -eq 0 ]]; then - echo "No valid clang-tidy paths found." >&2 - exit 1 +if [[ "$USE_DOCKER" == "true" ]]; then + if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then + echo "[lint] Building Docker image '$IMAGE' with clang-format (one-time)" + docker build -t "$IMAGE" - <<'DOCKERFILE' +FROM ubuntu:24.04 +RUN apt-get update \ + && apt-get install -y --no-install-recommends clang-format git \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /workspace +DOCKERFILE fi - mapfile -t source_files < <( - find "${existing_paths[@]}" -type f \( -name "*.c" -o -name "*.cc" -o -name "*.cpp" -o -name "*.cxx" \) | sort - ) - - if [[ ${#source_files[@]} -eq 0 ]]; then - echo "No C/C++ source files found for clang-tidy." >&2 - exit 1 + if [[ "$MODE" == "fix" ]]; then + echo "[lint] Running CI-equivalent clang-format file set in FIX mode via Docker" + docker run --rm --user "$(id -u):$(id -g)" -v "$ROOT_DIR:/workspace" "$IMAGE" \ + bash -lc "set -e && git ls-files -- '*.cpp' '*.h' | xargs clang-format -i" + echo "[lint] Formatting fixes applied" + else + echo "[lint] Running CI-equivalent clang-format check via Docker" + docker run --rm --user "$(id -u):$(id -g)" -v "$ROOT_DIR:/workspace" "$IMAGE" \ + bash -lc "set -e && git ls-files -- '*.cpp' '*.h' | xargs clang-format --dry-run --Werror" + echo "[lint] Formatting OK" fi - - clang_tidy_failed=0 - total_files=${#source_files[@]} - index=0 - for f in "${source_files[@]}"; do - index=$((index + 1)) - echo "[lint][clang-tidy] ${index}/${total_files}: $f" - clang_tidy_cmd=(clang-tidy -p "$BUILD_DIR") - if [[ "$APPLY_FIXES" == true ]]; then - clang_tidy_cmd+=("-fix") - fi - clang_tidy_cmd+=("$f") - if ! "${clang_tidy_cmd[@]}"; then - clang_tidy_failed=1 - fi - done - - if [[ $clang_tidy_failed -ne 0 ]]; then - echo "clang-tidy reported issues." >&2 +else + if ! command -v clang-format >/dev/null 2>&1; then + echo "clang-format not found. Install it or run without SKIP_DOCKER=1." >&2 exit 1 fi -fi -if [[ "$RUN_CPPCHECK" == true ]]; then - echo "[lint] Running cppcheck" - cppcheck \ - --enable=warning,style,performance,portability \ - --std=c++17 \ - --language=c++ \ - --inline-suppr \ - --error-exitcode=1 \ - -I include \ - -I src \ - src include test + echo "[lint] Using local clang-format: $(clang-format --version)" + if [[ "$MODE" == "fix" ]]; then + echo "[lint] Running CI-equivalent clang-format file set in FIX mode" + git ls-files -- '*.cpp' '*.h' | xargs clang-format -i + echo "[lint] Formatting fixes applied" + else + echo "[lint] Running CI-equivalent clang-format check" + git ls-files -- '*.cpp' '*.h' | xargs clang-format --dry-run --Werror + echo "[lint] Formatting OK" + fi fi - -echo "[lint] Completed successfully" diff --git a/src/accessibility_impl.h b/src/accessibility_impl.h index 6a327fb..3ff383c 100644 --- a/src/accessibility_impl.h +++ b/src/accessibility_impl.h @@ -33,22 +33,22 @@ class AccessibilityImpl : public IAccessibility ~AccessibilityImpl() override = default; - Result audioDescription() const override; + [[nodiscard]] Result audioDescription() const override; Result subscribeOnAudioDescriptionChanged(std::function&& notification) override; - Result closedCaptionsSettings() const override; + [[nodiscard]] Result closedCaptionsSettings() const override; Result subscribeOnClosedCaptionsSettingsChanged(std::function&& notification) override; - Result highContrastUI() const override; + [[nodiscard]] Result highContrastUI() const override; Result subscribeOnHighContrastUIChanged(std::function&& notification) override; - Result voiceGuidanceSettings() const override; + [[nodiscard]] Result voiceGuidanceSettings() const override; Result subscribeOnVoiceGuidanceSettingsChanged(std::function&& notification) override; - virtual Result unsubscribe(SubscriptionId id) override; - virtual void unsubscribeAll() override; + Result unsubscribe(SubscriptionId id) override; + void unsubscribeAll() override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/actions_impl.h b/src/actions_impl.h index 523f82d..a61d03b 100644 --- a/src/actions_impl.h +++ b/src/actions_impl.h @@ -36,11 +36,12 @@ class ActionsImpl : public IActions ActionsImpl& operator=(const ActionsImpl&) = delete; ~ActionsImpl() override = default; - Result intent() const override; + [[nodiscard]] Result intent() const override; Result subscribeOnIntent(std::function&& notification) override; - Result start(const IntentData& intent, std::optional handlerAppId = std::nullopt) const override; + [[nodiscard]] Result start(const IntentData& intent, + std::optional handlerAppId = std::nullopt) const override; Result unsubscribe(SubscriptionId id) override; void unsubscribeAll() override; diff --git a/src/advertising_impl.h b/src/advertising_impl.h index efad60f..cd0a5ff 100644 --- a/src/advertising_impl.h +++ b/src/advertising_impl.h @@ -32,7 +32,7 @@ class AdvertisingImpl : public IAdvertising ~AdvertisingImpl() override = default; - Result advertisingId() const override; + [[nodiscard]] Result advertisingId() const override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/device_impl.h b/src/device_impl.h index c706427..1c2dce2 100644 --- a/src/device_impl.h +++ b/src/device_impl.h @@ -32,19 +32,19 @@ class DeviceImpl : public IDevice ~DeviceImpl() override = default; - Result chipsetId() const override; - Result deviceClass() const override; - Result hdr() const override; - Result timeInActiveState() const override; - Result uid() const override; - Result uptime() const override; + [[nodiscard]] Result chipsetId() const override; + [[nodiscard]] Result deviceClass() const override; + [[nodiscard]] Result hdr() const override; + [[nodiscard]] Result timeInActiveState() const override; + [[nodiscard]] Result uid() const override; + [[nodiscard]] Result uptime() const override; Result subscribeOnHdrChanged(std::function&& notification) override; Result unsubscribe(SubscriptionId id) override; void unsubscribeAll() override; - Result dolbyAtmosExperienceAvailable() const override; + [[nodiscard]] Result dolbyAtmosExperienceAvailable() const override; Result subscribeOnDolbyAtmosExperienceAvailableChanged(std::function&& notification) override; diff --git a/src/discovery_impl.h b/src/discovery_impl.h index 285186e..6f864ec 100644 --- a/src/discovery_impl.h +++ b/src/discovery_impl.h @@ -33,13 +33,13 @@ class DiscoveryImpl : public IDiscovery ~DiscoveryImpl() override = default; - Result watched(const std::string& entityId, std::optional progress, std::optional completed, - std::optional watchedOn, - std::optional agePolicy) const override; + [[nodiscard]] Result watched(const std::string& entityId, std::optional progress, + std::optional completed, std::optional watchedOn, + std::optional agePolicy) const override; - Result watchedV2(const std::string& entityId, std::optional progress, std::optional completed, - std::optional watchedOn, - std::optional agePolicy) const override; + [[nodiscard]] Result watchedV2(const std::string& entityId, std::optional progress, + std::optional completed, std::optional watchedOn, + std::optional agePolicy) const override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/display_impl.h b/src/display_impl.h index bbe5bd7..0b99e72 100644 --- a/src/display_impl.h +++ b/src/display_impl.h @@ -32,9 +32,9 @@ class DisplayImpl : public IDisplay ~DisplayImpl() override = default; - Result edid() const override; - Result maxResolution() const override; - Result size() const override; + [[nodiscard]] Result edid() const override; + [[nodiscard]] Result maxResolution() const override; + [[nodiscard]] Result size() const override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/firebolt.cpp b/src/firebolt.cpp index 0afad53..140d8ef 100644 --- a/src/firebolt.cpp +++ b/src/firebolt.cpp @@ -31,6 +31,7 @@ #include "presentation_impl.h" #include "stats_impl.h" #include "texttospeech_impl.h" +#include "videooutput_impl.h" #include namespace Firebolt @@ -51,14 +52,15 @@ class FireboltAccessorImpl : public IFireboltAccessor network_(Firebolt::Helpers::GetHelperInstance()), presentation_(Firebolt::Helpers::GetHelperInstance()), stats_(Firebolt::Helpers::GetHelperInstance()), - textToSpeech_(Firebolt::Helpers::GetHelperInstance()) + textToSpeech_(Firebolt::Helpers::GetHelperInstance()), + videooutput_(Firebolt::Helpers::GetHelperInstance()) { } FireboltAccessorImpl(const FireboltAccessorImpl&) = delete; FireboltAccessorImpl& operator=(const FireboltAccessorImpl&) = delete; - ~FireboltAccessorImpl() { unsubscribeAll(); } + ~FireboltAccessorImpl() override { unsubscribeAll(); } Firebolt::Error Connect(const Firebolt::Config& config, OnConnectionChanged listener) override { @@ -86,6 +88,7 @@ class FireboltAccessorImpl : public IFireboltAccessor Stats::IStats& StatsInterface() override { return stats_; } TextToSpeech::ITextToSpeech& TextToSpeechInterface() override { return textToSpeech_; } Actions::IActions& ActionsInterface() override { return actions_; } + VideoOutput::IVideoOutput& VideoOutputInterface() override { return videooutput_; } private: void unsubscribeAll() @@ -97,9 +100,9 @@ class FireboltAccessorImpl : public IFireboltAccessor network_.unsubscribeAll(); presentation_.unsubscribeAll(); textToSpeech_.unsubscribeAll(); + videooutput_.unsubscribeAll(); } -private: Accessibility::AccessibilityImpl accessibility_; Advertising::AdvertisingImpl advertising_; Actions::ActionsImpl actions_; @@ -113,6 +116,7 @@ class FireboltAccessorImpl : public IFireboltAccessor Presentation::PresentationImpl presentation_; Stats::StatsImpl stats_; TextToSpeech::TextToSpeechImpl textToSpeech_; + VideoOutput::VideoOutputImpl videooutput_; }; /* static */ IFireboltAccessor& IFireboltAccessor::Instance() diff --git a/src/json_types/accessibility.h b/src/json_types/accessibility.h index e071f04..4037b10 100644 --- a/src/json_types/accessibility.h +++ b/src/json_types/accessibility.h @@ -36,7 +36,7 @@ class ClosedCaptionsSettings : public Firebolt::JSON::NL_Json_Basic<::Firebolt:: enabled_ = json["enabled"].get(); preferredLanguages_ = json["preferredLanguages"].get>(); } - ::Firebolt::Accessibility::ClosedCaptionsSettings value() const override + [[nodiscard]] ::Firebolt::Accessibility::ClosedCaptionsSettings value() const override { return ::Firebolt::Accessibility::ClosedCaptionsSettings{enabled_, preferredLanguages_}; } @@ -59,7 +59,7 @@ class VoiceGuidanceSettings : public Firebolt::JSON::NL_Json_Basic<::Firebolt::A rate_ = json["rate"].get(); navigationHints_ = json["navigationHints"].get(); } - ::Firebolt::Accessibility::VoiceGuidanceSettings value() const override + [[nodiscard]] ::Firebolt::Accessibility::VoiceGuidanceSettings value() const override { return ::Firebolt::Accessibility::VoiceGuidanceSettings{enabled_, rate_, navigationHints_}; } diff --git a/src/json_types/actions.h b/src/json_types/actions.h index 4335be8..0310384 100644 --- a/src/json_types/actions.h +++ b/src/json_types/actions.h @@ -28,10 +28,7 @@ #include #include -namespace Firebolt::Actions -{ - -namespace JsonData +namespace Firebolt::Actions::JsonData { // Deserialises the wire object {"intent":{"action":"...","context":{"source":"..."}},"intentId":N} @@ -52,19 +49,19 @@ class JsonValue : public Firebolt::JSON::NL_Json_Basic { IntentContext ctx; if (json["intent"]["context"].contains("source")) + { ctx.source = json["intent"]["context"]["source"].get(); + } value_.intent.context = ctx; } value_.intentId = json["intentId"].get(); } - Intent value() const override { return value_; } + [[nodiscard]] Intent value() const override { return value_; } private: Intent value_; }; -} // namespace JsonData - -} // namespace Firebolt::Actions +} // namespace Firebolt::Actions::JsonData #endif // FIREBOLT_ACTIONS_JSON_H diff --git a/src/json_types/advertising.h b/src/json_types/advertising.h index 38b2ecc..3036557 100644 --- a/src/json_types/advertising.h +++ b/src/json_types/advertising.h @@ -38,7 +38,10 @@ class IfaJson : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Advertising::If ifa_type = json["ifa_type"].get(); lmt = json["lmt"].get(); } - ::Firebolt::Advertising::Ifa value() const override { return ::Firebolt::Advertising::Ifa{ifa, ifa_type, lmt}; } + [[nodiscard]] ::Firebolt::Advertising::Ifa value() const override + { + return ::Firebolt::Advertising::Ifa{ifa, ifa_type, lmt}; + } private: std::string ifa; diff --git a/src/json_types/device.h b/src/json_types/device.h index 82c6993..9e78aea 100644 --- a/src/json_types/device.h +++ b/src/json_types/device.h @@ -36,7 +36,7 @@ class DeviceClassJson : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Device: { public: void fromJson(const nlohmann::json& json) override { deviceClass_ = DeviceClassEnum.at(json); } - ::Firebolt::Device::DeviceClass value() const override { return deviceClass_; } + [[nodiscard]] ::Firebolt::Device::DeviceClass value() const override { return deviceClass_; } private: ::Firebolt::Device::DeviceClass deviceClass_; @@ -56,7 +56,7 @@ class HDRFormat : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Device::HDRFo hdrFormat_.dolbyVision = json["dolbyVision"].get(); hdrFormat_.hlg = json["hlg"].get(); } - ::Firebolt::Device::HDRFormat value() const override { return hdrFormat_; } + [[nodiscard]] ::Firebolt::Device::HDRFormat value() const override { return hdrFormat_; } private: ::Firebolt::Device::HDRFormat hdrFormat_; diff --git a/src/json_types/display.h b/src/json_types/display.h index 7e14b18..40877c2 100644 --- a/src/json_types/display.h +++ b/src/json_types/display.h @@ -38,7 +38,10 @@ class DisplaySizeJson : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Display width_ = json["width"].get(); height_ = json["height"].get(); } - ::Firebolt::Display::DisplaySize value() const override { return Firebolt::Display::DisplaySize{width_, height_}; } + [[nodiscard]] ::Firebolt::Display::DisplaySize value() const override + { + return Firebolt::Display::DisplaySize{width_, height_}; + } private: uint32_t width_; diff --git a/src/json_types/lifecycle.h b/src/json_types/lifecycle.h index acc43dd..0b130be 100644 --- a/src/json_types/lifecycle.h +++ b/src/json_types/lifecycle.h @@ -44,7 +44,7 @@ class LifecycleState : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Lifecycl { public: void fromJson(const nlohmann::json& json) override { state_ = LifecycleStateEnum.at(json.get()); } - ::Firebolt::Lifecycle::LifecycleState value() const override { return state_; } + [[nodiscard]] ::Firebolt::Lifecycle::LifecycleState value() const override { return state_; } private: ::Firebolt::Lifecycle::LifecycleState state_; @@ -62,7 +62,7 @@ class StateChange : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Lifecycle:: oldState_ = LifecycleStateEnum.at(json["oldState"]); newState_ = LifecycleStateEnum.at(json["newState"]); } - ::Firebolt::Lifecycle::StateChange value() const override + [[nodiscard]] ::Firebolt::Lifecycle::StateChange value() const override { return ::Firebolt::Lifecycle::StateChange{oldState_, newState_}; } diff --git a/src/json_types/stats.h b/src/json_types/stats.h index e8ad013..89610a9 100644 --- a/src/json_types/stats.h +++ b/src/json_types/stats.h @@ -38,7 +38,7 @@ class MemoryInfo : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Stats::Memor gpuMemoryUsed = json["gpuMemoryUsed"].get(); gpuMemoryLimit = json["gpuMemoryLimit"].get(); } - ::Firebolt::Stats::MemoryInfo value() const override + [[nodiscard]] ::Firebolt::Stats::MemoryInfo value() const override { return ::Firebolt::Stats::MemoryInfo{userMemoryUsed, userMemoryLimit, gpuMemoryUsed, gpuMemoryLimit}; } diff --git a/src/json_types/texttospeech.h b/src/json_types/texttospeech.h index b0f2686..481bb0a 100644 --- a/src/json_types/texttospeech.h +++ b/src/json_types/texttospeech.h @@ -47,7 +47,7 @@ class ListVoicesResponse : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Text voices_.push_back(voice.get()); } } - ::Firebolt::TextToSpeech::ListVoicesResponse value() const override + [[nodiscard]] ::Firebolt::TextToSpeech::ListVoicesResponse value() const override { return ::Firebolt::TextToSpeech::ListVoicesResponse{ttsStatus_, voices_}; } @@ -68,7 +68,7 @@ class SpeechIdEvent : public Firebolt::JSON::NL_Json_Basic<::Firebolt::TextToSpe } speechId_ = json["speechid"].get(); } - ::Firebolt::TextToSpeech::SpeechIdEvent value() const override + [[nodiscard]] ::Firebolt::TextToSpeech::SpeechIdEvent value() const override { return ::Firebolt::TextToSpeech::SpeechIdEvent{speechId_}; } @@ -90,7 +90,7 @@ class SpeechResponse : public Firebolt::JSON::NL_Json_Basic<::Firebolt::TextToSp ttsStatus_ = json["TTS_Status"].get(); success_ = json["success"].get(); } - ::Firebolt::TextToSpeech::SpeechResponse value() const override + [[nodiscard]] ::Firebolt::TextToSpeech::SpeechResponse value() const override { return ::Firebolt::TextToSpeech::SpeechResponse{speechId_, ttsStatus_, success_}; } @@ -114,7 +114,7 @@ class SpeechStateResponse : public Firebolt::JSON::NL_Json_Basic<::Firebolt::Tex ttsStatus_ = json["TTS_Status"].get(); success_ = json["success"].get(); } - ::Firebolt::TextToSpeech::SpeechStateResponse value() const override + [[nodiscard]] ::Firebolt::TextToSpeech::SpeechStateResponse value() const override { return ::Firebolt::TextToSpeech::SpeechStateResponse{speechState_, ttsStatus_, success_}; } @@ -137,7 +137,7 @@ class TTSStatusResponse : public Firebolt::JSON::NL_Json_Basic<::Firebolt::TextT ttsStatus_ = json["TTS_Status"].get(); success_ = json["success"].get(); } - ::Firebolt::TextToSpeech::TTSStatusResponse value() const override + [[nodiscard]] ::Firebolt::TextToSpeech::TTSStatusResponse value() const override { return ::Firebolt::TextToSpeech::TTSStatusResponse{ttsStatus_, success_}; } diff --git a/src/json_types/videooutput.h b/src/json_types/videooutput.h new file mode 100644 index 0000000..9cc1398 --- /dev/null +++ b/src/json_types/videooutput.h @@ -0,0 +1,188 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +// +// ============================================================================ +// AUTO-GENERATED by firebolt-sdk-gen v0.1.0 — DO NOT EDIT +// ============================================================================ +#ifndef FIREBOLT_VIDEOOUTPUT_JSON_H +#define FIREBOLT_VIDEOOUTPUT_JSON_H + +#include "firebolt/videooutput.h" +#include +#include + +namespace Firebolt::VideoOutput::JsonData +{ + +NLOHMANN_JSON_SERIALIZE_ENUM(CecStateValue, { + {CecStateValue::Active, "active"}, + {CecStateValue::Inactive, "inactive"}, + {CecStateValue::Unsupported, "unsupported"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(ColorDepthValue, { + {ColorDepthValue::D0, "0"}, + {ColorDepthValue::D10, "10"}, + {ColorDepthValue::D12, "12"}, + {ColorDepthValue::D8, "8"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(ColorFormatValue, { + {ColorFormatValue::None, "none"}, + {ColorFormatValue::Rgb444, "rgb444"}, + {ColorFormatValue::Ycbcr420, "ycbcr420"}, + {ColorFormatValue::Ycbcr422, "ycbcr422"}, + {ColorFormatValue::Ycbcr444, "ycbcr444"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(DynamicRangeValue, { + {DynamicRangeValue::DolbyVision, "dolbyVision"}, + {DynamicRangeValue::Hdr10, "hdr10"}, + {DynamicRangeValue::Hdr10plus, "hdr10plus"}, + {DynamicRangeValue::Hlg, "hlg"}, + {DynamicRangeValue::None, "none"}, + {DynamicRangeValue::Sdr, "sdr"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(HdcpState, { + {HdcpState::Direct, "direct"}, + {HdcpState::Hdcp14, "hdcp1.4"}, + {HdcpState::Hdcp22, "hdcp2.2"}, + {HdcpState::None, "none"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(OutputColorimetry, { + {OutputColorimetry::Bt2020rgb, "bt2020rgb"}, + {OutputColorimetry::Bt2020ycc, "bt2020ycc"}, + {OutputColorimetry::Bt709, "bt709"}, + {OutputColorimetry::None, "none"}, + {OutputColorimetry::Oprgb, "oprgb"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(QuantizationRangeValue, { + {QuantizationRangeValue::Full, "full"}, + {QuantizationRangeValue::Limited, "limited"}, + {QuantizationRangeValue::None, "none"}, + }) + +NLOHMANN_JSON_SERIALIZE_ENUM(RefreshRateValue, { + {RefreshRateValue::R0, "0"}, + {RefreshRateValue::R23976, "23.976"}, + {RefreshRateValue::R24, "24"}, + {RefreshRateValue::R25, "25"}, + {RefreshRateValue::R2997, "29.97"}, + {RefreshRateValue::R30, "30"}, + {RefreshRateValue::R50, "50"}, + {RefreshRateValue::R5994, "59.94"}, + {RefreshRateValue::R60, "60"}, + }) + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::CecStateValue> CecStateValueEnum({ + {"active", ::Firebolt::VideoOutput::CecStateValue::Active}, + {"inactive", ::Firebolt::VideoOutput::CecStateValue::Inactive}, + {"unsupported", ::Firebolt::VideoOutput::CecStateValue::Unsupported}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::ColorDepthValue> ColorDepthValueEnum({ + {"0", ::Firebolt::VideoOutput::ColorDepthValue::D0}, + {"10", ::Firebolt::VideoOutput::ColorDepthValue::D10}, + {"12", ::Firebolt::VideoOutput::ColorDepthValue::D12}, + {"8", ::Firebolt::VideoOutput::ColorDepthValue::D8}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::ColorFormatValue> ColorFormatValueEnum({ + {"none", ::Firebolt::VideoOutput::ColorFormatValue::None}, + {"rgb444", ::Firebolt::VideoOutput::ColorFormatValue::Rgb444}, + {"ycbcr420", ::Firebolt::VideoOutput::ColorFormatValue::Ycbcr420}, + {"ycbcr422", ::Firebolt::VideoOutput::ColorFormatValue::Ycbcr422}, + {"ycbcr444", ::Firebolt::VideoOutput::ColorFormatValue::Ycbcr444}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::DynamicRangeValue> DynamicRangeValueEnum({ + {"dolbyVision", ::Firebolt::VideoOutput::DynamicRangeValue::DolbyVision}, + {"hdr10", ::Firebolt::VideoOutput::DynamicRangeValue::Hdr10}, + {"hdr10plus", ::Firebolt::VideoOutput::DynamicRangeValue::Hdr10plus}, + {"hlg", ::Firebolt::VideoOutput::DynamicRangeValue::Hlg}, + {"none", ::Firebolt::VideoOutput::DynamicRangeValue::None}, + {"sdr", ::Firebolt::VideoOutput::DynamicRangeValue::Sdr}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::HdcpState> HdcpStateEnum({ + {"direct", ::Firebolt::VideoOutput::HdcpState::Direct}, + {"hdcp1.4", ::Firebolt::VideoOutput::HdcpState::Hdcp14}, + {"hdcp2.2", ::Firebolt::VideoOutput::HdcpState::Hdcp22}, + {"none", ::Firebolt::VideoOutput::HdcpState::None}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::OutputColorimetry> OutputColorimetryEnum({ + {"bt2020rgb", ::Firebolt::VideoOutput::OutputColorimetry::Bt2020rgb}, + {"bt2020ycc", ::Firebolt::VideoOutput::OutputColorimetry::Bt2020ycc}, + {"bt709", ::Firebolt::VideoOutput::OutputColorimetry::Bt709}, + {"none", ::Firebolt::VideoOutput::OutputColorimetry::None}, + {"oprgb", ::Firebolt::VideoOutput::OutputColorimetry::Oprgb}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::QuantizationRangeValue> QuantizationRangeValueEnum({ + {"full", ::Firebolt::VideoOutput::QuantizationRangeValue::Full}, + {"limited", ::Firebolt::VideoOutput::QuantizationRangeValue::Limited}, + {"none", ::Firebolt::VideoOutput::QuantizationRangeValue::None}, +}); + +inline const Firebolt::JSON::EnumType<::Firebolt::VideoOutput::RefreshRateValue> RefreshRateValueEnum({ + {"0", ::Firebolt::VideoOutput::RefreshRateValue::R0}, + {"23.976", ::Firebolt::VideoOutput::RefreshRateValue::R23976}, + {"24", ::Firebolt::VideoOutput::RefreshRateValue::R24}, + {"25", ::Firebolt::VideoOutput::RefreshRateValue::R25}, + {"29.97", ::Firebolt::VideoOutput::RefreshRateValue::R2997}, + {"30", ::Firebolt::VideoOutput::RefreshRateValue::R30}, + {"50", ::Firebolt::VideoOutput::RefreshRateValue::R50}, + {"59.94", ::Firebolt::VideoOutput::RefreshRateValue::R5994}, + {"60", ::Firebolt::VideoOutput::RefreshRateValue::R60}, +}); + +class VideoOutputResolution : public Firebolt::JSON::NL_Json_Basic<::Firebolt::VideoOutput::VideoOutputResolution> +{ +public: + void fromJson(const nlohmann::json& json) override + { + if (!checkRequiredFields(json, {"height", "width"})) + { + throw std::invalid_argument("Missing required fields in JSON"); + } + height_ = json["height"].get(); + width_ = json["width"].get(); + } + [[nodiscard]] ::Firebolt::VideoOutput::VideoOutputResolution value() const override + { + return ::Firebolt::VideoOutput::VideoOutputResolution{height_, width_}; + } + +private: + uint32_t height_{}; + uint32_t width_{}; +}; + +inline void to_json(nlohmann::json& j, const Firebolt::VideoOutput::VideoOutputResolution& v) +{ + j = nlohmann::json::object(); + j["height"] = v.height; + j["width"] = v.width; +} +} // namespace Firebolt::VideoOutput::JsonData + +#endif // FIREBOLT_VIDEOOUTPUT_JSON_H diff --git a/src/lifecycle_impl.cpp b/src/lifecycle_impl.cpp index 0380b56..5817d38 100644 --- a/src/lifecycle_impl.cpp +++ b/src/lifecycle_impl.cpp @@ -32,7 +32,7 @@ LifecycleImpl::LifecycleImpl(Firebolt::Helpers::IHelper& helper) { } -LifecycleImpl::~LifecycleImpl() {} +LifecycleImpl::~LifecycleImpl() = default; Result LifecycleImpl::close(const CloseType& reason) const { diff --git a/src/lifecycle_impl.h b/src/lifecycle_impl.h index 43a7796..6135381 100644 --- a/src/lifecycle_impl.h +++ b/src/lifecycle_impl.h @@ -39,16 +39,15 @@ class LifecycleImpl : public ILifecycle LifecycleImpl& operator=(const LifecycleImpl&) = delete; ~LifecycleImpl() override; - virtual Result close(const CloseType& type) const override; - virtual Result state() const override; + [[nodiscard]] Result close(const CloseType& type) const override; + [[nodiscard]] Result state() const override; Result subscribeOnStateChanged(std::function&)>&& notification) override; - virtual Result unsubscribe(SubscriptionId id) override; - virtual void unsubscribeAll() override; + Result unsubscribe(SubscriptionId id) override; + void unsubscribeAll() override; -private: private: Firebolt::Helpers::IHelper& helper_; Firebolt::Helpers::SubscriptionManager subscriptionManager_; diff --git a/src/localization_impl.h b/src/localization_impl.h index eb9df69..3c05e14 100644 --- a/src/localization_impl.h +++ b/src/localization_impl.h @@ -33,10 +33,10 @@ class LocalizationImpl : public ILocalization ~LocalizationImpl() override = default; // Methods - Result country() const override; - Result> preferredAudioLanguages() const override; - Result presentationLanguage() const override; - Result timeZone() const override; + [[nodiscard]] Result country() const override; + [[nodiscard]] Result> preferredAudioLanguages() const override; + [[nodiscard]] Result presentationLanguage() const override; + [[nodiscard]] Result timeZone() const override; // Events Result subscribeOnCountryChanged(std::function&& notification) override; diff --git a/src/metrics_impl.h b/src/metrics_impl.h index ace303b..1bccfa6 100644 --- a/src/metrics_impl.h +++ b/src/metrics_impl.h @@ -32,41 +32,42 @@ class MetricsImpl : public IMetrics ~MetricsImpl() override = default; - Result ready() const override; - Result signIn() const override; - Result signOut() const override; - Result startContent(const std::optional& entityId, - const std::optional agePolicy) const override; - Result stopContent(const std::optional& entityId, - const std::optional agePolicy) const override; - Result page(const std::string& pageId, const std::optional& agePolicy) const override; - Result error(const ErrorType type, const std::string& code, const std::string& description, - const bool visible, const std::optional>& parameters, - const std::optional& agePolicy) const override; - Result mediaLoadStart(const std::string& entityId, - const std::optional& agePolicy) const override; - Result mediaPlay(const std::string& entityId, - const std::optional& agePolicy) const override; - Result mediaPlaying(const std::string& entityId, - const std::optional& agePolicy) const override; - Result mediaPause(const std::string& entityId, - const std::optional& agePolicy) const override; - Result mediaWaiting(const std::string& entityId, - const std::optional& agePolicy) const override; - Result mediaSeeking(const std::string& entityId, const double target, - const std::optional& agePolicy) const override; - Result mediaSeeked(const std::string& entityId, const double position, - const std::optional& agePolicy) const override; - Result mediaRateChanged(const std::string& entityId, const double rate, - const std::optional& agePolicy) const override; - Result mediaRenditionChanged(const std::string& entityId, const unsigned bitrate, const unsigned width, - const unsigned height, const std::optional& profile, - const std::optional& agePolicy) const override; - Result mediaEnded(const std::string& entityId, - const std::optional& agePolicy) const override; - Result event(const std::string& schema, const std::string& data, - const std::optional& agePolicy) const override; - Result appInfo(const std::string& build) const override; + [[nodiscard]] Result ready() const override; + [[nodiscard]] Result signIn() const override; + [[nodiscard]] Result signOut() const override; + [[nodiscard]] Result startContent(const std::optional& entityId, + std::optional agePolicy) const override; + [[nodiscard]] Result stopContent(const std::optional& entityId, + std::optional agePolicy) const override; + [[nodiscard]] Result page(const std::string& pageId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result error(ErrorType type, const std::string& code, const std::string& description, + bool visible, const std::optional>& parameters, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaLoadStart(const std::string& entityId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaPlay(const std::string& entityId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaPlaying(const std::string& entityId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaPause(const std::string& entityId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaWaiting(const std::string& entityId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaSeeking(const std::string& entityId, double target, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaSeeked(const std::string& entityId, double position, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaRateChanged(const std::string& entityId, double rate, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaRenditionChanged(const std::string& entityId, unsigned bitrate, unsigned width, + unsigned height, const std::optional& profile, + const std::optional& agePolicy) const override; + [[nodiscard]] Result mediaEnded(const std::string& entityId, + const std::optional& agePolicy) const override; + [[nodiscard]] Result event(const std::string& schema, const std::string& data, + const std::optional& agePolicy) const override; + [[nodiscard]] Result appInfo(const std::string& build) const override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/network_impl.h b/src/network_impl.h index 178d22d..50ce47b 100644 --- a/src/network_impl.h +++ b/src/network_impl.h @@ -32,7 +32,7 @@ class NetworkImpl : public INetwork ~NetworkImpl() override = default; - Result connected() const override; + [[nodiscard]] Result connected() const override; Result subscribeOnConnectedChanged(std::function&& notification) override; diff --git a/src/presentation_impl.h b/src/presentation_impl.h index b37485e..26637d4 100644 --- a/src/presentation_impl.h +++ b/src/presentation_impl.h @@ -34,11 +34,11 @@ class PresentationImpl : public IPresentation ~PresentationImpl() override = default; - Result focused() const override; + [[nodiscard]] Result focused() const override; Result subscribeOnFocusedChanged(std::function&& notification) override; - virtual Result unsubscribe(SubscriptionId id) override; - virtual void unsubscribeAll() override; + Result unsubscribe(SubscriptionId id) override; + void unsubscribeAll() override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/stats_impl.cpp b/src/stats_impl.cpp index a61e413..fa16a80 100644 --- a/src/stats_impl.cpp +++ b/src/stats_impl.cpp @@ -31,7 +31,7 @@ StatsImpl::StatsImpl(Firebolt::Helpers::IHelper& helper) { } -StatsImpl::~StatsImpl() {} +StatsImpl::~StatsImpl() = default; Result StatsImpl::memoryUsage() const { diff --git a/src/stats_impl.h b/src/stats_impl.h index fa693f6..f662375 100644 --- a/src/stats_impl.h +++ b/src/stats_impl.h @@ -32,7 +32,7 @@ class StatsImpl : public IStats StatsImpl& operator=(const StatsImpl&) = delete; ~StatsImpl() override; - virtual Result memoryUsage() const override; + [[nodiscard]] Result memoryUsage() const override; private: Firebolt::Helpers::IHelper& helper_; diff --git a/src/texttospeech_impl.h b/src/texttospeech_impl.h index a4aef02..6dc646d 100644 --- a/src/texttospeech_impl.h +++ b/src/texttospeech_impl.h @@ -32,12 +32,12 @@ class TextToSpeechImpl : public ITextToSpeech ~TextToSpeechImpl() override = default; - Result listVoices(const std::string& language) const override; - Result speak(const std::string& text) const override; - Result pause(SpeechId speechId) const override; - Result resume(SpeechId speechId) const override; - Result cancel(SpeechId speechId) const override; - Result getSpeechState(SpeechId speechId) const override; + [[nodiscard]] Result listVoices(const std::string& language) const override; + [[nodiscard]] Result speak(const std::string& text) const override; + [[nodiscard]] Result pause(SpeechId speechId) const override; + [[nodiscard]] Result resume(SpeechId speechId) const override; + [[nodiscard]] Result cancel(SpeechId speechId) const override; + [[nodiscard]] Result getSpeechState(SpeechId speechId) const override; Result subscribeOnWillSpeak(std::function&& notification) override; Result subscribeOnSpeechStart(std::function&& notification) override; diff --git a/src/videooutput_impl.cpp b/src/videooutput_impl.cpp new file mode 100644 index 0000000..73242b3 --- /dev/null +++ b/src/videooutput_impl.cpp @@ -0,0 +1,113 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +// +// ============================================================================ +// AUTO-GENERATED by firebolt-sdk-gen v0.1.0 — DO NOT EDIT +// ============================================================================ +#include "videooutput_impl.h" +#include "json_types/videooutput.h" +#include + +namespace Firebolt::VideoOutput +{ +VideoOutputImpl::VideoOutputImpl(Firebolt::Helpers::IHelper& helper) + : helper_(helper), + subscriptionManager_(helper, this) +{ +} + +Result VideoOutputImpl::resolution() const +{ + return helper_.get("VideoOutput.resolution"); +} +Result +VideoOutputImpl::subscribeOnResolutionChanged(std::function&& notification) +{ + return subscriptionManager_.subscribe("VideoOutput.onResolutionChanged", + std::move(notification)); +} + +Result VideoOutputImpl::hdcp() const +{ + return helper_.get, HdcpState>("VideoOutput.hdcp"); +} +Result VideoOutputImpl::subscribeOnHdcpChanged(std::function&& notification) +{ + return subscriptionManager_.subscribe>("VideoOutput.onHdcpChanged", + std::move(notification)); +} + +Result VideoOutputImpl::cecState() const +{ + return helper_.get, CecStateValue>("VideoOutput.cecState"); +} +Result VideoOutputImpl::subscribeOnCecStateChanged(std::function&& notification) +{ + return subscriptionManager_.subscribe>("VideoOutput.onCecStateChanged", + std::move(notification)); +} + +Result VideoOutputImpl::refreshRate() const +{ + return helper_.get, RefreshRateValue>("VideoOutput.refreshRate"); +} +Result +VideoOutputImpl::subscribeOnRefreshRateChanged(std::function&& notification) +{ + return subscriptionManager_ + .subscribe>("VideoOutput.onRefreshRateChanged", + std::move(notification)); +} + +Result VideoOutputImpl::colorDepth() const +{ + return helper_.get, ColorDepthValue>("VideoOutput.colorDepth"); +} + +Result VideoOutputImpl::colorFormat() const +{ + return helper_.get, ColorFormatValue>("VideoOutput.colorFormat"); +} + +Result VideoOutputImpl::colorimetry() const +{ + return helper_.get, OutputColorimetry>("VideoOutput.colorimetry"); +} + +Result VideoOutputImpl::dynamicRange() const +{ + return helper_.get, DynamicRangeValue>("VideoOutput.dynamicRange"); +} + +Result VideoOutputImpl::quantizationRange() const +{ + return helper_.get, QuantizationRangeValue>( + "VideoOutput.quantizationRange"); +} + +Result VideoOutputImpl::unsubscribe(SubscriptionId id) +{ + return subscriptionManager_.unsubscribe(id); +} + +void VideoOutputImpl::unsubscribeAll() +{ + subscriptionManager_.unsubscribeAll(); +} + +} // namespace Firebolt::VideoOutput diff --git a/src/videooutput_impl.h b/src/videooutput_impl.h new file mode 100644 index 0000000..8d2b4ec --- /dev/null +++ b/src/videooutput_impl.h @@ -0,0 +1,71 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#ifndef FIREBOLT_VIDEOOUTPUT_IMPL_H +#define FIREBOLT_VIDEOOUTPUT_IMPL_H + +#include "firebolt/videooutput.h" +#include + +namespace Firebolt::VideoOutput +{ + +class VideoOutputImpl : public IVideoOutput +{ +public: + explicit VideoOutputImpl(Firebolt::Helpers::IHelper& helper); + VideoOutputImpl(const VideoOutputImpl&) = delete; + VideoOutputImpl& operator=(const VideoOutputImpl&) = delete; + VideoOutputImpl(VideoOutputImpl&&) = delete; + VideoOutputImpl& operator=(VideoOutputImpl&&) = delete; + ~VideoOutputImpl() override = default; + [[nodiscard]] Result resolution() const override; + Result + subscribeOnResolutionChanged(std::function&& notification) override; + + [[nodiscard]] Result hdcp() const override; + Result subscribeOnHdcpChanged(std::function&& notification) override; + + [[nodiscard]] Result cecState() const override; + Result subscribeOnCecStateChanged(std::function&& notification) override; + + [[nodiscard]] Result refreshRate() const override; + Result + subscribeOnRefreshRateChanged(std::function&& notification) override; + + [[nodiscard]] Result colorDepth() const override; + + [[nodiscard]] Result colorFormat() const override; + + [[nodiscard]] Result colorimetry() const override; + + [[nodiscard]] Result dynamicRange() const override; + + [[nodiscard]] Result quantizationRange() const override; + + Result unsubscribe(SubscriptionId id) override; + void unsubscribeAll() override; + +private: + Firebolt::Helpers::IHelper& helper_; + Firebolt::Helpers::SubscriptionManager subscriptionManager_; +}; + +} // namespace Firebolt::VideoOutput + +#endif // FIREBOLT_VIDEOOUTPUT_IMPL_H diff --git a/test/component/accessibilityTest.cpp b/test/component/accessibilityTest.cpp index 856aca7..cf7d8db 100644 --- a/test/component/accessibilityTest.cpp +++ b/test/component/accessibilityTest.cpp @@ -50,7 +50,7 @@ TEST_F(AccessibilityCTest, SubscribeOnAudioDescriptionChanged) [&](const bool& enabled) { - std::cout << "[Subscription] Accessibility audio description changed" << std::endl; + std::cout << "[Subscription] Accessibility audio description changed" << '\n'; EXPECT_EQ(enabled, true); { @@ -83,7 +83,7 @@ TEST_F(AccessibilityCTest, SubscribeOnClosedCaptionsSettingsChanged) auto id = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().subscribeOnClosedCaptionsSettingsChanged( [&](const Firebolt::Accessibility::ClosedCaptionsSettings& settings) { - std::cout << "[Subscription] Accessibility closed captions settings changed" << std::endl; + std::cout << "[Subscription] Accessibility closed captions settings changed" << '\n'; EXPECT_EQ(settings.enabled, true); EXPECT_EQ(settings.preferredLanguages.size(), 2); @@ -126,7 +126,7 @@ TEST_F(AccessibilityCTest, SubscribeOnHighContrastUIChanged) auto id = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().subscribeOnHighContrastUIChanged( [&](const bool& enabled) { - std::cout << "[Subscription] Accessibility high contrast UI changed" << std::endl; + std::cout << "[Subscription] Accessibility high contrast UI changed" << '\n'; EXPECT_EQ(enabled, true); { @@ -161,7 +161,7 @@ TEST_F(AccessibilityCTest, SubscribeOnVoiceGuidanceSettingsChanged) auto id = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().subscribeOnVoiceGuidanceSettingsChanged( [&](const Firebolt::Accessibility::VoiceGuidanceSettings& settings) { - std::cout << "[Subscription] Accessibility voice guidance settings changed" << std::endl; + std::cout << "[Subscription] Accessibility voice guidance settings changed" << '\n'; EXPECT_EQ(settings.enabled, true); EXPECT_EQ(settings.rate, 0.8); diff --git a/test/component/actionsGeneratedTest.cpp b/test/component/actionsGeneratedTest.cpp index a3ce10a..ceb55a7 100644 --- a/test/component/actionsGeneratedTest.cpp +++ b/test/component/actionsGeneratedTest.cpp @@ -40,7 +40,7 @@ TEST_F(ActionsGeneratedCTest, Intent) ASSERT_TRUE(result->intent.context); ASSERT_TRUE(result->intent.context->source); EXPECT_EQ(*result->intent.context->source, "system"); - EXPECT_EQ(result->intentId, 0u); + EXPECT_EQ(result->intentId, 0U); } TEST_F(ActionsGeneratedCTest, SubscribeOnIntent) @@ -52,7 +52,7 @@ TEST_F(ActionsGeneratedCTest, SubscribeOnIntent) ASSERT_TRUE(payload.intent.context); ASSERT_TRUE(payload.intent.context->source); EXPECT_EQ(*payload.intent.context->source, "system"); - EXPECT_EQ(payload.intentId, 0u); + EXPECT_EQ(payload.intentId, 0U); { std::lock_guard lock(mtx); eventReceived = true; diff --git a/test/component/deviceTest.cpp b/test/component/deviceTest.cpp index 62f5858..5536070 100644 --- a/test/component/deviceTest.cpp +++ b/test/component/deviceTest.cpp @@ -69,7 +69,7 @@ TEST_F(DeviceCTest, TimeInActiveState) ASSERT_TRUE(result) << "DeviceImpl::timeInActiveState() returned an error"; if (expectedValue.empty()) { - std::cout << "[ !!! ] Expected is empty, received: " << *result << std::endl; + std::cout << "[ !!! ] Expected is empty, received: " << *result << '\n'; return; } EXPECT_EQ(*result, expectedValue); @@ -90,7 +90,7 @@ TEST_F(DeviceCTest, Uptime) ASSERT_TRUE(result) << "DeviceImpl::uptime() returned an error"; if (expectedValue.empty()) { - std::cout << "[ !!! ] Expected is empty, received: " << *result << std::endl; + std::cout << "[ !!! ] Expected is empty, received: " << *result << '\n'; return; } EXPECT_EQ(*result, expectedValue); @@ -101,7 +101,7 @@ TEST_F(DeviceCTest, SubscribeOnHdrChanged) auto id = Firebolt::IFireboltAccessor::Instance().DeviceInterface().subscribeOnHdrChanged( [&](const Firebolt::Device::HDRFormat& value) { - std::cout << "[Subscription] Device HDR changed" << std::endl; + std::cout << "[Subscription] Device HDR changed" << '\n'; EXPECT_EQ(value.hdr10, true); EXPECT_EQ(value.hdr10Plus, true); EXPECT_EQ(value.dolbyVision, true); @@ -135,7 +135,7 @@ TEST_F(DeviceCTest, SubscribeOnDolbyAtmosExperienceAvailableChanged) auto id = Firebolt::IFireboltAccessor::Instance().DeviceInterface().subscribeOnDolbyAtmosExperienceAvailableChanged( [&](const bool& value) { - std::cout << "[Subscription] Device Dolby Atmos experience availability changed" << std::endl; + std::cout << "[Subscription] Device Dolby Atmos experience availability changed" << '\n'; EXPECT_EQ(value, true); { std::lock_guard lock(mtx); diff --git a/test/component/discoveryTest.cpp b/test/component/discoveryTest.cpp index 8caf34f..bb04cca 100644 --- a/test/component/discoveryTest.cpp +++ b/test/component/discoveryTest.cpp @@ -30,7 +30,7 @@ class DiscoveryCTest : public ::testing::Test TEST_F(DiscoveryCTest, Watched) { auto expectedValue = jsonEngine.get_value("Discovery.watched"); - auto result = Firebolt::IFireboltAccessor::Instance().DiscoveryInterface().watched("entity123", 0.75f, true, + auto result = Firebolt::IFireboltAccessor::Instance().DiscoveryInterface().watched("entity123", 0.75F, true, "2024-10-01T12:00:00Z", Firebolt::AgePolicy::ADULT); ASSERT_TRUE(result) << "Failed to call watched"; @@ -40,7 +40,7 @@ TEST_F(DiscoveryCTest, Watched) TEST_F(DiscoveryCTest, WatchedV2) { - auto result = Firebolt::IFireboltAccessor::Instance().DiscoveryInterface().watchedV2("entity123", 0.75f, true, + auto result = Firebolt::IFireboltAccessor::Instance().DiscoveryInterface().watchedV2("entity123", 0.75F, true, "2024-10-01T12:00:00Z", Firebolt::AgePolicy::ADULT); ASSERT_TRUE(result) << "Failed to call watchedV2"; diff --git a/test/component/lifecycleTest.cpp b/test/component/lifecycleTest.cpp index d6504c9..4047461 100644 --- a/test/component/lifecycleTest.cpp +++ b/test/component/lifecycleTest.cpp @@ -59,9 +59,9 @@ TEST_F(LifecycleCTest, subscribeOnState_JSON_RPC_compliant) auto id = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().subscribeOnStateChanged( [&](const std::vector& changes) { - EXPECT_TRUE(changes.size() > 0); + EXPECT_TRUE(!changes.empty()); std::cout << "[Subscription] Lifecycle state changed: " << static_cast(changes[0].newState) - << ", old state: " << static_cast(changes[0].oldState) << std::endl; + << ", old state: " << static_cast(changes[0].oldState) << '\n'; EXPECT_EQ(changes[0].newState, Firebolt::Lifecycle::LifecycleState::PAUSED); EXPECT_EQ(changes[0].oldState, Firebolt::Lifecycle::LifecycleState::INITIALIZING); @@ -91,9 +91,9 @@ TEST_F(LifecycleCTest, subscribeOnState_noValue) auto id = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().subscribeOnStateChanged( [&](const std::vector& changes) { - EXPECT_TRUE(changes.size() > 0); + EXPECT_TRUE(!changes.empty()); std::cout << "[Subscription] Lifecycle state changed: " << static_cast(changes[0].newState) - << ", old state: " << static_cast(changes[0].oldState) << std::endl; + << ", old state: " << static_cast(changes[0].oldState) << '\n'; EXPECT_EQ(changes[0].newState, Firebolt::Lifecycle::LifecycleState::PAUSED); EXPECT_EQ(changes[0].oldState, Firebolt::Lifecycle::LifecycleState::INITIALIZING); @@ -109,7 +109,7 @@ TEST_F(LifecycleCTest, subscribeOnState_noValue) Firebolt::Config config; if (config.legacyRPCv1) { - std::cout << "Commented out as it cannot be tested in CI/CI due to unknown 'id' value" << std::endl; + std::cout << "Commented out as it cannot be tested in CI/CI due to unknown 'id' value" << '\n'; /* nlohmann::json p; p["id"] = 30; diff --git a/test/component/metricsTest.cpp b/test/component/metricsTest.cpp index 9e1d6fc..6c1e9b7 100644 --- a/test/component/metricsTest.cpp +++ b/test/component/metricsTest.cpp @@ -200,7 +200,7 @@ TEST_F(MetricsCTest, MediaEnded) TEST_F(MetricsCTest, Event) { auto result = Firebolt::IFireboltAccessor::Instance().MetricsInterface().event("https://com.example.event", - "{\"key\":\"value\"}", + R"({"key":"value"})", Firebolt::AgePolicy::ADULT); ASSERT_TRUE(result) << "MetricsImpl::event() returned an error"; } diff --git a/test/component/networkTest.cpp b/test/component/networkTest.cpp index aedf44c..ae74fb2 100644 --- a/test/component/networkTest.cpp +++ b/test/component/networkTest.cpp @@ -47,7 +47,7 @@ TEST_F(NetworkCTest, SubscribeOnConnectedChanged) auto id = Firebolt::IFireboltAccessor::Instance().NetworkInterface().subscribeOnConnectedChanged( [&](const bool& value) { - std::cout << "[Subscription] Network connected changed" << std::endl; + std::cout << "[Subscription] Network connected changed" << '\n'; EXPECT_EQ(value, true); { std::lock_guard lock(mtx); diff --git a/test/component/presentationTest.cpp b/test/component/presentationTest.cpp index a4bc8f5..d909b61 100644 --- a/test/component/presentationTest.cpp +++ b/test/component/presentationTest.cpp @@ -73,7 +73,7 @@ TEST_F(PresentationCTest, unsubscribeInCallback) Firebolt::IFireboltAccessor::Instance().PresentationInterface().subscribeOnFocusedChanged( [&](const bool& /* focus */) { - std::cout << "In the callback, unsubscribing from the event" << subscriptionId << std::endl; + std::cout << "In the callback, unsubscribing from the event" << subscriptionId << '\n'; auto result = Firebolt::IFireboltAccessor::Instance().PresentationInterface().unsubscribe(subscriptionId); verifyUnsubscribeResult(result); { diff --git a/test/component/videooutputGeneratedTest.cpp b/test/component/videooutputGeneratedTest.cpp new file mode 100644 index 0000000..b2f9958 --- /dev/null +++ b/test/component/videooutputGeneratedTest.cpp @@ -0,0 +1,36 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "firebolt/videooutput.h" +#include + +TEST(VideooutputGeneratedCTest, InterfaceSurfaceHasresolution) +{ + using Interface = Firebolt::VideoOutput::IVideoOutput; + auto ptr = &Interface::resolution; + (void)ptr; + SUCCEED(); +} + +TEST(VideooutputGeneratedCTest, InterfaceSurfaceHascolorDepth) +{ + using Interface = Firebolt::VideoOutput::IVideoOutput; + auto ptr = &Interface::colorDepth; + (void)ptr; + SUCCEED(); +} diff --git a/test/unit/actionsTest.cpp b/test/unit/actionsTest.cpp index 12a9089..98936f7 100644 --- a/test/unit/actionsTest.cpp +++ b/test/unit/actionsTest.cpp @@ -32,7 +32,7 @@ TEST_F(ActionsUTest, Intent) { mock_with_response("Actions.intent", nlohmann::json({{"intent", {{"action", "pre-load"}, {"context", {{"source", "system"}}}}}, - {"intentId", 0u}})); + {"intentId", 0U}})); auto result = actionsImpl_.intent(); ASSERT_TRUE(result) << "ActionsImpl::intent() returned an error"; @@ -40,7 +40,7 @@ TEST_F(ActionsUTest, Intent) ASSERT_TRUE(result->intent.context); ASSERT_TRUE(result->intent.context->source); EXPECT_EQ(*result->intent.context->source, "system"); - EXPECT_EQ(result->intentId, 0u); + EXPECT_EQ(result->intentId, 0U); } TEST_F(ActionsUTest, SubscribeOnIntent) diff --git a/test/unit/discoveryTest.cpp b/test/unit/discoveryTest.cpp index 09dd9da..aee6363 100644 --- a/test/unit/discoveryTest.cpp +++ b/test/unit/discoveryTest.cpp @@ -38,7 +38,7 @@ TEST_F(DiscoveryUTest, watched) { mock("Discovery.watched"); std::string entityId = "content123"; - std::optional progress = 0.75f; + std::optional progress = 0.75F; std::optional completed = true; std::optional watchedOn = "2024-06-01T12:00:00Z"; std::optional agePolicy = Firebolt::AgePolicy::ADULT; @@ -53,7 +53,7 @@ TEST_F(DiscoveryUTest, watched_payload) { nlohmann::json expected; expected["entityId"] = "content123"; - expected["progress"] = 0.75f; + expected["progress"] = 0.75F; expected["completed"] = true; expected["watchedOn"] = "2024-06-01T12:00:00Z"; expected["agePolicy"] = "app:adult"; @@ -67,7 +67,7 @@ TEST_F(DiscoveryUTest, watched_payload) return Firebolt::Result{nlohmann::json(res)}; })); std::string entityId = "content123"; - std::optional progress = 0.75f; + std::optional progress = 0.75F; std::optional completed = true; std::optional watchedOn = "2024-06-01T12:00:00Z"; std::optional agePolicy = Firebolt::AgePolicy::ADULT; @@ -80,7 +80,7 @@ TEST_F(DiscoveryUTest, watchedV2) { mockInvoke("Discovery.watched"); std::string entityId = "content123"; - std::optional progress = 0.75f; + std::optional progress = 0.75F; std::optional completed = true; std::optional watchedOn = "2024-06-01T12:00:00Z"; std::optional agePolicy = Firebolt::AgePolicy::ADULT; @@ -92,7 +92,7 @@ TEST_F(DiscoveryUTest, watchedV2_payload) { nlohmann::json expected; expected["entityId"] = "content123"; - expected["progress"] = 0.75f; + expected["progress"] = 0.75F; expected["completed"] = true; expected["watchedOn"] = "2024-06-01T12:00:00Z"; expected["agePolicy"] = "app:adult"; @@ -105,7 +105,7 @@ TEST_F(DiscoveryUTest, watchedV2_payload) return Firebolt::Result{Firebolt::Error::None}; })); std::string entityId = "content123"; - std::optional progress = 0.75f; + std::optional progress = 0.75F; std::optional completed = true; std::optional watchedOn = "2024-06-01T12:00:00Z"; std::optional agePolicy = Firebolt::AgePolicy::ADULT; diff --git a/test/unit/metricsTest.cpp b/test/unit/metricsTest.cpp index a7dbcab..627ec7e 100644 --- a/test/unit/metricsTest.cpp +++ b/test/unit/metricsTest.cpp @@ -173,7 +173,7 @@ TEST_F(MetricsUTest, MediaEnded) TEST_F(MetricsUTest, Event) { mockInvoke("Metrics.event"); - auto result = metricsImpl_.event("https://com.example.schema", "{\"key\":\"value\"}", Firebolt::AgePolicy::ADULT); + auto result = metricsImpl_.event("https://com.example.schema", R"({"key":"value"})", Firebolt::AgePolicy::ADULT); EXPECT_TRUE(result); } diff --git a/test/unit/videooutputGeneratedTest.cpp b/test/unit/videooutputGeneratedTest.cpp new file mode 100644 index 0000000..736ac6c --- /dev/null +++ b/test/unit/videooutputGeneratedTest.cpp @@ -0,0 +1,443 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mock_helper.h" +#include "videooutput_impl.h" +#include +#include + +class VideooutputGeneratedUTest : public ::testing::Test +{ +protected: + static bool areGetterParamsEmpty(const nlohmann::json& params) + { + return params.is_null() || (params.is_object() && params.empty()); + } + + void expectGetterResponse(const std::string& methodName, const nlohmann::json& response) + { + EXPECT_CALL(mockHelper, getJson(methodName, ::testing::_)) + .WillOnce(::testing::Invoke( + [methodName, response](const std::string& /*method*/, const nlohmann::json& params) + { + EXPECT_TRUE(areGetterParamsEmpty(params)) << methodName << " getter should not send request params"; + return Firebolt::Result{response}; + })); + } + + void expectGetterTransportError(const std::string& methodName, Firebolt::Error error = Firebolt::Error::General) + { + EXPECT_CALL(mockHelper, getJson(methodName, ::testing::_)) + .WillOnce(::testing::Invoke( + [methodName, error](const std::string& /*method*/, const nlohmann::json& params) + { + EXPECT_TRUE(areGetterParamsEmpty(params)) << methodName << " getter should not send request params"; + return Firebolt::Result{error}; + })); + } + + ::testing::NiceMock mockHelper; + Firebolt::VideoOutput::VideoOutputImpl impl{mockHelper}; +}; + +TEST_F(VideooutputGeneratedUTest, Constructs) +{ + SUCCEED(); +} + +TEST_F(VideooutputGeneratedUTest, UnsubscribeForwardsToHelper) +{ + EXPECT_CALL(mockHelper, unsubscribe(7)).WillOnce(::testing::Return(Firebolt::Result{Firebolt::Error::None})); + + auto result = impl.unsubscribe(7); + ASSERT_TRUE(result) << "unsubscribe should return success when helper succeeds"; +} + +TEST_F(VideooutputGeneratedUTest, UnsubscribeForwardsHelperErrors) +{ + EXPECT_CALL(mockHelper, unsubscribe(42)).WillOnce(::testing::Return(Firebolt::Result{Firebolt::Error::General})); + + auto result = impl.unsubscribe(42); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, UnsubscribeAllForwardsToHelper) +{ + EXPECT_CALL(mockHelper, unsubscribeAll(&impl)).Times(2); + + impl.unsubscribeAll(); +} + +TEST_F(VideooutputGeneratedUTest, ResolutionReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.resolution", nlohmann::json{{"height", 1080}, {"width", 1920}}); + + auto result = impl.resolution(); + ASSERT_TRUE(result); + EXPECT_EQ(result->height, 1080U); + EXPECT_EQ(result->width, 1920U); +} + +TEST_F(VideooutputGeneratedUTest, ResolutionForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.resolution"); + + auto result = impl.resolution(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, ResolutionReturnsInvalidParamsWhenPayloadIsMalformed) +{ + expectGetterResponse("VideoOutput.resolution", nlohmann::json{{"width", 1920}}); + + auto result = impl.resolution(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::InvalidParams); +} + +TEST_F(VideooutputGeneratedUTest, HdcpReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.hdcp", nlohmann::json(static_cast(Firebolt::VideoOutput::HdcpState::Hdcp22))); + + auto result = impl.hdcp(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::HdcpState::Hdcp22); +} + +TEST_F(VideooutputGeneratedUTest, HdcpForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.hdcp"); + + auto result = impl.hdcp(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, CecStateReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.cecState", + nlohmann::json(static_cast(Firebolt::VideoOutput::CecStateValue::Inactive))); + + auto result = impl.cecState(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::CecStateValue::Inactive); +} + +TEST_F(VideooutputGeneratedUTest, CecStateForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.cecState"); + + auto result = impl.cecState(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, RefreshRateReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.refreshRate", + nlohmann::json(static_cast(Firebolt::VideoOutput::RefreshRateValue::R5994))); + + auto result = impl.refreshRate(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::RefreshRateValue::R5994); +} + +TEST_F(VideooutputGeneratedUTest, RefreshRateForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.refreshRate"); + + auto result = impl.refreshRate(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, ColorDepthReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.colorDepth", + nlohmann::json(static_cast(Firebolt::VideoOutput::ColorDepthValue::D12))); + + auto result = impl.colorDepth(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::ColorDepthValue::D12); +} + +TEST_F(VideooutputGeneratedUTest, ColorDepthForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.colorDepth"); + + auto result = impl.colorDepth(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, ColorFormatReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.colorFormat", + nlohmann::json(static_cast(Firebolt::VideoOutput::ColorFormatValue::Ycbcr444))); + + auto result = impl.colorFormat(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::ColorFormatValue::Ycbcr444); +} + +TEST_F(VideooutputGeneratedUTest, ColorFormatForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.colorFormat"); + + auto result = impl.colorFormat(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, ColorimetryReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.colorimetry", + nlohmann::json(static_cast(Firebolt::VideoOutput::OutputColorimetry::Bt2020rgb))); + + auto result = impl.colorimetry(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::OutputColorimetry::Bt2020rgb); +} + +TEST_F(VideooutputGeneratedUTest, ColorimetryForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.colorimetry"); + + auto result = impl.colorimetry(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, DynamicRangeReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.dynamicRange", + nlohmann::json(static_cast(Firebolt::VideoOutput::DynamicRangeValue::Hdr10plus))); + + auto result = impl.dynamicRange(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::DynamicRangeValue::Hdr10plus); +} + +TEST_F(VideooutputGeneratedUTest, DynamicRangeForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.dynamicRange"); + + auto result = impl.dynamicRange(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, QuantizationRangeReturnsParsedValue) +{ + expectGetterResponse("VideoOutput.quantizationRange", + nlohmann::json(static_cast(Firebolt::VideoOutput::QuantizationRangeValue::Limited))); + + auto result = impl.quantizationRange(); + ASSERT_TRUE(result); + EXPECT_EQ(*result, Firebolt::VideoOutput::QuantizationRangeValue::Limited); +} + +TEST_F(VideooutputGeneratedUTest, QuantizationRangeForwardsTransportErrors) +{ + expectGetterTransportError("VideoOutput.quantizationRange"); + + auto result = impl.quantizationRange(); + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnResolutionChangedForwardsAndDispatchesParsedPayload) +{ + bool notified = false; + Firebolt::VideoOutput::VideoOutputResolution received{}; + + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onResolutionChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](void* owner, const std::string& eventName, std::any&& notification, + void (*callback)(void*, const nlohmann::json&)) + { + Firebolt::Helpers::SubscriptionData data{owner, eventName, std::move(notification)}; + callback(&data, nlohmann::json{{"height", 2160}, {"width", 3840}}); + return Firebolt::Result{99}; + })); + + auto result = impl.subscribeOnResolutionChanged( + [&](const Firebolt::VideoOutput::VideoOutputResolution& value) + { + notified = true; + received = value; + }); + + ASSERT_TRUE(result); + EXPECT_EQ(*result, 99U); + EXPECT_TRUE(notified); + EXPECT_EQ(received.height, 2160U); + EXPECT_EQ(received.width, 3840U); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnResolutionChangedSwallowsMalformedEventPayload) +{ + bool notified = false; + + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onResolutionChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](void* owner, const std::string& eventName, std::any&& notification, + void (*callback)(void*, const nlohmann::json&)) + { + Firebolt::Helpers::SubscriptionData data{owner, eventName, std::move(notification)}; + callback(&data, nlohmann::json{{"width", 3840}}); + return Firebolt::Result{5}; + })); + + auto result = impl.subscribeOnResolutionChanged([&](const Firebolt::VideoOutput::VideoOutputResolution& /*value*/) + { notified = true; }); + + ASSERT_TRUE(result); + EXPECT_EQ(*result, 5U); + EXPECT_FALSE(notified); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnResolutionChangedForwardsSubscribeErrors) +{ + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onResolutionChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Firebolt::Result{Firebolt::Error::General})); + + auto result = impl.subscribeOnResolutionChanged([](const Firebolt::VideoOutput::VideoOutputResolution& /*value*/) {}); + + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnHdcpChangedForwardsAndDispatchesParsedPayload) +{ + bool notified = false; + Firebolt::VideoOutput::HdcpState received = Firebolt::VideoOutput::HdcpState::None; + + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onHdcpChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](void* owner, const std::string& eventName, std::any&& notification, + void (*callback)(void*, const nlohmann::json&)) + { + Firebolt::Helpers::SubscriptionData data{owner, eventName, std::move(notification)}; + callback(&data, nlohmann::json(static_cast(Firebolt::VideoOutput::HdcpState::Direct))); + return Firebolt::Result{11}; + })); + + auto result = impl.subscribeOnHdcpChanged( + [&](const Firebolt::VideoOutput::HdcpState& value) + { + notified = true; + received = value; + }); + + ASSERT_TRUE(result); + EXPECT_EQ(*result, 11U); + EXPECT_TRUE(notified); + EXPECT_EQ(received, Firebolt::VideoOutput::HdcpState::Direct); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnHdcpChangedForwardsSubscribeErrors) +{ + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onHdcpChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Firebolt::Result{Firebolt::Error::General})); + + auto result = impl.subscribeOnHdcpChanged([](const Firebolt::VideoOutput::HdcpState& /*value*/) {}); + + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnCecStateChangedForwardsAndDispatchesParsedPayload) +{ + bool notified = false; + Firebolt::VideoOutput::CecStateValue received = Firebolt::VideoOutput::CecStateValue::Unsupported; + + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onCecStateChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](void* owner, const std::string& eventName, std::any&& notification, + void (*callback)(void*, const nlohmann::json&)) + { + Firebolt::Helpers::SubscriptionData data{owner, eventName, std::move(notification)}; + callback(&data, nlohmann::json(static_cast(Firebolt::VideoOutput::CecStateValue::Active))); + return Firebolt::Result{12}; + })); + + auto result = impl.subscribeOnCecStateChanged( + [&](const Firebolt::VideoOutput::CecStateValue& value) + { + notified = true; + received = value; + }); + + ASSERT_TRUE(result); + EXPECT_EQ(*result, 12U); + EXPECT_TRUE(notified); + EXPECT_EQ(received, Firebolt::VideoOutput::CecStateValue::Active); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnCecStateChangedForwardsSubscribeErrors) +{ + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onCecStateChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Firebolt::Result{Firebolt::Error::General})); + + auto result = impl.subscribeOnCecStateChanged([](const Firebolt::VideoOutput::CecStateValue& /*value*/) {}); + + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnRefreshRateChangedForwardsAndDispatchesParsedPayload) +{ + bool notified = false; + Firebolt::VideoOutput::RefreshRateValue received = Firebolt::VideoOutput::RefreshRateValue::R0; + + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onRefreshRateChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](void* owner, const std::string& eventName, std::any&& notification, + void (*callback)(void*, const nlohmann::json&)) + { + Firebolt::Helpers::SubscriptionData data{owner, eventName, std::move(notification)}; + callback(&data, nlohmann::json(static_cast(Firebolt::VideoOutput::RefreshRateValue::R24))); + return Firebolt::Result{13}; + })); + + auto result = impl.subscribeOnRefreshRateChanged( + [&](const Firebolt::VideoOutput::RefreshRateValue& value) + { + notified = true; + received = value; + }); + + ASSERT_TRUE(result); + EXPECT_EQ(*result, 13U); + EXPECT_TRUE(notified); + EXPECT_EQ(received, Firebolt::VideoOutput::RefreshRateValue::R24); +} + +TEST_F(VideooutputGeneratedUTest, SubscribeOnRefreshRateChangedForwardsSubscribeErrors) +{ + EXPECT_CALL(mockHelper, subscribe(&impl, "VideoOutput.onRefreshRateChanged", ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Firebolt::Result{Firebolt::Error::General})); + + auto result = impl.subscribeOnRefreshRateChanged([](const Firebolt::VideoOutput::RefreshRateValue& /*value*/) {}); + + ASSERT_FALSE(result); + EXPECT_EQ(result.error(), Firebolt::Error::General); +}