diff --git a/docs/openrpc/the-spec/firebolt-app-open-rpc.json b/docs/openrpc/the-spec/firebolt-app-open-rpc.json index b2eff49..04b62ba 100644 --- a/docs/openrpc/the-spec/firebolt-app-open-rpc.json +++ b/docs/openrpc/the-spec/firebolt-app-open-rpc.json @@ -774,6 +774,43 @@ } ] }, + { + "name": "Device.onDolbyAtmosExperienceAvailableChanged", + "summary": "Returns whether Dolby Atmos experience is available on the device", + "tags": [ + { + "name": "notifier", + "x-notifier-for": "Device.dolbyAtmosExperienceAvailable", + "x-event": "Device.onDolbyAtmosExperienceAvailableChanged" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:device:info" + ] + } + ], + "params": [ + { + "name": "dolbyAtmosExperienceAvailable", + "summary": "Whether Dolby Atmos experience is available on the device", + "schema": { + "type": "boolean" + } + } + ], + "examples": [ + { + "name": "Getting Dolby Atmos experience availability", + "params": [ + { + "name": "dolbyAtmosExperienceAvailable", + "value": true + } + ] + } + ] + }, { "name": "Network.onConnectedChanged", "summary": "Returns whether the device currently has a usable network connection.", diff --git a/docs/openrpc/the-spec/firebolt-open-rpc--legacy.json b/docs/openrpc/the-spec/firebolt-open-rpc--legacy.json index ea3b2d0..46667ad 100644 --- a/docs/openrpc/the-spec/firebolt-open-rpc--legacy.json +++ b/docs/openrpc/the-spec/firebolt-open-rpc--legacy.json @@ -752,6 +752,97 @@ } ] }, + { + "name": "Device.dolbyAtmosExperienceAvailable", + "summary": "Returns whether Dolby Atmos experience is available on the device", + "params": [], + "tags": [ + { + "name": "property:readonly" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:device:info" + ] + } + ], + "result": { + "name": "dolbyAtmosExperienceAvailable", + "summary": "Whether Dolby Atmos experience is available on the device", + "schema": { + "type": "boolean" + } + }, + "examples": [ + { + "name": "Getting Dolby Atmos experience availability", + "params": [], + "result": { + "name": "Default Result", + "value": true + } + } + ] + }, + { + "name": "Device.onDolbyAtmosExperienceAvailableChanged", + "summary": "Returns whether Dolby Atmos experience is available on the device", + "params": [ + { + "name": "listen", + "required": true, + "schema": { + "type": "boolean" + } + } + ], + "tags": [ + { + "name": "subscriber", + "x-subscriber-for": "Device.dolbyAtmosExperienceAvailable" + }, + { + "name": "event", + "x-alternative": "dolbyAtmosExperienceAvailable" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:device:info" + ] + } + ], + "result": { + "name": "dolbyAtmosExperienceAvailable", + "summary": "Whether Dolby Atmos experience is available on the device", + "schema": { + "anyOf": [ + { + "$ref": "#/x-schemas/Types/ListenResponse" + }, + { + "type": "boolean" + } + ] + } + }, + "examples": [ + { + "name": "Getting Dolby Atmos experience availability", + "params": [ + { + "name": "listen", + "value": true + } + ], + "result": { + "name": "Default Result", + "value": true + } + } + ] + }, { "name": "Discovery.watched", "summary": "Notify the platform that content was partially or completely watched", diff --git a/docs/openrpc/the-spec/firebolt-open-rpc.json b/docs/openrpc/the-spec/firebolt-open-rpc.json index 698d4f1..363b85c 100644 --- a/docs/openrpc/the-spec/firebolt-open-rpc.json +++ b/docs/openrpc/the-spec/firebolt-open-rpc.json @@ -527,6 +527,39 @@ } ] }, + { + "name": "Device.dolbyAtmosExperienceAvailable", + "summary": "Returns whether Dolby Atmos experience is available on the device", + "params": [], + "tags": [ + { + "name": "property:readonly" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:device:info" + ] + } + ], + "result": { + "name": "dolbyAtmosExperienceAvailable", + "summary": "Whether Dolby Atmos experience is available on the device", + "schema": { + "type": "boolean" + } + }, + "examples": [ + { + "name": "Getting Dolby Atmos experience availability", + "params": [], + "result": { + "name": "Default Result", + "value": true + } + } + ] + }, { "name": "Discovery.watched", "summary": "Notify the platform that content was partially or completely watched", @@ -3245,6 +3278,52 @@ } } }, + { + "name": "Device.onDolbyAtmosExperienceAvailableChanged", + "summary": "Returns whether Dolby Atmos experience is available on the device", + "params": [ + { + "name": "listen", + "schema": { + "type": "boolean" + } + } + ], + "tags": [ + { + "name": "event", + "x-notifier": "Device.onDolbyAtmosExperienceAvailableChanged", + "x-subscriber-for": "Device.dolbyAtmosExperienceAvailable" + }, + { + "name": "capabilities", + "x-uses": [ + "xrn:firebolt:capability:device:info" + ] + } + ], + "examples": [ + { + "name": "Getting Dolby Atmos experience availability", + "params": [ + { + "name": "listen", + "value": true + } + ], + "result": { + "name": "result", + "value": null + } + } + ], + "result": { + "name": "result", + "schema": { + "type": "null" + } + } + }, { "name": "Localization.onCountryChanged", "tags": [ diff --git a/include/firebolt/device.h b/include/firebolt/device.h index 29c3b0a..c95d3d0 100644 --- a/include/firebolt/device.h +++ b/include/firebolt/device.h @@ -95,6 +95,21 @@ class IDevice */ virtual Result uptime() const = 0; + /** + * @brief Returns whether Dolby Atmos experience is available on the device + * + * @retval True if Dolby Atmos experience is available, or error + */ + virtual Result dolbyAtmosExperienceAvailable() const = 0; + + /** + * @brief Subscribe to Dolby Atmos experience availability changes + * + * @retval SubscriptionId or error + */ + virtual Result + subscribeOnDolbyAtmosExperienceAvailableChanged(std::function&& notification) = 0; + /** * @brief Subscribe to HDR format changes * diff --git a/src/device_impl.cpp b/src/device_impl.cpp index 58447ff..e53455b 100644 --- a/src/device_impl.cpp +++ b/src/device_impl.cpp @@ -57,6 +57,17 @@ Result DeviceImpl::uptime() const return helper_.get("Device.uptime"); } +Result DeviceImpl::dolbyAtmosExperienceAvailable() const +{ + return helper_.get("Device.dolbyAtmosExperienceAvailable"); +} + +Result DeviceImpl::subscribeOnDolbyAtmosExperienceAvailableChanged(std::function&& notification) +{ + return subscriptionManager_.subscribe("Device.onDolbyAtmosExperienceAvailableChanged", + std::move(notification)); +} + Result DeviceImpl::subscribeOnHdrChanged(std::function&& notification) { return subscriptionManager_.subscribe("Device.onHdrChanged", std::move(notification)); diff --git a/src/device_impl.h b/src/device_impl.h index ca9a29f..08bc6c3 100644 --- a/src/device_impl.h +++ b/src/device_impl.h @@ -39,6 +39,10 @@ class DeviceImpl : public IDevice Result uid() const override; Result uptime() const override; + Result dolbyAtmosExperienceAvailable() const override; + Result + subscribeOnDolbyAtmosExperienceAvailableChanged(std::function&& notification) override; + Result subscribeOnHdrChanged(std::function&& notification) override; Result unsubscribe(SubscriptionId id) override; diff --git a/test/api_test_app/apis/deviceDemo.cpp b/test/api_test_app/apis/deviceDemo.cpp index 94c9cb2..fd63323 100644 --- a/test/api_test_app/apis/deviceDemo.cpp +++ b/test/api_test_app/apis/deviceDemo.cpp @@ -33,6 +33,7 @@ DeviceDemo::DeviceDemo() { methods_.push_back("Device.chipsetId"); methods_.push_back("Device.deviceClass"); + methods_.push_back("Device.dolbyAtmosExperienceAvailable"); methods_.push_back("Device.hdr"); methods_.push_back("Device.timeInActiveState"); methods_.push_back("Device.uid"); @@ -93,4 +94,12 @@ void DeviceDemo::runOption(const std::string& method) std::cout << "Device Uptime (seconds): " << *r << std::endl; } } + else if (method == "Device.dolbyAtmosExperienceAvailable") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().dolbyAtmosExperienceAvailable(); + if (succeed(r)) + { + std::cout << std::boolalpha << "Dolby Atmos Experience Available: " << *r << std::endl; + } + } } diff --git a/test/component/deviceTest.cpp b/test/component/deviceTest.cpp index 289a16a..62f5858 100644 --- a/test/component/deviceTest.cpp +++ b/test/component/deviceTest.cpp @@ -121,3 +121,34 @@ TEST_F(DeviceCTest, SubscribeOnHdrChanged) auto result = Firebolt::IFireboltAccessor::Instance().DeviceInterface().unsubscribe(id.value()); verifyUnsubscribeResult(result); } + +TEST_F(DeviceCTest, DolbyAtmosExperienceAvailable) +{ + auto expectedValue = jsonEngine.get_value("Device.dolbyAtmosExperienceAvailable"); + auto result = Firebolt::IFireboltAccessor::Instance().DeviceInterface().dolbyAtmosExperienceAvailable(); + ASSERT_TRUE(result) << "DeviceImpl::dolbyAtmosExperienceAvailable() returned an error"; + EXPECT_EQ(*result, expectedValue.get()); +} + +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; + EXPECT_EQ(value, true); + { + std::lock_guard lock(mtx); + eventReceived = true; + } + cv.notify_one(); + }); + + verifyEventSubscription(id); + + triggerEvent("Device.onDolbyAtmosExperienceAvailableChanged", R"({ "value": true })"); + verifyEventReceived(mtx, cv, eventReceived); + + auto result = Firebolt::IFireboltAccessor::Instance().DeviceInterface().unsubscribe(id.value()); + verifyUnsubscribeResult(result); +} diff --git a/test/unit/deviceTest.cpp b/test/unit/deviceTest.cpp index c708b9a..6ecd042 100644 --- a/test/unit/deviceTest.cpp +++ b/test/unit/deviceTest.cpp @@ -139,3 +139,34 @@ TEST_F(DeviceUTest, SubscribeOnHdrChanged) deviceImpl_.unsubscribe(*result); } + +TEST_F(DeviceUTest, DolbyAtmosExperienceAvailable) +{ + mock("Device.dolbyAtmosExperienceAvailable"); + auto expectedValue = jsonEngine.get_value("Device.dolbyAtmosExperienceAvailable"); + + auto result = deviceImpl_.dolbyAtmosExperienceAvailable(); + ASSERT_TRUE(result) << "DeviceImpl::dolbyAtmosExperienceAvailable() returned an error"; + + EXPECT_EQ(*result, expectedValue.get()); +} + +TEST_F(DeviceUTest, DolbyAtmosExperienceAvailableBadResponse) +{ + mock_with_response("Device.dolbyAtmosExperienceAvailable", "invalid_response"); + ASSERT_FALSE(deviceImpl_.dolbyAtmosExperienceAvailable()) + << "DeviceImpl::dolbyAtmosExperienceAvailable() did not return an error"; +} + +TEST_F(DeviceUTest, SubscribeOnDolbyAtmosExperienceAvailableChanged) +{ + nlohmann::json expectedValue = 1; + mockSubscribe("Device.onDolbyAtmosExperienceAvailableChanged"); + + auto result = deviceImpl_.subscribeOnDolbyAtmosExperienceAvailableChanged([&](const bool& /*value*/) {}); + + ASSERT_TRUE(result) << "DeviceImpl::subscribeOnDolbyAtmosExperienceAvailableChanged() returned an error"; + EXPECT_EQ(*result, expectedValue); + + deviceImpl_.unsubscribe(*result); +}