VLCAppDelegate.m 9.88 KB
Newer Older
Felix Paul Kühne's avatar
Felix Paul Kühne committed
1
2
3
4
5
6
7
//
//  VLCAppDelegate.m
//  AspenProject
//
//  Created by Felix Paul Kühne on 27.02.13.
//  Copyright (c) 2013 VideoLAN. All rights reserved.
//
8
9
//  Refer to the COPYING file of the official project for license.
//
Felix Paul Kühne's avatar
Felix Paul Kühne committed
10
11

#import "VLCAppDelegate.h"
Gleb Pinigin's avatar
Gleb Pinigin committed
12
#import "VLCMediaFileDiscoverer.h"
13
#import "NSString+SupportedMedia.h"
14
#import "UIDevice+SpeedCategory.h"
Felix Paul Kühne's avatar
Felix Paul Kühne committed
15
16

#import "VLCPlaylistViewController.h"
17
#import "VLCMenuViewController.h"
18
#import "VLCMovieViewController.h"
19
#import "PAPasscodeViewController.h"
20
#import "UINavigationController+Theme.h"
21
#import "VLCHTTPUploaderController.h"
22

Gleb Pinigin's avatar
Gleb Pinigin committed
23
@interface VLCAppDelegate () <PAPasscodeViewControllerDelegate, VLCMediaFileDiscovererDelegate> {
Gleb Pinigin's avatar
Gleb Pinigin committed
24
    PAPasscodeViewController *_passcodeLockController;
Gleb Pinigin's avatar
Gleb Pinigin committed
25
    VLCDropboxTableViewController *_dropboxTableViewController;
26
    int _idleCounter;
Gleb Pinigin's avatar
Gleb Pinigin committed
27
}
28
29
30
31

@property (nonatomic) BOOL passcodeValidated;

@end
Felix Paul Kühne's avatar
Felix Paul Kühne committed
32
33
34

@implementation VLCAppDelegate

35
36
37
38
+ (void)initialize
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

39
40
41
42
43
    NSNumber *skipLoopFilterDefaultValue;
    int deviceSpeedCategory = [[UIDevice currentDevice] speedCategory];
    if (deviceSpeedCategory < 3)
        skipLoopFilterDefaultValue = kVLCSettingSkipLoopFilterNonKey;
    else
44
        skipLoopFilterDefaultValue = kVLCSettingSkipLoopFilterNonRef;
45

46
    NSDictionary *appDefaults = @{kVLCSettingPasscodeKey : @"", kVLCSettingPasscodeOnKey : @(NO), kVLCSettingContinueAudioInBackgroundKey : @(YES), kVLCSettingStretchAudio : @(NO), kVLCSettingTextEncoding : kVLCSettingTextEncodingDefaultValue, kVLCSettingSkipLoopFilter : skipLoopFilterDefaultValue, kVLCSettingSubtitlesFont : kVLCSettingSubtitlesFontDefaultValue, kVLCSettingSubtitlesFontColor : kVLCSettingSubtitlesFontColorDefaultValue, kVLCSettingSubtitlesFontSize : kVLCSettingSubtitlesFontSizeDefaultValue};
47
48
49
50

    [defaults registerDefaults:appDefaults];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
51
52
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
53
54
55
    // Init the HTTP Server
    self.uploadController = [[VLCHTTPUploaderController alloc] init];

56
57
58
    // enable crash preventer
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];

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

61
    _playlistViewController = [[VLCPlaylistViewController alloc] init];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
62

Felix Paul Kühne's avatar
Felix Paul Kühne committed
63
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:_playlistViewController];
64
    [self.navigationController loadTheme];
65

66
    self.window.rootViewController = self.navigationController;
Felix Paul Kühne's avatar
Felix Paul Kühne committed
67
    [self.window makeKeyAndVisible];
68

Gleb Pinigin's avatar
Gleb Pinigin committed
69
70
71
    VLCMediaFileDiscoverer *discoverer = [VLCMediaFileDiscoverer sharedInstance];
    [discoverer addObserver:self];
    [discoverer startDiscovering:[self directoryPath]];
72

73
    [self validatePasscode];
74

Felix Paul Kühne's avatar
Felix Paul Kühne committed
75
76
77
    return YES;
}

78
79
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
80
81
82
83
84
    if ([[DBSession sharedSession] handleOpenURL:url]) {
        [self.dropboxTableViewController updateViewAfterSessionChange];
        return YES;
    }

85
86
    if (_playlistViewController && url != nil) {
        APLog(@"%@ requested %@ to be opened", sourceApplication, url);
87

88
        if (url.isFileURL) {
89
90
91
92
93
94
95
96
97
            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
98
99
100
101
        } else {
            NSURL *parsedUrl = [self parseOpenURL:url];
            [_playlistViewController openMovieFromURL:parsedUrl];
        }
102
103
104
105
106
        return YES;
    }
    return NO;
}

