VLCAppDelegate.m 14.2 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-2014 VideoLAN. All rights reserved.
6 7 8 9 10 11 12 13 14 15
 * $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>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
Felix Paul Kühne's avatar
Felix Paul Kühne committed
16 17

#import "VLCAppDelegate.h"
18
#import "VLCMediaFileDiscoverer.h"
19
#import "NSString+SupportedMedia.h"
20
#import "UIDevice+SpeedCategory.h"
Felix Paul Kühne's avatar
Felix Paul Kühne committed
21 22

#import "VLCPlaylistViewController.h"
23
#import "VLCMovieViewController.h"
24
#import "PAPasscodeViewController.h"
25
#import "UINavigationController+Theme.h"
26
#import "VLCHTTPUploaderController.h"
27
#import "VLCMenuTableViewController.h"
28
#import "BWQuincyManager.h"
29

30
@interface VLCAppDelegate () <PAPasscodeViewControllerDelegate, VLCMediaFileDiscovererDelegate, BWQuincyManagerDelegate> {
Gleb Pinigin's avatar
Gleb Pinigin committed
31
    PAPasscodeViewController *_passcodeLockController;
32
    VLCDropboxTableViewController *_dropboxTableViewController;
Carola Nitz's avatar
Carola Nitz committed
33
    VLCGoogleDriveTableViewController *_googleDriveTableViewController;
34
    VLCDownloadViewController *_downloadViewController;
35
    int _idleCounter;
36
    VLCMovieViewController *_movieViewController;
Gleb Pinigin's avatar
Gleb Pinigin committed
37
}
38 39 40 41

@property (nonatomic) BOOL passcodeValidated;

@end
Felix Paul Kühne's avatar
Felix Paul Kühne committed
42 43 44

@implementation VLCAppDelegate

45 46 47 48
+ (void)initialize
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

49 50 51 52 53
    NSNumber *skipLoopFilterDefaultValue;
    int deviceSpeedCategory = [[UIDevice currentDevice] speedCategory];
    if (deviceSpeedCategory < 3)
        skipLoopFilterDefaultValue = kVLCSettingSkipLoopFilterNonKey;
    else
54
        skipLoopFilterDefaultValue = kVLCSettingSkipLoopFilterNonRef;
55

56
    NSDictionary *appDefaults = @{kVLCSettingPasscodeKey : @"", kVLCSettingPasscodeOnKey : @(NO), kVLCSettingContinueAudioInBackgroundKey : @(YES), kVLCSettingStretchAudio : @(NO), kVLCSettingTextEncoding : kVLCSettingTextEncodingDefaultValue, kVLCSettingSkipLoopFilter : skipLoopFilterDefaultValue, kVLCSettingSubtitlesFont : kVLCSettingSubtitlesFontDefaultValue, kVLCSettingSubtitlesFontColor : kVLCSettingSubtitlesFontColorDefaultValue, kVLCSettingSubtitlesFontSize : kVLCSettingSubtitlesFontSizeDefaultValue, kVLCSettingDeinterlace : kVLCSettingDeinterlaceDefaultValue};
57 58 59 60

    [defaults registerDefaults:appDefaults];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
61 62
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
63 64 65 66 67
    BWQuincyManager *quincyManager = [BWQuincyManager sharedQuincyManager];
    [quincyManager setSubmissionURL:@"http://crash.videolan.org/crash_v200.php"];
    [quincyManager setDelegate:self];
    [quincyManager setShowAlwaysButton:YES];
    [quincyManager setFeedbackActivated:YES];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
68

69 70
    /* clean caches on launch (since those are used for wifi upload only) */
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
71
    NSString* uploadDirPath = [searchPaths[0] stringByAppendingPathComponent:@"Upload"];
72 73 74 75
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:uploadDirPath])
        [fileManager removeItemAtPath:uploadDirPath error:nil];

76 77 78
    // Init the HTTP Server
    self.uploadController = [[VLCHTTPUploaderController alloc] init];

79 80 81
    // enable crash preventer
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];

Felix Paul Kühne's avatar
Felix Paul Kühne committed
82
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
83

84
    _playlistViewController = [[VLCPlaylistViewController alloc] init];
85 86
    UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_playlistViewController];
    [navCon loadTheme];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
87

88
    _revealController = [[GHRevealViewController alloc] initWithNibName:nil bundle:nil];
89
    _revealController.wantsFullScreenLayout = YES;
90 91
    _menuViewController = [[VLCMenuTableViewController alloc] initWithNibName:nil bundle:nil];
    _revealController.sidebarViewController = _menuViewController;
92
    _revealController.contentViewController = navCon;
93

94
    self.window.rootViewController = self.revealController;
95 96
    // necessary to avoid navbar blinking in VLCOpenNetworkStreamViewController & VLCDownloadViewController
    _revealController.contentViewController.view.backgroundColor = [UIColor colorWithWhite:.122 alpha:1.];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
97
    [self.window makeKeyAndVisible];
98

