VLCAppDelegate.m 15.3 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * VLCAppDelegate.m
 * VLC for iOS
 *****************************************************************************
Felix Paul Kühne's avatar
Felix Paul Kühne committed
5
 * Copyright (c) 2013-2015 VideoLAN. All rights reserved.
6 7 8 9 10 11 12
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan.org>
 *          Gleb Pinigin <gpinigin # gmail.com>
 *          Jean-Romain Prévost <jr # 3on.fr>
 *          Luis Fernandes <zipleen # gmail.com>
 *          Carola Nitz <nitz.carola # googlemail.com>
13
 *          Tamas Timar <ttimar.vlc # gmail.com>
Tobias's avatar
Tobias committed
14
 *          Tobias Conradi <videolan # tobias-conradi.de>
15
 *          Soomin Lee <TheHungryBu # gmail.com>
16 17 18
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
Felix Paul Kühne's avatar
Felix Paul Kühne committed
19 20

#import "VLCAppDelegate.h"
21
#import "VLCMediaFileDiscoverer.h"
22
#import "NSString+SupportedMedia.h"
Felix Paul Kühne's avatar
Felix Paul Kühne committed
23
#import "UIDevice+VLC.h"
24
#import "VLCHTTPUploaderController.h"
25
#import "VLCMigrationViewController.h"
26
#import "VLCPlaybackController.h"
27
#import "VLCPlaybackController+MediaLibrary.h"
Tobias's avatar
Tobias committed
28
#import <MediaPlayer/MediaPlayer.h>
Felix Paul Kühne's avatar
Felix Paul Kühne committed
29
#import <HockeySDK/HockeySDK.h>
30
#import "VLCActivityManager.h"
31
#import "VLCDropboxConstants.h"
32
#import "VLCPlaybackNavigationController.h"
33
#import "PAPasscodeViewController.h"
34
#import "VLC-Swift.h"
35

Felix Paul Kühne's avatar
Felix Paul Kühne committed
36 37
#define BETA_DISTRIBUTION 1

38 39
@interface VLCAppDelegate () <VLCMediaFileDiscovererDelegate>
{
40
    BOOL _isRunningMigration;
Carola Nitz's avatar
Carola Nitz committed
41
    BOOL _isComingFromHandoff;
42
    VLCKeychainCoordinator *_keychainCoordinator;
43 44
    AppCoordinator *appCoordinator;
    UITabBarController *rootViewController;
Gleb Pinigin's avatar
Gleb Pinigin committed
45
}
46 47

@end
Felix Paul Kühne's avatar
Felix Paul Kühne committed
48 49 50

@implementation VLCAppDelegate

51 52 53 54
+ (void)initialize
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

55 56
    NSDictionary *appDefaults = @{kVLCSettingPasscodeAllowFaceID : @(1),
                                  kVLCSettingPasscodeAllowTouchID : @(1),
Felix Paul Kühne's avatar
Felix Paul Kühne committed
57 58 59
                                  kVLCSettingContinueAudioInBackgroundKey : @(YES),
                                  kVLCSettingStretchAudio : @(NO),
                                  kVLCSettingTextEncoding : kVLCSettingTextEncodingDefaultValue,
60
                                  kVLCSettingSkipLoopFilter : kVLCSettingSkipLoopFilterNonRef,
Felix Paul Kühne's avatar
Felix Paul Kühne committed
61 62 63 64 65
                                  kVLCSettingSubtitlesFont : kVLCSettingSubtitlesFontDefaultValue,
                                  kVLCSettingSubtitlesFontColor : kVLCSettingSubtitlesFontColorDefaultValue,
                                  kVLCSettingSubtitlesFontSize : kVLCSettingSubtitlesFontSizeDefaultValue,
                                  kVLCSettingSubtitlesBoldFont: kVLCSettingSubtitlesBoldFontDefaultValue,
                                  kVLCSettingDeinterlace : kVLCSettingDeinterlaceDefaultValue,
66
                                  kVLCSettingHardwareDecoding : kVLCSettingHardwareDecodingDefault,
Felix Paul Kühne's avatar
Felix Paul Kühne committed
67
                                  kVLCSettingNetworkCaching : kVLCSettingNetworkCachingDefaultValue,
68 69 70 71 72 73
                                  kVLCSettingVolumeGesture : @(YES),
                                  kVLCSettingPlayPauseGesture : @(YES),
                                  kVLCSettingBrightnessGesture : @(YES),
                                  kVLCSettingSeekGesture : @(YES),
                                  kVLCSettingCloseGesture : @(YES),
                                  kVLCSettingVariableJumpDuration : @(NO),
74
                                  kVLCSettingVideoFullscreenPlayback : @(YES),
75
                                  kVLCSettingContinuePlayback : @(1),
76
                                  kVLCSettingContinueAudioPlayback : @(1),
Felix Paul Kühne's avatar
Felix Paul Kühne committed
77 78 79 80 81
                                  kVLCSettingFTPTextEncoding : kVLCSettingFTPTextEncodingDefaultValue,
                                  kVLCSettingWiFiSharingIPv6 : kVLCSettingWiFiSharingIPv6DefaultValue,
                                  kVLCSettingEqualizerProfile : kVLCSettingEqualizerProfileDefaultValue,
                                  kVLCSettingPlaybackForwardSkipLength : kVLCSettingPlaybackForwardSkipLengthDefaultValue,
                                  kVLCSettingPlaybackBackwardSkipLength : kVLCSettingPlaybackBackwardSkipLengthDefaultValue,
82 83
                                  kVLCSettingOpenAppForPlayback : kVLCSettingOpenAppForPlaybackDefaultValue,
                                  kVLCAutomaticallyPlayNextItem : @(YES)};
84 85 86
    [defaults registerDefaults:appDefaults];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
87 88
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
89
    BITHockeyManager *hockeyManager = [BITHockeyManager sharedHockeyManager];
90 91 92
    [hockeyManager configureWithBetaIdentifier:@"0114ca8e265244ce588d2ebd035c3577"
                                liveIdentifier:@"c95f4227dff96c61f8b3a46a25edc584"
                                      delegate:nil];
93
    [hockeyManager startManager];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
94

95 96 97
    // Configure Dropbox
    [DBClientsManager setupWithAppKey:kVLCDropboxAppKey];

98
    [VLCApperanceManager setupAppearanceWithTheme:PresentationTheme.current];
99

Felix Paul Kühne's avatar
Felix Paul Kühne committed
100
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
101 102 103
    rootViewController = [UITabBarController new];
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
104
    // enable crash preventer
105 106 107 108
    void (^setupBlock)(void) = ^{
        void (^setupLibraryBlock)(void) = ^{
            self->appCoordinator = [[AppCoordinator alloc] initWithTabBarController:self->rootViewController];
            [self->appCoordinator start];
109 110
        };
        [self validatePasscodeIfNeededWithCompletion:setupLibraryBlock];
111

112
        BOOL spotlightEnabled = ![VLCKeychainCoordinator passcodeLockEnabled];
113
        [[MLMediaLibrary sharedMediaLibrary] setSpotlightIndexingEnabled:spotlightEnabled];
114 115
        [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];

116
        VLCMediaFileDiscoverer *discoverer = [VLCMediaFileDiscoverer sharedInstance];
117 118
        NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        discoverer.directoryPath = [searchPaths firstObject];
119
        [discoverer addObserver:self];
120
        [discoverer startDiscovering];
121 122 123
    };

    NSError *error = nil;
