diff --git a/examples/tv-casting-app/APIs.md b/examples/tv-casting-app/APIs.md index 4afb4f6556fe28..f0fdb32484a72e 100644 --- a/examples/tv-casting-app/APIs.md +++ b/examples/tv-casting-app/APIs.md @@ -773,7 +773,8 @@ func connect(selectedCastingPlayer: MCCastingPlayer?) { ### Select an Endpoint on the Casting Player -_{Complete Endpoint selection examples: [Linux](linux/simple-app-helper.cpp)}_ +_{Complete Endpoint selection examples: [Linux](linux/simple-app-helper.cpp) | +[iOS](darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift)}_ On a successful connection with a `CastingPlayer`, a Casting Client may select one of the Endpoints to interact with based on its attributes (e.g. Vendor ID, @@ -799,6 +800,19 @@ if (it != endpoints.end()) } ``` +On iOS, it can select an `MCEndpoint` similarly and as shown below. + +```swift +// VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection +let sampleEndpointVid: Int = 65521 +... +// select the MCEndpoint on the MCCastingPlayer to invoke the command on +if let endpoint: MCEndpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid}).first +{ +... +} +``` + ## Interacting with a Casting Endpoint Once the Casting Client has selected an `Endpoint`, it is ready to @@ -819,13 +833,14 @@ response types to use with these APIs: ### Issuing Commands -_{Complete Command invocation examples: [Linux](linux/simple-app-helper.cpp)}_ +_{Complete Command invocation examples: [Linux](linux/simple-app-helper.cpp) | +[iOS](darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift)}_ -The Casting Client can get a reference to a `endpoint` on a `CastingPlayer`, +The Casting Client can get a reference to an `Endpoint` on a `CastingPlayer`, check if it supports the required cluster/command, and send commands to it. It can then handle any command response / error the `CastingPlayer` sends back. -On Linux, for example, given an `endpoint`, it can send a `LaunchURL` command +On Linux, for example, given an `Endpoint`, it can send a `LaunchURL` command (part of the Content Launcher cluster) by calling the `Invoke` API on a `Command` of type `matter::casting::core::Command` @@ -865,9 +880,65 @@ void InvokeContentLauncherLaunchURL(matter::casting::memory::Strong + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h new file mode 100644 index 00000000000000..ba9f40c24c519c --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h @@ -0,0 +1,48 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "MCObserver.h" + +#import + +#ifndef MCAttribute_h +#define MCAttribute_h + +@interface MCAttribute<__covariant ObjectType> : NSObject + +/** + * @brief Reads the value of the MCAttribute that belongs to the associated MCEndpoint and corresponding MCCluster + * @param context current context passed back in completion block + * @param completion Called when attribute read completes with nil NSError if successful and before, after values. On failure, the NSError describes the error + */ +- (void)read:(void * _Nullable)context + completion:(void (^_Nonnull)(void * _Nullable context, ObjectType _Nullable before, ObjectType _Nullable after, NSError * _Nullable error))completion; + +/** + * @brief Subscribe to the value of the MCAttribute that belongs to the associated MCEndpoint and corresponding MCCluster + * @param context current context passed back in completion block + * @param completion Called when attribute read completes with nil NSError if successful and before, after values. On failure, the NSError describes the error + * @param minInterval the requested minimum interval boundary floor in seconds for attribute udpates + * @param maxInterval the requested maximum interval boundary ceiling in seconds for attribute udpates + */ +- (void)subscribe:(void * _Nullable)context + completion:(void (^_Nonnull)(void * _Nullable context, ObjectType _Nullable before, ObjectType _Nullable after, NSError * _Nullable error))completion + minInterval:(NSNumber * _Nonnull)minInterval + maxInterval:(NSNumber * _Nonnull)maxInterval; +@end + +#endif /* MCAttribute_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.mm new file mode 100644 index 00000000000000..09397ab86f7060 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.mm @@ -0,0 +1,50 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCAttribute_Internal.h" +#import "MCCastingApp.h" + +#import + +@implementation MCAttribute + +- (instancetype _Nonnull)initWithCppAttribute:(void *)cppAttribute +{ + if (self = [super init]) { + _cppAttribute = cppAttribute; + } + return self; +} + +- (void)read:(void * _Nullable)context completion:(void (^_Nonnull __strong)(void * _Nullable, id _Nullable __strong, id _Nullable __strong, NSError * _Nullable __strong))completion +{ +} + +- (void)subscribe:(void * _Nullable)context completion:(void (^_Nonnull __strong)(void * _Nullable, id _Nullable __strong, id _Nullable __strong, NSError * _Nullable __strong))completion minInterval:(NSNumber *)minInterval maxInterval:(NSNumber *)maxInterval +{ +} + +- (void)write:(id _Nonnull)value withCompletionBlock:(void (^_Nonnull __strong)(NSError * _Nullable __strong))completionBlock +{ +} + +- (id _Nullable)getObjTypeFromCpp:(std::any)cppValue +{ + return nil; +} + +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttributeObjects.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttributeObjects.h new file mode 100644 index 00000000000000..d8f371ee1eebbe --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttributeObjects.h @@ -0,0 +1,30 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "MCAttribute.h" +#import + +#ifndef MCAttributeObjects_h +#define MCAttributeObjects_h + +@interface MCApplicationBasicClusterVendorIDAttribute : MCAttribute +@end + +@interface MCMediaPlaybackClusterCurrentStateAttribute : MCAttribute +@end + +#endif /* MCAttributeObjects_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttributeObjects.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttributeObjects.mm new file mode 100644 index 00000000000000..5ce91d5ec781bb --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttributeObjects.mm @@ -0,0 +1,109 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCAttributeObjects.h" + +#import "MCAttribute_Internal.h" +#import "MCCastingApp.h" +#import "MCErrorUtils.h" + +#include "core/Attribute.h" +#include + +#import + +@implementation MCApplicationBasicClusterVendorIDAttribute +- (void)read:(void * _Nullable)context + completion:(void (^_Nonnull __strong)(void * _Nullable, id _Nullable __strong before, id _Nullable __strong after, NSError * _Nullable __strong error))completion +{ + MCAttributeTemplate * mcAttribute = new MCAttributeTemplate(self.cppAttribute, + [self](std::any cppValue) { + return [self getObjTypeFromCpp:cppValue]; + }); + mcAttribute->read(context, [mcAttribute, completion](void * context, id before, id after, NSError * err) { + completion(context, before, after, err); + delete mcAttribute; + }); +} + +- (void)subscribe:(void * _Nullable)context + completion:(void (^_Nonnull __strong)(void * _Nullable, id _Nullable __strong before, id _Nullable __strong after, NSError * _Nullable __strong error))completion + minInterval:(NSNumber * _Nonnull)minInterval + maxInterval:(NSNumber * _Nonnull)maxInterval +{ + MCAttributeTemplate * mcAttribute = new MCAttributeTemplate(self.cppAttribute, + [self](std::any cppValue) { + return [self getObjTypeFromCpp:cppValue]; + }); + mcAttribute->subscribe( + context, [mcAttribute, completion](void * context, id before, id after, NSError * err) { + completion(context, before, after, err); + delete mcAttribute; + }, minInterval, maxInterval); +} + +- (id _Nullable)getObjTypeFromCpp:(std::any)cppValue +{ + NSNumber * outValue = nil; + if (cppValue.type() == typeid(std::shared_ptr)) { + std::shared_ptr valueSharedPtr = std::any_cast>(cppValue); + outValue = valueSharedPtr != nil ? [NSNumber numberWithUnsignedInteger:*valueSharedPtr] : nil; + } + return outValue; +} +@end + +@implementation MCMediaPlaybackClusterCurrentStateAttribute +- (void)read:(void * _Nullable)context + completion:(void (^_Nonnull __strong)(void * _Nullable, id _Nullable __strong before, id _Nullable __strong after, NSError * _Nullable __strong error))completion +{ + MCAttributeTemplate * mcAttribute = new MCAttributeTemplate(self.cppAttribute, + [self](std::any cppValue) { + return [self getObjTypeFromCpp:cppValue]; + }); + mcAttribute->read(context, [mcAttribute, completion](void * context, id before, id after, NSError * err) { + completion(context, before, after, err); + delete mcAttribute; + }); +} + +- (void)subscribe:(void * _Nullable)context + completion:(void (^_Nonnull __strong)(void * _Nullable, id _Nullable __strong before, id _Nullable __strong after, NSError * _Nullable __strong error))completion + minInterval:(NSNumber * _Nonnull)minInterval + maxInterval:(NSNumber * _Nonnull)maxInterval +{ + MCAttributeTemplate * mcAttribute = new MCAttributeTemplate(self.cppAttribute, + [self](std::any cppValue) { + return [self getObjTypeFromCpp:cppValue]; + }); + mcAttribute->subscribe( + context, [mcAttribute, completion](void * context, id before, id after, NSError * err) { + completion(context, before, after, err); + delete mcAttribute; + }, minInterval, maxInterval); +} + +- (id _Nullable)getObjTypeFromCpp:(std::any)cppValue +{ + NSNumber * outValue = nil; + if (cppValue.type() == typeid(std::shared_ptr)) { + std::shared_ptr valueSharedPtr = std::any_cast>(cppValue); + outValue = valueSharedPtr != nil ? [NSNumber numberWithUnsignedInteger:static_cast(*valueSharedPtr)] : nil; + } + return outValue; +} +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute_Internal.h new file mode 100644 index 00000000000000..9a0c7e0385f515 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute_Internal.h @@ -0,0 +1,120 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCAttribute.h" + +#import "MCCastingApp.h" +#import "MCErrorUtils.h" +#include "core/Attribute.h" +#include + +#import +#include +#include +#include + +#ifndef MCAttribute_Internal_h +#define MCAttribute_Internal_h + +@interface MCAttribute () + +@property (nonatomic, readwrite) void * _Nonnull cppAttribute; + +- (instancetype _Nonnull)initWithCppAttribute:(void * _Nonnull)cppAttribute; + +- (id _Nullable)getObjTypeFromCpp:(std::any)cppValue; + +@end + +template +class MCAttributeTemplate { +public: + MCAttributeTemplate(void * _Nonnull cppAttribute, + std::function getObjTypeFromCppFn) + { + mCppAttribute = cppAttribute; + mGetObjTypeFromCppFn = getObjTypeFromCppFn; + } + + void read(void * _Nullable context, std::function completion) + { + dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue], clientQueue = [[MCCastingApp getSharedInstance] getClientQueue]; + dispatch_sync(workQueue, ^{ + matter::casting::core::Attribute * attribute = static_cast *>(mCppAttribute); + + attribute->Read( + context, + [clientQueue, completion, this](void * context, chip::Optional before, typename TypeInfo::DecodableArgType after) { + NSNumber *objCBefore = nil, *objCAfter = nil; + if (before.HasValue()) { + ChipLogProgress(AppServer, " converting 'before' value from Cpp to ObjC"); + std::any anyBefore = std::any(std::make_shared(before.Value())); + objCBefore = mGetObjTypeFromCppFn(anyBefore); + } + ChipLogProgress(AppServer, " converting 'after' value from Cpp to ObjC"); + std::any anyAfter = std::any(std::make_shared(after)); + objCAfter = mGetObjTypeFromCppFn(anyAfter); + dispatch_async(clientQueue, ^{ + completion(context, objCBefore, objCAfter, nil); + }); + }, + [clientQueue, completion](void * context, CHIP_ERROR error) { + dispatch_async(clientQueue, ^{ + completion(context, nil, nil, [MCErrorUtils NSErrorFromChipError:error]); + }); + }); + }); + } + + void subscribe(void * _Nullable context, std::function completion, + NSNumber * _Nonnull minInterval, NSNumber * _Nonnull maxInterval) + { + dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue], clientQueue = [[MCCastingApp getSharedInstance] getClientQueue]; + dispatch_sync(workQueue, ^{ + matter::casting::core::Attribute * attribute = static_cast *>(mCppAttribute); + + attribute->Subscribe( + context, + [clientQueue, completion, this](void * context, chip::Optional before, typename TypeInfo::DecodableArgType after) { + NSNumber *objCBefore = nil, *objCAfter = nil; + if (before.HasValue()) { + ChipLogProgress(AppServer, " converting 'before' value from Cpp to ObjC"); + std::any anyBefore = std::any(std::make_shared(before.Value())); + objCBefore = mGetObjTypeFromCppFn(anyBefore); + } + ChipLogProgress(AppServer, " converting 'after' value from Cpp to ObjC"); + std::any anyAfter = std::any(std::make_shared(after)); + objCAfter = mGetObjTypeFromCppFn(anyAfter); + dispatch_async(clientQueue, ^{ + completion(context, objCBefore, objCAfter, nil); + }); + }, + [clientQueue, completion](void * context, CHIP_ERROR error) { + dispatch_async(clientQueue, ^{ + completion(context, nil, nil, [MCErrorUtils NSErrorFromChipError:error]); + }); + }, + minInterval.intValue, + maxInterval.intValue); + }); + } + +private: + void * _Nonnull mCppAttribute; + std::function mGetObjTypeFromCppFn; +}; +#endif /* MCAttribute_Internal_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h index 4259fe53cc7121..cc3d90e8a2f922 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h @@ -48,20 +48,20 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError * _Nullable))completion timeout:(long long)timeout desiredEndpointFilter:(MCEndpointFilter * _Nullable)desiredEndpointFilter; /** - * @brief (async) Verifies that a connection exists with this CastingPlayer, or triggers a new session request. If the - * CastingApp does not have the nodeId and fabricIndex of this CastingPlayer cached on disk, this will execute the user + * @brief (async) Verifies that a connection exists with this MCCastingPlayer, or triggers a new session request. If the + * MCCastingApp does not have the nodeId and fabricIndex of this MCCastingPlayer cached on disk, this will execute the user * directed commissioning process. * * @param completion - called back when the connection process completes. Parameter is nil if it completed successfully - * @param desiredEndpointFilter - Attributes (such as VendorId) describing an Endpoint that the client wants to interact + * @param desiredEndpointFilter - Attributes (such as VendorId) describing an MCEndpoint that the client wants to interact * with after commissioning. If this value is passed in, the VerifyOrEstablishConnection will force User Directed - * Commissioning, in case the desired Endpoint is not found in the on-device cached information about the CastingPlayer + * Commissioning, in case the desired Endpoint is not found in the on-device cached information about the MCCastingPlayer * (if any) */ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError * _Nullable))completion desiredEndpointFilter:(MCEndpointFilter * _Nullable)desiredEndpointFilter; /** - * @brief Sets the internal connection state of this CastingPlayer to "disconnected" + * @brief Sets the internal connection state of this MCCastingPlayer to "disconnected" */ - (void)disconnect; @@ -72,8 +72,10 @@ - (uint32_t)deviceType; - (NSArray * _Nonnull)ipAddresses; -// TODO -// - (NSArray * _Nonnull)endpoints; +/** + * @brief Returns the NSArray of MCEndpoints associated with this MCCastingPlayer + */ +- (NSArray * _Nonnull)endpoints; - (nonnull instancetype)init UNAVAILABLE_ATTRIBUTE; + (nonnull instancetype)new UNAVAILABLE_ATTRIBUTE; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm index 40ea160d5abc3b..45cc9568f472a1 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm @@ -18,6 +18,7 @@ #import "MCCastingPlayer.h" #import "MCCastingApp.h" +#import "MCEndpoint_Internal.h" #import "MCErrorUtils.h" #import "core/CastingPlayer.h" @@ -78,12 +79,6 @@ - (void)disconnect }); } -- (NSString * _Nonnull)description -{ - return [NSString stringWithFormat:@"%@ with Product ID: %d and Vendor ID: %d. Resolved IPAddr?: %@", - self.deviceName, self.productId, self.vendorId, self.ipAddresses != nil && self.ipAddresses.count > 0 ? @"YES" : @"NO"]; -} - - (instancetype _Nonnull)initWithCppCastingPlayer:(matter::casting::memory::Strong)cppCastingPlayer { if (self = [super init]) { @@ -92,6 +87,12 @@ - (instancetype _Nonnull)initWithCppCastingPlayer:(matter::casting::memory::Stro return self; } +- (NSString * _Nonnull)description +{ + return [NSString stringWithFormat:@"%@ with Product ID: %hu and Vendor ID: %hu. Resolved IPAddr?: %@", + self.deviceName, self.productId, self.vendorId, self.ipAddresses != nil && self.ipAddresses.count > 0 ? @"YES" : @"NO"]; +} + - (NSString * _Nonnull)identifier { return [NSString stringWithCString:_cppCastingPlayer->GetId() encoding:NSUTF8StringEncoding]; @@ -128,11 +129,16 @@ - (NSArray * _Nonnull)ipAddresses return ipAddresses; } -// TODO convert to Obj-C endpoints and return -/*- (NSArray * _Nonnull)endpoints +- (NSArray * _Nonnull)endpoints { - return [NSMutableArray new]; -}*/ + NSMutableArray * endpoints = [NSMutableArray new]; + const std::vector> cppEndpoints = _cppCastingPlayer->GetEndpoints(); + for (matter::casting::memory::Strong cppEndpoint : cppEndpoints) { + MCEndpoint * endpoint = [[MCEndpoint alloc] initWithCppEndpoint:cppEndpoint]; + [endpoints addObject:endpoint]; + } + return endpoints; +} - (BOOL)isEqualToMCCastingPlayer:(MCCastingPlayer * _Nullable)other { diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h new file mode 100644 index 00000000000000..6c52733c3d6909 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h @@ -0,0 +1,33 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCastingPlayer.h" + +#import "core/CastingPlayer.h" + +#import + +#ifndef MCCastingPlayer_Internal_h +#define MCCastingPlayer_Internal_h + +@interface MCCastingPlayer () + +- (instancetype _Nonnull)initWithCppCastingPlayer:(matter::casting::memory::Strong)cppCastingPlayer; + +@end + +#endif /* MCCastingPlayer_Internal_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster.h new file mode 100644 index 00000000000000..bd150b7c6ea8e5 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster.h @@ -0,0 +1,36 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCommand.h" +#import "MCEndpoint.h" +#import + +#ifndef MCCluster_h +#define MCCluster_h + +@class MCEndpoint; + +@interface MCCluster : NSObject + +/** + * @brief Get the MCEndpoint corresponding to this MCCluster + */ +- (MCEndpoint * _Nonnull)endpoint; + +@end + +#endif /* MCCluster_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster.mm new file mode 100644 index 00000000000000..ecb7a9175925d2 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster.mm @@ -0,0 +1,42 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCClusterObjects.h" +#import "MCCluster_Internal.h" + +#import "MCEndpoint_Internal.h" + +#import "core/Endpoint.h" + +#import + +@implementation MCCluster + +- (instancetype _Nonnull)initWithCppCluster:(matter::casting::memory::Strong)cppCluster +{ + if (self = [super init]) { + _cppCluster = cppCluster; + } + return self; +} + +- (MCEndpoint * _Nonnull)endpoint +{ + return [[MCEndpoint alloc] initWithCppEndpoint:_cppCluster->GetEndpoint().lock()]; +} + +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCClusterObjects.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCClusterObjects.h new file mode 100644 index 00000000000000..290b747702e272 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCClusterObjects.h @@ -0,0 +1,47 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "MCAttributeObjects.h" +#import "MCCluster.h" +#import "MCCommandObjects.h" +#import + +#ifndef MCClusterObjects_h +#define MCClusterObjects_h + +@interface MCContentLauncherCluster : MCCluster +/** + * @brief Returns non-nil pointer to MCContentLauncherClusterLaunchURLCommand if supported, nil otherwise + */ +- (MCContentLauncherClusterLaunchURLCommand * _Nullable)launchURLCommand; +@end + +@interface MCApplicationBasicCluster : MCCluster +/** + * @brief Returns non-nil pointer to MCApplicationBasicClusterVendorIDAttribute if supported, nil otherwise + */ +- (MCApplicationBasicClusterVendorIDAttribute * _Nullable)vendorIDAttribute; +@end + +@interface MCMediaPlaybackCluster : MCCluster +/** + * @brief Returns non-nil pointer to MCMediaPlaybackClusterCurrentStateAttribute if supported, nil otherwise + */ +- (MCMediaPlaybackClusterCurrentStateAttribute * _Nullable)currentStateAttribute; +@end + +#endif /* MCClusterObjects_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCClusterObjects.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCClusterObjects.mm new file mode 100644 index 00000000000000..397dc628ffb405 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCClusterObjects.mm @@ -0,0 +1,52 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCClusterObjects.h" + +#import "MCAttribute_Internal.h" +#import "MCCluster_Internal.h" +#import "MCCommand_Internal.h" + +#include "core/Attribute.h" +#include "core/Command.h" +#include + +#import + +@implementation MCContentLauncherCluster +- (id)launchURLCommand +{ + void * cppCommand = self.cppCluster->GetCommand(chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Id); + return cppCommand != nil ? [[MCContentLauncherClusterLaunchURLCommand alloc] initWithCppCommand:cppCommand] : nil; +} +@end + +@implementation MCApplicationBasicCluster +- (id)vendorIDAttribute +{ + void * cppAttribute = self.cppCluster->GetAttribute(chip::app::Clusters::ApplicationBasic::Attributes::VendorID::Id); + return cppAttribute != nil ? [[MCApplicationBasicClusterVendorIDAttribute alloc] initWithCppAttribute:cppAttribute] : nil; +} +@end + +@implementation MCMediaPlaybackCluster +- (id)currentStateAttribute +{ + void * cppAttribute = self.cppCluster->GetAttribute(chip::app::Clusters::MediaPlayback::Attributes::CurrentState::Id); + return cppAttribute != nil ? [[MCMediaPlaybackClusterCurrentStateAttribute alloc] initWithCppAttribute:cppAttribute] : nil; +} +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster_Internal.h new file mode 100644 index 00000000000000..5342d5e466109f --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCluster_Internal.h @@ -0,0 +1,35 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCluster.h" + +#import "core/Endpoint.h" + +#import + +#ifndef MCCluster_Internal_h +#define MCCluster_Internal_h + +@interface MCCluster () + +@property (nonatomic, readwrite) matter::casting::memory::Strong cppCluster; + +- (instancetype _Nonnull)initWithCppCluster:(matter::casting::memory::Strong)cppCluster; + +@end + +#endif /* MCCluster_Internal_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand.h new file mode 100644 index 00000000000000..634d72a75affb5 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand.h @@ -0,0 +1,39 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import + +#ifndef MCCommand_h +#define MCCommand_h + +@interface MCCommand : NSObject + +/** + * @brief Invokes this MCCommand on the associated MCEndpoint and corresponding MCCluster + * + * @param request request data corresponding to this command invocation + * @param completion Called when command execution completes with nil NSError if successful and responseData. On failure, the NSError describes the error + * @param timedInvokeTimeoutMs command timeout in ms + */ +- (void)invoke:(RequestType _Nonnull)request + context:(void * _Nullable)context + completion:(void (^_Nonnull)(void * _Nullable, NSError * _Nullable, ResponseType _Nullable))completion + timedInvokeTimeoutMs:(NSNumber * _Nullable)timedInvokeTimeoutMs; + +@end + +#endif /* MCCommand_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand.mm new file mode 100644 index 00000000000000..b70945c7b022be --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand.mm @@ -0,0 +1,50 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCastingApp.h" +#import "MCCommand_Internal.h" + +#import + +@implementation MCCommand + +- (instancetype _Nonnull)initWithCppCommand:(void *)cppCommand +{ + if (self = [super init]) { + _cppCommand = cppCommand; + } + return self; +} + +- (void)invoke:(id _Nonnull)request + context:(void * _Nullable)context + completion:(void (^_Nonnull __strong)(void * _Nullable, NSError * _Nullable __strong, id _Nullable __strong))completion + timedInvokeTimeoutMs:(NSNumber * _Nullable)timedInvokeTimeoutMs +{ +} + +- (std::any)getCppRequestFromObjC:(id _Nonnull)objcRequest +{ + return nil; +} + +- (id _Nullable)getObjCResponseFromCpp:(std::any)cppResponse +{ + return nil; +} + +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommandObjects.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommandObjects.h new file mode 100644 index 00000000000000..c600d151febf1f --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommandObjects.h @@ -0,0 +1,60 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCommand.h" +#import + +#ifndef MCCommandObjects_h +#define MCCommandObjects_h + +@interface MCContentLauncherClusterDimensionStruct : NSObject +@property (nonatomic, copy) NSNumber * _Nonnull width; +@property (nonatomic, copy) NSNumber * _Nonnull height; +@property (nonatomic, copy) NSNumber * _Nonnull metric; +@end + +@interface MCContentLauncherClusterStyleInformationStruct : NSObject +@property (nonatomic, copy) NSString * _Nullable imageURL; +@property (nonatomic, copy) NSString * _Nullable imageUrl; +@property (nonatomic, copy) NSString * _Nullable color; +@property (nonatomic, copy) MCContentLauncherClusterDimensionStruct * _Nullable size; +@end + +@interface MCContentLauncherClusterBrandingInformationStruct : NSObject +@property (nonatomic, copy) NSString * _Nonnull providerName; +@property (nonatomic, copy) MCContentLauncherClusterStyleInformationStruct * _Nullable background; +@property (nonatomic, copy) MCContentLauncherClusterStyleInformationStruct * _Nullable logo; +@property (nonatomic, copy) MCContentLauncherClusterStyleInformationStruct * _Nullable progressBar; +@property (nonatomic, copy) MCContentLauncherClusterStyleInformationStruct * _Nullable splash; +@property (nonatomic, copy) MCContentLauncherClusterStyleInformationStruct * _Nullable waterMark; +@end + +@interface MCContentLauncherClusterLaunchURLRequest : NSObject +@property (nonatomic, copy) NSString * _Nonnull contentURL; +@property (nonatomic, copy) NSString * _Nullable displayString; +@property (nonatomic, copy) MCContentLauncherClusterBrandingInformationStruct * _Nullable brandingInformation; +@end + +@interface MCContentLauncherClusterLauncherResponse : NSObject +@property (nonatomic, copy) NSNumber * _Nonnull status; +@property (nonatomic, copy) NSString * _Nullable data; +@end + +@interface MCContentLauncherClusterLaunchURLCommand : MCCommand +@end + +#endif /* MCCommandObjects_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommandObjects.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommandObjects.mm new file mode 100644 index 00000000000000..8c37d0911668fb --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommandObjects.mm @@ -0,0 +1,132 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCommandObjects.h" + +#import "MCCastingApp.h" +#import "MCCommand_Internal.h" +#import "MCErrorUtils.h" + +#include "core/Command.h" +#include + +#import + +@implementation MCContentLauncherClusterLaunchURLRequest + +- (instancetype)init +{ + if (self = [super init]) { + _contentURL = @""; + _displayString = nil; + _brandingInformation = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MCContentLauncherClusterLaunchURLRequest alloc] init]; + other.contentURL = self.contentURL; + other.displayString = self.displayString; + other.brandingInformation = self.brandingInformation; + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: contentURL:%@; displayString:%@; brandingInformation:%@; >", NSStringFromClass([self class]), _contentURL, _displayString, _brandingInformation]; + return descriptionString; +} +@end + +@implementation MCContentLauncherClusterLauncherResponse + +- (instancetype)init +{ + if (self = [super init]) { + _status = @(0); + _data = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MCContentLauncherClusterLauncherResponse alloc] init]; + + other.status = self.status; + other.data = self.data; + return other; +} + +- (instancetype)initWithDecodableStruct:(const chip::app::Clusters::ContentLauncher::Commands::LauncherResponse::DecodableType &)decodableStruct +{ + if (self = [super init]) { + _status = [NSNumber numberWithUnsignedChar:chip::to_underlying(decodableStruct.status)]; + _data = [[NSString alloc] initWithBytes:decodableStruct.data.Value().data() length:decodableStruct.data.Value().size() encoding:NSUTF8StringEncoding]; + } + return self; +} + +@end + +@implementation MCContentLauncherClusterLaunchURLCommand + +- (void)invoke:(id)request + context:(void * _Nullable)context + completion:(void (^_Nonnull __strong)(void *, NSError *, id))completion + timedInvokeTimeoutMs:(NSNumber * _Nullable)timedInvokeTimeoutMs +{ + MCCommandTemplate * mcCommand = new MCCommandTemplate( + self.cppCommand, + [self](id objCRequest) { + return [self getCppRequestFromObjC:objCRequest]; + }, + [self](std::any cppResponse) { + return [self getObjCResponseFromCpp:cppResponse]; + }); + mcCommand->invoke( + request, context, [mcCommand, completion](void * context, NSError * err, id response) { + completion(context, err, response); + delete mcCommand; + }, timedInvokeTimeoutMs); +} + +- (std::any)getCppRequestFromObjC:(MCContentLauncherClusterLaunchURLRequest *)objcRequest +{ + VerifyOrReturnValue(objcRequest != nil, nullptr); + + std::shared_ptr cppRequest = std::make_shared(); + cppRequest->contentURL = chip::CharSpan([objcRequest.contentURL UTF8String], [objcRequest.contentURL lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + if (objcRequest.displayString != nil) { + cppRequest->displayString = chip::Optional(chip::CharSpan([objcRequest.displayString UTF8String], [objcRequest.displayString lengthOfBytesUsingEncoding:NSUTF8StringEncoding])); + } + cppRequest->brandingInformation = chip::MakeOptional(chip::app::Clusters::ContentLauncher::Structs::BrandingInformationStruct::Type()); // TODO: map brandingInformation + return std::any(cppRequest); +} + +- (id)getObjCResponseFromCpp:(std::any)cppResponse +{ + MCContentLauncherClusterLauncherResponse * objCResponse = nil; + if (cppResponse.type() == typeid(std::shared_ptr)) { + std::shared_ptr responseSharedPtr = std::any_cast>(cppResponse); + objCResponse = responseSharedPtr != nil ? [[MCContentLauncherClusterLauncherResponse alloc] initWithDecodableStruct:*responseSharedPtr] : nil; + } + return objCResponse; +} +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand_Internal.h new file mode 100644 index 00000000000000..384004467fef30 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommand_Internal.h @@ -0,0 +1,98 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCCommand.h" + +#import "MCCastingApp.h" +#import "MCErrorUtils.h" +#include "core/Command.h" +#include + +#import +#include +#include +#include + +#ifndef MCCommand_Internal_h +#define MCCommand_Internal_h + +@interface MCCommand () + +@property (nonatomic, readwrite) void * _Nonnull cppCommand; + +- (instancetype _Nonnull)initWithCppCommand:(void * _Nonnull)cppCommand; + +- (std::any)getCppRequestFromObjC:(id _Nonnull)objcRequest; + +- (id _Nullable)getObjCResponseFromCpp:(std::any)cppResponse; +@end + +template +class MCCommandTemplate { +public: + MCCommandTemplate(void * _Nonnull cppCommand, + std::function getCppRequestFromObjCFn, + std::function getObjCResponseFromCppFn) + { + mCppCommand = cppCommand; + mGetCppRequestFromObjCFn = getCppRequestFromObjCFn; + mGetObjCResponseFromCppFn = getObjCResponseFromCppFn; + } + + void invoke(id _Nonnull request, void * _Nullable context, std::function completion, NSNumber * _Nullable timedInvokeTimeoutMs) + { + dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue], clientQueue = [[MCCastingApp getSharedInstance] getClientQueue]; + dispatch_sync(workQueue, ^{ + ChipLogProgress(AppServer, " converting 'request' from ObjC to Cpp"); + std::shared_ptr cppRequest = nil; + std::any anyRequest = mGetCppRequestFromObjCFn(request); + if (anyRequest.type() == typeid(std::shared_ptr)) { + cppRequest = std::any_cast>(anyRequest); + } + if (cppRequest == nil) { + dispatch_async(clientQueue, ^{ + completion(context, [MCErrorUtils NSErrorFromChipError:CHIP_ERROR_INVALID_ARGUMENT], nil); + }); + return; + } + + matter::casting::core::Command * command = static_cast *>(mCppCommand); + command->Invoke( + *cppRequest, context, + [clientQueue, completion, this](void * context, const typename Type::ResponseType & response) { + ChipLogProgress(AppServer, " converting 'response' from Cpp to ObjC"); + id objCResponse = mGetObjCResponseFromCppFn(std::any(std::make_shared(response))); + dispatch_async(clientQueue, ^{ + completion(context, nil, objCResponse); + }); + }, + [clientQueue, completion](void * context, CHIP_ERROR err) { + dispatch_async(clientQueue, ^{ + completion(context, [MCErrorUtils NSErrorFromChipError:err], nil); + }); + }, + timedInvokeTimeoutMs != nil ? chip::MakeOptional(timedInvokeTimeoutMs.intValue) : chip::NullOptional); + }); + } + +private: + void * _Nonnull mCppCommand; + std::function mGetCppRequestFromObjCFn; + std::function mGetObjCResponseFromCppFn; +}; + +#endif /* MCCommand_Internal_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceTypeStruct.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceTypeStruct.h new file mode 100644 index 00000000000000..e893f65ecbf7a5 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceTypeStruct.h @@ -0,0 +1,33 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import + +#ifndef MCDeviceTypeStruct_h +#define MCDeviceTypeStruct_h + +@interface MCDeviceTypeStruct : NSObject + +@property (nonatomic, strong, readonly) NSNumber * _Nonnull deviceType; + +@property (nonatomic, strong, readonly) NSNumber * _Nonnull revision; + +- (instancetype _Nonnull)initWithDeviceType:(uint32_t)deviceType revision:(uint16_t)revision; + +@end + +#endif /* MCDeviceTypeStruct_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceTypeStruct.m b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceTypeStruct.m new file mode 100644 index 00000000000000..d50e81a83f09e1 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceTypeStruct.m @@ -0,0 +1,31 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCDeviceTypeStruct.h" + +@implementation MCDeviceTypeStruct + +- (instancetype _Nonnull)initWithDeviceType:(uint32_t)deviceType revision:(uint16_t)revision +{ + if (self = [super init]) { + _deviceType = [NSNumber numberWithUnsignedInt:deviceType]; + _revision = [NSNumber numberWithUnsignedShort:revision]; + } + return self; +} + +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h new file mode 100644 index 00000000000000..d252bd3c92f3e1 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h @@ -0,0 +1,46 @@ +/** + * + * Copyright (c) 2020-2023 Project CHIP Authors + * + * 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. + */ + +#import "MCCastingPlayer.h" +#import "MCCluster.h" +#import "MCEndpointClusterType.h" + +#import + +#ifndef MCEndpoint_h +#define MCEndpoint_h + +@class MCCastingPlayer; +@class MCCluster; + +@interface MCEndpoint : NSObject + +- (NSNumber * _Nonnull)identifier; +- (NSNumber * _Nonnull)vendorId; +- (NSNumber * _Nonnull)productId; +- (NSArray * _Nonnull)deviceTypeList; +- (MCCastingPlayer * _Nonnull)castingPlayer; + +- (nonnull instancetype)init UNAVAILABLE_ATTRIBUTE; ++ (nonnull instancetype)new UNAVAILABLE_ATTRIBUTE; + +- (BOOL)hasCluster:(MCEndpointClusterType)type; +- (MCCluster * _Nullable)clusterForType:(MCEndpointClusterType)type; + +@end + +#endif /* MCEndpoint_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm new file mode 100644 index 00000000000000..006488aed03eb5 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm @@ -0,0 +1,133 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * 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. + */ + +#import "MCEndpoint_Internal.h" + +#import "MCCastingPlayer_Internal.h" +#import "MCCluster_Internal.h" +#import "MCDeviceTypeStruct.h" + +#import "MCClusterObjects.h" + +#import "clusters/Clusters.h" +#import "core/Endpoint.h" + +#import + +@interface MCEndpoint () + +@property (nonatomic, readwrite) matter::casting::memory::Strong cppEndpoint; + +@end + +@implementation MCEndpoint + +- (instancetype _Nonnull)initWithCppEndpoint:(matter::casting::memory::Strong)cppEndpoint +{ + if (self = [super init]) { + _cppEndpoint = cppEndpoint; + } + return self; +} + +- (NSNumber * _Nonnull)identifier +{ + return [NSNumber numberWithUnsignedShort:_cppEndpoint->GetId()]; +} + +- (NSNumber * _Nonnull)productId +{ + return [NSNumber numberWithUnsignedShort:_cppEndpoint->GetProductId()]; +} + +- (NSNumber * _Nonnull)vendorId +{ + return [NSNumber numberWithUnsignedShort:_cppEndpoint->GetVendorId()]; +} + +- (NSArray * _Nonnull)deviceTypeList +{ + NSMutableArray * deviceTypeList = [NSMutableArray new]; + std::vector cppDeviceTypeList = _cppEndpoint->GetDeviceTypeList(); + for (chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::DecodableType cppDeviceTypeStruct : cppDeviceTypeList) { + MCDeviceTypeStruct * deviceTypeStruct = [[MCDeviceTypeStruct alloc] initWithDeviceType:cppDeviceTypeStruct.deviceType revision:cppDeviceTypeStruct.revision]; + [deviceTypeList addObject:deviceTypeStruct]; + } + return deviceTypeList; +} + +- (MCCastingPlayer * _Nonnull)castingPlayer +{ + return [[MCCastingPlayer alloc] initWithCppCastingPlayer:std::shared_ptr(_cppEndpoint->GetCastingPlayer())]; +} + +- (MCCluster * _Nullable)clusterForType:(MCEndpointClusterType)type +{ + switch (type) { + case MCEndpointClusterTypeContentLauncher: + return [[MCContentLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + + case MCEndpointClusterTypeApplicationBasic: + return [[MCApplicationBasicCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + + case MCEndpointClusterTypeMediaPlayback: + return [[MCMediaPlaybackCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + + default: + ChipLogError(AppServer, "MCEndpointClusterType not found"); + break; + } + return nil; +} + +- (BOOL)hasCluster:(MCEndpointClusterType)type +{ + return [self clusterForType:type] != nil; +} + +- (BOOL)isEqualToMCEndpoint:(MCEndpoint * _Nullable)other +{ + return [self.identifier isEqualToNumber:other.identifier]; +} + +- (BOOL)isEqual:(id _Nullable)other +{ + if (other == nil) { + return NO; + } + + if (self == other) { + return YES; + } + + if (![other isKindOfClass:[MCEndpoint class]]) { + return NO; + } + + return [self isEqualToMCEndpoint:(MCEndpoint *) other]; +} + +- (NSUInteger)hash +{ + const NSUInteger prime = 31; + NSUInteger result = 1; + + result = prime * result + [self.identifier hash]; + + return result; +} +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpointClusterType.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpointClusterType.h new file mode 100644 index 00000000000000..7137dd1ed96042 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpointClusterType.h @@ -0,0 +1,28 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#ifndef MCEndpointClusterType_h +#define MCEndpointClusterType_h + +typedef enum _MCEndpointClusterType +{ + MCEndpointClusterTypeApplicationBasic, + MCEndpointClusterTypeContentLauncher, + MCEndpointClusterTypeMediaPlayback +} MCEndpointClusterType; + +#endif /* MCEndpointClusterType_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h new file mode 100644 index 00000000000000..53b1d6bf22218e --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h @@ -0,0 +1,33 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MCEndpoint.h" + +#import "core/Endpoint.h" + +#import + +#ifndef MCEndpoint_Internal_h +#define MCEndpoint_Internal_h + +@interface MCEndpoint () + +- (instancetype _Nonnull)initWithCppEndpoint:(matter::casting::memory::Strong)cppEndpoint; + +@end + +#endif /* MCEndpoint_Internal_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCObserver.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCObserver.h new file mode 100644 index 00000000000000..a1ca48f8b87616 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCObserver.h @@ -0,0 +1,29 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import + +#ifndef MCObserver_h +#define MCObserver_h + +@protocol MCObserver + +- (void)attribute:(NSObject * _Nonnull)sender valueDidChange:(NSValue * _Nullable)value oldValue:(NSValue * _Nullable)oldValue; + +@end + +#endif /* MCObserver_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h index 9329bc657b9c32..093f02b9455b0d 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h @@ -26,11 +26,19 @@ FOUNDATION_EXPORT const unsigned char MatterTvCastingBridgeVersionString[]; #import "CastingServerBridge.h" // Add simplified casting API headers here +#import "MCAttribute.h" +#import "MCAttributeObjects.h" #import "MCCastingApp.h" #import "MCCastingPlayer.h" #import "MCCastingPlayerDiscovery.h" +#import "MCCluster.h" +#import "MCClusterObjects.h" +#import "MCCommand.h" +#import "MCCommandObjects.h" #import "MCCommissionableData.h" #import "MCCryptoUtils.h" #import "MCDataSource.h" #import "MCDeviceAttestationCredentials.h" +#import "MCEndpointClusterType.h" #import "MCEndpointFilter.h" +#import "MCObserver.h" diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj index 1fd70f6b3f48fb..e7005121a06352 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj @@ -7,6 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 3C40586E2B632DC500C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C40586D2B632DC500C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleView.swift */; }; + 3C4058702B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C40586F2B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift */; }; + 3C4F52302B51F32000BB8A10 /* MCContentLauncherLaunchURLExampleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4F522F2B51F32000BB8A10 /* MCContentLauncherLaunchURLExampleViewModel.swift */; }; + 3C4F52322B5721D000BB8A10 /* MCContentLauncherLaunchURLExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4F52312B5721D000BB8A10 /* MCContentLauncherLaunchURLExampleView.swift */; }; + 3C621CB12B6078A9005CDBA3 /* MCApplicationBasicReadVendorIDExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C621CB02B6078A9005CDBA3 /* MCApplicationBasicReadVendorIDExampleView.swift */; }; + 3C621CB32B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C621CB22B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift */; }; + 3C621CB52B607FFD005CDBA3 /* MCActionSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C621CB42B607FFD005CDBA3 /* MCActionSelectorView.swift */; }; 3C69204A2AA1368F00D0F613 /* MCInitializationExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C6920492AA1368F00D0F613 /* MCInitializationExample.swift */; }; 3C81C75328F8C79E001CB9D1 /* StartFromCacheView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C75228F8C79E001CB9D1 /* StartFromCacheView.swift */; }; 3C81C75528F8C7B6001CB9D1 /* StartFromCacheViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C75428F8C7B6001CB9D1 /* StartFromCacheViewModel.swift */; }; @@ -51,6 +58,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 3C40586D2B632DC500C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCMediaPlaybackSubscribeToCurrentStateExampleView.swift; sourceTree = ""; }; + 3C40586F2B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift; sourceTree = ""; }; + 3C4F522F2B51F32000BB8A10 /* MCContentLauncherLaunchURLExampleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCContentLauncherLaunchURLExampleViewModel.swift; sourceTree = ""; }; + 3C4F52312B5721D000BB8A10 /* MCContentLauncherLaunchURLExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCContentLauncherLaunchURLExampleView.swift; sourceTree = ""; }; + 3C621CB02B6078A9005CDBA3 /* MCApplicationBasicReadVendorIDExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCApplicationBasicReadVendorIDExampleView.swift; sourceTree = ""; }; + 3C621CB22B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCApplicationBasicReadVendorIDExampleViewModel.swift; sourceTree = ""; }; + 3C621CB42B607FFD005CDBA3 /* MCActionSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCActionSelectorView.swift; sourceTree = ""; }; 3C6920492AA1368F00D0F613 /* MCInitializationExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCInitializationExample.swift; sourceTree = ""; }; 3C75075E284C1DF800D7DB3A /* TvCasting.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TvCasting.entitlements; sourceTree = ""; }; 3C7507AC285299DF00D7DB3A /* CommissionerDiscoveryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissionerDiscoveryView.swift; sourceTree = ""; }; @@ -131,6 +145,13 @@ 3C94377C2B364D380096E5F4 /* MCDiscoveryExampleViewModel.swift */, 3C94378F2B3B3FF90096E5F4 /* MCConnectionExampleView.swift */, 3C94377E2B364D510096E5F4 /* MCConnectionExampleViewModel.swift */, + 3C621CB42B607FFD005CDBA3 /* MCActionSelectorView.swift */, + 3C4F52312B5721D000BB8A10 /* MCContentLauncherLaunchURLExampleView.swift */, + 3C4F522F2B51F32000BB8A10 /* MCContentLauncherLaunchURLExampleViewModel.swift */, + 3C621CB02B6078A9005CDBA3 /* MCApplicationBasicReadVendorIDExampleView.swift */, + 3C621CB22B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift */, + 3C40586D2B632DC500C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleView.swift */, + 3C40586F2B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift */, EAF14298296D561900E17793 /* CertTestView.swift */, EAF1429A296D57DF00E17793 /* CertTestViewModel.swift */, 3CC0E8FB2841DD3400EC6A18 /* ContentView.swift */, @@ -248,9 +269,14 @@ files = ( 3C81C75328F8C79E001CB9D1 /* StartFromCacheView.swift in Sources */, 3C94377F2B364D510096E5F4 /* MCConnectionExampleViewModel.swift in Sources */, + 3C4058702B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift in Sources */, 3C81C75528F8C7B6001CB9D1 /* StartFromCacheViewModel.swift in Sources */, 3CCB8745286A5D0F00771BAD /* CommissionerDiscoveryView.swift in Sources */, + 3C621CB12B6078A9005CDBA3 /* MCApplicationBasicReadVendorIDExampleView.swift in Sources */, 3CCB8746286A5D0F00771BAD /* CommissionerDiscoveryViewModel.swift in Sources */, + 3C4F52302B51F32000BB8A10 /* MCContentLauncherLaunchURLExampleViewModel.swift in Sources */, + 3C621CB32B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift in Sources */, + 3C621CB52B607FFD005CDBA3 /* MCActionSelectorView.swift in Sources */, 3C81C75928F8E42D001CB9D1 /* ConnectionViewModel.swift in Sources */, 3CA1CA7A28E281080023ED44 /* ClusterSelectorView.swift in Sources */, 3C94378E2B3B3CB00096E5F4 /* MCDiscoveryExampleView.swift in Sources */, @@ -259,6 +285,7 @@ 3C94377D2B364D380096E5F4 /* MCDiscoveryExampleViewModel.swift in Sources */, 3CCB8747286A5D0F00771BAD /* CommissioningView.swift in Sources */, 3CCB8748286A5D0F00771BAD /* CommissioningViewModel.swift in Sources */, + 3C4F52322B5721D000BB8A10 /* MCContentLauncherLaunchURLExampleView.swift in Sources */, 3CAC955B29BA948700BEA5C3 /* ExampleDAC.swift in Sources */, 3CA1CA7E28E284950023ED44 /* MediaPlaybackViewModel.swift in Sources */, 3CCB8749286A5D0F00771BAD /* ContentLauncherView.swift in Sources */, @@ -268,6 +295,7 @@ 3CC0E8FC2841DD3400EC6A18 /* ContentView.swift in Sources */, 3CA1CA7C28E282150023ED44 /* MediaPlaybackView.swift in Sources */, 3CC0E8FA2841DD3400EC6A18 /* TvCastingApp.swift in Sources */, + 3C40586E2B632DC500C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleView.swift in Sources */, 3C9437902B3B3FF90096E5F4 /* MCConnectionExampleView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting Release.xcscheme b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting Release.xcscheme index 05333fbe6fe932..e769afbac5e4a5 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting Release.xcscheme +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting Release.xcscheme @@ -53,7 +53,7 @@ diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting.xcscheme b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting.xcscheme index 2bdbabd75539cb..c64d5160489c18 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting.xcscheme +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/xcshareddata/xcschemes/TvCasting.xcscheme @@ -53,7 +53,7 @@ diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCActionSelectorView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCActionSelectorView.swift new file mode 100644 index 00000000000000..1ddc8d9539f554 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCActionSelectorView.swift @@ -0,0 +1,72 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +import SwiftUI + +struct MCActionSelectorView: View { + var selectedCastingPlayer: MCCastingPlayer? + + init(_selectedCastingPlayer: MCCastingPlayer?) { + self.selectedCastingPlayer = _selectedCastingPlayer + } + + var body: some View { + VStack(alignment: .leading) { + NavigationLink( + destination: MCContentLauncherLaunchURLExampleView(_selectedCastingPlayer: self.selectedCastingPlayer), + label: { + Text("ContentLauncher Launch URL") + .frame(width: 300, height: 30, alignment: .center) + .border(Color.black, width: 1) + } + ).background(Color.blue) + .foregroundColor(Color.white) + .padding() + + NavigationLink( + destination: MCApplicationBasicReadVendorIDExampleView(_selectedCastingPlayer: self.selectedCastingPlayer), + label: { + Text("ApplicationBasic Read VendorID") + .frame(width: 300, height: 30, alignment: .center) + .border(Color.black, width: 1) + } + ).background(Color.blue) + .foregroundColor(Color.white) + .padding() + + NavigationLink( + destination: MCMediaPlaybackSubscribeToCurrentStateExampleView(_selectedCastingPlayer: self.selectedCastingPlayer), + label: { + Text("MediaPlayback Subscribe to CurrentState") + .frame(width: 300, height: 30, alignment: .center) + .border(Color.black, width: 1) + } + ).background(Color.blue) + .foregroundColor(Color.white) + .padding() + + } + .navigationTitle("Select an action") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + } +} + +struct MCActionSelectorView_Previews: PreviewProvider { + static var previews: some View { + MCActionSelectorView(_selectedCastingPlayer: nil) + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleView.swift new file mode 100644 index 00000000000000..7a84abf1ab0ce4 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleView.swift @@ -0,0 +1,52 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +import SwiftUI + +struct MCApplicationBasicReadVendorIDExampleView: View { + @StateObject var viewModel = MCApplicationBasicReadVendorIDExampleViewModel() + + var selectedCastingPlayer: MCCastingPlayer? + + init(_selectedCastingPlayer: MCCastingPlayer?) { + self.selectedCastingPlayer = _selectedCastingPlayer + } + + var body: some View { + VStack(alignment: .leading) + { + Button("Read VendorID!") { + viewModel.read(castingPlayer: self.selectedCastingPlayer!) + } + .background(Color.blue) + .foregroundColor(Color.white) + .cornerRadius(4) + .border(Color.black, width: 1) + .padding() + + Text(viewModel.status ?? "") + } + .navigationTitle("ApplicationBasic Read VendorID") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + } +} + +struct MCApplicationBasicReadVendorIDExampleView_Previews: PreviewProvider { + static var previews: some View { + MCApplicationBasicReadVendorIDExampleView(_selectedCastingPlayer: nil) + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift new file mode 100644 index 00000000000000..32e20e4b324ca3 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift @@ -0,0 +1,96 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + + +import Foundation +import os.log + +class MCApplicationBasicReadVendorIDExampleViewModel: ObservableObject { + let Log = Logger(subsystem: "com.matter.casting", + category: "MCApplicationBasicReadVendorIDExampleViewModel") + + @Published var status: String?; + + // VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection + let sampleEndpointVid: Int = 65521 + + func read(castingPlayer: MCCastingPlayer) + { + // select the MCEndpoint on the MCCastingPlayer to invoke the command on + if let endpoint: MCEndpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid}).first + { + // validate that the selected endpoint supports the ApplicationBasic cluster + if(!endpoint.hasCluster(MCEndpointClusterTypeApplicationBasic)) + { + self.Log.error("No ApplicationBasic cluster supporting endpoint found") + DispatchQueue.main.async + { + self.status = "No ApplicationBasic cluster supporting endpoint found" + } + return + } + + // get ApplicationBasic cluster from the endpoint + let applicationBasiccluster: MCApplicationBasicCluster = endpoint.cluster(for: MCEndpointClusterTypeApplicationBasic) as! MCApplicationBasicCluster + + // get the vendorIDAttribute from the applicationBasiccluster + let vendorIDAttribute: MCApplicationBasicClusterVendorIDAttribute? = applicationBasiccluster.vendorIDAttribute() + if(vendorIDAttribute == nil) + { + self.Log.error("VendorID attribute not supported on cluster") + DispatchQueue.main.async + { + self.status = "VendorID attribute not supported on cluster" + } + return + } + + + // call read on vendorIDAttribute and pass in a completion block + vendorIDAttribute!.read(nil) { context, before, after, err in + DispatchQueue.main.async + { + if(err != nil) + { + self.Log.error("Error when reading VendorID value \(String(describing: err))") + self.status = "Error when reading VendorID value \(String(describing: err))" + return + } + + if(before != nil) + { + self.Log.info("Read VendorID value: \(String(describing: after)) Before: \(String(describing: before))") + self.status = "Read VendorID value: \(String(describing: after)) Before: \(String(describing: before))" + } + else + { + self.Log.info("Read VendorID value: \(String(describing: after))") + self.status = "Read VendorID value: \(String(describing: after))" + } + } + } + } + else + { + self.Log.error("No endpoint matching the example VID found") + DispatchQueue.main.async + { + self.status = "No endpoint matching the example VID found" + } + } + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift index 0dd6d302f7b968..87448bf46b4790 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift @@ -39,9 +39,8 @@ struct MCConnectionExampleView: View { if(connectionSuccess) { - /* TODO add this back in - NavigationLink( - destination: ClusterSelectorView(), + NavigationLink( + destination: MCActionSelectorView(_selectedCastingPlayer: self.selectedCastingPlayer), label: { Text("Next") .frame(width: 100, height: 30, alignment: .center) @@ -50,7 +49,7 @@ struct MCConnectionExampleView: View { ).background(Color.blue) .foregroundColor(Color.white) .frame(maxHeight: .infinity, alignment: .bottom) - .padding()*/ + .padding() } } } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift index 9d130b5e7737ee..13cdad3d8e60f1 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift @@ -35,15 +35,18 @@ class MCConnectionExampleViewModel: ObservableObject { desiredEndpointFilter.vendorId = kDesiredEndpointVendorId selectedCastingPlayer?.verifyOrEstablishConnection(completionBlock: { err in self.Log.error("MCConnectionExampleViewModel connect() completed with \(err)") - if(err == nil) + DispatchQueue.main.async { - self.connectionSuccess = true - self.connectionStatus = "Connected!" - } - else - { - self.connectionSuccess = false - self.connectionStatus = "Connection failed with \(String(describing: err))" + if(err == nil) + { + self.connectionSuccess = true + self.connectionStatus = "Connected!" + } + else + { + self.connectionSuccess = false + self.connectionStatus = "Connection failed with \(String(describing: err))" + } } }, desiredEndpointFilter: desiredEndpointFilter) } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleView.swift new file mode 100644 index 00000000000000..520ea86804e765 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleView.swift @@ -0,0 +1,79 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +import SwiftUI + +struct MCContentLauncherLaunchURLExampleView : View { + @StateObject var viewModel = MCContentLauncherLaunchURLExampleViewModel() + + var selectedCastingPlayer: MCCastingPlayer? + + @State private var contentUrl: String = "" + @State private var displayString: String = "" + + init(_selectedCastingPlayer: MCCastingPlayer?) { + self.selectedCastingPlayer = _selectedCastingPlayer + } + + var body: some View { + VStack(alignment: .leading) { + + HStack() { + Text("Content URL") + + TextField( + "https://www.test.com/videoid", + text: $contentUrl + ) + .textInputAutocapitalization(.never) + .disableAutocorrection(true) + .border(.secondary) + } + + HStack() { + Text("Display string") + + TextField( + "Test video", + text: $displayString + ) + .textInputAutocapitalization(.never) + .disableAutocorrection(true) + .border(.secondary) + } + + Button("Invoke Launch URL!") { + viewModel.invokeCommand(castingPlayer: self.selectedCastingPlayer!, contentUrl: contentUrl, displayString: displayString) + } + .background(Color.blue) + .foregroundColor(Color.white) + .cornerRadius(4) + .border(Color.black, width: 1) + .padding() + + Text(viewModel.status ?? "") + } + .navigationTitle("Content Launcher Launch URL") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + } +} + +struct MCCommandInvocationExampleView_Previews: PreviewProvider { + static var previews: some View { + MCContentLauncherLaunchURLExampleView(_selectedCastingPlayer: nil) + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift new file mode 100644 index 00000000000000..b74a91a77b7286 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift @@ -0,0 +1,94 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + + +import Foundation +import os.log + +class MCContentLauncherLaunchURLExampleViewModel: ObservableObject { + let Log = Logger(subsystem: "com.matter.casting", + category: "MCContentLauncherLaunchURLExampleViewModel") + + @Published var status: String?; + + // VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection + let sampleEndpointVid: Int = 65521 + + func invokeCommand(castingPlayer: MCCastingPlayer, contentUrl: String, displayString: String) + { + // select the MCEndpoint on the MCCastingPlayer to invoke the command on + if let endpoint: MCEndpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid}).first + { + // validate that the selected endpoint supports the ContentLauncher cluster + if(!endpoint.hasCluster(MCEndpointClusterTypeContentLauncher)) + { + self.Log.error("No ContentLauncher cluster supporting endpoint found") + DispatchQueue.main.async + { + self.status = "No ContentLauncher cluster supporting endpoint found" + } + return + } + + // get ContentLauncher cluster from the endpoint + let contentLaunchercluster: MCContentLauncherCluster = endpoint.cluster(for: MCEndpointClusterTypeContentLauncher) as! MCContentLauncherCluster + + // get the launchURLCommand from the contentLauncherCluster + let launchURLCommand: MCContentLauncherClusterLaunchURLCommand? = contentLaunchercluster.launchURLCommand() + if(launchURLCommand == nil) + { + self.Log.error("LaunchURL not supported on cluster") + DispatchQueue.main.async + { + self.status = "LaunchURL not supported on cluster" + } + return + } + + // create the LaunchURL request + let request: MCContentLauncherClusterLaunchURLRequest = MCContentLauncherClusterLaunchURLRequest() + request.contentURL = contentUrl + request.displayString = displayString + + // call invoke on launchURLCommand while passing in a completion block + launchURLCommand!.invoke(request, context: nil, completion: { context, err, response in + DispatchQueue.main.async + { + if(err == nil) + { + self.Log.info("LaunchURLCommand invoke completion success with \(String(describing: response))") + self.status = "Success. Response data: \(String(describing: response?.data))" + } + else + { + self.Log.error("LaunchURLCommand invoke completion failure with \(String(describing: err))") + self.status = "Failure: \(String(describing: err))" + } + } + }, + timedInvokeTimeoutMs: 5000) // time out after 5000ms + } + else + { + self.Log.error("No endpoint matching the example VID found") + DispatchQueue.main.async + { + self.status = "No endpoint matching the example VID found" + } + } + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleView.swift new file mode 100644 index 00000000000000..f99ea71cd0875b --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleView.swift @@ -0,0 +1,52 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +import SwiftUI + +struct MCMediaPlaybackSubscribeToCurrentStateExampleView: View { + @StateObject var viewModel = MCMediaPlaybackSubscribeToCurrentStateExampleViewModel() + + var selectedCastingPlayer: MCCastingPlayer? + + init(_selectedCastingPlayer: MCCastingPlayer?) { + self.selectedCastingPlayer = _selectedCastingPlayer + } + + var body: some View { + VStack(alignment: .leading) + { + Button("Subscribe to CurrentState!") { + viewModel.subscribe(castingPlayer: self.selectedCastingPlayer!) + } + .background(Color.blue) + .foregroundColor(Color.white) + .cornerRadius(4) + .border(Color.black, width: 1) + .padding() + + Text(viewModel.status ?? "") + } + .navigationTitle("MediaPlayback Subscribe to CurrentState") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + } +} + +struct MCMediaPlaybackSubscribeToCurrentStateExampleView_Previews: PreviewProvider { + static var previews: some View { + MCMediaPlaybackSubscribeToCurrentStateExampleView(_selectedCastingPlayer: nil) + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift new file mode 100644 index 00000000000000..5d30f096052a84 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift @@ -0,0 +1,99 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + + +import Foundation +import os.log + +class MCMediaPlaybackSubscribeToCurrentStateExampleViewModel: ObservableObject { + let Log = Logger(subsystem: "com.matter.casting", + category: "MCMediaPlaybackSubscribeToCurrentStateExampleViewModel") + + @Published var status: String?; + + // VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection + let sampleEndpointVid: Int = 65521 + + func subscribe(castingPlayer: MCCastingPlayer) + { + // select the MCEndpoint on the MCCastingPlayer to invoke the command on + if let endpoint: MCEndpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid}).first + { + // validate that the selected endpoint supports the MediaPlayback cluster + if(!endpoint.hasCluster(MCEndpointClusterTypeMediaPlayback)) + { + self.Log.error("No MediaPlayback cluster supporting endpoint found") + DispatchQueue.main.async + { + self.status = "No MediaPlayback cluster supporting endpoint found" + } + return + } + + // get MediaPlayback cluster from the endpoint + let mediaPlaybackCluster: MCMediaPlaybackCluster = endpoint.cluster(for: MCEndpointClusterTypeMediaPlayback) as! MCMediaPlaybackCluster + + // get the currentStateAttribute from the mediaPlaybackCluster + let currentStateAttribute: MCMediaPlaybackClusterCurrentStateAttribute? = mediaPlaybackCluster.currentStateAttribute() + if(currentStateAttribute == nil) + { + self.Log.error("CurrentState attribute not supported on cluster") + DispatchQueue.main.async + { + self.status = "CurrentState attribute not supported on cluster" + } + return + } + + + // call read on currentStateAttribute and pass in a completion block + currentStateAttribute!.read(nil) { context, before, after, err in + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "HH:mm:ss" + let currentTime = dateFormatter.string(from: Date()) + DispatchQueue.main.async + { + if(err != nil) + { + self.Log.error("Error when reading CurrentState value \(String(describing: err)) at \(currentTime)") + self.status = "Error when reading CurrentState value \(String(describing: err)) at \(currentTime)" + return + } + if(before != nil) + { + self.Log.info("Read CurrentState value: \(String(describing: after)) Before: \(String(describing: before)) at \(currentTime)") + self.status = "Read CurrentState value: \(String(describing: after)) Before: \(String(describing: before)) at \(currentTime)" + } + else + { + self.Log.info("Read CurrentState value: \(String(describing: after)) at \(currentTime)") + self.status = "Read CurrentState value: \(String(describing: after)) at \(currentTime)" + } + } + } + } + else + { + self.Log.error("No endpoint matching the example VID found") + DispatchQueue.main.async + { + self.status = "No endpoint matching the example VID found" + } + } + } +} diff --git a/examples/tv-casting-app/tv-casting-common/core/Attribute.h b/examples/tv-casting-app/tv-casting-common/core/Attribute.h index 08296135afa070..6ce2aa046680ad 100644 --- a/examples/tv-casting-app/tv-casting-common/core/Attribute.h +++ b/examples/tv-casting-app/tv-casting-common/core/Attribute.h @@ -67,8 +67,7 @@ class Attribute /** * @brief Reads the value of the Attribute that belongs to the associated Endpoint and corresponding Cluster - * - * @param context + * @param context current context passed back in successCb/FailureCb * @param successCb Called when the Attribute is read successfully, with the value of the attribute after reading, as well as * before (if the Attribute had been previously read) * @param failureCb Called when there is a failure in reading the Attribute @@ -159,7 +158,7 @@ class Attribute * @brief Writes the value of the Attribute to an associated Endpoint and corresponding Cluster * * @param requestData value of the Attribute to be written - * @param context + * @param context current context passed back in successCb/FailureCb * @param successCb Called when the Attribute is written successfully * @param failureCb Called when there is a failure in writing the Attribute * @param aTimedWriteTimeoutMs write timeout @@ -239,12 +238,12 @@ class Attribute /** * @brief Subscribes to the value of the Attribute that belongs to the associated Endpoint and corresponding Cluster * - * @param context + * @param context current context passed back in successCb/FailureCb * @param successCb Called when the Attribute is read successfully, with the value of the attribute after reading, as well as * before (if the Attribute had been previously read) * @param failureCb Called when there is a failure in reading the Attribute - * @param minIntervalFloorSeconds - * @param maxIntervalCeilingSeconds + * @param minIntervalFloorSeconds the requested minimum interval boundary floor in seconds for attribute udpates + * @param maxIntervalCeilingSeconds the requested maximum interval boundary ceiling in seconds for attribute udpates */ void Subscribe(void * context, ReadResponseSuccessCallbackFn successCb, ReadResponseFailureCallbackFn failureCb, uint16_t minIntervalFloorSeconds, uint16_t maxIntervalCeilingSeconds) diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.h b/examples/tv-casting-app/tv-casting-common/core/CastingApp.h index ed26e24709e6c5..f286aad3cbde7f 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.h @@ -47,7 +47,7 @@ class CastingApp /** * @brief Initializes the CastingApp with appParameters * - * @param appParameters + * @param appParameters AppParameters required to Start up the CastingApp * @return CHIP_ERROR */ CHIP_ERROR Initialize(const matter::casting::support::AppParameters & appParameters); diff --git a/examples/tv-casting-app/tv-casting-common/core/Command.h b/examples/tv-casting-app/tv-casting-common/core/Command.h index 3075053b98493a..b3e3e44ec50457 100644 --- a/examples/tv-casting-app/tv-casting-common/core/Command.h +++ b/examples/tv-casting-app/tv-casting-common/core/Command.h @@ -43,7 +43,6 @@ class Command * @brief Invokes this command on the associated Endpoint and corresponding Cluster * * @param request request data corresponding to this command invocation - * @param context * @param successCb Called on command execution success, with responseData * @param failureCb Called on command execution failure * @param timedInvokeTimeoutMs command timeout diff --git a/examples/tv-casting-app/tv-casting-common/core/Endpoint.h b/examples/tv-casting-app/tv-casting-common/core/Endpoint.h index 006fde019dd182..4da8cd56210b07 100644 --- a/examples/tv-casting-app/tv-casting-common/core/Endpoint.h +++ b/examples/tv-casting-app/tv-casting-common/core/Endpoint.h @@ -46,6 +46,7 @@ class EndpointAttributes }; class CastingPlayer; +class BaseCluster; /** * @brief An Endpoint on a CastingPlayer e.g. a Speaker or a Matter Content App