VLCOneDriveController.m 9.12 KB
Newer Older
Felix Paul Kühne's avatar
Felix Paul Kühne committed
1 2 3 4
/*****************************************************************************
 * VLCOneDriveController.m
 * VLC for iOS
 *****************************************************************************
5
 * Copyright (c) 2014-2015 VideoLAN. All rights reserved.
Felix Paul Kühne's avatar
Felix Paul Kühne committed
6 7 8 9 10 11 12 13 14
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan.org>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/

#import "VLCOneDriveController.h"
#import "VLCOneDriveConstants.h"
15
#import "VLCOneDriveObject.h"
Felix Paul Kühne's avatar
Felix Paul Kühne committed
16 17

/* the Live SDK doesn't have an umbrella header so we need to import what we need */
18
#import "LiveConnectClient.h"
Felix Paul Kühne's avatar
Felix Paul Kühne committed
19 20

/* include private API headers */
21
#import "LiveApiHelper.h"
22
#import "LiveAuthStorage.h"
Felix Paul Kühne's avatar
Felix Paul Kühne committed
23

24
@interface VLCOneDriveController () <LiveAuthDelegate, VLCOneDriveObjectDelegate, VLCOneDriveObjectDownloadDelegate>
Felix Paul Kühne's avatar
Felix Paul Kühne committed
25 26
{
    LiveConnectClient *_liveClient;
27
    NSString *_folderId;
Felix Paul Kühne's avatar
Felix Paul Kühne committed
28
    NSArray *_liveScopes;
29
    BOOL _activeSession;
30
    BOOL _userAuthenticated;
31 32 33 34 35 36 37 38

    NSMutableArray *_pendingDownloads;
    BOOL _downloadInProgress;

    CGFloat _averageSpeed;
    CGFloat _fileSize;
    NSTimeInterval _startDL;
    NSTimeInterval _lastStatsUpdate;
Felix Paul Kühne's avatar
Felix Paul Kühne committed
39 40 41 42 43 44
}

@end

@implementation VLCOneDriveController

45
+ (VLCCloudStorageController *)sharedInstance
Felix Paul Kühne's avatar
Felix Paul Kühne committed
46 47 48 49 50
{
    static VLCOneDriveController *sharedInstance = nil;
    static dispatch_once_t pred;

    dispatch_once(&pred, ^{
51
        sharedInstance = [[VLCOneDriveController alloc] init];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
52 53 54 55 56 57 58 59 60 61 62 63
    });

    return sharedInstance;
}

- (instancetype)init
{
    self = [super init];

    if (!self)
        return self;

64 65 66 67 68 69 70
    [self setupSession];

    return self;
}

- (void)setupSession
{
71 72
    [self restoreFromSharedCredentials];

73
    _liveScopes = @[@"wl.signin",@"wl.offline_access",@"wl.skydrive"];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
74 75

    _liveClient = [[LiveConnectClient alloc] initWithClientId:kVLCOneDriveClientID
76
                                                       scopes:_liveScopes
Felix Paul Kühne's avatar
Felix Paul Kühne committed
77 78 79 80 81 82
                                                     delegate:self
                                                    userState:@"init"];
}

#pragma mark - authentication

83 84 85 86 87
- (BOOL)activeSession
{
    return _activeSession;
}

88
- (void)loginWithViewController:(UIViewController *)presentingViewController
Felix Paul Kühne's avatar
Felix Paul Kühne committed
89
{
90
    [_liveClient login:presentingViewController
91 92 93
                scopes:_liveScopes
              delegate:self
             userState:@"login"];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
94 95 96 97 98
}

- (void)logout
{
    [_liveClient logoutWithDelegate:self userState:@"logout"];
99 100

    NSUbiquitousKeyValueStore *ubiquitousStore = [NSUbiquitousKeyValueStore defaultStore];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
101
    [ubiquitousStore removeObjectForKey:kVLCStoreOneDriveCredentials];
102 103
    [ubiquitousStore synchronize];

104
    _activeSession = NO;
105
    _userAuthenticated = NO;
106 107 108
    _currentFolder = nil;
    if ([self.delegate respondsToSelector:@selector(mediaListUpdated)])
        [self.delegate mediaListUpdated];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
109 110
}

111 112 113 114 115 116 117 118 119 120
- (NSArray *)currentListFiles
{
    return _currentFolder.items;
}

- (BOOL)isAuthorized
{
    return _liveClient.session != NULL;
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
121 122
- (void)authCompleted:(LiveConnectSessionStatus)status session:(LiveConnectSession *)session userState:(id)userState
{
123
    APLog(@"OneDrive: authCompleted, status %i, state %@", status, userState);
124

125
    if (session != NULL && [userState isEqualToString:@"init"] && status == 1)
126
        _activeSession = YES;
127

128
    if (session != NULL && [userState isEqualToString:@"login"] && status == 1)
129
        _userAuthenticated = YES;
130 131 132

    if (status == 0) {
        _activeSession = NO;
133
        _userAuthenticated = NO;
134
    }
135 136 137 138 139

    if (self.delegate) {
        if ([self.delegate respondsToSelector:@selector(sessionWasUpdated)])
            [self.delegate performSelector:@selector(sessionWasUpdated)];
    }
140
    [[NSNotificationCenter defaultCenter] postNotificationName:VLCOneDriveControllerSessionUpdated object:self];
141 142

    [self shareCredentials];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
143 144 145 146
}

- (void)authFailed:(NSError *)error userState:(id)userState
{
147 148
    APLog(@"OneDrive auth failed: %@, %@", error, userState);
    _activeSession = NO;
149 150 151 152 153

    if (self.delegate) {
        if ([self.delegate respondsToSelector:@selector(sessionWasUpdated)])
            [self.delegate performSelector:@selector(sessionWasUpdated)];
    }
154
    [[NSNotificationCenter defaultCenter] postNotificationName:VLCOneDriveControllerSessionUpdated object:self];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
155 156
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
- (void)shareCredentials
{
    /* share our credentials */
    LiveAuthStorage *authStorage = [[LiveAuthStorage alloc] initWithClientId:kVLCOneDriveClientID];
    NSString *credentials = [authStorage refreshToken];
    if (credentials == nil)
        return;

    NSUbiquitousKeyValueStore *ubiquitousStore = [NSUbiquitousKeyValueStore defaultStore];
    [ubiquitousStore setString:credentials forKey:kVLCStoreOneDriveCredentials];
    [ubiquitousStore synchronize];
}

- (BOOL)restoreFromSharedCredentials
{
    LiveAuthStorage *authStorage = [[LiveAuthStorage alloc] initWithClientId:kVLCOneDriveClientID];
    NSUbiquitousKeyValueStore *ubiquitousStore = [NSUbiquitousKeyValueStore defaultStore];
    [ubiquitousStore synchronize];
    NSString *credentials = [ubiquitousStore stringForKey:kVLCStoreOneDriveCredentials];
    if (!credentials)
        return NO;

    [authStorage setRefreshToken:credentials];
    return YES;
}

183 184 185 186 187 188 189 190 191 192
- (void)liveOperationSucceeded:(LiveDownloadOperation *)operation
{
    APLog(@"ODC: liveOperationSucceeded (%@)", operation.userState);
}

- (void)liveOperationFailed:(NSError *)error operation:(LiveDownloadOperation *)operation
{
    APLog(@"ODC: liveOperationFailed %@ (%@)", error, operation.userState);
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
193 194
#pragma mark - listing

195 196 197 198 199
- (void)requestDirectoryListingAtPath:(NSString *)path
{
    [self loadCurrentFolder];
}

200
- (void)loadTopLevelFolder
Felix Paul Kühne's avatar
Felix Paul Kühne committed
201
{
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
    _rootFolder = [[VLCOneDriveObject alloc] init];
    _rootFolder.objectId = @"me/skydrive";
    _rootFolder.name = @"OneDrive";
    _rootFolder.type = @"folder";
    _rootFolder.liveClient = _liveClient;
    _rootFolder.delegate = self;

    _currentFolder = _rootFolder;
    [_rootFolder loadFolderContent];
}

- (void)loadCurrentFolder
{
    if (_currentFolder == nil)
        [self loadTopLevelFolder];
    else {
        _currentFolder.delegate = self;
        [_currentFolder loadFolderContent];
    }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
221 222 223 224
}

#pragma mark - file handling

225 226 227 228 229
- (BOOL)canPlayAll
{
    return YES;
}

230
- (void)downloadObject:(VLCOneDriveObject *)object
Felix Paul Kühne's avatar
Felix Paul Kühne committed
231
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
232 233
    if (object == nil)
        return;
234 235 236 237 238 239 240 241 242
    if (object.isFolder)
        return;

    object.downloadDelegate = self;
    if (!_pendingDownloads)
        _pendingDownloads = [[NSMutableArray alloc] init];
    [_pendingDownloads addObject:object];

    [self _triggerNextDownload];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
243 244
}

245
- (void)_triggerNextDownload
Felix Paul Kühne's avatar
Felix Paul Kühne committed
246
{
247 248 249 250 251 252 253 254
    if (_pendingDownloads.count > 0 && !_downloadInProgress) {
        _downloadInProgress = YES;
        [_pendingDownloads[0] saveObjectToDocuments];
        [_pendingDownloads removeObjectAtIndex:0];

        if ([self.delegate respondsToSelector:@selector(numberOfFilesWaitingToBeDownloadedChanged)])
            [self.delegate numberOfFilesWaitingToBeDownloadedChanged];
    }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
255 256
}

257
- (void)downloadStarted:(VLCOneDriveObject *)object
Felix Paul Kühne's avatar
Felix Paul Kühne committed
258
{
259 260 261
    _startDL = [NSDate timeIntervalSinceReferenceDate];
    if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStarted)])
        [self.delegate operationWithProgressInformationStarted];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