Luis's avatar
Luis committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
- (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)];
            if (numberOfUrlMatches == 0) {
                parsedString = [@"http://" stringByAppendingString:parsedString];
            }

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

134
135
136
137
138
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
139
140
141
142
143
144
145
- (void)applicationWillResignActive:(UIApplication *)application
{
    [[MLMediaLibrary sharedMediaLibrary] applicationWillExit];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
146
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
147
148
149
    [self updateMediaList];
}

150
151
152
153
154
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [self validatePasscode]; // Lock library when going to background
}

155
156
157
158
159
- (void)applicationWillTerminate:(UIApplication *)application
{
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Gleb Pinigin's avatar
Gleb Pinigin committed
160
161
162
163
164
#pragma mark - properties

- (VLCDropboxTableViewController *)dropboxTableViewController
{
    if (_dropboxTableViewController == nil) {
165
        _dropboxTableViewController = [[VLCDropboxTableViewController alloc] initWithNibName:nil bundle:nil];
Gleb Pinigin's avatar
Gleb Pinigin committed
166
167
168
169
170
    }

    return _dropboxTableViewController;
}

Gleb Pinigin's avatar
Gleb Pinigin committed
171
#pragma mark - media discovering
172

Gleb Pinigin's avatar
Gleb Pinigin committed
173
174
175
176
- (void)mediaFileAdded:(NSString *)fileName loading:(BOOL)isLoading {
    if (!isLoading) {
        MLMediaLibrary *sharedLibrary = [MLMediaLibrary sharedMediaLibrary];
        [sharedLibrary addFilePaths:@[fileName]];
177

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

Gleb Pinigin's avatar
Gleb Pinigin committed
182
183
        // TODO Should we update media db after adding new files?
        [sharedLibrary updateMediaDatabase];
184
        [_playlistViewController updateViewContents];
185
186
187
    }
}

Gleb Pinigin's avatar
Gleb Pinigin committed
188
189
190
191
192
- (void)mediaFileDeleted:(NSString *)name {
    [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
    [_playlistViewController updateViewContents];
}

193
194
195
#pragma mark - media list methods

- (NSString *)directoryPath
Felix Paul Kühne's avatar
Felix Paul Kühne committed
196
{
197
#define LOCAL_PLAYBACK_HACK 0
Felix Paul Kühne's avatar
Felix Paul Kühne committed
198
199
200
#if LOCAL_PLAYBACK_HACK && TARGET_IPHONE_SIMULATOR
    NSString *directoryPath = @"/Users/fkuehne/Desktop/VideoLAN docs/Clips/sel/";
#else
201
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Felix Paul Kühne's avatar
Felix Paul Kühne committed
202
    NSString *directoryPath = searchPaths[0];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
203
#endif
204
205
206
207
208
209
210

    return directoryPath;
}

- (void)updateMediaList
{
    NSString *directoryPath = [self directoryPath];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
211
212
    NSArray *foundFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:nil];
    NSMutableArray *filePaths = [NSMutableArray arrayWithCapacity:[foundFiles count]];
213
    NSURL *fileURL;
Felix Paul Kühne's avatar
Felix Paul Kühne committed
214
    for (NSString *fileName in foundFiles) {
215
        if ([fileName isSupportedMediaFormat] || [fileName isSupportedAudioMediaFormat]) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
216
            [filePaths addObject:[directoryPath stringByAppendingPathComponent:fileName]];
217
218

            /* exclude media files from backup (QA1719) */
219
            fileURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:fileName]];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
220
            [fileURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
221
222
223
        }
    }
    [[MLMediaLibrary sharedMediaLibrary] addFilePaths:filePaths];
224
    [_playlistViewController updateViewContents];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
225
226
}

227
228
229
230
231
232
#pragma mark - pass code validation

- (void)validatePasscode
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *passcode = [defaults objectForKey:kVLCSettingPasscodeKey];
233
    if ([passcode isEqualToString:@""] || ![[defaults objectForKey:kVLCSettingPasscodeOnKey] boolValue]) {
234
235
236
        self.passcodeValidated = YES;
        return;
    }
237

238
239
240
241
242
243
244
245
246
247
248
249
250
    if (!self.passcodeValidated) {
        if ([self.nextPasscodeCheckDate earlierDate:[NSDate date]] == self.nextPasscodeCheckDate) {
            _passcodeLockController = [[PAPasscodeViewController alloc] initForAction:PasscodeActionEnter];
            _passcodeLockController.delegate = self;
            _passcodeLockController.passcode = passcode;
            self.window.rootViewController = _passcodeLockController;
        } else
            self.passcodeValidated = YES;
    }
}

- (void)PAPasscodeViewControllerDidEnterPasscode:(PAPasscodeViewController *)controller
{
251
252
    // TODO add transition animation, i.e. fade
    self.nextPasscodeCheckDate = [NSDate dateWithTimeIntervalSinceNow:300];
253
254
255
256
257
258
259
260
    self.window.rootViewController = self.navigationController;
}

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

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#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;
}

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