Skip to content

Commit

Permalink
Adding Media subscriptions support to Linux tv-casting-app (#22709)
Browse files Browse the repository at this point in the history
  • Loading branch information
sharadb-amazon authored Sep 23, 2022
1 parent 977cfa4 commit bd6fa79
Show file tree
Hide file tree
Showing 14 changed files with 686 additions and 33 deletions.
62 changes: 59 additions & 3 deletions examples/tv-casting-app/linux/CastingUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ using namespace chip::Dnssd;
// 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()
{
Expand Down Expand Up @@ -114,14 +115,69 @@ void LaunchURLResponseCallback(CHIP_ERROR err)
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!");
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions examples/tv-casting-app/linux/CastingUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ void HandleCommissioningCompleteCallback(CHIP_ERROR err);

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
Expand Down
4 changes: 4 additions & 0 deletions examples/tv-casting-app/tv-casting-common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,20 @@ chip_data_model("tv-casting-common") {
"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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -51,3 +53,11 @@ class HideAppCommand : public MediaCommandBase<chip::app::Clusters::ApplicationL
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) {}
};
164 changes: 163 additions & 1 deletion examples/tv-casting-app/tv-casting-common/include/CastingServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include "ApplicationLauncher.h"
#include "Channel.h"
#include "ContentLauncher.h"
#include "KeypadInput.h"
#include "LevelControl.h"
Expand All @@ -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
Expand Down Expand Up @@ -73,35 +76,170 @@ class CastingServer
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,
std::function<void(CHIP_ERROR)> responseCallback);
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);
CHIP_ERROR MediaPlayback_Next(std::function<void(CHIP_ERROR)> responseCallback);
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);
Expand All @@ -127,6 +265,10 @@ class CastingServer
StepCommand mStepCommand;
MoveToLevelCommand mMoveToLevelCommand;

CurrentLevelSubscriber mCurrentLevelSubscriber;
MinLevelSubscriber mMinLevelSubscriber;
MaxLevelSubscriber mMaxLevelSubscriber;

/**
* @brief Media Playback cluster
*/
Expand All @@ -138,20 +280,40 @@ class CastingServer
SkipForwardCommand mSkipForwardCommand;
SkipBackwardCommand mSkipBackwardCommand;

CurrentStateSubscriber mCurrentStateSubscriber;
StartTimeSubscriber mStartTimeSubscriber;
DurationSubscriber mDurationSubscriber;
SampledPositionSubscriber mSampledPositionSubscriber;
PlaybackSpeedSubscriber mPlaybackSpeedSubscriber;
SeekRangeEndSubscriber mSeekRangeEndSubscriber;
SeekRangeStartSubscriber mSeekRangeStartSubscriber;

/**
* @brief Application Launcher cluster
*/
LaunchAppCommand mLaunchAppCommand;
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;
};
Loading

0 comments on commit bd6fa79

Please sign in to comment.