99 100 101
    VLCMediaFileDiscoverer *discoverer = [VLCMediaFileDiscoverer sharedInstance];
    [discoverer addObserver:self];
    [discoverer startDiscovering:[self directoryPath]];
102

103
    [self validatePasscode];
104

Felix Paul Kühne's avatar
Felix Paul Kühne committed
105 106 107
    return YES;
}

108 109
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
110 111 112 113 114
    if ([[DBSession sharedSession] handleOpenURL:url]) {
        [self.dropboxTableViewController updateViewAfterSessionChange];
        return YES;
    }

115 116
    if (_playlistViewController && url != nil) {
        APLog(@"%@ requested %@ to be opened", sourceApplication, url);
117

118
        if (url.isFileURL) {
119 120 121 122 123 124
            NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *directoryPath = searchPaths[0];
            NSURL *destinationURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", directoryPath, url.lastPathComponent]];
            NSError *theError;
            [[NSFileManager defaultManager] moveItemAtURL:url toURL:destinationURL error:&theError];
            if (theError.code != noErr)
125
                APLog(@"saving the file failed (%li): %@", theError.code, theError.localizedDescription);
126 127

            [self updateMediaList];
Luis's avatar
Luis committed
128
        } else {
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
            NSString *receivedUrl = [url absoluteString];
            if ([receivedUrl length] > 6) {
                NSString *verifyVlcUrl = [receivedUrl substringToIndex:6];
                if ([verifyVlcUrl isEqualToString:@"vlc://"]) {
                    NSString *parsedString = [receivedUrl substringFromIndex:6];
                    NSUInteger location = [parsedString rangeOfString:@"//"].location;

                    /* Safari & al mangle vlc://http:// so fix this */
                    if (location != NSNotFound && [parsedString characterAtIndex:location - 1] != 0x3a) { // :
                            parsedString = [NSString stringWithFormat:@"%@://%@", [parsedString substringToIndex:location], [parsedString substringFromIndex:location+2]];
                    } else
                        parsedString = [@"http://" stringByAppendingString:[receivedUrl substringFromIndex:6]];

                    url = [NSURL URLWithString:parsedString];
                }
            }
145
            [self.menuViewController selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
146
            [self openMovieFromURL:url];
Luis's avatar
Luis committed
147
        }
148 149 150 151 152
        return YES;
    }
    return NO;
}

153 154 155
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];
156
    [self validatePasscode];
157 158
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
159 160
- (void)applicationWillResignActive:(UIApplication *)application
{
161
    self.passcodeValidated = NO;
162
    [self validatePasscode];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
163 164 165 166 167
    [[MLMediaLibrary sharedMediaLibrary] applicationWillExit];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
168
    [self validatePasscode];
169
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
170 171 172
    [self updateMediaList];
}

173 174
- (void)applicationWillTerminate:(UIApplication *)application
{
175
    self.passcodeValidated = NO;
176 177 178
    [[NSUserDefaults standardUserDefaults] synchronize];
}

179 180 181 182
#pragma mark - properties

- (VLCDropboxTableViewController *)dropboxTableViewController
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
183
    if (_dropboxTableViewController == nil)
184
        _dropboxTableViewController = [[VLCDropboxTableViewController alloc] initWithNibName:@"VLCCloudStorageTableViewController" bundle:nil];
185 186 187 188

    return _dropboxTableViewController;
}

Carola Nitz's avatar
Carola Nitz committed
189 190
- (VLCGoogleDriveTableViewController *)googleDriveTableViewController
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
191
    if (_googleDriveTableViewController == nil)
192
        _googleDriveTableViewController = [[VLCGoogleDriveTableViewController alloc] initWithNibName:@"VLCCloudStorageTableViewController" bundle:nil];
Carola Nitz's avatar
Carola Nitz committed
193 194 195 196 197

    return _googleDriveTableViewController;
}


198 199
- (VLCDownloadViewController *)downloadViewController
{
200 201 202 203 204 205
    if (_downloadViewController == nil) {
        if (SYSTEM_RUNS_IOS7_OR_LATER)
            _downloadViewController = [[VLCDownloadViewController alloc] initWithNibName:@"VLCFutureDownloadViewController" bundle:nil];
        else
            _downloadViewController = [[VLCDownloadViewController alloc] initWithNibName:@"VLCDownloadViewController" bundle:nil];
    }
206 207 208 209

    return _downloadViewController;
}

210
#pragma mark - media discovering
211

