1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "JavaPlayerEventDispatcher.h" 27 #include "JniUtils.h" 28 #include "Logger.h" 29 #include <com_sun_media_jfxmedia_track_AudioTrack.h> 30 #include <com_sun_media_jfxmediaimpl_NativeMediaPlayer.h> 31 #include <Common/VSMemory.h> 32 #include <Utils/LowLevelPerf.h> 33 #include <jni/Logger.h> 34 35 static bool areJMethodIDsInitialized = false; 36 37 jmethodID CJavaPlayerEventDispatcher::m_SendWarningMethod = 0; 38 39 jmethodID CJavaPlayerEventDispatcher::m_SendPlayerMediaErrorEventMethod = 0; 40 jmethodID CJavaPlayerEventDispatcher::m_SendPlayerHaltEventMethod = 0; 41 jmethodID CJavaPlayerEventDispatcher::m_SendPlayerStateEventMethod = 0; 42 jmethodID CJavaPlayerEventDispatcher::m_SendNewFrameEventMethod = 0; 43 jmethodID CJavaPlayerEventDispatcher::m_SendFrameSizeChangedEventMethod = 0; 44 jmethodID CJavaPlayerEventDispatcher::m_SendAudioTrackEventMethod = 0; 45 jmethodID CJavaPlayerEventDispatcher::m_SendVideoTrackEventMethod = 0; 46 jmethodID CJavaPlayerEventDispatcher::m_SendSubtitleTrackEventMethod = 0; 47 jmethodID CJavaPlayerEventDispatcher::m_SendMarkerEventMethod = 0; 48 jmethodID CJavaPlayerEventDispatcher::m_SendBufferProgressEventMethod = 0; 49 jmethodID CJavaPlayerEventDispatcher::m_SendDurationUpdateEventMethod = 0; 50 jmethodID CJavaPlayerEventDispatcher::m_SendAudioSpectrumEventMethod = 0; 51 52 CJavaPlayerEventDispatcher::CJavaPlayerEventDispatcher() 53 : m_PlayerVM(NULL), 54 m_PlayerInstance(NULL), 55 m_MediaReference(0L) 56 { 57 } 58 59 CJavaPlayerEventDispatcher::~CJavaPlayerEventDispatcher() 60 { 61 Dispose(); 62 } 63 64 void CJavaPlayerEventDispatcher::Init(JNIEnv *env, jobject PlayerInstance, CMedia* pMedia) 65 { 66 LOWLEVELPERF_EXECTIMESTART("CJavaPlayerEventDispatcher::Init()"); 67 68 if (env->GetJavaVM(&m_PlayerVM) != JNI_OK) { 69 // FIXME: Warning/error message?? 70 return; 71 } 72 m_PlayerInstance = env->NewGlobalRef(PlayerInstance); 73 m_MediaReference = (jlong) ptr_to_jlong(pMedia); 74 75 // Initialize jmethodID data members. These are derived from the class of 76 // the object and not its instance. No, this particular implementation is 77 // not thread-safe, but the worst that can happen is that the jmethodIDs are 78 // initialized more than once which is still better than once per player. 79 if (false == areJMethodIDsInitialized) 80 { 81 jclass klass = env->GetObjectClass(m_PlayerInstance); 82 83 m_SendWarningMethod = env->GetMethodID(klass, "sendWarning", "(ILjava/lang/String;)V"); 84 85 m_SendPlayerMediaErrorEventMethod = env->GetMethodID(klass, "sendPlayerMediaErrorEvent", "(I)V"); 86 m_SendPlayerHaltEventMethod = env->GetMethodID(klass, "sendPlayerHaltEvent", "(Ljava/lang/String;D)V"); 87 m_SendPlayerStateEventMethod = env->GetMethodID(klass, "sendPlayerStateEvent", "(ID)V"); 88 m_SendNewFrameEventMethod = env->GetMethodID(klass, "sendNewFrameEvent", "(J)V"); 89 m_SendFrameSizeChangedEventMethod = env->GetMethodID(klass, "sendFrameSizeChangedEvent", "(II)V"); 90 m_SendAudioTrackEventMethod = env->GetMethodID(klass, "sendAudioTrack", "(ZJLjava/lang/String;ILjava/lang/String;IIF)V"); 91 m_SendVideoTrackEventMethod = env->GetMethodID(klass, "sendVideoTrack", "(ZJLjava/lang/String;IIIFZ)V"); 92 m_SendSubtitleTrackEventMethod = env->GetMethodID(klass, "sendSubtitleTrack", "(ZJLjava/lang/String;ILjava/lang/String;)V"); 93 m_SendMarkerEventMethod = env->GetMethodID(klass, "sendMarkerEvent", "(Ljava/lang/String;D)V"); 94 m_SendBufferProgressEventMethod = env->GetMethodID(klass, "sendBufferProgressEvent", "(DJJJ)V"); 95 m_SendDurationUpdateEventMethod = env->GetMethodID(klass, "sendDurationUpdateEvent", "(D)V"); 96 m_SendAudioSpectrumEventMethod = env->GetMethodID(klass, "sendAudioSpectrumEvent", "(DD)V"); 97 98 env->DeleteLocalRef(klass); 99 100 areJMethodIDsInitialized = true; 101 } 102 103 LOWLEVELPERF_EXECTIMESTOP("CJavaPlayerEventDispatcher::Init()"); 104 } 105 106 void CJavaPlayerEventDispatcher::Dispose() 107 { 108 LOWLEVELPERF_EXECTIMESTART("CJavaPlayerEventDispatcher::Dispose()"); 109 CJavaEnvironment jenv(m_PlayerVM); 110 JNIEnv *pEnv = jenv.getEnvironment(); 111 if (pEnv) { 112 pEnv->DeleteGlobalRef(m_PlayerInstance); 113 } 114 115 LOWLEVELPERF_EXECTIMESTOP("CJavaPlayerEventDispatcher::Dispose()"); 116 } 117 118 void CJavaPlayerEventDispatcher::Warning(int warningCode, const char* warningMessage) 119 { 120 if (NULL == m_PlayerInstance) 121 return; 122 123 CJavaEnvironment jenv(m_PlayerVM); 124 JNIEnv *pEnv = jenv.getEnvironment(); 125 if (pEnv) { 126 jstring jmessage = NULL; 127 if (warningMessage) { 128 jmessage = pEnv->NewStringUTF(warningMessage); 129 } 130 pEnv->CallVoidMethod(m_PlayerInstance, m_SendWarningMethod, 131 (jint)warningCode, jmessage); 132 if (jmessage) { 133 pEnv->DeleteLocalRef(jmessage); 134 } 135 } 136 } 137 138 bool CJavaPlayerEventDispatcher::SendPlayerMediaErrorEvent(int errorCode) 139 { 140 return SendToJava_PlayerMediaErrorEvent(errorCode); 141 } 142 143 bool CJavaPlayerEventDispatcher::SendPlayerHaltEvent(const char* message, double time) 144 { 145 return SendToJava_PlayerHaltEvent(message, time); 146 } 147 148 bool CJavaPlayerEventDispatcher::SendPlayerStateEvent(int newState, double presentTime) 149 { 150 long newJavaState; 151 152 switch(newState) 153 { 154 case CPipeline::Unknown: 155 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerUnknown; 156 break; 157 case CPipeline::Ready: 158 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerReady; 159 break; 160 case CPipeline::Playing: 161 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerPlaying; 162 break; 163 case CPipeline::Paused: 164 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerPaused; 165 break; 166 case CPipeline::Stopped: 167 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerStopped; 168 break; 169 case CPipeline::Stalled: 170 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerStalled; 171 break; 172 case CPipeline::Finished: 173 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerFinished; 174 break; 175 case CPipeline::Error: 176 newJavaState = com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerError; 177 break; 178 default: 179 return false; 180 } 181 182 return SendToJava_PlayerStateEvent(newJavaState, presentTime); 183 } 184 185 bool CJavaPlayerEventDispatcher::SendNewFrameEvent(CVideoFrame* pVideoFrame) 186 { 187 return SendToJava_NewFrameEvent(pVideoFrame); 188 } 189 190 bool CJavaPlayerEventDispatcher::SendFrameSizeChangedEvent(int width, int height) 191 { 192 return SendToJava_FrameSizeChangedEvent(width, height); 193 } 194 195 bool CJavaPlayerEventDispatcher::SendAudioTrackEvent(CAudioTrack* pTrack) 196 { 197 return SendToJava_AudioTrackEvent(pTrack); 198 } 199 200 bool CJavaPlayerEventDispatcher::SendVideoTrackEvent(CVideoTrack* pTrack) 201 { 202 return SendToJava_VideoTrackEvent(pTrack); 203 } 204 205 bool CJavaPlayerEventDispatcher::SendSubtitleTrackEvent(CSubtitleTrack* pTrack) 206 { 207 return SendToJava_SubtitleTrackEvent(pTrack); 208 } 209 210 bool CJavaPlayerEventDispatcher::SendMarkerEvent(string name, double time) 211 { 212 return SendToJava_MarkerEvent(name, time); 213 } 214 215 bool CJavaPlayerEventDispatcher::SendBufferProgressEvent(double clipDuration, int64_t start, int64_t stop, int64_t position) 216 { 217 return SendToJava_BufferProgressEvent(clipDuration, start, stop, position); 218 } 219 220 bool CJavaPlayerEventDispatcher::SendDurationUpdateEvent(double time) 221 { 222 return SendToJava_DurationUpdateEvent(time); 223 } 224 225 bool CJavaPlayerEventDispatcher::SendAudioSpectrumEvent(double time, double duration) 226 { 227 return SendToJava_AudioSpectrumEvent(time, duration); 228 } 229 /********************************************************************************* 230 * SendToJava methods section 231 **********************************************************************************/ 232 bool CJavaPlayerEventDispatcher::SendToJava_PlayerMediaErrorEvent(int errorCode) 233 { 234 if (NULL == m_PlayerInstance) 235 return false; 236 237 CJavaEnvironment jenv(m_PlayerVM); 238 JNIEnv *pEnv = jenv.getEnvironment(); 239 if (pEnv) { 240 pEnv->CallVoidMethod(m_PlayerInstance, m_SendPlayerMediaErrorEventMethod, errorCode); 241 return !jenv.reportException(); 242 } 243 244 return false; 245 } 246 247 bool CJavaPlayerEventDispatcher::SendToJava_PlayerHaltEvent(const char* message, double time) 248 { 249 if (NULL == m_PlayerInstance) 250 return false; 251 252 CJavaEnvironment jenv(m_PlayerVM); 253 JNIEnv *pEnv = jenv.getEnvironment(); 254 if (pEnv) { 255 jstring jmessage = pEnv->NewStringUTF(message); 256 pEnv->CallVoidMethod(m_PlayerInstance, m_SendPlayerHaltEventMethod, jmessage, time); 257 pEnv->DeleteLocalRef(jmessage); 258 return !jenv.reportException(); 259 } 260 261 return false; 262 } 263 264 bool CJavaPlayerEventDispatcher::SendToJava_PlayerStateEvent(long eventID, double presentTime) 265 { 266 if (NULL == m_PlayerInstance) 267 return false; 268 269 switch(eventID) { 270 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerUnknown: 271 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerReady: 272 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerPlaying: 273 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerPaused: 274 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerStopped: 275 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerFinished: 276 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerStalled: 277 case com_sun_media_jfxmediaimpl_NativeMediaPlayer_eventPlayerError: 278 { 279 LOWLEVELPERF_EXECTIMESTOP("gstInitPlatformToSendToJavaPlayerStateEventPaused"); 280 LOWLEVELPERF_EXECTIMESTOP("gstPauseToSendToJavaPlayerStateEventPaused"); 281 LOWLEVELPERF_EXECTIMESTOP("gstStopToSendToJavaPlayerStateEventStopped"); 282 LOWLEVELPERF_EXECTIMESTOP("gstPlayToSendToJavaPlayerStateEventPlaying"); 283 // Send an event only if the ID is valid. 284 CJavaEnvironment jenv(m_PlayerVM); 285 JNIEnv *pEnv = jenv.getEnvironment(); 286 if (pEnv) { 287 pEnv->CallVoidMethod(m_PlayerInstance, m_SendPlayerStateEventMethod, eventID, presentTime); 288 return !jenv.reportException(); 289 } 290 break; 291 } 292 default: 293 break; 294 } 295 296 return false; 297 } 298 299 bool CJavaPlayerEventDispatcher::SendToJava_NewFrameEvent(CVideoFrame* pVideoFrame) 300 { 301 LOWLEVELPERF_EXECTIMESTART("CJavaPlayerEventDispatcher::SendToJava_NewFrameEvent()"); 302 bool bSucceeded = false; 303 304 if (NULL == m_PlayerInstance) 305 return false; 306 307 CJavaEnvironment jenv(m_PlayerVM); 308 JNIEnv *pEnv = jenv.getEnvironment(); 309 if (pEnv) { 310 // SendNewFrameEvent will create the NativeVideoBuffer wrapper for the java side 311 pEnv->CallVoidMethod(m_PlayerInstance, m_SendNewFrameEventMethod, ptr_to_jlong(pVideoFrame)); 312 bSucceeded = !jenv.reportException(); 313 } 314 315 LOWLEVELPERF_EXECTIMESTOP("CJavaPlayerEventDispatcher::SendToJava_NewFrameEvent()"); 316 317 return bSucceeded; 318 } 319 320 bool CJavaPlayerEventDispatcher::SendToJava_FrameSizeChangedEvent(int width, int height) 321 { 322 if (NULL == m_PlayerInstance) 323 return false; 324 325 CJavaEnvironment jenv(m_PlayerVM); 326 JNIEnv *pEnv = jenv.getEnvironment(); 327 if (pEnv) { 328 pEnv->CallVoidMethod(m_PlayerInstance, m_SendFrameSizeChangedEventMethod, (jint)width, (jint)height); 329 return !jenv.reportException(); 330 } 331 332 return false; 333 } 334 335 bool CJavaPlayerEventDispatcher::SendToJava_AudioTrackEvent(CAudioTrack* pTrack) 336 { 337 if (NULL == m_PlayerInstance) 338 return false; 339 340 CJavaEnvironment jenv(m_PlayerVM); 341 JNIEnv *pEnv = jenv.getEnvironment(); 342 if (pEnv) { 343 jstring name = pEnv->NewStringUTF(pTrack->GetName().c_str()); 344 jstring language = pEnv->NewStringUTF(pTrack->GetLanguage().c_str()); 345 346 // Translate channel mask bits from native values to Java values. 347 int nativeChannelMask = pTrack->GetChannelMask(); 348 jint javaChannelMask = 0; 349 if (nativeChannelMask & CAudioTrack::UNKNOWN) 350 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_UNKNOWN; 351 if (nativeChannelMask & CAudioTrack::FRONT_LEFT) 352 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_FRONT_LEFT; 353 if (nativeChannelMask & CAudioTrack::FRONT_RIGHT) 354 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_FRONT_RIGHT; 355 if (nativeChannelMask & CAudioTrack::FRONT_CENTER) 356 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_FRONT_CENTER; 357 if (nativeChannelMask & CAudioTrack::REAR_LEFT) 358 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_REAR_LEFT; 359 if (nativeChannelMask & CAudioTrack::REAR_RIGHT) 360 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_REAR_RIGHT; 361 if (nativeChannelMask & CAudioTrack::REAR_CENTER) 362 javaChannelMask |= com_sun_media_jfxmedia_track_AudioTrack_REAR_CENTER; 363 364 pEnv->CallVoidMethod(m_PlayerInstance, m_SendAudioTrackEventMethod, 365 (jboolean)pTrack->isEnabled(), (jlong)pTrack->GetTrackID(), name, pTrack->GetEncoding(), language, 366 pTrack->GetNumChannels(), javaChannelMask, pTrack->GetSampleRate()); 367 368 pEnv->DeleteLocalRef(name); 369 pEnv->DeleteLocalRef(language); 370 return !jenv.reportException(); 371 } 372 373 return false; 374 } 375 376 bool CJavaPlayerEventDispatcher::SendToJava_VideoTrackEvent(CVideoTrack* pTrack) 377 { 378 if (NULL == m_PlayerInstance) 379 return false; 380 381 CJavaEnvironment jenv(m_PlayerVM); 382 JNIEnv *pEnv = jenv.getEnvironment(); 383 if (pEnv) { 384 jstring name = pEnv->NewStringUTF(pTrack->GetName().c_str()); 385 pEnv->CallVoidMethod(m_PlayerInstance, m_SendVideoTrackEventMethod, 386 (jboolean)pTrack->isEnabled(), (jlong)pTrack->GetTrackID(), name, pTrack->GetEncoding(), 387 pTrack->GetWidth(), pTrack->GetHeight(), 388 pTrack->GetFrameRate(), pTrack->HasAlphaChannel()); 389 pEnv->DeleteLocalRef(name); 390 return !jenv.reportException(); 391 } 392 393 return false; 394 } 395 396 bool CJavaPlayerEventDispatcher::SendToJava_SubtitleTrackEvent(CSubtitleTrack* pTrack) 397 { 398 if (NULL == m_PlayerInstance) 399 return false; 400 401 CJavaEnvironment jenv(m_PlayerVM); 402 JNIEnv *pEnv = jenv.getEnvironment(); 403 if (pEnv) { 404 jstring name = pEnv->NewStringUTF(pTrack->GetName().c_str()); 405 jstring language = pEnv->NewStringUTF(pTrack->GetLanguage().c_str()); 406 407 pEnv->CallVoidMethod(m_PlayerInstance, m_SendSubtitleTrackEventMethod, 408 (jboolean)pTrack->isEnabled(), (jlong)pTrack->GetTrackID(), 409 name, pTrack->GetEncoding(), language); 410 pEnv->DeleteLocalRef(name); 411 pEnv->DeleteLocalRef(language); 412 413 return !jenv.reportException(); 414 } 415 416 return false; 417 } 418 419 /****************************************************************************************** 420 * Creates any object with any arguments 421 ******************************************************************************************/ 422 jobject CJavaPlayerEventDispatcher::CreateObject(JNIEnv *env, jmethodID *cid, 423 const char* class_name, const char* signature, 424 jvalue* value) 425 { 426 jclass classe; 427 jobject result; 428 429 classe = env->FindClass(class_name); 430 if( classe == NULL ) 431 return NULL; /* can't find/load the class, exception thrown */ 432 433 if( *cid == NULL) 434 { 435 *cid = env->GetMethodID(classe, "<init>", signature); 436 if( *cid == NULL ) 437 { 438 env->DeleteLocalRef(classe); 439 return NULL; /* can't find/get the method, exception thrown */ 440 } 441 } 442 443 result = env->NewObjectA(classe, *cid, value); 444 445 env->DeleteLocalRef(classe); 446 return result; 447 } 448 449 jobject CJavaPlayerEventDispatcher::CreateBoolean(JNIEnv *env, jboolean boolean_value) 450 { 451 static jmethodID cid = NULL; 452 jvalue value; 453 454 value.z = boolean_value; 455 456 return CreateObject(env, &cid, "java/lang/Boolean", "(Z)V", &value); 457 } 458 459 jobject CJavaPlayerEventDispatcher::CreateInteger(JNIEnv *env, jint int_value) 460 { 461 static jmethodID cid = NULL; 462 jvalue value; 463 464 value.i = int_value; 465 466 return CreateObject(env, &cid, "java/lang/Integer", "(I)V", &value); 467 } 468 469 jobject CJavaPlayerEventDispatcher::CreateLong(JNIEnv *env, jlong long_value) 470 { 471 static jmethodID cid = NULL; 472 jvalue value; 473 474 value.j = long_value; 475 476 return CreateObject(env, &cid, "java/lang/Long", "(J)V", &value); 477 } 478 479 jobject CJavaPlayerEventDispatcher::CreateDouble(JNIEnv *env, jdouble double_value) 480 { 481 static jmethodID cid = NULL; 482 jvalue value; 483 484 value.d = double_value; 485 486 return CreateObject(env, &cid, "java/lang/Double", "(D)V", &value); 487 } 488 489 jobject CJavaPlayerEventDispatcher::CreateDuration(JNIEnv *env, jlong duration) 490 { 491 static jmethodID constructorID = NULL; 492 // We receive duration in nanoseconds, but javafx.util.Duration needs in milliseconds 493 jdouble millis = duration/1000000.0; 494 495 jclass durationClass = env->FindClass("javafx/util/Duration"); 496 if (durationClass == NULL) 497 return NULL; /* can't find/load the class, exception thrown */ 498 499 if (constructorID == NULL) 500 { 501 constructorID = env->GetMethodID(durationClass, "<init>", "(D)V"); 502 if( constructorID == NULL ) 503 { 504 env->DeleteLocalRef(durationClass); 505 return NULL; /* can't find/get the method, exception thrown */ 506 } 507 } 508 509 jobject result = env->NewObject(durationClass, constructorID, millis); 510 511 env->DeleteLocalRef(durationClass); 512 513 return result; 514 } 515 516 bool CJavaPlayerEventDispatcher::SendToJava_MarkerEvent(string name, double time) 517 { 518 if (NULL == m_PlayerInstance) 519 return false; 520 521 CJavaEnvironment jenv(m_PlayerVM); 522 JNIEnv *pEnv = jenv.getEnvironment(); 523 if (pEnv) { 524 jobject jname = pEnv->NewStringUTF(name.c_str()); 525 pEnv->CallVoidMethod(m_PlayerInstance, m_SendMarkerEventMethod, 526 jname, time); 527 pEnv->DeleteLocalRef(jname); 528 return !jenv.reportException(); 529 } 530 531 return false; 532 } 533 534 bool CJavaPlayerEventDispatcher::SendToJava_BufferProgressEvent(double clipDuration, int64_t start, int64_t stop, int64_t position) 535 { 536 if (NULL == m_PlayerInstance) 537 return false; 538 539 CJavaEnvironment jenv(m_PlayerVM); 540 JNIEnv *pEnv = jenv.getEnvironment(); 541 if (pEnv) { 542 pEnv->CallVoidMethod(m_PlayerInstance, m_SendBufferProgressEventMethod, clipDuration, start, stop, position); 543 return !jenv.reportException(); 544 } 545 546 return false; 547 } 548 549 bool CJavaPlayerEventDispatcher::SendToJava_DurationUpdateEvent(double time) 550 { 551 if (NULL == m_PlayerInstance) 552 return false; 553 554 CJavaEnvironment jenv(m_PlayerVM); 555 JNIEnv *pEnv = jenv.getEnvironment(); 556 if (pEnv) { 557 pEnv->CallVoidMethod(m_PlayerInstance, m_SendDurationUpdateEventMethod, 558 (jdouble)time); 559 return !jenv.reportException(); 560 } 561 562 return false; 563 } 564 565 bool CJavaPlayerEventDispatcher::SendToJava_AudioSpectrumEvent(double time, double duration) 566 { 567 if (NULL == m_PlayerInstance) 568 return false; 569 570 CJavaEnvironment jenv(m_PlayerVM); 571 JNIEnv *pEnv = jenv.getEnvironment(); 572 if (pEnv) { 573 pEnv->CallVoidMethod(m_PlayerInstance, m_SendAudioSpectrumEventMethod, time, duration); 574 return !jenv.reportException(); 575 } 576 577 return false; 578 }