124 125

    if ([[MLMediaLibrary sharedMediaLibrary] libraryMigrationNeeded]){
126 127 128 129
        _isRunningMigration = YES;

        VLCMigrationViewController *migrationController = [[VLCMigrationViewController alloc] initWithNibName:@"VLCMigrationViewController" bundle:nil];
        migrationController.completionHandler = ^{
130

131 132
            //migrate
            setupBlock();
133
            self->_isRunningMigration = NO;
134
            [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
135
            [[VLCMediaFileDiscoverer sharedInstance] updateMediaList];
136
        };
Felix Paul Kühne's avatar
Felix Paul Kühne committed
137

138 139
        self.window.rootViewController = migrationController;
        [self.window makeKeyAndVisible];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
140

141 142
    } else {
        if (error != nil) {
143
            APLog(@"removed persistentStore since it was corrupt");
144 145 146 147 148
            NSURL *storeURL = ((MLMediaLibrary *)[MLMediaLibrary sharedMediaLibrary]).persistentStoreURL;
            [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
        }
        setupBlock();
    }
149

150
    /* add our static shortcut items the dynamic way to ease l10n and dynamic elements to be introduced later */
151
    if (@available(iOS 9, *)) {
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        if (application.shortcutItems == nil || application.shortcutItems.count < 4) {
            UIApplicationShortcutItem *localLibraryItem = [[UIApplicationShortcutItem alloc] initWithType:kVLCApplicationShortcutLocalLibrary
                                                                                           localizedTitle:NSLocalizedString(@"SECTION_HEADER_LIBRARY",nil)
                                                                                        localizedSubtitle:nil
                                                                                                     icon:[UIApplicationShortcutIcon iconWithTemplateImageName:@"AllFiles"]
                                                                                                 userInfo:nil];
            UIApplicationShortcutItem *localServerItem = [[UIApplicationShortcutItem alloc] initWithType:kVLCApplicationShortcutLocalServers
                                                                                           localizedTitle:NSLocalizedString(@"LOCAL_NETWORK",nil)
                                                                                        localizedSubtitle:nil
                                                                                                     icon:[UIApplicationShortcutIcon iconWithTemplateImageName:@"Local"]
                                                                                                 userInfo:nil];
            UIApplicationShortcutItem *openNetworkStreamItem = [[UIApplicationShortcutItem alloc] initWithType:kVLCApplicationShortcutOpenNetworkStream
                                                                                           localizedTitle:NSLocalizedString(@"OPEN_NETWORK",nil)
                                                                                        localizedSubtitle:nil
                                                                                                     icon:[UIApplicationShortcutIcon iconWithTemplateImageName:@"OpenNetStream"]
                                                                                                 userInfo:nil];
            UIApplicationShortcutItem *cloudsItem = [[UIApplicationShortcutItem alloc] initWithType:kVLCApplicationShortcutClouds
                                                                                           localizedTitle:NSLocalizedString(@"CLOUD_SERVICES",nil)
                                                                                        localizedSubtitle:nil
                                                                                                     icon:[UIApplicationShortcutIcon iconWithTemplateImageName:@"iCloudIcon"]
                                                                                                 userInfo:nil];
            application.shortcutItems = @[localLibraryItem, localServerItem, openNetworkStreamItem, cloudsItem];
        }
    }

177 178
    return YES;
}
179

Carola Nitz's avatar
Carola Nitz committed
180 181
#pragma mark - Handoff

182 183
- (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType
{
184 185 186
    if ([userActivityType isEqualToString:kVLCUserActivityLibraryMode] ||
        [userActivityType isEqualToString:kVLCUserActivityPlaying] ||
        [userActivityType isEqualToString:kVLCUserActivityLibrarySelection])
Carola Nitz's avatar
Carola Nitz committed
187
        return YES;
188

Carola Nitz's avatar
Carola Nitz committed
189 190 191
    return NO;
}

192 193 194 195 196
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray *))restorationHandler
{
    NSString *userActivityType = userActivity.activityType;
197 198 199
    NSDictionary *dict = userActivity.userInfo;
    if([userActivityType isEqualToString:kVLCUserActivityLibraryMode] ||
       [userActivityType isEqualToString:kVLCUserActivityLibrarySelection]) {
200
        //TODO: Add restoreUserActivityState to the mediaviewcontroller
Carola Nitz's avatar
Carola Nitz committed
201
        _isComingFromHandoff = YES;
Carola Nitz's avatar
Carola Nitz committed
202
        return YES;
203
    } else {
Tobias's avatar
Tobias committed
204 205 206 207 208 209 210 211 212 213 214
        NSURL *uriRepresentation = nil;
        if ([userActivityType isEqualToString:CSSearchableItemActionType]) {
            uriRepresentation = [NSURL URLWithString:dict[CSSearchableItemActivityIdentifier]];
        } else {
            uriRepresentation = dict[@"playingmedia"];
        }

        if (!uriRepresentation) {
            return NO;
        }

215 216 217 218 219 220 221
        NSManagedObject *managedObject = [[MLMediaLibrary sharedMediaLibrary] objectForURIRepresentation:uriRepresentation];
        if (managedObject == nil) {
            APLog(@"%s file not found: %@",__PRETTY_FUNCTION__,userActivity);
            return NO;
        }
        [[VLCPlaybackController sharedInstance] openMediaLibraryObject:managedObject];
        return YES;
Carola Nitz's avatar
Carola Nitz committed
222 223 224 225
    }
    return NO;
}