262 263
}

264 265
- (void)downloadEnded:(VLCOneDriveObject *)object
{
266 267
    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, NSLocalizedString(@"GDRIVE_DOWNLOAD_SUCCESSFUL", nil));

268 269
    if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStopped)])
        [self.delegate operationWithProgressInformationStopped];
270

271 272 273 274 275
    _downloadInProgress = NO;
    [self _triggerNextDownload];
}

- (void)progressUpdated:(CGFloat)progress
276
{
277 278
    if ([self.delegate respondsToSelector:@selector(currentProgressInformation:)])
        [self.delegate currentProgressInformation:progress];
279 280
}

281
- (void)calculateRemainingTime:(CGFloat)receivedDataSize expectedDownloadSize:(CGFloat)expectedDownloadSize
282
{
283 284 285 286 287 288 289 290 291 292 293 294 295 296
    CGFloat lastSpeed = receivedDataSize / ([NSDate timeIntervalSinceReferenceDate] - _startDL);
    CGFloat smoothingFactor = 0.005;
    _averageSpeed = isnan(_averageSpeed) ? lastSpeed : smoothingFactor * lastSpeed + (1 - smoothingFactor) * _averageSpeed;

    CGFloat RemainingInSeconds = (expectedDownloadSize - receivedDataSize)/_averageSpeed;

    NSDate *date = [NSDate dateWithTimeIntervalSince1970:RemainingInSeconds];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"HH:mm:ss"];
    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

    NSString  *remaingTime = [formatter stringFromDate:date];
    if ([self.delegate respondsToSelector:@selector(updateRemainingTime:)])
        [self.delegate updateRemainingTime:remaingTime];
297 298
}

299 300 301
#pragma mark - onedrive object delegation

- (void)folderContentLoaded:(VLCOneDriveObject *)sender
302
{
303 304
    if (self.delegate)
        [self.delegate performSelector:@selector(mediaListUpdated)];
305 306
}

307
- (void)folderContentLoadingFailed:(NSError *)error sender:(VLCOneDriveObject *)sender
308
{
309
    APLog(@"folder content loading failed %@", error);
310 311 312 313 314 315 316 317
}

- (void)fullFolderTreeLoaded:(VLCOneDriveObject *)sender
{
    if (self.delegate)
        [self.delegate performSelector:@selector(mediaListUpdated)];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
318
@end