212 213 214 215
- (void)mediaFileAdded:(NSString *)fileName loading:(BOOL)isLoading {
    if (!isLoading) {
        MLMediaLibrary *sharedLibrary = [MLMediaLibrary sharedMediaLibrary];
        [sharedLibrary addFilePaths:@[fileName]];
216

217 218 219
        /* exclude media files from backup (QA1719) */
        NSURL *excludeURL = [NSURL fileURLWithPath:fileName];
        [excludeURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
220

221 222
        // TODO Should we update media db after adding new files?
        [sharedLibrary updateMediaDatabase];
223
        [_playlistViewController updateViewContents];
224 225 226
    }
}

227 228 229 230 231
- (void)mediaFileDeleted:(NSString *)name {
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
    [_playlistViewController updateViewContents];
}

232 233 234
#pragma mark - media list methods

- (NSString *)directoryPath
Felix Paul Kühne's avatar
Felix Paul Kühne committed
235
{
236
#define LOCAL_PLAYBACK_HACK 0
Felix Paul Kühne's avatar
Felix Paul Kühne committed
237 238 239
#if LOCAL_PLAYBACK_HACK && TARGET_IPHONE_SIMULATOR
    NSString *directoryPath = @"/Users/fkuehne/Desktop/VideoLAN docs/Clips/sel/";
#else
240
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Felix Paul Kühne's avatar
Felix Paul Kühne committed
241
    NSString *directoryPath = searchPaths[0];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
242
#endif
243 244 245 246 247 248 249

    return directoryPath;
}

- (void)updateMediaList
{
    NSString *directoryPath = [self directoryPath];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
250 251
    NSArray *foundFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:nil];
    NSMutableArray *filePaths = [NSMutableArray arrayWithCapacity:[foundFiles count]];
252
    NSURL *fileURL;
253
    for (NSString *fileName in foundFiles) {
254
        if ([fileName isSupportedMediaFormat] || [fileName isSupportedAudioMediaFormat]) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
255
            [filePaths addObject:[directoryPath stringByAppendingPathComponent:fileName]];
256 257

            /* exclude media files from backup (QA1719) */
258
            fileURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:fileName]];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
259
            [fileURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
260 261 262
        }
    }
    [[MLMediaLibrary sharedMediaLibrary] addFilePaths:filePaths];
263
    [_playlistViewController updateViewContents];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
264 265
}

266 267 268 269 270 271
#pragma mark - pass code validation

- (void)validatePasscode
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *passcode = [defaults objectForKey:kVLCSettingPasscodeKey];
272
    if ([passcode isEqualToString:@""] || ![[defaults objectForKey:kVLCSettingPasscodeOnKey] boolValue]) {
273 274 275
        self.passcodeValidated = YES;
        return;
    }
276

277
    if (!self.passcodeValidated) {
278 279 280 281
        _passcodeLockController = [[PAPasscodeViewController alloc] initForAction:PasscodeActionEnter];
        _passcodeLockController.delegate = self;
        _passcodeLockController.passcode = passcode;
        self.window.rootViewController = _passcodeLockController;
282 283 284 285 286
    }
}

- (void)PAPasscodeViewControllerDidEnterPasscode:(PAPasscodeViewController *)controller
{
287
    // TODO add transition animation, i.e. fade
288
    self.window.rootViewController = self.revealController;
289 290 291 292 293 294 295
}

- (void)PAPasscodeViewController:(PAPasscodeViewController *)controller didFailToEnterPasscode:(NSInteger)attempts
{
    // TODO handle error attempts
}

296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
#pragma mark - idle timer preventer
- (void)disableIdleTimer
{
    _idleCounter++;
    if ([UIApplication sharedApplication].idleTimerDisabled == NO)
        [UIApplication sharedApplication].idleTimerDisabled = YES;
}

- (void)activateIdleTimer
{
    _idleCounter--;
    if (_idleCounter < 1)
        [UIApplication sharedApplication].idleTimerDisabled = NO;
}

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
#pragma mark - playback view handling

- (void)openMediaFromManagedObject:(NSManagedObject *)mediaObject
{
    if (!_movieViewController)
        _movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];

    if ([mediaObject isKindOfClass:[MLFile class]])
        _movieViewController.mediaItem = (MLFile *)mediaObject;
    else if ([mediaObject isKindOfClass:[MLAlbumTrack class]])
        _movieViewController.mediaItem = [(MLAlbumTrack*)mediaObject files].anyObject;
    else if ([mediaObject isKindOfClass:[MLShowEpisode class]])
        _movieViewController.mediaItem = [(MLShowEpisode*)mediaObject files].anyObject;

    UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_movieViewController];
    navCon.modalPresentationStyle = UIModalPresentationFullScreen;
    [self.window.rootViewController presentViewController:navCon animated:YES completion:nil];
}

- (void)openMovieFromURL:(NSURL *)url
{
    if (!_movieViewController)
        _movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];

    _movieViewController.url = url;

    UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_movieViewController];
    navCon.modalPresentationStyle = UIModalPresentationFullScreen;
    [self.window.rootViewController presentViewController:navCon animated:YES completion:nil];
}

342
- (void)openMediaList:(VLCMediaList*)list atIndex:(int)index
343 344 345 346 347 348 349 350 351 352 353 354 355
{
    if (!_movieViewController)
        _movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];

    _movieViewController.mediaList = list;
    _movieViewController.itemInMediaListToBePlayedFirst = index;

    UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_movieViewController];
    navCon.modalPresentationStyle = UIModalPresentationFullScreen;
    [self.window.rootViewController presentViewController:navCon animated:YES completion:nil];
}


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