226 227 228
- (void)application:(UIApplication *)application
didFailToContinueUserActivityWithType:(NSString *)userActivityType
              error:(NSError *)error
Carola Nitz's avatar
Carola Nitz committed
229 230 231 232 233 234
{
    if (error.code != NSUserCancelledError){
        //TODO: present alert
    }
}

Carola Nitz's avatar
Carola Nitz committed
235
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
236
{
237 238 239 240 241
    for (id<VLCURLHandler> handler in URLHandlers.handlers) {
        if ([handler canHandleOpenWithUrl:url options:options]) {
            if ([handler performOpenWithUrl:url options:options]) {
                break;
            }
242
        }
243
    }
244 245 246
    return NO;
}

247 248 249 250 251
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
252 253
- (void)applicationWillResignActive:(UIApplication *)application
{
254 255 256 257 258 259 260 261
    //Touch ID is shown 
    if ([_window.rootViewController.presentedViewController isKindOfClass:[UINavigationController class]]){
        UINavigationController *navCon = (UINavigationController *)_window.rootViewController.presentedViewController;
        if ([navCon.topViewController isKindOfClass:[PAPasscodeViewController class]]){
            return;
        }
    }
    [self validatePasscodeIfNeededWithCompletion:^{
262
        //TODO: handle updating the videoview and
263
        if ([VLCPlaybackController sharedInstance].isPlaying){
264
            //TODO: push playback
265 266
        }
    }];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
267 268 269 270 271
    [[MLMediaLibrary sharedMediaLibrary] applicationWillExit];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
Carola Nitz's avatar
Carola Nitz committed
272
    if (!_isRunningMigration && !_isComingFromHandoff) {
273
        [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
274 275
      //  [[VLCMediaFileDiscoverer sharedInstance] updateMediaList];
        [[VLCPlaybackController sharedInstance] recoverDisplayedMetadata];
Carola Nitz's avatar
Carola Nitz committed
276 277
    } else if(_isComingFromHandoff) {
        _isComingFromHandoff = NO;
278
    }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
279 280
}

281 282
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
283
    //TODO: shortcutItem should be implemented
284 285
}

286
#pragma mark - media discovering
287

288 289
- (void)mediaFileAdded:(NSString *)fileName loading:(BOOL)isLoading
{
290 291 292
    if (!isLoading) {
        MLMediaLibrary *sharedLibrary = [MLMediaLibrary sharedMediaLibrary];
        [sharedLibrary addFilePaths:@[fileName]];
293

294 295 296
        /* exclude media files from backup (QA1719) */
        NSURL *excludeURL = [NSURL fileURLWithPath:fileName];
        [excludeURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
297

298 299
        // TODO Should we update media db after adding new files?
        [sharedLibrary updateMediaDatabase];
300
        // TODO: update the VideoViewController
301 302 303
    }
}

304 305
- (void)mediaFileDeleted:(NSString *)name
{
306
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
307
   // TODO: update the VideoViewController
308 309
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
310
- (void)mediaFilesFoundRequiringAdditionToStorageBackend:(NSArray<NSString *> *)foundFiles
311 312
{
    [[MLMediaLibrary sharedMediaLibrary] addFilePaths:foundFiles];
313
  // TODO: update the VideoViewController
314 315
}

316
#pragma mark - pass code validation
317 318 319 320 321 322 323
- (VLCKeychainCoordinator *)keychainCoordinator
{
    if (!_keychainCoordinator) {
        _keychainCoordinator = [[VLCKeychainCoordinator alloc] init];
    }
    return _keychainCoordinator;
}
324

325
- (void)validatePasscodeIfNeededWithCompletion:(void(^)(void))completion
326
{
327
    if ([VLCKeychainCoordinator passcodeLockEnabled]) {
328
        //TODO: Dimiss playback
329
        [self.keychainCoordinator validatePasscodeWithCompletion:completion];
330
    } else {
331
        completion();
332
    }
333 334
}

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