Commit 82f8e9d1 authored by Carola Nitz's avatar Carola Nitz

Devicemotion: add devicemotion for 360 videos

(cherry picked from commit 9deda384)
parent 0d51c932
/*****************************************************************************
* DeviceMotion.swift
* VLC for iOS
*****************************************************************************
* Copyright (c) 2018 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <caro # videolan.org>
*
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
import Foundation
import CoreMotion
@objc(VLCDeviceMotionDelegate)
protocol DeviceMotionDelegate:NSObjectProtocol {
func deviceMotionHasAttitude(deviceMotion:DeviceMotion, pitch:Double, yaw:Double, roll:Double)
}
@objc(VLCDeviceMotion)
class DeviceMotion:NSObject {
let motion = CMMotionManager()
var referenceAttitude:CMAttitude? = nil
@objc weak var delegate: DeviceMotionDelegate? = nil
@objc func startDeviceMotion() {
if motion.isDeviceMotionAvailable {
motion.gyroUpdateInterval = 1.0 / 60.0 // 60 Hz
motion.startDeviceMotionUpdates(using: .xTrueNorthZVertical, to: .main) {
[weak self] (data, error) in
guard let strongSelf = self, let data = data else {
return
}
//We're using the initial angle of phone as 0.0.0 reference for all axis
//we need to create a copy here, otherwise we just have a reference which is being changed in the next line
if strongSelf.referenceAttitude == nil {
strongSelf.referenceAttitude = data.attitude.copy() as? CMAttitude
}
// this line basically substracts the reference attitude so that we have yaw, pitch and roll changes in
// relation to the very first angle
data.attitude.multiply(byInverseOf: strongSelf.referenceAttitude!)
let pitch = -(180/Double.pi)*data.attitude.pitch // -90; 90
let yaw = -(180/Double.pi)*data.attitude.yaw // -180; 180
let roll = -(180/Double.pi)*data.attitude.roll// -180; 180
//print(pitch,yaw,roll)
strongSelf.delegate?.deviceMotionHasAttitude(deviceMotion:strongSelf, pitch:pitch, yaw:yaw, roll:roll)
}
}
}
@objc func stopDeviceMotion() {
if motion.isDeviceMotionActive {
motion.stopDeviceMotionUpdates()
self.referenceAttitude = nil
}
}
}
......@@ -36,6 +36,7 @@
#import "VLCTrackSelectorView.h"
#import "VLCMetadata.h"
#import "UIDevice+VLC.h"
#import "VLC_iOS-Swift.h"
#define FORWARD_SWIPE_DURATION 30
#define BACKWARD_SWIPE_DURATION 10
......@@ -54,7 +55,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
VLCPanTypeProjection
};
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate>
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate, VLCPlaybackControllerDelegate, VLCDeviceMotionDelegate>
{
BOOL _controlsHidden;
BOOL _videoFiltersHidden;
......@@ -78,7 +79,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
BOOL _seekGestureEnabled;
BOOL _closeGestureEnabled;
BOOL _variableJumpDurationEnabled;
BOOL _mediaHasProjection;
BOOL _playbackWillClose;
BOOL _isTapSeeking;
VLCMovieJumpState _previousJumpState;
......@@ -111,6 +111,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
NSInteger _mediaDuration;
NSInteger _numberOfTapSeek;
VLCDeviceMotion *_deviceMotion;
CGFloat _fov;
CGPoint _saveLocation;
CGSize _screenSizePixel;
......@@ -415,8 +416,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
[self updateDefaults];
//Disabling video gestures, media not init in the player yet.
[self enableNormalVideoGestures:NO];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateDefaults) name:NSUserDefaultsDidChangeNotification object:nil];
}
......@@ -433,14 +432,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
_multiSelectionView.shuffleMode = _vpc.isShuffleMode;
//Media is loaded in the media player, checking the projection type and configuring accordingly.
_fov = 0.f;
_mediaHasProjection = NO;
if ([_vpc currentMediaProjection] == VLCMediaProjectionEquiRectangular) {
_fov = DEFAULT_FOV;
_mediaHasProjection = YES;
}
[self enableNormalVideoGestures:!_mediaHasProjection];
[self setupForMediaProjection];
}
- (void)viewDidLayoutSubviews
......@@ -512,6 +504,12 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
[[NSUserDefaults standardUserDefaults] setBool:_displayRemainingTime forKey:kVLCShowRemainingTime];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[self.deviceMotion stopDeviceMotion];
}
- (BOOL)canBecomeFirstResponder
{
return YES;
......@@ -650,7 +648,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
CGFloat diff = DEFAULT_FOV * -(ZOOM_SENSITIVITY * recognizer.velocity / _screenSizePixel.width);
if (_mediaHasProjection) {
if ([_vpc currentMediaProjection] == VLCMediaProjectionEquiRectangular) {
if ([_vpc updateViewpoint:0 pitch:0 roll:0 fov:diff absolute:NO]) {
//Checking for fov value in case of
_fov = MAX(MIN(_fov + diff, MAX_FOV), MIN_FOV);
......@@ -838,15 +836,35 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
return [super nextResponder];
}
- (void)enableNormalVideoGestures:(BOOL)enable
- (VLCDeviceMotion *)deviceMotion
{
[_tapRecognizer setEnabled:enable];
[_swipeRecognizerUp setEnabled:enable];
[_swipeRecognizerDown setEnabled:enable];
[_swipeRecognizerLeft setEnabled:enable];
[_swipeRecognizerRight setEnabled:enable];
if (!_deviceMotion) {
_deviceMotion = [VLCDeviceMotion new];
_deviceMotion.delegate = self;
}
return _deviceMotion;
}
- (void)setupForMediaProjection
{
BOOL mediaHasProjection = [_vpc currentMediaProjection] == VLCMediaProjectionEquiRectangular;
_fov = mediaHasProjection ? DEFAULT_FOV : 0.f;
[_panRecognizer setEnabled:mediaHasProjection];
[_swipeRecognizerUp setEnabled:!mediaHasProjection];
[_swipeRecognizerDown setEnabled:!mediaHasProjection];
[_swipeRecognizerLeft setEnabled:!mediaHasProjection];
[_swipeRecognizerRight setEnabled:!mediaHasProjection];
if (mediaHasProjection) {
[self.deviceMotion startDeviceMotion];
}
}
- (void)deviceMotionHasAttitudeWithDeviceMotion:(VLCDeviceMotion *)deviceMotion pitch:(double)pitch yaw:(double)yaw roll:(double)roll
{
[_vpc updateViewpoint:yaw pitch:pitch roll:roll fov:_fov absolute:YES];
}
#pragma mark - controls
- (IBAction)closePlayback:(id)sender
......@@ -1318,12 +1336,15 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
panType = VLCPanTypeBrightness;
// only check for seeking gesture if on iPad , will overwrite last statements if true
if ([deviceType isEqualToString:@"iPad"]) {
if (location.y < 110)
if ([deviceType isEqualToString:@"iPad"] && location.y < 110) {
panType = VLCPanTypeSeek;
}
return panType;
if ([_vpc currentMediaProjection] == VLCMediaProjectionEquiRectangular) {
panType = VLCPanTypeProjection;
}
return panType;
}
- (void)panRecognized:(UIPanGestureRecognizer*)panRecognizer
......@@ -1331,10 +1352,6 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
CGFloat panDirectionX = [panRecognizer velocityInView:self.view].x;
CGFloat panDirectionY = [panRecognizer velocityInView:self.view].y;
if (panRecognizer.state == UIGestureRecognizerStateBegan) {
_currentPanType = _mediaHasProjection ? VLCPanTypeProjection : [self detectPanTypeForPan:panRecognizer];
}
if (_currentPanType == VLCPanTypeSeek) {
if (!_seekGestureEnabled)
return;
......@@ -1405,7 +1422,7 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
_currentPanType = VLCPanTypeNone;
//Invalidate saved location when the gesture is ended
if (_mediaHasProjection)
if ([_vpc currentMediaProjection] == VLCMediaProjectionEquiRectangular)
_saveLocation = CGPointMake(-1.f, -1.f);
}
}
......
......@@ -18,6 +18,7 @@
4152F1621FEF19BD00F1908B /* KeychainCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */; };
416DEFF61FEEA76A00F4FC59 /* LayoutAnchorContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416DEFF51FEEA76A00F4FC59 /* LayoutAnchorContainer.swift */; };
4171D35018A2C19000A16EF9 /* VLCFolderCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 4171D34F18A2C19000A16EF9 /* VLCFolderCollectionViewFlowLayout.m */; };
416443862048419E00CAC646 /* DeviceMotion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416443852048419E00CAC646 /* DeviceMotion.swift */; };
417CDA231A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 417CDA211A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.m */; };
417CDA241A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 417CDA221A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.xib */; };
417D7F601F7BA26200DDF36A /* VLCRemoteControlService.m in Sources */ = {isa = PBXBuildFile; fileRef = 417D7F5F1F7BA26200DDF36A /* VLCRemoteControlService.m */; };
......@@ -742,6 +743,7 @@
41273A3B1A955C4100A2EF77 /* VLCMigrationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCMigrationViewController.xib; path = Sources/VLCMigrationViewController.xib; sourceTree = SOURCE_ROOT; };
412BE7521FC4947400ACCC42 /* VLCMediaData+VLCDragAndDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "VLCMediaData+VLCDragAndDrop.swift"; path = "Sources/VLCMediaData+VLCDragAndDrop.swift"; sourceTree = SOURCE_ROOT; };
4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = KeychainCoordinator.swift; path = Sources/KeychainCoordinator.swift; sourceTree = "<group>"; };
416443852048419E00CAC646 /* DeviceMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DeviceMotion.swift; path = Sources/DeviceMotion.swift; sourceTree = "<group>"; };
416DEFF51FEEA76A00F4FC59 /* LayoutAnchorContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LayoutAnchorContainer.swift; path = Sources/LayoutAnchorContainer.swift; sourceTree = "<group>"; };
4171D34E18A2C19000A16EF9 /* VLCFolderCollectionViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCFolderCollectionViewFlowLayout.h; path = Sources/VLCFolderCollectionViewFlowLayout.h; sourceTree = SOURCE_ROOT; };
4171D34F18A2C19000A16EF9 /* VLCFolderCollectionViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCFolderCollectionViewFlowLayout.m; path = Sources/VLCFolderCollectionViewFlowLayout.m; sourceTree = SOURCE_ROOT; };
......@@ -1888,6 +1890,7 @@
7D5F7AB9175265B2006CCCFA /* Playback */ = {
isa = PBXGroup;
children = (
416443852048419E00CAC646 /* DeviceMotion.swift */,
DD8F842F1B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.h */,
DD8F84301B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m */,
7D37848D183A98B6009EE944 /* VLCMovieViewController.h */,
......@@ -2934,7 +2937,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = VLC;
LastSwiftUpdateCheck = 0720;
LastSwiftUpdateCheck = 0930;
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = VideoLAN;
TargetAttributes = {
......@@ -3862,6 +3865,7 @@
7DC19B0C1868D21800810BF7 /* VLCFirstStepsSixthPageViewController.m in Sources */,
DD3EFEED1BDEBA3800B68579 /* VLCNetworkServerBrowserViewController.m in Sources */,
DD3EABFC1BE14C4B003668DA /* UIViewController+VLCAlert.m in Sources */,
416443862048419E00CAC646 /* DeviceMotion.swift in Sources */,
7D9289751877459B009108FD /* VLCFirstStepsThirdPageViewController.m in Sources */,
7D95610B1AF3E9E800779745 /* VLCMiniPlaybackView.m in Sources */,
DD3EFF451BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserManualConnect.m in Sources */,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment