VLCAppDelegate.m 12.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*****************************************************************************
 * VLCAppDelegate.m
 * VLC for iOS
 *****************************************************************************
 * Copyright (c) 2013 VideoLAN. All rights reserved.
 * $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"
Gleb Pinigin's avatar
Gleb Pinigin committed
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

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

@property (nonatomic) BOOL passcodeValidated;

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

@implementation VLCAppDelegate

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

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

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

    [defaults registerDefaults:appDefaults];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
60
61
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
62
63
64
    // Init the HTTP Server
    self.uploadController = [[VLCHTTPUploaderController alloc] init];

65
66
67
    // enable crash preventer
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];

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

70
    _playlistViewController = [[VLCPlaylistViewController alloc] init];
71
72
    UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_playlistViewController];
    [navCon loadTheme];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
73

74
    _revealController = [[GHRevealViewController alloc] initWithNibName:nil bundle:nil];
75
    _revealController.wantsFullScreenLayout = YES;
76
77
    _menuViewController = [[VLCMenuTableViewController alloc] initWithNibName:nil bundle:nil];
    _revealController.sidebarViewController = _menuViewController;
78
    _revealController.contentViewController = navCon;
79

80
    self.window.rootViewController = self.revealController;
81
82
    // 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
83
    [self.window makeKeyAndVisible];
84

Gleb Pinigin's avatar
Gleb Pinigin committed
85
86
87
    VLCMediaFileDiscoverer *discoverer = [VLCMediaFileDiscoverer sharedInstance];
    [discoverer addObserver:self];
    [discoverer startDiscovering:[self directoryPath]];
88

89
    [self validatePasscode];
90

Felix Paul Kühne's avatar
Felix Paul Kühne committed
91
92
93
    return YES;
}

94
95
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
96
97
98
99
100
    if ([[DBSession sharedSession] handleOpenURL:url]) {
        [self.dropboxTableViewController updateViewAfterSessionChange];
        return YES;
    }

101
102
    if (_playlistViewController && url != nil) {
        APLog(@"%@ requested %@ to be opened", sourceApplication, url);
103

104
        if (url.isFileURL) {
105
106
107
108
109
110
111
112
113
            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)
                APLog(@"saving the file failed (%i): %@", theError.code, theError.localizedDescription);

            [self updateMediaList];
Luis's avatar
Luis committed
114
115
        } else {
            NSURL *parsedUrl = [self parseOpenURL:url];
116
            [self.menuViewController selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
117
            [self.playlistViewController performSelector:@selector(openMovieFromURL:) withObject:parsedUrl afterDelay:kGHRevealSidebarDefaultAnimationDuration];
Luis's avatar
Luis committed
118
        }
119
120
121
122
123
        return YES;
    }
    return NO;
}

Luis's avatar
Luis committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
- (NSURL *)parseOpenURL:(NSURL *)url
{
    NSString *receivedUrl = [url absoluteString];
    if ([receivedUrl length] > 6) {
        NSString *verifyVlcUrl = [receivedUrl substringToIndex:6];
        if ([verifyVlcUrl isEqualToString:@"vlc://"]) {
            NSString *parsedString = [receivedUrl substringFromIndex:6];

            // "url decode" so we can parse http:// links
            parsedString = [parsedString stringByReplacingOccurrencesOfString:@"+"withString:@" "];
            parsedString = [parsedString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

            // add http:// if nothing is there
            NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:(NSTextCheckingTypes)NSTextCheckingTypeLink error:nil];
            NSUInteger parsedStringLength = [parsedString length];
            NSUInteger numberOfUrlMatches = [detector numberOfMatchesInString:parsedString options:0 range:NSMakeRange(0, parsedStringLength)];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
140
            if (numberOfUrlMatches == 0)
Luis's avatar
Luis committed
141
142
143
144
145
146
147
148
149
                parsedString = [@"http://" stringByAppendingString:parsedString];

            NSURL *targetUrl = [NSURL URLWithString:parsedString];
            return targetUrl;
        }
    }
    return url;
}

150
151
152
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];
153
    [self validatePasscode];
154
155
}

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

- (void)applicationDidBecomeActive:(UIApplication *)application
{
164
    [self validatePasscode];
165
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
166
167
168
    [self updateMediaList];
}

169
170
- (void)applicationWillTerminate:(UIApplication *)application
{
171
    self.passcodeValidated = NO;
172
173
174
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Gleb Pinigin's avatar
Gleb Pinigin committed
175
176
177
178
#pragma mark - properties

- (VLCDropboxTableViewController *)dropboxTableViewController
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
179
    if (_dropboxTableViewController == nil)
180
        _dropboxTableViewController = [[VLCDropboxTableViewController alloc] initWithNibName:nil bundle:nil];
Gleb Pinigin's avatar
Gleb Pinigin committed
181
182
183
184

    return _dropboxTableViewController;
}

Carola's avatar
Carola committed
185
186
- (VLCGoogleDriveTableViewController *)googleDriveTableViewController
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
187
    if (_googleDriveTableViewController == nil)
Carola's avatar
Carola committed
188
189
190
191
192
193
        _googleDriveTableViewController = [[VLCGoogleDriveTableViewController alloc] initWithNibName:nil bundle:nil];

    return _googleDriveTableViewController;
}


194
195
- (VLCDownloadViewController *)downloadViewController
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
196
    if (_downloadViewController == nil)
197
198
199
200
201
        _downloadViewController = [[VLCDownloadViewController alloc] init];

    return _downloadViewController;
}

Gleb Pinigin's avatar
Gleb Pinigin committed
202
#pragma mark - media discovering
203

Gleb Pinigin's avatar
Gleb Pinigin committed
204
205
206
207
- (void)mediaFileAdded:(NSString *)fileName loading:(BOOL)isLoading {
    if (!isLoading) {
        MLMediaLibrary *sharedLibrary = [MLMediaLibrary sharedMediaLibrary];
        [sharedLibrary addFilePaths:@[fileName]];
208

Gleb Pinigin's avatar
Gleb Pinigin committed
209
210
211
        /* exclude media files from backup (QA1719) */
        NSURL *excludeURL = [NSURL fileURLWithPath:fileName];
        [excludeURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
212

Gleb Pinigin's avatar
Gleb Pinigin committed
213
214
        // TODO Should we update media db after adding new files?
        [sharedLibrary updateMediaDatabase];
215
        [_playlistViewController updateViewContents];
216
217
218
    }
}

Gleb Pinigin's avatar
Gleb Pinigin committed
219
220
221
222
223
- (void)mediaFileDeleted:(NSString *)name {
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
    [_playlistViewController updateViewContents];
}

224
225
226
#pragma mark - media list methods

- (NSString *)directoryPath
Felix Paul Kühne's avatar
Felix Paul Kühne committed
227
{
228
#define LOCAL_PLAYBACK_HACK 0
Felix Paul Kühne's avatar
Felix Paul Kühne committed
229
230
231
#if LOCAL_PLAYBACK_HACK && TARGET_IPHONE_SIMULATOR
    NSString *directoryPath = @"/Users/fkuehne/Desktop/VideoLAN docs/Clips/sel/";
#else
232
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Felix Paul Kühne's avatar
Felix Paul Kühne committed
233
    NSString *directoryPath = searchPaths[0];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
234
#endif
235
236
237
238
239
240
241

    return directoryPath;
}

- (void)updateMediaList
{
    NSString *directoryPath = [self directoryPath];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
242
243
    NSArray *foundFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:nil];
    NSMutableArray *filePaths = [NSMutableArray arrayWithCapacity:[foundFiles count]];
244
    NSURL *fileURL;
Felix Paul Kühne's avatar
Felix Paul Kühne committed
245
    for (NSString *fileName in foundFiles) {
246
        if ([fileName isSupportedMediaFormat] || [fileName isSupportedAudioMediaFormat]) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
247
            [filePaths addObject:[directoryPath stringByAppendingPathComponent:fileName]];
248
249

            /* exclude media files from backup (QA1719) */
250
            fileURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:fileName]];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
251
            [fileURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
252
253
254
        }
    }
    [[MLMediaLibrary sharedMediaLibrary] addFilePaths:filePaths];
255
    [_playlistViewController updateViewContents];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
256
257
}

258
259
260
261
262
263
#pragma mark - pass code validation

- (void)validatePasscode
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *passcode = [defaults objectForKey:kVLCSettingPasscodeKey];
264
    if ([passcode isEqualToString:@""] || ![[defaults objectForKey:kVLCSettingPasscodeOnKey] boolValue]) {
265
266
267
        self.passcodeValidated = YES;
        return;
    }
268

269
    if (!self.passcodeValidated) {
270
271
272
273
        _passcodeLockController = [[PAPasscodeViewController alloc] initForAction:PasscodeActionEnter];
        _passcodeLockController.delegate = self;
        _passcodeLockController.passcode = passcode;
        self.window.rootViewController = _passcodeLockController;
274
275
276
277
278
    }
}

- (void)PAPasscodeViewControllerDidEnterPasscode:(PAPasscodeViewController *)controller
{
279
    // TODO add transition animation, i.e. fade
280
    self.window.rootViewController = self.revealController;
281
282
283
284
285
286
287
}

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

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#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;
}

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#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];
}

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