MediaPlaybackManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /**
  2. *
  3. * Copyright (c) 2021 Project CHIP Authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include "MediaPlaybackManager.h"
  18. #include "TvApp-JNI.h"
  19. #include <app-common/zap-generated/attributes/Accessors.h>
  20. #include <app-common/zap-generated/ids/Clusters.h>
  21. #include <app/util/config.h>
  22. #include <cstdint>
  23. #include <jni.h>
  24. #include <lib/support/CHIPJNIError.h>
  25. #include <lib/support/JniReferences.h>
  26. #include <lib/support/JniTypeWrappers.h>
  27. #include "MediaPlaybackManager.h"
  28. using namespace chip;
  29. using namespace chip::app;
  30. using namespace chip::app::DataModel;
  31. using namespace chip::app::Clusters::MediaPlayback;
  32. using namespace chip::Uint8;
  33. using chip::CharSpan;
  34. /** @brief Media PlayBack Cluster Init
  35. *
  36. * This function is called when a specific cluster is initialized. It gives the
  37. * application an opportunity to take care of cluster initialization procedures.
  38. * It is called exactly once for each endpoint where cluster is present.
  39. *
  40. * @param endpoint Ver.: always
  41. *
  42. */
  43. void emberAfMediaPlaybackClusterInitCallback(chip::EndpointId endpoint)
  44. {
  45. ChipLogProgress(Zcl, "TV Android App: MediaPlayback::PostClusterInit");
  46. TvAppJNIMgr().PostClusterInit(chip::app::Clusters::MediaPlayback::Id, endpoint);
  47. }
  48. void MediaPlaybackManager::NewManager(jint endpoint, jobject manager)
  49. {
  50. ChipLogProgress(Zcl, "TV Android App: MediaPlayback::SetDefaultDelegate");
  51. MediaPlaybackManager * mgr = new MediaPlaybackManager();
  52. mgr->InitializeWithObjects(manager);
  53. chip::app::Clusters::MediaPlayback::SetDefaultDelegate(static_cast<EndpointId>(endpoint), mgr);
  54. }
  55. PlaybackStateEnum MediaPlaybackManager::HandleGetCurrentState()
  56. {
  57. uint64_t ret = HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_PLAYBACK_STATE);
  58. return static_cast<PlaybackStateEnum>(ret);
  59. }
  60. uint64_t MediaPlaybackManager::HandleGetStartTime()
  61. {
  62. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_START_TIME);
  63. }
  64. uint64_t MediaPlaybackManager::HandleGetDuration()
  65. {
  66. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_DURATION);
  67. }
  68. float MediaPlaybackManager::HandleGetPlaybackSpeed()
  69. {
  70. long ret = HandleMediaRequestGetLongAttribute(MEDIA_PLAYBACK_ATTRIBUTE_SPEED);
  71. return static_cast<float>(ret);
  72. }
  73. uint64_t MediaPlaybackManager::HandleGetSeekRangeStart()
  74. {
  75. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_SEEK_RANGE_START);
  76. }
  77. uint64_t MediaPlaybackManager::HandleGetSeekRangeEnd()
  78. {
  79. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_SEEK_RANGE_END);
  80. }
  81. void MediaPlaybackManager::HandlePlay(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  82. {
  83. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_PLAY, 0));
  84. }
  85. void MediaPlaybackManager::HandlePause(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  86. {
  87. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_PAUSE, 0));
  88. }
  89. void MediaPlaybackManager::HandleStop(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  90. {
  91. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_STOP, 0));
  92. }
  93. void MediaPlaybackManager::HandleFastForward(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  94. {
  95. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_FAST_FORWARD, 0));
  96. }
  97. void MediaPlaybackManager::HandlePrevious(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  98. {
  99. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_PREVIOUS, 0));
  100. }
  101. void MediaPlaybackManager::HandleRewind(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  102. {
  103. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_REWIND, 0));
  104. }
  105. void MediaPlaybackManager::HandleSkipBackward(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper,
  106. const uint64_t & deltaPositionMilliseconds)
  107. {
  108. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_SKIP_BACKWARD, deltaPositionMilliseconds));
  109. }
  110. void MediaPlaybackManager::HandleSkipForward(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper,
  111. const uint64_t & deltaPositionMilliseconds)
  112. {
  113. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_SKIP_FORWARD, deltaPositionMilliseconds));
  114. }
  115. void MediaPlaybackManager::HandleSeek(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper,
  116. const uint64_t & positionMilliseconds)
  117. {
  118. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_SEEK, positionMilliseconds));
  119. }
  120. void MediaPlaybackManager::HandleNext(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  121. {
  122. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_NEXT, 0));
  123. }
  124. void MediaPlaybackManager::HandleStartOver(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  125. {
  126. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_START_OVER, 0));
  127. }
  128. void MediaPlaybackManager::InitializeWithObjects(jobject managerObject)
  129. {
  130. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  131. VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for MediaPlaybackManager"));
  132. mMediaPlaybackManagerObject = env->NewGlobalRef(managerObject);
  133. VerifyOrReturn(mMediaPlaybackManagerObject != nullptr, ChipLogError(Zcl, "Failed to NewGlobalRef MediaPlaybackManager"));
  134. jclass mMediaPlaybackManagerClass = env->GetObjectClass(managerObject);
  135. VerifyOrReturn(mMediaPlaybackManagerClass != nullptr, ChipLogError(Zcl, "Failed to get MediaPlaybackManager Java class"));
  136. mGetAttributeMethod = env->GetMethodID(mMediaPlaybackManagerClass, "getAttributes", "(I)J");
  137. if (mGetAttributeMethod == nullptr)
  138. {
  139. ChipLogError(Zcl, "Failed to access MediaPlaybackManager 'getAttributes' method");
  140. env->ExceptionClear();
  141. }
  142. mRequestMethod = env->GetMethodID(mMediaPlaybackManagerClass, "request", "(IJ)I");
  143. if (mRequestMethod == nullptr)
  144. {
  145. ChipLogError(Zcl, "Failed to access MediaPlaybackManager 'request' method");
  146. env->ExceptionClear();
  147. }
  148. mGetPositionMethod =
  149. env->GetMethodID(mMediaPlaybackManagerClass, "getPosition", "()Lcom/matter/tv/server/tvapp/MediaPlaybackPosition;");
  150. if (mGetPositionMethod == nullptr)
  151. {
  152. ChipLogError(Zcl, "Failed to access MediaPlaybackManager 'getPosition' method");
  153. env->ExceptionClear();
  154. }
  155. }
  156. uint64_t MediaPlaybackManager::HandleMediaRequestGetAttribute(MediaPlaybackRequestAttribute attribute)
  157. {
  158. uint64_t ret = std::numeric_limits<uint64_t>::max();
  159. jlong jAttributeValue = -1;
  160. CHIP_ERROR err = CHIP_NO_ERROR;
  161. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  162. ChipLogProgress(Zcl, "Received MediaPlaybackManager::HandleMediaRequestGetAttribute:%d", attribute);
  163. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  164. VerifyOrExit(mGetAttributeMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  165. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  166. jAttributeValue = env->CallLongMethod(mMediaPlaybackManagerObject, mGetAttributeMethod, static_cast<jint>(attribute));
  167. if (env->ExceptionCheck())
  168. {
  169. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::GetAttribute");
  170. env->ExceptionDescribe();
  171. env->ExceptionClear();
  172. goto exit;
  173. }
  174. if (jAttributeValue >= 0)
  175. {
  176. ret = static_cast<uint64_t>(jAttributeValue);
  177. }
  178. else
  179. {
  180. err = CHIP_ERROR_INCORRECT_STATE;
  181. }
  182. exit:
  183. if (err != CHIP_NO_ERROR)
  184. {
  185. ChipLogError(Zcl, "MediaPlaybackManager::GetAttribute status error: %s", err.AsString());
  186. }
  187. return ret;
  188. }
  189. long MediaPlaybackManager::HandleMediaRequestGetLongAttribute(MediaPlaybackRequestAttribute attribute)
  190. {
  191. long ret = 0;
  192. jlong jAttributeValue = -1;
  193. CHIP_ERROR err = CHIP_NO_ERROR;
  194. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  195. ChipLogProgress(Zcl, "Received MediaPlaybackManager::HandleMediaRequestGetLongAttribute:%d", attribute);
  196. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  197. VerifyOrExit(mGetAttributeMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  198. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  199. jAttributeValue = env->CallLongMethod(mMediaPlaybackManagerObject, mGetAttributeMethod, static_cast<jint>(attribute));
  200. if (env->ExceptionCheck())
  201. {
  202. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::GetAttribute");
  203. env->ExceptionDescribe();
  204. env->ExceptionClear();
  205. goto exit;
  206. }
  207. ret = static_cast<long>(jAttributeValue);
  208. exit:
  209. if (err != CHIP_NO_ERROR)
  210. {
  211. ChipLogError(Zcl, "MediaPlaybackManager::GetAttribute status error: %s", err.AsString());
  212. }
  213. return ret;
  214. }
  215. Commands::PlaybackResponse::Type MediaPlaybackManager::HandleMediaRequest(MediaPlaybackRequest mediaPlaybackRequest,
  216. uint64_t deltaPositionMilliseconds)
  217. {
  218. Commands::PlaybackResponse::Type response;
  219. jint ret = -1;
  220. CHIP_ERROR err = CHIP_NO_ERROR;
  221. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  222. ChipLogProgress(Zcl, "MediaPlaybackManager::Request %d-%ld", mediaPlaybackRequest,
  223. static_cast<long>(deltaPositionMilliseconds));
  224. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  225. VerifyOrExit(mRequestMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  226. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  227. env->ExceptionClear();
  228. ret = env->CallIntMethod(mMediaPlaybackManagerObject, mRequestMethod, static_cast<jint>(mediaPlaybackRequest),
  229. static_cast<jlong>(deltaPositionMilliseconds));
  230. if (env->ExceptionCheck())
  231. {
  232. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::Request %d", mediaPlaybackRequest);
  233. env->ExceptionDescribe();
  234. env->ExceptionClear();
  235. response.status = MediaPlaybackStatusEnum::kInvalidStateForCommand;
  236. }
  237. response.status = static_cast<MediaPlaybackStatusEnum>(ret);
  238. exit:
  239. if (err != CHIP_NO_ERROR)
  240. {
  241. response.status = MediaPlaybackStatusEnum::kInvalidStateForCommand;
  242. ChipLogError(Zcl, "MediaPlaybackManager::HandleMediaRequest status error: %s", err.AsString());
  243. }
  244. return response;
  245. }
  246. CHIP_ERROR MediaPlaybackManager::HandleGetSampledPosition(AttributeValueEncoder & aEncoder)
  247. {
  248. Structs::PlaybackPositionStruct::Type response;
  249. response.updatedAt = 0;
  250. response.position = Nullable<uint64_t>(0);
  251. jobject positionObj;
  252. CHIP_ERROR err = CHIP_NO_ERROR;
  253. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  254. ChipLogProgress(Zcl, "MediaPlaybackManager::HandleGetSampledPosition");
  255. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  256. VerifyOrExit(mGetPositionMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  257. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  258. env->ExceptionClear();
  259. positionObj = env->CallObjectMethod(mMediaPlaybackManagerObject, mGetPositionMethod);
  260. if (env->ExceptionCheck())
  261. {
  262. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::HandleGetSampledPosition");
  263. env->ExceptionDescribe();
  264. env->ExceptionClear();
  265. goto exit;
  266. }
  267. {
  268. jclass inputClass = env->GetObjectClass(positionObj);
  269. jfieldID positionId = env->GetFieldID(inputClass, "position", "J");
  270. jfieldID updatedAtId = env->GetFieldID(inputClass, "updatedAt", "J");
  271. response.position = Nullable<uint64_t>(static_cast<uint64_t>(env->GetLongField(positionObj, positionId)));
  272. response.updatedAt = static_cast<uint64_t>(env->GetLongField(positionObj, updatedAtId));
  273. }
  274. exit:
  275. if (err != CHIP_NO_ERROR)
  276. {
  277. ChipLogError(Zcl, "MediaPlaybackManager::GetAttribute status error: %s", err.AsString());
  278. }
  279. return aEncoder.Encode(response);
  280. }
  281. uint32_t MediaPlaybackManager::GetFeatureMap(chip::EndpointId endpoint)
  282. {
  283. if (endpoint >= EMBER_AF_CONTENT_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT)
  284. {
  285. return mDynamicEndpointFeatureMap;
  286. }
  287. uint32_t featureMap = 0;
  288. Attributes::FeatureMap::Get(endpoint, &featureMap);
  289. return featureMap;
  290. }