Commit 9deda384 authored by Carola Nitz's avatar Carola Nitz

Devicemotion: add devicemotion for 360 videos

parent 5ef0cba8
/*****************************************************************************
* 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
}
}
}
......@@ -35,6 +35,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
......@@ -53,7 +54,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
VLCPanTypeProjection
};
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate>
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate, VLCPlaybackControllerDelegate, VLCDeviceMotionDelegate>
{
BOOL _controlsHidden;
BOOL _videoFiltersHidden;
......@@ -77,7 +78,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
BOOL _seekGestureEnabled;
BOOL _closeGestureEnabled;
BOOL _variableJumpDurationEnabled;
BOOL _mediaHasProjection;
BOOL _playbackWillClose;
BOOL _isTapSeeking;
VLCMovieJumpState _previousJumpState;
......@@ -110,6 +110,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
NSInteger _mediaDuration;
NSInteger _numberOfTapSeek;
VLCDeviceMotion *_deviceMotion;
CGFloat _fov;
CGPoint _saveLocation;
CGSize _screenSizePixel;
......@@ -411,8 +412,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];
}
......@@ -429,14 +428,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
......@@ -508,6 +500,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;
......@@ -646,7 +644,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);
......@@ -834,15 +832,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
......@@ -1314,12 +1332,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
......@@ -1327,10 +1348,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;
......@@ -1401,7 +1418,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);
}
}
......
......@@ -20,6 +20,7 @@
414396C22023316C005E3FAF /* AppearanceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414396C12023316C005E3FAF /* AppearanceManager.swift */; };
4144C4661A0ED6C700918C89 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D3784E6183A99E1009EE944 /* Reachability.m */; };
4152F1621FEF19BD00F1908B /* KeychainCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */; };
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 */; };
......@@ -491,6 +492,7 @@
4142AB4420A31EC500039380 /* VLCMediaDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VLCMediaDataSource.swift; path = Sources/VLCMediaDataSource.swift; sourceTree = "<group>"; };
414396C12023316C005E3FAF /* AppearanceManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppearanceManager.swift; path = Sources/AppearanceManager.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>"; };
417CDA201A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCCloudServicesTableViewController.h; path = Sources/VLCCloudServicesTableViewController.h; sourceTree = SOURCE_ROOT; };
417CDA211A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCCloudServicesTableViewController.m; path = Sources/VLCCloudServicesTableViewController.m; sourceTree = SOURCE_ROOT; };
......@@ -1542,6 +1544,7 @@
7D5F7AB9175265B2006CCCFA /* Playback */ = {
isa = PBXGroup;
children = (
416443852048419E00CAC646 /* DeviceMotion.swift */,
DD8F842F1B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.h */,
DD8F84301B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m */,
7D37848D183A98B6009EE944 /* VLCMovieViewController.h */,
......@@ -2474,7 +2477,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = VLC;
LastSwiftUpdateCheck = 0720;
LastSwiftUpdateCheck = 0930;
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = VideoLAN;
TargetAttributes = {
......@@ -3119,6 +3122,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 */,
4142AB4520A31EC500039380 /* VLCMediaDataSource.swift in Sources */,
7D95610B1AF3E9E800779745 /* VLCMiniPlaybackView.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