Skip to content

Commit

Permalink
2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
bnussey committed Dec 16, 2016
1 parent afe82d3 commit 6dba41c
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 34 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ Mutes the native video player.

Sets the native video player to loop once playback has finished.

- **aspect - (boolean)** - *optional* **ANDROID ONLY**
- **fill - (boolean)** - *optional* **ANDROID ONLY**

Defaults to true. If set to false, the aspect ratio of the video will not be honored and it will fill the entire container available.Ï
If set to true, the aspect ratio of the video will not be honored and it will fill the entire space available.

- **loadingComplete - (function)** - *optional* **ANDROID ONLY**
- **loadingComplete - (function)** - *optional*

Attribute to specify an event callback to execute when the video has loaded.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nativescript-videoplayer",
"version": "2.0.0",
"version": "2.1.0",
"main": "videoplayer.js",
"typings": "videoplayer.d.ts",
"description": "A NativeScript plugin that uses the native video players to play local and remote videos.",
Expand Down
16 changes: 7 additions & 9 deletions videoplayer-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import platform = require("platform");
import utils = require("utils/utils");
import * as types from "utils/types";


var SRC = "src";
var VIDEO_SOURCE = "videoSource";
var VIDEO = "Video";
Expand All @@ -17,7 +16,7 @@ var AUTOPLAY = "autoplay";
var CONTROLS = "controls";
var LOOP = "loop";
var MUTED = "muted";
var ASPECT = "aspect";
var FILL = "fill";

// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
var AffectsLayout = platform.device.os === platform.platformNames.android ? dependencyObservable.PropertyMetadataSettings.None : dependencyObservable.PropertyMetadataSettings.AffectsLayout;
Expand Down Expand Up @@ -97,8 +96,8 @@ export class Video extends view.View {
VIDEO,
new proxy.PropertyMetadata(false, dependencyObservable.PropertyMetadataSettings.None)
);
public static aspectProperty = new dependencyObservable.Property(
ASPECT,
public static fillProperty = new dependencyObservable.Property(
FILL,
VIDEO,
new proxy.PropertyMetadata(false, dependencyObservable.PropertyMetadataSettings.None)
);
Expand Down Expand Up @@ -153,14 +152,13 @@ export class Video extends view.View {
this._setValue(Video.mutedProperty, value);
}

get aspect(): any {
return this._getValue(Video.aspectProperty);
get fill(): any {
return this._getValue(Video.fillProperty);
}
set aspect(value: any) {
this._setValue(Video.aspectProperty, value);
set fill(value: any) {
this._setValue(Video.fillProperty, value);
}


public _setNativeVideo(nativeVideo: any) {
//
}
Expand Down
4 changes: 2 additions & 2 deletions videoplayer.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class Video extends videoCommon.Video {

this.owner.mediaState = SURFACE_READY;

if (this.owner.aspect !== false) {
if (this.owner.fill !== true) {
this.owner._setupAspectRatio();
}

Expand Down Expand Up @@ -198,7 +198,7 @@ export class Video extends videoCommon.Video {
this.owner.videoHeight = mediaPlayer.getVideoHeight();
if (this.owner.videoWidth !== 0 && this.owner.videoHeight !== 0) {
this.owner._android.getSurfaceTexture().setDefaultBufferSize(this.owner.videoWidth, this.owner.videoHeight);
if (this.owner.aspect !== false) {
if (this.owner.fill !== true) {
this.owner._setupAspectRatio();
}
}
Expand Down
53 changes: 34 additions & 19 deletions videoplayer.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import definition = require("./videoplayer");
import * as typesModule from "utils/types";
import * as application from 'application';

declare var NSURL, AVPlayer, AVPlayerViewController, AVPlayerItemDidPlayToEndTimeNotification, UIView, CMTimeMakeWithSeconds, NSNotification, NSNotificationCenter, CMTimeGetSeconds, CMTimeMake, kCMTimeZero;
declare var NSURL, AVPlayer, AVPlayerViewController, AVPlayerItemDidPlayToEndTimeNotification, UIView, CMTimeMakeWithSeconds, NSNotification, NSNotificationCenter, CMTimeGetSeconds, CMTimeMake, kCMTimeZero, AVPlayerItemStatusReadyToPlay;


global.moduleMerge(common, exports);
Expand All @@ -27,6 +27,8 @@ export class Video extends common.Video {
private _playerController: any; /// AVPlayerViewController
private _ios: any; /// UIView
private _src: string;
private _AVPlayerItemDidPlayToEndTimeObserver: any;
private _observer: NSObject;

constructor() {
super();
Expand All @@ -38,6 +40,8 @@ export class Video extends common.Video {
// showsPlaybackControls must be set to false on init to avoid any potential 'Unable to simultaneously satisfy constraints' errors
this._playerController.showsPlaybackControls = false;
this._ios = this._playerController.view;
this._observer = PlayerObserverClass.alloc();
this._observer["_owner"] = this;

}

Expand Down Expand Up @@ -70,10 +74,6 @@ export class Video extends common.Video {

this._playerController.player = this._player;

if (this.autoplay === true) {
this.play();
}

if (isNaN(this.width) || isNaN(this.height)) {
this.requestLayout();
}
Expand All @@ -82,25 +82,22 @@ export class Video extends common.Video {
this._player.muted = true;
}

this._player.currentItem.addObserverForKeyPathOptionsContext(this._observer, "status", 0, null);

if (this.finishedCallback) {
application.ios.addNotificationObserver(AVPlayerItemDidPlayToEndTimeNotification, this.AVPlayerItemDidPlayToEndTimeNotification.bind(this));
this._AVPlayerItemDidPlayToEndTimeObserver = application.ios.addNotificationObserver(AVPlayerItemDidPlayToEndTimeNotification, this.AVPlayerItemDidPlayToEndTimeNotification.bind(this));
}
}

private AVPlayerItemDidPlayToEndTimeNotification(notification: any) {
if (this._player.currentItem) {
// This will match exactly to the object from the notification so can ensure only looping the video that has finished.
let currentItem = this._player.currentItem.toString();
let notificationString = notification.toString();
if (this._player.currentItem && this._player.currentItem === notification.object) {
// This will match exactly to the object from the notification so can ensure only looping and finished event for the video that has finished.
// Notification is structured like so: NSConcreteNotification 0x61000024f690 {name = AVPlayerItemDidPlayToEndTimeNotification; object = <AVPlayerItem: 0x600000204190, asset = <AVURLAsset: 0x60000022b7a0, URL = https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4>>}
// Check if object exists in notification.
if (notificationString.includes(currentItem)) {
this._emit(common.Video.finishedEvent);
if (this.loop === true && this._player !== null) {
// Go in 5ms for more seamless looping
this.seekToTime(CMTimeMake(5, 100));
this.play();
}
this._emit(common.Video.finishedEvent);
if (this.loop === true && this._player !== null) {
// Go in 5ms for more seamless looping
this.seekToTime(CMTimeMake(5, 100));
this.play();
}
}
}
Expand Down Expand Up @@ -141,11 +138,29 @@ export class Video extends common.Video {

public destroy() {
if (this.finishedCallback) {
application.ios.removeNotificationObserver(AVPlayerItemDidPlayToEndTimeNotification);
application.ios.removeNotificationObserver(this._AVPlayerItemDidPlayToEndTimeObserver, AVPlayerItemDidPlayToEndTimeNotification);
}
this._player.currentItem.removeObserverForKeyPath(this._observer, "status");
this.pause();
this._player.replaceCurrentItemWithPlayerItem(null); //de-allocates the AVPlayer
this._playerController = null;
}

private _loadingComplete() {
this._emit(common.Video.loadingCompleteEvent);
}

}

class PlayerObserverClass extends NSObject {
observeValueForKeyPathOfObjectChangeContext(path: string, obj: Object, change: NSDictionary<any, any>, context: any) {
if (path === "status") {
if (this["_owner"]._player.currentItem.status === AVPlayerItemStatusReadyToPlay) {
this["_owner"]._loadingComplete();
if (this["_owner"].autoplay === true) {
this["_owner"].play();
}
}
}
}
}

0 comments on commit 6dba41c

Please sign in to comment.