From 2310480c4a6e43b276ed8d38feee97c2b3dab224 Mon Sep 17 00:00:00 2001 From: amitnj <74272437+amitnj@users.noreply.github.com> Date: Tue, 24 Jan 2023 06:19:01 -0800 Subject: [PATCH] Add ability to run tv casting app cert tests from the UI (#24559) * Add ability to run tv casting app cert tests from the UI * Restyled by clang-format * Remove some comments added by the IDE Co-authored-by: Restyled.io --- .../CastingServerBridge.h | 47 +++ .../CastingServerBridge.mm | 70 ++++ .../TvCasting.xcodeproj/project.pbxproj | 12 +- .../TvCasting/TvCasting/CertTestView.swift | 69 ++++ .../TvCasting/CertTestViewModel.swift | 377 ++++++++++++++++++ .../TvCasting/ClusterSelectorView.swift | 11 + 6 files changed, 584 insertions(+), 2 deletions(-) create mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestView.swift create mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h index 9c7a4abcb9cdb7..2e1b9801cc03c2 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h @@ -1137,5 +1137,52 @@ requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; +/*! + @brief Send a OnOff:On request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)onOff_on:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(bool))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; + +/*! + @brief Send a OnOff:Off request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)onOff_off:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(bool))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; + +/*! + @brief Send a OnOff:Toggle request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)onOff_toggle:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(bool))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; @end #endif /* CastingServerBridge_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm index 72bcb8c9e706ac..6e64a999feaaf9 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm @@ -2156,4 +2156,74 @@ - (void)applicationBasic_readApplicationVersion:(ContentApp * _Nonnull)contentAp }); } +- (void)onOff_on:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(bool))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().onOff_on() called on Content App with endpoint ID %d", contentApp.endpointId); + + [_commandResponseCallbacks setObject:responseCallback forKey:@"onOff_on"]; + dispatch_async(_chipWorkQueue, ^{ + TargetEndpointInfo endpoint; + [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; + + CHIP_ERROR err = CastingServer::GetInstance()->OnOff_On(&endpoint, [](CHIP_ERROR err) { + void (^responseCallback)(bool) = + [[CastingServerBridge getSharedInstance].commandResponseCallbacks objectForKey:@"onOff_on"]; + responseCallback(CHIP_NO_ERROR == err); + }); + dispatch_async(clientQueue, ^{ + requestSentHandler(CHIP_NO_ERROR == err); + }); + }); +} + +- (void)onOff_off:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(bool))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler +{ + ChipLogProgress( + AppServer, "CastingServerBridge().onOff_off() called on Content App with endpoint ID %d", contentApp.endpointId); + + [_commandResponseCallbacks setObject:responseCallback forKey:@"onOff_off"]; + dispatch_async(_chipWorkQueue, ^{ + TargetEndpointInfo endpoint; + [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; + + CHIP_ERROR err = CastingServer::GetInstance()->OnOff_Off(&endpoint, [](CHIP_ERROR err) { + void (^responseCallback)(bool) = + [[CastingServerBridge getSharedInstance].commandResponseCallbacks objectForKey:@"onOff_off"]; + responseCallback(CHIP_NO_ERROR == err); + }); + dispatch_async(clientQueue, ^{ + requestSentHandler(CHIP_NO_ERROR == err); + }); + }); +} + +- (void)onOff_toggle:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(bool))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler +{ + ChipLogProgress( + AppServer, "CastingServerBridge().onOff_toggle() called on Content App with endpoint ID %d", contentApp.endpointId); + + [_commandResponseCallbacks setObject:responseCallback forKey:@"onOff_toggle"]; + dispatch_async(_chipWorkQueue, ^{ + TargetEndpointInfo endpoint; + [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; + + CHIP_ERROR err = CastingServer::GetInstance()->OnOff_Toggle(&endpoint, [](CHIP_ERROR err) { + void (^responseCallback)(bool) = + [[CastingServerBridge getSharedInstance].commandResponseCallbacks objectForKey:@"onOff_toggle"]; + responseCallback(CHIP_NO_ERROR == err); + }); + dispatch_async(clientQueue, ^{ + requestSentHandler(CHIP_NO_ERROR == err); + }); + }); +} @end 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 6252d2cb145612..5ddb457fc7464f 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj @@ -26,6 +26,8 @@ 3CCB8748286A5D0F00771BAD /* CommissioningViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */; }; 3CCB8749286A5D0F00771BAD /* ContentLauncherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA19434285BA780004768D5 /* ContentLauncherView.swift */; }; 3CCB874A286A5D0F00771BAD /* ContentLauncherViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA19436285BA877004768D5 /* ContentLauncherViewModel.swift */; }; + EAF14299296D561900E17793 /* CertTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF14298296D561900E17793 /* CertTestView.swift */; }; + EAF1429B296D57DF00E17793 /* CertTestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1429A296D57DF00E17793 /* CertTestViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -64,6 +66,8 @@ 3CC0E9002841DD3500EC6A18 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 3CC0E90C2841DECC00EC6A18 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 3CCB872A28690A5D00771BAD /* MatterTvCastingBridge.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MatterTvCastingBridge.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EAF14298296D561900E17793 /* CertTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertTestView.swift; sourceTree = ""; }; + EAF1429A296D57DF00E17793 /* CertTestViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertTestViewModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -109,6 +113,8 @@ children = ( 3CC0E8FD2841DD3500EC6A18 /* Assets.xcassets */, 3C75075E284C1DF800D7DB3A /* TvCasting.entitlements */, + EAF14298296D561900E17793 /* CertTestView.swift */, + EAF1429A296D57DF00E17793 /* CertTestViewModel.swift */, 3CC0E8F92841DD3400EC6A18 /* TvCastingApp.swift */, 3CC0E8FB2841DD3400EC6A18 /* ContentView.swift */, 3C81C75228F8C79E001CB9D1 /* StartFromCacheView.swift */, @@ -226,11 +232,13 @@ 3CCB8746286A5D0F00771BAD /* CommissionerDiscoveryViewModel.swift in Sources */, 3C81C75928F8E42D001CB9D1 /* ConnectionViewModel.swift in Sources */, 3CA1CA7A28E281080023ED44 /* ClusterSelectorView.swift in Sources */, + EAF14299296D561900E17793 /* CertTestView.swift in Sources */, 3CCB8747286A5D0F00771BAD /* CommissioningView.swift in Sources */, 3CCB8748286A5D0F00771BAD /* CommissioningViewModel.swift in Sources */, 3CA1CA7E28E284950023ED44 /* MediaPlaybackViewModel.swift in Sources */, 3CCB8749286A5D0F00771BAD /* ContentLauncherView.swift in Sources */, 3CCB874A286A5D0F00771BAD /* ContentLauncherViewModel.swift in Sources */, + EAF1429B296D57DF00E17793 /* CertTestViewModel.swift in Sources */, 3C81C75728F8E418001CB9D1 /* ConnectionView.swift in Sources */, 3CC0E8FC2841DD3400EC6A18 /* ContentView.swift in Sources */, 3CA1CA7C28E282150023ED44 /* MediaPlaybackView.swift in Sources */, @@ -371,7 +379,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"TvCasting/Preview Content\""; - DEVELOPMENT_TEAM = R7NUZ7N74U; + DEVELOPMENT_TEAM = KCRB72LX9T; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -441,7 +449,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"TvCasting/Preview Content\""; - DEVELOPMENT_TEAM = R7NUZ7N74U; + DEVELOPMENT_TEAM = KCRB72LX9T; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestView.swift new file mode 100644 index 00000000000000..f38e84a7ac30fc --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestView.swift @@ -0,0 +1,69 @@ + +/** + * + * Copyright (c) 2020-2022 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 CertTestView: View { + @StateObject var viewModel = CertTestViewModel() + @State private var targetContentAppId: String = "" + + var body: some View { + VStack(alignment: .leading) { + if(viewModel.contentAppIds.isEmpty) + { + Text("No Content Launcher cluster supporting content apps found on this video player!") + } + else + { + HStack() { + Text("Content App Endpoint Id") + + VStack() + { + Picker("Select", selection: $targetContentAppId) { + Text("Select").tag(nil as String?) + ForEach(viewModel.contentAppIds, id: \.self) { contentAppId in + Text(String(contentAppId)) + } + } + .pickerStyle(.menu) + .padding(2) + } + .border(.secondary) + } + + Button("Launch Test") { + viewModel.launchTest(targetContentAppId: targetContentAppId) + } + .background(Color.blue) + .foregroundColor(Color.white) + .cornerRadius(4) + .border(Color.black, width: 1) + .padding() + + Text(viewModel.status ?? "") + } + + } + .navigationTitle("Cert Test Launcher") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + .onAppear(perform: { + viewModel.populateAndInitializeEndpoints() + }) + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift new file mode 100644 index 00000000000000..154c8156f22d97 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift @@ -0,0 +1,377 @@ +/** + * + * Copyright (c) 2020-2022 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 CallbackHelper { + var testCaseName: String; + var certTestViewModel: CertTestViewModel; + let Log = Logger(subsystem: "com.matter.casting", + category: "CertTestViewModel") + + init(testCaseName: String, certTestViewModel: CertTestViewModel) { + self.testCaseName = testCaseName + self.certTestViewModel = certTestViewModel + } + + func responseCallback(result: Bool) + { + self.Log.info("CertTestViewModel.responseCallback.\(self.testCaseName) result \(result)") + DispatchQueue.main.async { + self.certTestViewModel.status = result ? "Test \(self.testCaseName) successful" : "Test \(self.testCaseName) failed" + } + } + + func requestSentHandler(result: Bool) + { + self.Log.info("CertTestViewModel.requestSentHandler.\(self.testCaseName) result \(result)") + } + + func successCallbackString(result: String) + { + self.Log.info("CertTestViewModel.successCallback.\(self.testCaseName) result \(result)") + DispatchQueue.main.async { + self.certTestViewModel.status = "Test \(self.testCaseName) successful" + } + } + + func successCallbackInteger(result: UInt16) + { + self.Log.info("CertTestViewModel.successCallback.\(self.testCaseName) result \(result)") + DispatchQueue.main.async { + self.certTestViewModel.status = "Test \(self.testCaseName) successful" + } + } + + func successCallbackNumber(result: NSNumber) + { + self.Log.info("CertTestViewModel.successCallback.\(self.testCaseName) result \(result)") + DispatchQueue.main.async { + self.certTestViewModel.status = "Test \(self.testCaseName) successful" + } + } + + func failureCallback(result: MatterError) + { + self.Log.info("CertTestViewModel.failureCallback.\(self.testCaseName) failed. Code : \(result.code). Message : \(result.message ?? "")") + DispatchQueue.main.async { + self.certTestViewModel.status = "Test \(self.testCaseName) failed. Code : \(result.code). Message : \(result.message ?? "")" + } + } + + func requestSentHandlerError(result: MatterError) + { + self.Log.info("CertTestViewModel.requestSentHandler.\(self.testCaseName). Code : \(result.code). Message : result.message") + } + +} + +class CertTestViewModel: ObservableObject { + let Log = Logger(subsystem: "com.matter.casting", + category: "CertTestViewModel") + + @Published var status: String?; + + @Published var contentAppIds: [String] = []; + + var targetVideoPlayer: VideoPlayer?; + var deviceEndpoint: ContentApp?; + var deviceSpeakerEndpoint: ContentApp?; + var testCaseName: String = ""; + + func runCertTest(testCaseName: String, test: (CallbackHelper) -> ()) + { + self.testCaseName = testCaseName; + test(CallbackHelper(testCaseName: testCaseName, certTestViewModel: self)); + } + + func launchTest(targetContentAppId: String?) + { + if (targetContentAppId != nil && !targetContentAppId!.isEmpty) + { + var targetContentApp: ContentApp? + for contentApp in (targetVideoPlayer!.contentApps as! [ContentApp]) { + if(UInt16(targetContentAppId!) == contentApp.endpointId) + { + targetContentApp = contentApp + break + } + } + + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + runCertTest(testCaseName: "keypadInput_sendKey", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.keypadInput_sendKey(deviceEndpoint!, keyCode: 10, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "applicationLauncher_launch", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationLauncher_launch(deviceEndpoint!, catalogVendorId: 123, applicationId: "exampleid", data: nil, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "applicationLauncher_stop", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationLauncher_stop(deviceEndpoint!, + catalogVendorId: 123, applicationId: "exampleid", + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "applicationLauncher_hide", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationLauncher_hide(deviceEndpoint!, + catalogVendorId: 123, applicationId: "exampleid", + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "targetNavigator_navigateTarget", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.targetNavigator_navigateTarget(deviceEndpoint!, + target: 1, data: "", + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "contentLauncher_launchUrl", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.contentLauncher_launchUrl(targetContentApp!, + contentUrl: "https://dummyurl", + contentDisplayStr: "Dummy Content", + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "contentLauncher_launchContent", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.contentLauncher_launchContent(targetContentApp!, + contentSearch: ContentLauncher_ContentSearch(parameterList: [ContentLauncher_Parameter(type: ContentLauncher_ParameterEnum.Video, value: "Dummy Video", externalIDList: [ContentLauncher_AdditionalInfo(name: "imdb", value: "dummyId"),]),]), + autoPlay: true, data: "", + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "mediaPlayback_play", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.mediaPlayback_play(targetContentApp!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "mediaPlayback_next", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.mediaPlayback_next(targetContentApp!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "mediaPlayback_skipForward", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.mediaPlayback_skipForward(targetContentApp!, + deltaPositionMilliseconds: 10000, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "mediaPlayback_skipBackward", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.mediaPlayback_skipBackward(targetContentApp!, + deltaPositionMilliseconds: 10000, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "mediaPlayback_pause", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.mediaPlayback_pause(targetContentApp!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "mediaPlayback_stopPlayback", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.mediaPlayback_stopPlayback(targetContentApp!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "onOff_on", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.onOff_(on: deviceEndpoint!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "onOff_off", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.onOff_off(deviceEndpoint!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "onOff_toggle", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.onOff_toggle(deviceEndpoint!, + responseCallback:callbackHelper.responseCallback, + clientQueue: DispatchQueue.main, + requestSentHandler:callbackHelper.requestSentHandler + ) + } + ) + + runCertTest(testCaseName: "applicationBasic_readApplicationVersion", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationBasic_readApplicationVersion(targetContentApp!, + clientQueue: DispatchQueue.main, + requestSentHandler: callbackHelper.requestSentHandlerError, + successCallback: callbackHelper.successCallbackString, + failureCallback: callbackHelper.failureCallback + ) + } + ) + + runCertTest(testCaseName: "applicationBasic_readVendorName", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationBasic_readVendorName(targetContentApp!, + clientQueue: DispatchQueue.main, + requestSentHandler: callbackHelper.requestSentHandlerError, + successCallback: callbackHelper.successCallbackString, + failureCallback: callbackHelper.failureCallback + ) + } + ) + + runCertTest(testCaseName: "applicationBasic_readApplicationName", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationBasic_readApplicationName(targetContentApp!, + clientQueue: DispatchQueue.main, + requestSentHandler: callbackHelper.requestSentHandlerError, + successCallback: callbackHelper.successCallbackString, + failureCallback: callbackHelper.failureCallback + ) + } + ) + + runCertTest(testCaseName: "applicationBasic_readVendorID", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationBasic_readVendorID(targetContentApp!, + clientQueue: DispatchQueue.main, + requestSentHandler: callbackHelper.requestSentHandlerError, + successCallback: callbackHelper.successCallbackNumber, + failureCallback: callbackHelper.failureCallback + ) + } + ) + + runCertTest(testCaseName: "applicationBasic_readProductID", + test: { (callbackHelper: CallbackHelper) -> () in + castingServerBridge.applicationBasic_readProductID(targetContentApp!, + clientQueue: DispatchQueue.main, + requestSentHandler: callbackHelper.requestSentHandlerError, + successCallback: callbackHelper.successCallbackInteger, + failureCallback: callbackHelper.failureCallback + ) + } + ) + } + } + else + { + Log.debug("CertTestViewModel.launchTest input(s) missing!") + self.status = "Missing input parameter(s)!" + } + } + + func populateAndInitializeEndpoints() + { + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + castingServerBridge.getActiveTargetVideoPlayers(DispatchQueue.main, + activeTargetVideoPlayersHandler: { (targetVideoPlayers: NSMutableArray?) -> () in + let targetVideoPlayer: VideoPlayer = targetVideoPlayers![0] as! VideoPlayer + if(targetVideoPlayer.isInitialized && targetVideoPlayer.isConnected) + { + self.targetVideoPlayer = targetVideoPlayer + for contentApp in (targetVideoPlayer.contentApps as! [ContentApp]) + { + if(contentApp.endpointId == 1) + { + self.deviceEndpoint = contentApp + } else if(contentApp.endpointId == 2) + { + self.deviceSpeakerEndpoint = contentApp + } else + { + self.contentAppIds.append(String(contentApp.endpointId)) + } + } + } + }) + } + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift index d7285e82ec1a2b..9dbc9f16d84fa6 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift @@ -41,6 +41,17 @@ struct ClusterSelectorView: View { ).background(Color.blue) .foregroundColor(Color.white) .padding() + + NavigationLink( + destination: CertTestView(), + label: { + Text("Certification Tests") + .frame(width: 300, height: 30, alignment: .center) + .border(Color.black, width: 1) + } + ).background(Color.blue) + .foregroundColor(Color.white) + .padding() } .navigationTitle("Cluster selection") .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top)