Adding Media subscriptions support to Linux tv-casting-app (#22709)
diff --git a/examples/tv-casting-app/linux/CastingUtils.cpp b/examples/tv-casting-app/linux/CastingUtils.cpp
index 0e6fc87..6f5ea53 100644
--- a/examples/tv-casting-app/linux/CastingUtils.cpp
+++ b/examples/tv-casting-app/linux/CastingUtils.cpp
@@ -26,6 +26,7 @@
// TODO: Accept these values over CLI
const char * kContentUrl = "https://www.test.com/videoid";
const char * kContentDisplayStr = "Test video";
+int gInitialContextVal = 121212;
CHIP_ERROR DiscoverCommissioners()
{
@@ -114,14 +115,69 @@
ChipLogProgress(AppServer, "LaunchURLResponseCallback called with %" CHIP_ERROR_FORMAT, err.Format());
}
+void OnCurrentStateReadResponseSuccess(
+ void * context, chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType responseData)
+{
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess called with responseData: %d", static_cast<int>(responseData));
+ switch (responseData)
+ {
+ case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kPlaying:
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Playing");
+ break;
+ case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kPaused:
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Paused");
+ break;
+ case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kNotPlaying:
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Not Playing");
+ break;
+ case chip::app::Clusters::MediaPlayback::PlaybackStateEnum::kBuffering:
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess CurrentState: Buffering");
+ break;
+ default:
+ ChipLogError(AppServer, "OnCurrentStateReadResponseSuccess Invalid CurrentState!");
+ break;
+ }
+
+ if (context != nullptr)
+ {
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseSuccess context value: %d", *(static_cast<int *>(context)));
+ }
+}
+
+void OnCurrentStateReadResponseFailure(void * context, CHIP_ERROR err)
+{
+ ChipLogProgress(AppServer, "OnCurrentStateReadResponseFailure called with %" CHIP_ERROR_FORMAT, err.Format());
+}
+
+void OnCurrentStateSubscriptionEstablished(void * context)
+{
+ ChipLogProgress(AppServer, "OnCurrentStateSubscriptionEstablished called");
+ if (context != nullptr)
+ {
+ ChipLogProgress(AppServer, "OnCurrentStateSubscriptionEstablished context value: %d", *(static_cast<int *>(context)));
+ }
+}
+
void HandleCommissioningCompleteCallback(CHIP_ERROR err)
{
ChipLogProgress(AppServer, "HandleCommissioningCompleteCallback called with %" CHIP_ERROR_FORMAT, err.Format());
if (err == CHIP_NO_ERROR)
{
- ReturnOnFailure(
- CastingServer::GetInstance()->ContentLauncherLaunchURL(kContentUrl, kContentDisplayStr, LaunchURLResponseCallback));
- ChipLogProgress(AppServer, "ContentLauncherLaunchURL called successfully");
+ // Subscribe to a media attribute
+ err = CastingServer::GetInstance()->MediaPlayback_SubscribeToCurrentState(
+ static_cast<void *>(&gInitialContextVal), OnCurrentStateReadResponseSuccess, OnCurrentStateReadResponseFailure, 0, 4000,
+ OnCurrentStateSubscriptionEstablished);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "MediaPlayback_SubscribeToCurrentState call failed!");
+ }
+
+ // Send a media command
+ err = CastingServer::GetInstance()->ContentLauncherLaunchURL(kContentUrl, kContentDisplayStr, LaunchURLResponseCallback);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "ContentLauncherLaunchURL call failed!");
+ }
}
}
diff --git a/examples/tv-casting-app/linux/CastingUtils.h b/examples/tv-casting-app/linux/CastingUtils.h
index 177bedf..172b018 100644
--- a/examples/tv-casting-app/linux/CastingUtils.h
+++ b/examples/tv-casting-app/linux/CastingUtils.h
@@ -42,6 +42,13 @@
void LaunchURLResponseCallback(CHIP_ERROR err);
+void OnCurrentStateReadResponseSuccess(
+ void * context, chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType responseData);
+
+void OnCurrentStateReadResponseFailure(void * context, CHIP_ERROR err);
+
+void OnCurrentStateSubscriptionEstablished(void * context);
+
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
void HandleUDCSendExpiration(chip::System::Layer * aSystemLayer, void * context);
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn
index b421fad..dd3644a 100644
--- a/examples/tv-casting-app/tv-casting-common/BUILD.gn
+++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn
@@ -49,16 +49,20 @@
"commands/common/CHIPCommand.cpp",
"include/ApplicationLauncher.h",
"include/CastingServer.h",
+ "include/Channel.h",
"include/ContentLauncher.h",
"include/KeypadInput.h",
"include/LevelControl.h",
+ "include/MediaBase.h",
"include/MediaCommandBase.h",
"include/MediaPlayback.h",
+ "include/MediaSubscriptionBase.h",
"include/TargetEndpointInfo.h",
"include/TargetNavigator.h",
"include/TargetVideoPlayerInfo.h",
"src/ApplicationLauncher.cpp",
"src/CastingServer.cpp",
+ "src/Channel.cpp",
"src/ContentLauncher.cpp",
"src/KeypadInput.cpp",
"src/LevelControl.cpp",
diff --git a/examples/tv-casting-app/tv-casting-common/include/ApplicationLauncher.h b/examples/tv-casting-app/tv-casting-common/include/ApplicationLauncher.h
index d3365be..3444955 100644
--- a/examples/tv-casting-app/tv-casting-common/include/ApplicationLauncher.h
+++ b/examples/tv-casting-app/tv-casting-common/include/ApplicationLauncher.h
@@ -17,10 +17,12 @@
*/
#include "MediaCommandBase.h"
+#include "MediaSubscriptionBase.h"
#include <functional>
#include <zap-generated/CHIPClusters.h>
+// COMMAND CLASSES
class LaunchAppCommand
: public MediaCommandBase<chip::app::Clusters::ApplicationLauncher::Commands::LaunchApp::Type,
chip::app::Clusters::ApplicationLauncher::Commands::LauncherResponse::DecodableType>
@@ -51,3 +53,11 @@
CHIP_ERROR Invoke(chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application,
std::function<void(CHIP_ERROR)> responseCallback);
};
+
+// SUBSCRIBER CLASSES
+class CurrentAppSubscriber
+ : public MediaSubscriptionBase<chip::app::Clusters::ApplicationLauncher::Attributes::CurrentApp::TypeInfo>
+{
+public:
+ CurrentAppSubscriber() : MediaSubscriptionBase(chip::app::Clusters::ApplicationLauncher::Id) {}
+};
diff --git a/examples/tv-casting-app/tv-casting-common/include/CastingServer.h b/examples/tv-casting-app/tv-casting-common/include/CastingServer.h
index b29f82e..b91a0e0 100644
--- a/examples/tv-casting-app/tv-casting-common/include/CastingServer.h
+++ b/examples/tv-casting-app/tv-casting-common/include/CastingServer.h
@@ -19,6 +19,7 @@
#pragma once
#include "ApplicationLauncher.h"
+#include "Channel.h"
#include "ContentLauncher.h"
#include "KeypadInput.h"
#include "LevelControl.h"
@@ -27,13 +28,15 @@
#include "TargetNavigator.h"
#include "TargetVideoPlayerInfo.h"
+#include <app-common/zap-generated/cluster-objects.h>
#include <app/server/Server.h>
#include <controller/CHIPCommissionableNodeController.h>
#include <functional>
+#include <tv-casting-app/zap-generated/CHIPClientCallbacks.h>
#include <zap-generated/CHIPClusters.h>
constexpr chip::System::Clock::Seconds16 kCommissioningWindowTimeout = chip::System::Clock::Seconds16(3 * 60);
-constexpr chip::EndpointId kTvEndpoint = 1;
+constexpr chip::EndpointId kTvEndpoint = 4;
/**
* @brief Represents a TV Casting server that can get the casting app commissioned
@@ -73,6 +76,9 @@
chip::FabricIndex CurrentFabricIndex() { return mTargetVideoPlayerInfo.GetFabricIndex(); }
void SetDefaultFabricIndex();
+ /**
+ * @brief Content Launcher cluster
+ */
CHIP_ERROR ContentLauncher_LaunchURL(
const char * contentUrl, const char * contentDisplayStr,
chip::Optional<chip::app::Clusters::ContentLauncher::Structs::BrandingInformation::Type> brandingInformation,
@@ -80,10 +86,43 @@
CHIP_ERROR ContentLauncher_LaunchContent(chip::app::Clusters::ContentLauncher::Structs::ContentSearch::Type search,
bool autoPlay, chip::Optional<chip::CharSpan> data,
std::function<void(CHIP_ERROR)> responseCallback);
+
+ /**
+ * @brief Level Control cluster
+ */
CHIP_ERROR LevelControl_Step(chip::app::Clusters::LevelControl::StepMode stepMode, uint8_t stepSize, uint16_t transitionTime,
uint8_t optionMask, uint8_t optionOverride, std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR LevelControl_MoveToLevel(uint8_t level, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride,
std::function<void(CHIP_ERROR)> responseCallback);
+
+ CHIP_ERROR
+ LevelControl_SubscribeToCurrentLevel(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::LevelControl::Attributes::CurrentLevel::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR
+ LevelControl_SubscribeToMinLevel(void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::LevelControl::Attributes::MinLevel::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval,
+ uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR
+ LevelControl_SubscribeToMaxLevel(void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::LevelControl::Attributes::MaxLevel::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval,
+ uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+
+ /**
+ * @brief Media Playback cluster
+ */
CHIP_ERROR MediaPlayback_Play(std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR MediaPlayback_Pause(std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR MediaPlayback_StopPlayback(std::function<void(CHIP_ERROR)> responseCallback);
@@ -91,17 +130,116 @@
CHIP_ERROR MediaPlayback_Seek(uint64_t position, std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR MediaPlayback_SkipForward(uint64_t deltaPositionMilliseconds, std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR MediaPlayback_SkipBackward(uint64_t deltaPositionMilliseconds, std::function<void(CHIP_ERROR)> responseCallback);
+
+ CHIP_ERROR MediaPlayback_SubscribeToCurrentState(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR
+ MediaPlayback_SubscribeToStartTime(void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::StartTime::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval,
+ uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR
+ MediaPlayback_SubscribeToDuration(void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::Duration::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval,
+ uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR MediaPlayback_SubscribeToSampledPosition(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::SampledPosition::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR MediaPlayback_SubscribeToPlaybackSpeed(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::PlaybackSpeed::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR MediaPlayback_SubscribeToSeekRangeEnd(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR MediaPlayback_SubscribeToSeekRangeStart(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::MediaPlayback::Attributes::SeekRangeStart::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+
+ /**
+ * @brief Application Launcher cluster
+ */
CHIP_ERROR ApplicationLauncher_LaunchApp(chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application,
chip::Optional<chip::ByteSpan> data, std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR ApplicationLauncher_StopApp(chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application,
std::function<void(CHIP_ERROR)> responseCallback);
CHIP_ERROR ApplicationLauncher_HideApp(chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application,
std::function<void(CHIP_ERROR)> responseCallback);
+
+ CHIP_ERROR
+ ApplicationLauncher_SubscribeToCurrentApp(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::ApplicationLauncher::Attributes::CurrentApp::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+
+ /**
+ * @brief Target Navigator cluster
+ */
CHIP_ERROR TargetNavigator_NavigateTarget(const uint8_t target, const chip::Optional<chip::CharSpan> data,
std::function<void(CHIP_ERROR)> responseCallback);
+
+ CHIP_ERROR TargetNavigator_SubscribeToTargetList(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::TargetNavigator::Attributes::TargetList::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+ CHIP_ERROR TargetNavigator_SubscribeToCurrentTarget(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<
+ chip::app::Clusters::TargetNavigator::Attributes::CurrentTarget::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+
+ /**
+ * @brief Keypad Input cluster
+ */
CHIP_ERROR KeypadInput_SendKey(const chip::app::Clusters::KeypadInput::CecKeyCode keyCode,
std::function<void(CHIP_ERROR)> responseCallback);
+ /**
+ * @brief Channel cluster
+ */
+ CHIP_ERROR Channel_ChangeChannelCommand(const chip::CharSpan & match, std::function<void(CHIP_ERROR)> responseCallback);
+ CHIP_ERROR Channel_SubscribeToLineup(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<chip::app::Clusters::Channel::Attributes::Lineup::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished);
+
private:
CHIP_ERROR InitBindingHandlers();
static void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
@@ -127,6 +265,10 @@
StepCommand mStepCommand;
MoveToLevelCommand mMoveToLevelCommand;
+ CurrentLevelSubscriber mCurrentLevelSubscriber;
+ MinLevelSubscriber mMinLevelSubscriber;
+ MaxLevelSubscriber mMaxLevelSubscriber;
+
/**
* @brief Media Playback cluster
*/
@@ -138,6 +280,14 @@
SkipForwardCommand mSkipForwardCommand;
SkipBackwardCommand mSkipBackwardCommand;
+ CurrentStateSubscriber mCurrentStateSubscriber;
+ StartTimeSubscriber mStartTimeSubscriber;
+ DurationSubscriber mDurationSubscriber;
+ SampledPositionSubscriber mSampledPositionSubscriber;
+ PlaybackSpeedSubscriber mPlaybackSpeedSubscriber;
+ SeekRangeEndSubscriber mSeekRangeEndSubscriber;
+ SeekRangeStartSubscriber mSeekRangeStartSubscriber;
+
/**
* @brief Application Launcher cluster
*/
@@ -145,13 +295,25 @@
StopAppCommand mStopAppCommand;
HideAppCommand mHideAppCommand;
+ CurrentAppSubscriber mCurrentAppSubscriber;
+
/**
* @brief Target Navigator cluster
*/
NavigateTargetCommand mNavigateTargetCommand;
+ TargetListSubscriber mTargetListSubscriber;
+ CurrentTargetSubscriber mCurrentTargetSubscriber;
+
/**
* @brief Keypad Input cluster
*/
SendKeyCommand mSendKeyCommand;
+
+ /**
+ * @brief Channel cluster
+ */
+ ChangeChannelCommand mChangeChannelCommand;
+
+ LineupSubscriber mLineupSubscriber;
};
diff --git a/examples/tv-casting-app/tv-casting-common/include/Channel.h b/examples/tv-casting-app/tv-casting-common/include/Channel.h
new file mode 100644
index 0000000..1a0a18e
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/include/Channel.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#include "MediaCommandBase.h"
+#include "MediaSubscriptionBase.h"
+
+#include <functional>
+#include <zap-generated/CHIPClusters.h>
+
+// COMMAND CLASSES
+class ChangeChannelCommand : public MediaCommandBase<chip::app::Clusters::Channel::Commands::ChangeChannel::Type,
+ chip::app::Clusters::Channel::Commands::ChangeChannelResponse::DecodableType>
+{
+public:
+ ChangeChannelCommand() : MediaCommandBase(chip::app::Clusters::Channel::Id) {}
+
+ CHIP_ERROR Invoke(const chip::CharSpan & match, std::function<void(CHIP_ERROR)> responseCallback);
+};
+
+// SUBSCRIBER CLASSES
+class LineupSubscriber : public MediaSubscriptionBase<chip::app::Clusters::Channel::Attributes::Lineup::TypeInfo>
+{
+public:
+ LineupSubscriber() : MediaSubscriptionBase(chip::app::Clusters::Channel::Id) {}
+};
diff --git a/examples/tv-casting-app/tv-casting-common/include/LevelControl.h b/examples/tv-casting-app/tv-casting-common/include/LevelControl.h
index d431e3b..a1fd172 100644
--- a/examples/tv-casting-app/tv-casting-common/include/LevelControl.h
+++ b/examples/tv-casting-app/tv-casting-common/include/LevelControl.h
@@ -17,10 +17,12 @@
*/
#include "MediaCommandBase.h"
+#include "MediaSubscriptionBase.h"
#include <functional>
#include <zap-generated/CHIPClusters.h>
+// COMMAND CLASSES
class StepCommand
: public MediaCommandBase<chip::app::Clusters::LevelControl::Commands::Step::Type, chip::app::DataModel::NullObjectType>
{
@@ -41,3 +43,22 @@
CHIP_ERROR Invoke(uint8_t level, chip::app::DataModel::Nullable<uint16_t> transitionTime, uint8_t optionMask,
uint8_t optionOverride, std::function<void(CHIP_ERROR)> responseCallback);
};
+
+// SUBSCRIBER CLASSES
+class CurrentLevelSubscriber : public MediaSubscriptionBase<chip::app::Clusters::LevelControl::Attributes::CurrentLevel::TypeInfo>
+{
+public:
+ CurrentLevelSubscriber() : MediaSubscriptionBase(chip::app::Clusters::LevelControl::Id) {}
+};
+
+class MinLevelSubscriber : public MediaSubscriptionBase<chip::app::Clusters::LevelControl::Attributes::MinLevel::TypeInfo>
+{
+public:
+ MinLevelSubscriber() : MediaSubscriptionBase(chip::app::Clusters::LevelControl::Id) {}
+};
+
+class MaxLevelSubscriber : public MediaSubscriptionBase<chip::app::Clusters::LevelControl::Attributes::MaxLevel::TypeInfo>
+{
+public:
+ MaxLevelSubscriber() : MediaSubscriptionBase(chip::app::Clusters::LevelControl::Id) {}
+};
diff --git a/examples/tv-casting-app/tv-casting-common/include/MediaBase.h b/examples/tv-casting-app/tv-casting-common/include/MediaBase.h
new file mode 100644
index 0000000..3686161
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/include/MediaBase.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * 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.
+ */
+#pragma once
+
+#include "TargetVideoPlayerInfo.h"
+
+#include <controller/CHIPCluster.h>
+
+class MediaBase
+{
+public:
+ MediaBase(chip::ClusterId clusterId) { mClusterId = clusterId; }
+
+ CHIP_ERROR SetTarget(TargetVideoPlayerInfo & targetVideoPlayerInfo, chip::EndpointId tvEndpoint)
+ {
+ auto deviceProxy = targetVideoPlayerInfo.GetOperationalDeviceProxy();
+ if (deviceProxy == nullptr)
+ {
+ ChipLogError(AppServer, "Failed in getting an instance of OperationalDeviceProxy");
+ return CHIP_ERROR_PEER_NODE_NOT_FOUND;
+ }
+ mTargetVideoPlayerInfo = &targetVideoPlayerInfo;
+ mTvEndpoint = tvEndpoint;
+ return CHIP_NO_ERROR;
+ }
+
+ class MediaClusterBase : public chip::Controller::ClusterBase
+ {
+ public:
+ MediaClusterBase(chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
+ chip::ClusterId cluster, chip::EndpointId endpoint) :
+ ClusterBase(exchangeManager, session, cluster, endpoint)
+ {}
+ };
+
+protected:
+ chip::ClusterId mClusterId;
+ TargetVideoPlayerInfo * mTargetVideoPlayerInfo = nullptr;
+ chip::EndpointId mTvEndpoint;
+};
diff --git a/examples/tv-casting-app/tv-casting-common/include/MediaCommandBase.h b/examples/tv-casting-app/tv-casting-common/include/MediaCommandBase.h
index a125f18..1b9c3d2 100644
--- a/examples/tv-casting-app/tv-casting-common/include/MediaCommandBase.h
+++ b/examples/tv-casting-app/tv-casting-common/include/MediaCommandBase.h
@@ -17,29 +17,15 @@
*/
#pragma once
-#include "TargetVideoPlayerInfo.h"
+#include "MediaBase.h"
-#include <controller/CHIPCluster.h>
#include <functional>
template <typename RequestType, typename ResponseType>
-class MediaCommandBase
+class MediaCommandBase : public MediaBase
{
public:
- MediaCommandBase(chip::ClusterId clusterId) { mClusterId = clusterId; }
-
- CHIP_ERROR SetTarget(TargetVideoPlayerInfo & targetVideoPlayerInfo, chip::EndpointId tvEndpoint)
- {
- auto deviceProxy = targetVideoPlayerInfo.GetOperationalDeviceProxy();
- if (deviceProxy == nullptr)
- {
- ChipLogError(AppServer, "Failed in getting an instance of OperationalDeviceProxy");
- return CHIP_ERROR_PEER_NODE_NOT_FOUND;
- }
- mTargetVideoPlayerInfo = &targetVideoPlayerInfo;
- mTvEndpoint = tvEndpoint;
- return CHIP_NO_ERROR;
- }
+ MediaCommandBase(chip::ClusterId clusterId) : MediaBase(clusterId) {}
CHIP_ERROR Invoke(RequestType request, std::function<void(CHIP_ERROR)> responseCallback)
{
@@ -50,15 +36,6 @@
sResponseCallback = responseCallback;
- class MediaClusterBase : public chip::Controller::ClusterBase
- {
- public:
- MediaClusterBase(chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
- chip::ClusterId cluster, chip::EndpointId endpoint) :
- ClusterBase(exchangeManager, session, cluster, endpoint)
- {}
- };
-
MediaClusterBase cluster(*deviceProxy->GetExchangeManager(), deviceProxy->GetSecureSession().Value(), mClusterId,
mTvEndpoint);
return cluster.InvokeCommand(request, nullptr, OnSuccess, OnFailure);
@@ -69,9 +46,6 @@
static void OnFailure(void * context, CHIP_ERROR error) { sResponseCallback(error); }
protected:
- chip::ClusterId mClusterId;
- TargetVideoPlayerInfo * mTargetVideoPlayerInfo = nullptr;
- chip::EndpointId mTvEndpoint;
static std::function<void(CHIP_ERROR)> sResponseCallback;
};
diff --git a/examples/tv-casting-app/tv-casting-common/include/MediaPlayback.h b/examples/tv-casting-app/tv-casting-common/include/MediaPlayback.h
index ca551bd..c4d540f 100644
--- a/examples/tv-casting-app/tv-casting-common/include/MediaPlayback.h
+++ b/examples/tv-casting-app/tv-casting-common/include/MediaPlayback.h
@@ -17,10 +17,12 @@
*/
#include "MediaCommandBase.h"
+#include "MediaSubscriptionBase.h"
#include <functional>
#include <zap-generated/CHIPClusters.h>
+// COMMAND CLASSES
class PlayCommand : public MediaCommandBase<chip::app::Clusters::MediaPlayback::Commands::Play::Type,
chip::app::Clusters::MediaPlayback::Commands::PlaybackResponse::DecodableType>
{
@@ -83,3 +85,49 @@
CHIP_ERROR Invoke(uint64_t deltaPositionMilliseconds, std::function<void(CHIP_ERROR)> responseCallback);
};
+
+// SUBSCRIBER CLASSES
+class CurrentStateSubscriber : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo>
+{
+public:
+ CurrentStateSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
+
+class StartTimeSubscriber : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::StartTime::TypeInfo>
+{
+public:
+ StartTimeSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
+
+class DurationSubscriber : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::Duration::TypeInfo>
+{
+public:
+ DurationSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
+
+class SampledPositionSubscriber
+ : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::SampledPosition::TypeInfo>
+{
+public:
+ SampledPositionSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
+
+class PlaybackSpeedSubscriber
+ : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::PlaybackSpeed::TypeInfo>
+{
+public:
+ PlaybackSpeedSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
+
+class SeekRangeEndSubscriber : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::TypeInfo>
+{
+public:
+ SeekRangeEndSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
+
+class SeekRangeStartSubscriber
+ : public MediaSubscriptionBase<chip::app::Clusters::MediaPlayback::Attributes::SeekRangeStart::TypeInfo>
+{
+public:
+ SeekRangeStartSubscriber() : MediaSubscriptionBase(chip::app::Clusters::MediaPlayback::Id) {}
+};
diff --git a/examples/tv-casting-app/tv-casting-common/include/MediaSubscriptionBase.h b/examples/tv-casting-app/tv-casting-common/include/MediaSubscriptionBase.h
new file mode 100644
index 0000000..e2a065e
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/include/MediaSubscriptionBase.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * 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.
+ */
+#pragma once
+
+#include "MediaBase.h"
+
+template <typename TypeInfo>
+class MediaSubscriptionBase : public MediaBase
+{
+public:
+ MediaSubscriptionBase(chip::ClusterId clusterId) : MediaBase(clusterId) {}
+
+ CHIP_ERROR SubscribeAttribute(void * context,
+ chip::Controller::ReadResponseSuccessCallback<typename TypeInfo::DecodableArgType> successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval,
+ uint16_t maxInterval, chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished)
+ {
+ VerifyOrDieWithMsg(mTargetVideoPlayerInfo != nullptr, AppServer, "Target unknown");
+
+ auto deviceProxy = mTargetVideoPlayerInfo->GetOperationalDeviceProxy();
+ ReturnErrorCodeIf(deviceProxy == nullptr || !deviceProxy->ConnectionReady(), CHIP_ERROR_PEER_NODE_NOT_FOUND);
+
+ MediaClusterBase cluster(*deviceProxy->GetExchangeManager(), deviceProxy->GetSecureSession().Value(), mClusterId,
+ mTvEndpoint);
+
+ return cluster.template SubscribeAttribute<TypeInfo>(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+ }
+};
diff --git a/examples/tv-casting-app/tv-casting-common/include/TargetNavigator.h b/examples/tv-casting-app/tv-casting-common/include/TargetNavigator.h
index 731dfb7..b42d168 100644
--- a/examples/tv-casting-app/tv-casting-common/include/TargetNavigator.h
+++ b/examples/tv-casting-app/tv-casting-common/include/TargetNavigator.h
@@ -17,10 +17,12 @@
*/
#include "MediaCommandBase.h"
+#include "MediaSubscriptionBase.h"
#include <functional>
#include <zap-generated/CHIPClusters.h>
+// COMMAND CLASSES
class NavigateTargetCommand
: public MediaCommandBase<chip::app::Clusters::TargetNavigator::Commands::NavigateTarget::Type,
chip::app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::DecodableType>
@@ -31,3 +33,17 @@
CHIP_ERROR Invoke(const uint8_t target, const chip::Optional<chip::CharSpan> data,
std::function<void(CHIP_ERROR)> responseCallback);
};
+
+// SUBSCRIBER CLASSES
+class TargetListSubscriber : public MediaSubscriptionBase<chip::app::Clusters::TargetNavigator::Attributes::TargetList::TypeInfo>
+{
+public:
+ TargetListSubscriber() : MediaSubscriptionBase(chip::app::Clusters::TargetNavigator::Id) {}
+};
+
+class CurrentTargetSubscriber
+ : public MediaSubscriptionBase<chip::app::Clusters::TargetNavigator::Attributes::CurrentTarget::TypeInfo>
+{
+public:
+ CurrentTargetSubscriber() : MediaSubscriptionBase(chip::app::Clusters::TargetNavigator::Id) {}
+};
diff --git a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp
index 67c5f2f..1acc685 100644
--- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp
+++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp
@@ -282,6 +282,9 @@
ChipLogError(AppServer, " -- No initialized fabrics with video players");
}
+/**
+ * @brief Content Launcher cluster
+ */
CHIP_ERROR CastingServer::ContentLauncher_LaunchURL(
const char * contentUrl, const char * contentDisplayStr,
chip::Optional<chip::app::Clusters::ContentLauncher::Structs::BrandingInformation::Type> brandingInformation,
@@ -299,6 +302,9 @@
return mLaunchContentCommand.Invoke(search, autoPlay, data, responseCallback);
}
+/**
+ * @brief Level Control cluster
+ */
CHIP_ERROR CastingServer::LevelControl_Step(chip::app::Clusters::LevelControl::StepMode stepMode, uint8_t stepSize,
uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride,
std::function<void(CHIP_ERROR)> responseCallback)
@@ -322,6 +328,42 @@
return mMoveToLevelCommand.Invoke(level, nullableTransitionTime, optionMask, optionOverride, responseCallback);
}
+CHIP_ERROR CastingServer::LevelControl_SubscribeToCurrentLevel(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::LevelControl::Attributes::CurrentLevel::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mCurrentLevelSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mCurrentLevelSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::LevelControl_SubscribeToMinLevel(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::LevelControl::Attributes::MinLevel::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mMinLevelSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mMinLevelSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::LevelControl_SubscribeToMaxLevel(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::LevelControl::Attributes::MaxLevel::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mMaxLevelSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mMaxLevelSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+/**
+ * @brief Media Playback cluster
+ */
CHIP_ERROR CastingServer::MediaPlayback_Play(std::function<void(CHIP_ERROR)> responseCallback)
{
ReturnErrorOnFailure(mPlayCommand.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
@@ -366,6 +408,89 @@
return mSkipBackwardCommand.Invoke(deltaPositionMilliseconds, responseCallback);
}
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToCurrentState(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mCurrentStateSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mCurrentStateSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToStartTime(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::StartTime::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mStartTimeSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mStartTimeSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToDuration(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::Duration::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mDurationSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mDurationSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToSampledPosition(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::SampledPosition::TypeInfo::DecodableArgType>
+ successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mSampledPositionSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mSampledPositionSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToPlaybackSpeed(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::PlaybackSpeed::TypeInfo::DecodableArgType>
+ successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mPlaybackSpeedSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mPlaybackSpeedSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToSeekRangeEnd(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mSeekRangeEndSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mSeekRangeEndSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::MediaPlayback_SubscribeToSeekRangeStart(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::MediaPlayback::Attributes::SeekRangeStart::TypeInfo::DecodableArgType>
+ successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mSeekRangeStartSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mSeekRangeStartSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+/**
+ * @brief Application Launcher cluster
+ */
CHIP_ERROR
CastingServer::ApplicationLauncher_LaunchApp(chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application,
chip::Optional<chip::ByteSpan> data, std::function<void(CHIP_ERROR)> responseCallback)
@@ -390,6 +515,21 @@
return mHideAppCommand.Invoke(application, responseCallback);
}
+CHIP_ERROR CastingServer::ApplicationLauncher_SubscribeToCurrentApp(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::ApplicationLauncher::Attributes::CurrentApp::TypeInfo::DecodableArgType>
+ successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mCurrentAppSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mCurrentAppSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+/**
+ * @brief Target Navigator cluster
+ */
CHIP_ERROR CastingServer::TargetNavigator_NavigateTarget(const uint8_t target, const chip::Optional<chip::CharSpan> data,
std::function<void(CHIP_ERROR)> responseCallback)
{
@@ -397,9 +537,56 @@
return mNavigateTargetCommand.Invoke(target, data, responseCallback);
}
+CHIP_ERROR CastingServer::TargetNavigator_SubscribeToTargetList(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::TargetNavigator::Attributes::TargetList::TypeInfo::DecodableArgType> successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mTargetListSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mTargetListSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+CHIP_ERROR CastingServer::TargetNavigator_SubscribeToCurrentTarget(
+ void * context,
+ ReadResponseSuccessCallback<chip::app::Clusters::TargetNavigator::Attributes::CurrentTarget::TypeInfo::DecodableArgType>
+ successFn,
+ ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mCurrentTargetSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mCurrentTargetSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval,
+ onSubscriptionEstablished);
+}
+
+/**
+ * @brief Keypad Input cluster
+ */
CHIP_ERROR CastingServer::KeypadInput_SendKey(const chip::app::Clusters::KeypadInput::CecKeyCode keyCode,
std::function<void(CHIP_ERROR)> responseCallback)
{
ReturnErrorOnFailure(mSendKeyCommand.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
return mSendKeyCommand.Invoke(keyCode, responseCallback);
}
+
+/**
+ * @brief Channel cluster
+ */
+CHIP_ERROR CastingServer::Channel_ChangeChannelCommand(const chip::CharSpan & match,
+ std::function<void(CHIP_ERROR)> responseCallback)
+{
+ ReturnErrorOnFailure(mChangeChannelCommand.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mChangeChannelCommand.Invoke(match, responseCallback);
+}
+
+CHIP_ERROR CastingServer::Channel_SubscribeToLineup(
+ void * context,
+ chip::Controller::ReadResponseSuccessCallback<chip::app::Clusters::Channel::Attributes::Lineup::TypeInfo::DecodableArgType>
+ successFn,
+ chip::Controller::ReadResponseFailureCallback failureFn, uint16_t minInterval, uint16_t maxInterval,
+ chip::Controller::SubscriptionEstablishedCallback onSubscriptionEstablished)
+{
+ ReturnErrorOnFailure(mLineupSubscriber.SetTarget(mTargetVideoPlayerInfo, kTvEndpoint));
+ return mLineupSubscriber.SubscribeAttribute(context, successFn, failureFn, minInterval, maxInterval, onSubscriptionEstablished);
+}
diff --git a/examples/tv-casting-app/tv-casting-common/src/Channel.cpp b/examples/tv-casting-app/tv-casting-common/src/Channel.cpp
new file mode 100644
index 0000000..2f11367
--- /dev/null
+++ b/examples/tv-casting-app/tv-casting-common/src/Channel.cpp
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#include "Channel.h"
+
+using namespace chip;
+using namespace chip::app::Clusters;
+
+CHIP_ERROR ChangeChannelCommand::Invoke(const CharSpan & match, std::function<void(CHIP_ERROR)> responseCallback)
+{
+ Channel::Commands::ChangeChannel::Type request;
+ request.match = match;
+ return MediaCommandBase::Invoke(request, responseCallback);
+}