blob: 4b43e8964e29b2766f293a566bfadc2f7bd67a78 [file] [log] [blame]
/*
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#import "OSXMediaPlayer.h"
#import "OSXPlayerProtocol.h"
#import "com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer.h"
#import <Utils/JObjectPeers.h>
#import <Utils/JavaUtils.h>
#import <CoreAudio/CoreAudio.h>
#import <jni/Logger.h>
#import <jni/JniUtils.h>
#import <jfxmedia_errors.h>
#import <objc/runtime.h>
#define USE_WEAK_REFS 0
// Don't access directly, use the OSXMediaPlayer static methods to ensure thread safe access
static JObjectPeers *gMediaPlayerPeers = nil;
static Class gMediaPlayerClass = nil;
@implementation OSXMediaPlayer
+ (void) initialize
{
gMediaPlayerPeers = [[JObjectPeers alloc] init];
}
+ (OSXMediaPlayer*) peerForPlayer:(jobject)javaPlayer andEnv:(JNIEnv*)javaEnv
{
return [gMediaPlayerPeers peerForJObject:javaPlayer javaEnv:javaEnv];
}
+ (void) setPeer:(OSXMediaPlayer*)player forJavaPlayer:(jobject)javaPlayer andEnv:(JNIEnv*)javaEnv
{
[gMediaPlayerPeers setPeer:player forJObject:javaPlayer javaEnv:javaEnv];
}
+ (void) removePlayerPeers:(OSXMediaPlayer*)player
{
[gMediaPlayerPeers removePeer:player];
}
+ (BOOL) initPlayerPlatform
{
BOOL enableAVF = YES;
// Check environment to see if platforms are enabled
char *value = getenv("JFXMEDIA_AVF");
if (value ? strncasecmp(value, "yes", 3) != 0 : NO) {
enableAVF = NO;
}
// Determine if we can use OSX native player libs, without linking directly
Class klass;
if (enableAVF) {
klass = objc_getClass("AVFMediaPlayer");
if (klass) {
if ([klass conformsToProtocol:@protocol(OSXPlayerProtocol)]) {
if ([klass respondsToSelector:@selector(playerAvailable)] ? [klass playerAvailable] : YES) {
gMediaPlayerClass = klass;
return YES;
}
}
}
}
return NO;
}
- (id) init
{
if ((self = [super init]) != nil) {
}
return self;
}
- (id) initWithURL:(NSURL *)source javaPlayer:(jobject)jp andEnv:(JNIEnv*)env eventHandler:(CJavaPlayerEventDispatcher*)hdlr
{
if (!gMediaPlayerClass) {
// No player class available, abort
return nil;
}
if ((self = [super init]) != nil) {
movieURL = [source retain];
env->GetJavaVM(&javaPlayerVM);
if (env->ExceptionCheck()) {
env->ExceptionClear();
return nil;
}
#if USE_WEAK_REFS
javaPlayer = env->NewWeakGlobalRef(jp);
#else
javaPlayer = env->NewGlobalRef(jp);
#endif
// set up the peer association
[OSXMediaPlayer setPeer:self forJavaPlayer:javaPlayer andEnv:env];
eventHandler = hdlr;
// create the player object
player = [[gMediaPlayerClass alloc] initWithURL:movieURL eventHandler:eventHandler];
}
return self;
}
- (id) initWithURL:(NSURL *)source eventHandler:(CJavaPlayerEventDispatcher*)hdlr
{
// stub initWithURL message to satisfy the protocol requirements, this should
// never be called
return nil;
}
- (void) dealloc
{
[self dispose]; // just in case
[movieURL release];
[super dealloc];
}
- (void) dispose
{
@synchronized(self) {
[player dispose];
[player release];
player = nil;
if (eventHandler) {
eventHandler->Dispose();
delete eventHandler;
}
eventHandler = NULL;
[OSXMediaPlayer removePlayerPeers:self];
if (javaPlayerVM && javaPlayer) {
BOOL attached = NO;
JNIEnv *env = GetJavaEnvironment(javaPlayerVM, &attached);
// remove peer association
[OSXMediaPlayer removePlayerPeers:self];
#if USE_WEAK_REFS
env->DeleteWeakGlobalRef(javaPlayer);
#else
env->DeleteGlobalRef(javaPlayer);
#endif
if (attached) {
javaPlayerVM->DetachCurrentThread();
}
}
javaPlayer = 0;
javaPlayerVM = NULL;
}
}
- (id<OSXPlayerProtocol>) player
{
return [[player retain] autorelease];
}
- (CAudioEqualizer*) audioEqualizer
{
return player.audioEqualizer;
}
- (CAudioSpectrum*) audioSpectrum
{
return player.audioSpectrum;
}
- (int64_t) audioSyncDelay
{
return player.audioSyncDelay;
}
- (void) setAudioSyncDelay:(int64_t)audioSyncDelay
{
player.audioSyncDelay = audioSyncDelay;
}
- (double) duration
{
return player.duration;
}
- (float) rate
{
return player.rate;
}
- (void) setRate:(float)rate
{
player.rate = rate;
}
- (double) currentTime
{
return player.currentTime;
}
- (void) setCurrentTime:(double)currentTime
{
player.currentTime = currentTime;
}
- (BOOL) mute
{
return player.mute;
}
- (void) setMute:(BOOL)mute
{
player.mute = mute;
}
- (float) volume
{
return player.volume;
}
- (void) setVolume:(float)volume
{
player.volume = volume;
}
- (float) balance
{
return player.balance;
}
- (void) setBalance:(float)balance
{
player.balance = balance;
}
- (void) play
{
[player play];
}
- (void) pause
{
[player pause];
}
- (void) finish
{
[player finish];
}
- (void) stop
{
[player stop];
}
@end
#pragma mark -
#pragma mark JNI Methods
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxCreatePlayer
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxCreatePlayer
(JNIEnv *env, jobject playerObject, jstring sourceURI)
{
// create the event dispatcher, init later
CJavaPlayerEventDispatcher *eventHandler = new CJavaPlayerEventDispatcher();
eventHandler->Init(env, playerObject, NULL);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *sourceURIString = NSStringFromJavaString(env, sourceURI);
if (!sourceURIString) {
LOGGER_ERRORMSG("OSXMediaPlayer: Unable to create sourceURIString\n");
ThrowJavaException(env, "com/sun/media/jfxmedia/MediaException",
"OSXMediaPlayer: Unable to create sourceURIString");
return;
}
NSURL *mediaURL = [[NSURL alloc] initWithString:sourceURIString];
if (!mediaURL) {
LOGGER_WARNMSG("OSXMediaPlayer: Unable to create mediaURL\n");
ThrowJavaException(env, "com/sun/media/jfxmedia/MediaException",
"OSXMediaPlayer: Unable to create mediaURL");
return;
}
OSXMediaPlayer *player = [[OSXMediaPlayer alloc] initWithURL:mediaURL javaPlayer:playerObject andEnv:env eventHandler:eventHandler];
if (!player) {
LOGGER_WARNMSG("OSXMediaPlayer: Unable to create player\n");
ThrowJavaException(env, "com/sun/media/jfxmedia/MediaException",
"OSXMediaPlayer: Unable to create player");
[mediaURL release];
return;
}
[player release]; // The player peer list retains for us
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetAudioEqualizerRef
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetAudioEqualizerRef
(JNIEnv *env, jobject playerObject) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
CAudioEqualizer *eq = 0;
if (player) {
eq = player.audioEqualizer;
}
[pool drain];
return ptr_to_jlong(eq);
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetAudioSpectrumRef
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetAudioSpectrumRef
(JNIEnv *env, jobject playerObject) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
CAudioSpectrum *spectrum = NULL;
if (player) {
spectrum = player.audioSpectrum;
}
[pool drain];
return ptr_to_jlong(spectrum);
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetAudioSyncDelay
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetAudioSyncDelay
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
jlong asd = 0;
if (player) {
asd = (jlong)player.audioSyncDelay;
}
[pool drain];
return asd;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxSetAudioSyncDelay
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxSetAudioSyncDelay
(JNIEnv *env, jobject playerObject, jlong delay)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
player.audioSyncDelay = (int64_t)delay;
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxPlay
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxPlay
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
[player play];
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxStop
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxStop
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
[player stop];
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxPause
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxPause
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
[player pause];
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxFinish
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxFinish
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
[player finish];
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetRate
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetRate
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
jfloat rc = 0.0;
if (player) {
rc = (jfloat)player.rate;
}
[pool drain];
return rc;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxSetRate
* Signature: (F)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxSetRate
(JNIEnv *env, jobject playerObject, jfloat rate)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
player.rate = (double)rate;
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetPresentationTime
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetPresentationTime
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
jdouble rc = 0.0;
if (player) {
rc = player.currentTime;
}
[pool drain];
return rc;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetMute
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetMute
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
jboolean rc = JNI_FALSE;
if (player) {
rc = (player.mute != NO);
}
[pool drain];
return rc;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxSetMute
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxSetMute
(JNIEnv *env, jobject playerObject, jboolean mute)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
player.mute = (mute != JNI_FALSE);
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetVolume
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetVolume
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
jfloat rc = 0.0;
if (player) {
rc = (jfloat)player.volume;
}
[pool drain];
return rc;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxSetVolume
* Signature: (F)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxSetVolume
(JNIEnv *env, jobject playerObject, jfloat volume)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
player.volume = (double)volume;
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetBalance
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetBalance
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
jfloat rc = 0.0;
if (player) {
rc = (jfloat)player.balance;
}
[pool drain];
return rc;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxSetBalance
* Signature: (F)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxSetBalance
(JNIEnv *env, jobject playerObject, jfloat balance)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
player.balance = (double)balance;
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxGetDuration
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxGetDuration
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
double duration = -1.0;
if (player) {
duration = (jdouble)player.duration;
}
[pool drain];
return duration;
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxSeek
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxSeek
(JNIEnv *env, jobject playerObject, jdouble time)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
player.currentTime = (double)time;
}
[pool drain];
}
/*
* Class: com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer
* Method: osxDispose
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_sun_media_jfxmediaimpl_platform_osx_OSXMediaPlayer_osxDispose
(JNIEnv *env, jobject playerObject)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OSXMediaPlayer *player = [OSXMediaPlayer peerForPlayer:playerObject andEnv:env];
if (player) {
[player dispose];
// This should pop the last retain, aside from the autoreleased reference...
[OSXMediaPlayer removePlayerPeers:player];
}
[pool drain];
}