Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux tv-casting-app: Adding Media subscriptions support #22709

Merged
merged 1 commit into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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