MediaPlaybackManager.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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/ids/Clusters.h>
  20. #include <cstdint>
  21. #include <jni.h>
  22. #include <lib/support/CHIPJNIError.h>
  23. #include <lib/support/JniReferences.h>
  24. #include <lib/support/JniTypeWrappers.h>
  25. #include "MediaPlaybackManager.h"
  26. using namespace chip;
  27. using namespace chip::app;
  28. using namespace chip::app::DataModel;
  29. using namespace chip::app::Clusters::MediaPlayback;
  30. using namespace chip::Uint8;
  31. using chip::CharSpan;
  32. /** @brief Media PlayBack Cluster Init
  33. *
  34. * This function is called when a specific cluster is initialized. It gives the
  35. * application an opportunity to take care of cluster initialization procedures.
  36. * It is called exactly once for each endpoint where cluster is present.
  37. *
  38. * @param endpoint Ver.: always
  39. *
  40. */
  41. void emberAfMediaPlaybackClusterInitCallback(chip::EndpointId endpoint)
  42. {
  43. ChipLogProgress(Zcl, "TV Android App: MediaPlayback::PostClusterInit");
  44. TvAppJNIMgr().PostClusterInit(chip::app::Clusters::MediaPlayback::Id, endpoint);
  45. }
  46. void MediaPlaybackManager::NewManager(jint endpoint, jobject manager)
  47. {
  48. ChipLogProgress(Zcl, "TV Android App: MediaPlayback::SetDefaultDelegate");
  49. MediaPlaybackManager * mgr = new MediaPlaybackManager();
  50. mgr->InitializeWithObjects(manager);
  51. chip::app::Clusters::MediaPlayback::SetDefaultDelegate(static_cast<EndpointId>(endpoint), mgr);
  52. }
  53. PlaybackStateEnum MediaPlaybackManager::HandleGetCurrentState()
  54. {
  55. uint64_t ret = HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_PLAYBACK_STATE);
  56. return static_cast<PlaybackStateEnum>(ret);
  57. }
  58. uint64_t MediaPlaybackManager::HandleGetStartTime()
  59. {
  60. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_START_TIME);
  61. }
  62. uint64_t MediaPlaybackManager::HandleGetDuration()
  63. {
  64. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_DURATION);
  65. }
  66. float MediaPlaybackManager::HandleGetPlaybackSpeed()
  67. {
  68. uint64_t ret = HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_SPEED);
  69. return static_cast<float>(ret) / 10000.0f;
  70. }
  71. uint64_t MediaPlaybackManager::HandleGetSeekRangeStart()
  72. {
  73. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_SEEK_RANGE_START);
  74. }
  75. uint64_t MediaPlaybackManager::HandleGetSeekRangeEnd()
  76. {
  77. return HandleMediaRequestGetAttribute(MEDIA_PLAYBACK_ATTRIBUTE_SEEK_RANGE_END);
  78. }
  79. void MediaPlaybackManager::HandlePlay(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  80. {
  81. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_PLAY, 0));
  82. }
  83. void MediaPlaybackManager::HandlePause(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  84. {
  85. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_PAUSE, 0));
  86. }
  87. void MediaPlaybackManager::HandleStop(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  88. {
  89. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_STOP, 0));
  90. }
  91. void MediaPlaybackManager::HandleFastForward(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  92. {
  93. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_FAST_FORWARD, 0));
  94. }
  95. void MediaPlaybackManager::HandlePrevious(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  96. {
  97. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_PREVIOUS, 0));
  98. }
  99. void MediaPlaybackManager::HandleRewind(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  100. {
  101. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_REWIND, 0));
  102. }
  103. void MediaPlaybackManager::HandleSkipBackward(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper,
  104. const uint64_t & deltaPositionMilliseconds)
  105. {
  106. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_SKIP_BACKWARD, deltaPositionMilliseconds));
  107. }
  108. void MediaPlaybackManager::HandleSkipForward(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper,
  109. const uint64_t & deltaPositionMilliseconds)
  110. {
  111. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_SKIP_FORWARD, deltaPositionMilliseconds));
  112. }
  113. void MediaPlaybackManager::HandleSeek(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper,
  114. const uint64_t & positionMilliseconds)
  115. {
  116. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_SEEK, positionMilliseconds));
  117. }
  118. void MediaPlaybackManager::HandleNext(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  119. {
  120. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_NEXT, 0));
  121. }
  122. void MediaPlaybackManager::HandleStartOver(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper)
  123. {
  124. helper.Success(HandleMediaRequest(MEDIA_PLAYBACK_REQUEST_START_OVER, 0));
  125. }
  126. void MediaPlaybackManager::InitializeWithObjects(jobject managerObject)
  127. {
  128. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  129. VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for MediaPlaybackManager"));
  130. mMediaPlaybackManagerObject = env->NewGlobalRef(managerObject);
  131. VerifyOrReturn(mMediaPlaybackManagerObject != nullptr, ChipLogError(Zcl, "Failed to NewGlobalRef MediaPlaybackManager"));
  132. jclass mMediaPlaybackManagerClass = env->GetObjectClass(managerObject);
  133. VerifyOrReturn(mMediaPlaybackManagerClass != nullptr, ChipLogError(Zcl, "Failed to get MediaPlaybackManager Java class"));
  134. mGetAttributeMethod = env->GetMethodID(mMediaPlaybackManagerClass, "getAttributes", "(I)J");
  135. if (mGetAttributeMethod == nullptr)
  136. {
  137. ChipLogError(Zcl, "Failed to access MediaPlaybackManager 'getAttributes' method");
  138. env->ExceptionClear();
  139. }
  140. mRequestMethod = env->GetMethodID(mMediaPlaybackManagerClass, "request", "(IJ)I");
  141. if (mRequestMethod == nullptr)
  142. {
  143. ChipLogError(Zcl, "Failed to access MediaPlaybackManager 'request' method");
  144. env->ExceptionClear();
  145. }
  146. mGetPositionMethod =
  147. env->GetMethodID(mMediaPlaybackManagerClass, "getPosition", "()[Lcom/tcl/chip/tvapp/MediaPlaybackPosition;");
  148. if (mGetPositionMethod == nullptr)
  149. {
  150. ChipLogError(Zcl, "Failed to access MediaPlaybackManager 'getPosition' method");
  151. env->ExceptionClear();
  152. }
  153. }
  154. uint64_t MediaPlaybackManager::HandleMediaRequestGetAttribute(MediaPlaybackRequestAttribute attribute)
  155. {
  156. uint64_t ret = std::numeric_limits<uint64_t>::max();
  157. jlong jAttributeValue = -1;
  158. CHIP_ERROR err = CHIP_NO_ERROR;
  159. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  160. ChipLogProgress(Zcl, "Received MediaPlaybackManager::HandleMediaRequestGetAttribute:%d", attribute);
  161. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  162. VerifyOrExit(mGetAttributeMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  163. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  164. jAttributeValue = env->CallLongMethod(mMediaPlaybackManagerObject, mGetAttributeMethod, static_cast<jint>(attribute));
  165. if (env->ExceptionCheck())
  166. {
  167. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::GetAttribute");
  168. env->ExceptionDescribe();
  169. env->ExceptionClear();
  170. goto exit;
  171. }
  172. if (jAttributeValue >= 0)
  173. {
  174. ret = static_cast<uint64_t>(jAttributeValue);
  175. }
  176. else
  177. {
  178. err = CHIP_ERROR_INCORRECT_STATE;
  179. }
  180. exit:
  181. if (err != CHIP_NO_ERROR)
  182. {
  183. ChipLogError(Zcl, "MediaPlaybackManager::GetAttribute status error: %s", err.AsString());
  184. }
  185. return ret;
  186. }
  187. Commands::PlaybackResponse::Type MediaPlaybackManager::HandleMediaRequest(MediaPlaybackRequest mediaPlaybackRequest,
  188. uint64_t deltaPositionMilliseconds)
  189. {
  190. Commands::PlaybackResponse::Type response;
  191. jint ret = -1;
  192. CHIP_ERROR err = CHIP_NO_ERROR;
  193. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  194. ChipLogProgress(Zcl, "MediaPlaybackManager::Request %d-%ld", mediaPlaybackRequest,
  195. static_cast<long>(deltaPositionMilliseconds));
  196. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  197. VerifyOrExit(mRequestMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  198. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  199. env->ExceptionClear();
  200. ret = env->CallIntMethod(mMediaPlaybackManagerObject, mRequestMethod, static_cast<jint>(mediaPlaybackRequest),
  201. static_cast<jlong>(deltaPositionMilliseconds));
  202. if (env->ExceptionCheck())
  203. {
  204. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::Request %d", mediaPlaybackRequest);
  205. env->ExceptionDescribe();
  206. env->ExceptionClear();
  207. response.status = MediaPlaybackStatusEnum::kInvalidStateForCommand;
  208. }
  209. response.status = static_cast<MediaPlaybackStatusEnum>(ret);
  210. exit:
  211. if (err != CHIP_NO_ERROR)
  212. {
  213. response.status = MediaPlaybackStatusEnum::kInvalidStateForCommand;
  214. ChipLogError(Zcl, "MediaPlaybackManager::HandleMediaRequest status error: %s", err.AsString());
  215. }
  216. return response;
  217. }
  218. CHIP_ERROR MediaPlaybackManager::HandleGetSampledPosition(AttributeValueEncoder & aEncoder)
  219. {
  220. Structs::PlaybackPosition::Type response;
  221. response.updatedAt = 0;
  222. response.position = Nullable<uint64_t>(0);
  223. jobject positionObj;
  224. CHIP_ERROR err = CHIP_NO_ERROR;
  225. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  226. ChipLogProgress(Zcl, "MediaPlaybackManager::HandleGetSampledPosition");
  227. VerifyOrExit(mMediaPlaybackManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  228. VerifyOrExit(mGetPositionMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  229. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  230. env->ExceptionClear();
  231. positionObj = env->CallObjectMethod(mMediaPlaybackManagerObject, mGetPositionMethod);
  232. if (env->ExceptionCheck())
  233. {
  234. ChipLogError(AppServer, "Java exception in MediaPlaybackManager::HandleGetSampledPosition");
  235. env->ExceptionDescribe();
  236. env->ExceptionClear();
  237. goto exit;
  238. }
  239. {
  240. jclass inputClass = env->GetObjectClass(positionObj);
  241. jfieldID positionId = env->GetFieldID(inputClass, "position", "J");
  242. jfieldID updatedAtId = env->GetFieldID(inputClass, "updatedAt", "J");
  243. response.position = Nullable<uint64_t>(static_cast<uint64_t>(env->GetIntField(positionObj, positionId)));
  244. response.updatedAt = static_cast<uint64_t>(env->GetIntField(positionObj, updatedAtId));
  245. }
  246. exit:
  247. if (err != CHIP_NO_ERROR)
  248. {
  249. ChipLogError(Zcl, "MediaPlaybackManager::GetAttribute status error: %s", err.AsString());
  250. }
  251. return aEncoder.Encode(response);
  252. }