VLCLocalServerFolderListViewController.m 24.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*****************************************************************************
 * VLCLocalServerFolderListViewController.m
 * VLC for iOS
 *****************************************************************************
 * Copyright (c) 2013 VideoLAN. All rights reserved.
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan.org>
 *          Pierre SAGASPE <pierre.sagaspe # me.com>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
13
14
15
16
17
18
19

#import "VLCLocalServerFolderListViewController.h"
#import "MediaServerBasicObjectParser.h"
#import "MediaServer1ItemObject.h"
#import "MediaServer1ContainerObject.h"
#import "MediaServer1Device.h"
#import "VLCLocalNetworkListCell.h"
20
21
22
#import "VLCAppDelegate.h"
#import "VLCPlaylistViewController.h"
#import "UINavigationController+Theme.h"
23
#import "VLCDownloadViewController.h"
24
#import "WhiteRaccoon.h"
25
#import "NSString+SupportedMedia.h"
26
#import "VLCStatusLabel.h"
27

28
29
#define kVLCServerTypeUPNP 0
#define kVLCServerTypeFTP 1
30

31
@interface VLCLocalServerFolderListViewController () <UITableViewDataSource, UITableViewDelegate, WRRequestDelegate, VLCLocalNetworkListCell, UISearchBarDelegate, UISearchDisplayDelegate>
32
{
33
    /* UI */
34
35
    UIBarButtonItem *_backButton;

36
    /* generic data storage */
37
    NSString *_listTitle;
38
    NSArray *_objectList;
39
    NSMutableArray *_mutableObjectList;
40
41
    NSUInteger _serverType;

42
    /* UPNP specifics */
43
44
    MediaServer1Device *_UPNPdevice;
    NSString *_UPNProotID;
45
46
47
48
49
50

    /* FTP specifics */
    NSString *_ftpServerAddress;
    NSString *_ftpServerUserName;
    NSString *_ftpServerPassword;
    NSString *_ftpServerPath;
51
    WRRequestListDirectory *_FTPListDirRequest;
52
53
54
55

    NSMutableArray *_searchData;
    UISearchBar *_searchBar;
    UISearchDisplayController *_searchDisplayController;
56
57
58
59
60
61
62
63
64
}

@end

@implementation VLCLocalServerFolderListViewController

- (void)loadView
{
    _tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
65
    _tableView.backgroundColor = [UIColor VLCDarkBackgroundColor];
66
67
    _tableView.delegate = self;
    _tableView.dataSource = self;
68
    _tableView.rowHeight = [VLCLocalNetworkListCell heightOfCell];
69
70
71
    self.view = _tableView;
}

72
- (id)initWithUPNPDevice:(MediaServer1Device*)device header:(NSString*)header andRootID:(NSString*)rootID
73
74
75
76
{
    self = [super init];

    if (self) {
77
78
79
        _UPNPdevice = device;
        _listTitle = header;
        _UPNProotID = rootID;
80
        _serverType = kVLCServerTypeUPNP;
81
        _mutableObjectList = [[NSMutableArray alloc] init];
82
83
84
85
86
87
88
89
    }

    return self;
}

- (id)initWithFTPServer:(NSString *)serverAddress userName:(NSString *)username andPassword:(NSString *)password atPath:(NSString *)path
{
    self = [super init];
90

91
92
93
94
95
    if (self) {
        _ftpServerAddress = serverAddress;
        _ftpServerUserName = username;
        _ftpServerPassword = password;
        _ftpServerPath = path;
96
        _serverType = kVLCServerTypeFTP;
97
98
99
100
101
102
103
104
105
    }

    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

106
    if (_serverType == kVLCServerTypeUPNP) {
107
108
109
110
111
112
113
114
115
        NSString *sortCriteria = @"";
        NSMutableString *outSortCaps = [[NSMutableString alloc] init];
        [[_UPNPdevice contentDirectory] GetSortCapabilitiesWithOutSortCaps:outSortCaps];

        if ([outSortCaps rangeOfString:@"dc:title"].location != NSNotFound)
        {
            sortCriteria = @"+dc:title";
        }

116
117
118
119
        NSMutableString *outResult = [[NSMutableString alloc] init];
        NSMutableString *outNumberReturned = [[NSMutableString alloc] init];
        NSMutableString *outTotalMatches = [[NSMutableString alloc] init];
        NSMutableString *outUpdateID = [[NSMutableString alloc] init];
120

121
        [[_UPNPdevice contentDirectory] BrowseWithObjectID:_UPNProotID BrowseFlag:@"BrowseDirectChildren" Filter:@"*" StartingIndex:@"0" RequestedCount:@"0" SortCriteria:sortCriteria OutResult:outResult OutNumberReturned:outNumberReturned OutTotalMatches:outTotalMatches OutUpdateID:outUpdateID];
122

123
        [_mutableObjectList removeAllObjects];
124
        NSData *didl = [outResult dataUsingEncoding:NSUTF8StringEncoding];
125
        MediaServerBasicObjectParser *parser = [[MediaServerBasicObjectParser alloc] initWithMediaObjectArray:_mutableObjectList itemsOnly:NO];
126
        [parser parseFromData:didl];
127
    } else if (_serverType == kVLCServerTypeFTP) {
128
129
130
131
132
        if ([_ftpServerPath isEqualToString:@"/"])
            _listTitle = _ftpServerAddress;
        else
            _listTitle = [_ftpServerPath lastPathComponent];
        [self _listFTPDirectory];
133
    }
134

135
136
    self.tableView.separatorColor = [UIColor VLCDarkBackgroundColor];
    self.view.backgroundColor = [UIColor VLCDarkBackgroundColor];
137

138
    self.title = _listTitle;
139
140
141
142
143
144

    _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    _searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
    _searchDisplayController.delegate = self;
    _searchDisplayController.searchResultsDataSource = self;
    _searchDisplayController.searchResultsDelegate = self;
145
146
    if (SYSTEM_RUNS_IOS7_OR_LATER)
        _searchDisplayController.searchBar.searchBarStyle = UIBarStyleBlack;
147
148
149
150
151
    _searchBar.delegate = self;
    self.tableView.tableHeaderView = _searchBar; //this line add the searchBar on the top of tableView.

    _searchData = [[NSMutableArray alloc] init];
    [_searchData removeAllObjects];
152
153
}

154
- (BOOL)shouldAutorotate
155
{
156
    UIInterfaceOrientation toInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
        return NO;
    return YES;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
171
172
    if (tableView == self.searchDisplayController.searchResultsTableView)
        return _searchData.count;
173
    else {
174
175
        if (_serverType == kVLCServerTypeUPNP)
            return _mutableObjectList.count;
176

177
178
        return _objectList.count;
    }
179
180
181
182
183
184
185
186
187
188
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"LocalNetworkCellDetail";

    VLCLocalNetworkListCell *cell = (VLCLocalNetworkListCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
        cell = [VLCLocalNetworkListCell cellWithReuseIdentifier:CellIdentifier];

189
    if (_serverType == kVLCServerTypeUPNP) {
190
191
192
193
194
195
        MediaServer1BasicObject *item;
        if (tableView == self.searchDisplayController.searchResultsTableView)
            item = _searchData[indexPath.row];
        else
            item = _mutableObjectList[indexPath.row];

196
        if (![item isContainer]) {
197
            MediaServer1ItemObject *mediaItem;
198
            long long mediaSize = 0;
199
200
            unsigned int durationInSeconds = 0;
            unsigned int bitrate = 0;
201

202
203
204
205
206
            if (tableView == self.searchDisplayController.searchResultsTableView)
                mediaItem = _searchData[indexPath.row];
            else
                mediaItem = _mutableObjectList[indexPath.row];

207
208
209
210
211
212
213
214
            MediaServer1ItemRes *resource = nil;
            NSEnumerator *e = [[mediaItem resources] objectEnumerator];
            while((resource = (MediaServer1ItemRes*)[e nextObject])){
                if (resource.bitrate > 0 && resource.durationInSeconds > 0) {
                    mediaSize = resource.size;
                    durationInSeconds = resource.durationInSeconds;
                    bitrate = resource.bitrate;
                }
215
            }
216
            if (mediaSize < 1)
217
                mediaSize = [mediaItem.size longLongValue];
218

219
            if (mediaSize < 1)
220
                mediaSize = (bitrate * durationInSeconds);
221
222

            [cell setSubtitle: [NSString stringWithFormat:@"%@ (%@)", [NSByteCountFormatter stringFromByteCount:mediaSize countStyle:NSByteCountFormatterCountStyleFile], [VLCTime timeWithInt:durationInSeconds * 1000].stringValue]];
223
            [cell setIsDirectory:NO];
Pierre SAGASPE's avatar
Pierre SAGASPE committed
224
            cell.isDownloadable = YES;
225
            if (mediaItem.albumArt != nil)
226
227
                [cell setIconURL:[NSURL URLWithString:mediaItem.albumArt]];
            [cell setIcon:[UIImage imageNamed:@"blank"]];
Pierre SAGASPE's avatar
Pierre SAGASPE committed
228
            cell.delegate = self;
229
230
        } else {
            [cell setIsDirectory:YES];
231
232
            if (item.albumArt != nil)
                [cell setIconURL:[NSURL URLWithString:item.albumArt]];
233
234
235
            [cell setIcon:[UIImage imageNamed:@"folder"]];
        }
        [cell setTitle:[item title]];
236
    } else if (_serverType == kVLCServerTypeFTP) {
237
238
239
240
241
242
243
244
        NSMutableArray *ObjList = [[NSMutableArray alloc] init];
        [ObjList removeAllObjects];

        if (tableView == self.searchDisplayController.searchResultsTableView)
            [ObjList addObjectsFromArray:_searchData];
        else
            [ObjList addObjectsFromArray:_objectList];

245
        NSString *rawFileName = [ObjList[indexPath.row] objectForKey:(id)kCFFTPResourceName];
246
        NSData *flippedData = [rawFileName dataUsingEncoding:[[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingFTPTextEncoding] intValue] allowLossyConversion:YES];
247
        cell.title = [[NSString alloc] initWithData:flippedData encoding:NSUTF8StringEncoding];
248
249

        if ([[ObjList[indexPath.row] objectForKey:(id)kCFFTPResourceType] intValue] == 4) {
250
251
252
253
254
            cell.isDirectory = YES;
            cell.icon = [UIImage imageNamed:@"folder"];
        } else {
            cell.isDirectory = NO;
            cell.icon = [UIImage imageNamed:@"blank"];
255
            cell.subtitle = [NSString stringWithFormat:@"%0.2f MB", (float)([[ObjList[indexPath.row] objectForKey:(id)kCFFTPResourceSize] intValue] / 1e6)];
256
257
            cell.isDownloadable = YES;
            cell.delegate = self;
258
        }
259
    }
260
261
262
263
264
    return cell;
}

#pragma mark - Table view delegate

265
- (void)tableView:(UITableView *)tableView willDisplayCell:(VLCLocalNetworkListCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
266
{
267
    UIColor *color = (indexPath.row % 2 == 0)? [UIColor blackColor]: [UIColor VLCDarkBackgroundColor];
268
    cell.contentView.backgroundColor = cell.titleLabel.backgroundColor = cell.folderTitleLabel.backgroundColor = cell.subtitleLabel.backgroundColor =  color;
269
270
271
272

    if (_serverType == kVLCServerTypeFTP)
        if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row)
            [(VLCAppDelegate*)[UIApplication sharedApplication].delegate networkActivityStopped];
273
274
}

275
276
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
277
    if (_serverType == kVLCServerTypeUPNP) {
278
279
280
281
282
283
        MediaServer1BasicObject *item;
        if (tableView == self.searchDisplayController.searchResultsTableView)
            item = _searchData[indexPath.row];
        else
            item = _mutableObjectList[indexPath.row];

284
        if ([item isContainer]) {
285
286
287
288
289
290
            MediaServer1ContainerObject *container;
            if (tableView == self.searchDisplayController.searchResultsTableView)
                container = _searchData[indexPath.row];
            else
                container = _mutableObjectList[indexPath.row];

291
292
293
            VLCLocalServerFolderListViewController *targetViewController = [[VLCLocalServerFolderListViewController alloc] initWithUPNPDevice:_UPNPdevice header:[container title] andRootID:[container objectID]];
            [[self navigationController] pushViewController:targetViewController animated:YES];
        } else {
294
295
            MediaServer1ItemObject *mediaItem;

296
            if (tableView == self.searchDisplayController.searchResultsTableView)
297
                mediaItem = _searchData[indexPath.row];
298
            else
299
                mediaItem = _mutableObjectList[indexPath.row];
300
301

            NSURL *itemURL;
302
303
304
305
306
307
308
309
310
            NSArray *uriCollectionKeys = [[mediaItem uriCollection] allKeys];
            NSUInteger count = uriCollectionKeys.count;
            NSRange position;
            NSUInteger correctIndex = 0;
            for (NSUInteger i = 0; i < count; i++) {
                position = [uriCollectionKeys[i] rangeOfString:@"http-get:*:video/"];
                if (position.location != NSNotFound)
                    correctIndex = i;
            }
311
            NSArray *uriCollectionObjects = [[mediaItem uriCollection] allValues];
312

313
314
            if (uriCollectionObjects.count > 0)
                itemURL = [NSURL URLWithString:uriCollectionObjects[correctIndex]];
315
            if (itemURL) {
316
                VLCAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
317
                [appDelegate openMovieFromURL:itemURL];
318
            }
319
        }
320
    } else if (_serverType == kVLCServerTypeFTP) {
321
322
323
324
325
326
327
328
329
330
        NSMutableArray *ObjList = [[NSMutableArray alloc] init];
        [ObjList removeAllObjects];

        if (tableView == self.searchDisplayController.searchResultsTableView)
            [ObjList addObjectsFromArray:_searchData];
        else
            [ObjList addObjectsFromArray:_objectList];

        if ([[ObjList[indexPath.row] objectForKey:(id)kCFFTPResourceType] intValue] == 4) {
            NSString *newPath = [NSString stringWithFormat:@"%@/%@", _ftpServerPath, [ObjList[indexPath.row] objectForKey:(id)kCFFTPResourceName]];
331
332
333
334

            VLCLocalServerFolderListViewController *targetViewController = [[VLCLocalServerFolderListViewController alloc] initWithFTPServer:_ftpServerAddress userName:_ftpServerUserName andPassword:_ftpServerPassword atPath:newPath];
            [self.navigationController pushViewController:targetViewController animated:YES];
        } else {
335
            NSString *rawObjectName = [ObjList[indexPath.row] objectForKey:(id)kCFFTPResourceName];
336
            NSData *flippedData = [rawObjectName dataUsingEncoding:[[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingFTPTextEncoding] intValue] allowLossyConversion:YES];
337
338
339
            NSString *properObjectName = [[NSString alloc] initWithData:flippedData encoding:NSUTF8StringEncoding];
            if (![properObjectName isSupportedFormat]) {
                UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"FILE_NOT_SUPPORTED", @"") message:[NSString stringWithFormat:NSLocalizedString(@"FILE_NOT_SUPPORTED_LONG", @""), properObjectName] delegate:self cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", @"") otherButtonTitles:nil];
340
341
                [alert show];
            } else
342
343
                [self _streamFTPFile:properObjectName];
        }
344
    }
345
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
346
347
}

348
349
350
#pragma mark - FTP specifics
- (void)_listFTPDirectory
{
351
    if (_FTPListDirRequest)
352
353
        return;

354
355
356
357
358
359
360
    _FTPListDirRequest = [[WRRequestListDirectory alloc] init];
    _FTPListDirRequest.delegate = self;
    _FTPListDirRequest.hostname = _ftpServerAddress;
    _FTPListDirRequest.username = _ftpServerUserName;
    _FTPListDirRequest.password = _ftpServerPassword;
    _FTPListDirRequest.path = _ftpServerPath;
    _FTPListDirRequest.passive = YES;
361

362
    [(VLCAppDelegate*)[UIApplication sharedApplication].delegate networkActivityStarted];
363
364
365
    [_FTPListDirRequest start];
}

366
- (NSString *)_credentials
367
{
368
    NSString * cred;
369

370
371
372
373
374
375
376
    if (_ftpServerUserName.length > 0) {
        if (_ftpServerPassword.length > 0)
            cred = [NSString stringWithFormat:@"%@:%@@", _ftpServerUserName, _ftpServerPassword];
        else
            cred = [NSString stringWithFormat:@"%@@", _ftpServerPassword];
    } else
        cred = @"";
377

378
379
    return [cred stringByStandardizingPath];
}
380

381
382
- (void)_downloadFTPFile:(NSString *)fileName
{
383
    NSURL *URLToQueue = [NSURL URLWithString:[[@"ftp" stringByAppendingFormat:@"://%@%@/%@/%@", [self _credentials], _ftpServerAddress, _ftpServerPath, fileName] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
384

Pierre SAGASPE's avatar
Pierre SAGASPE committed
385
386
387
    [[(VLCAppDelegate*)[UIApplication sharedApplication].delegate downloadViewController] addURLToDownloadList:URLToQueue fileNameOfMedia:nil];
}

388
- (void)_downloadUPNPFileFromMediaItem:(MediaServer1ItemObject *)mediaItem
Pierre SAGASPE's avatar
Pierre SAGASPE committed
389
{
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    NSURL *itemURL;
    NSArray *uriCollectionKeys = [[mediaItem uriCollection] allKeys];
    NSUInteger count = uriCollectionKeys.count;
    NSRange position;
    NSUInteger correctIndex = 0;
    for (NSUInteger i = 0; i < count; i++) {
        position = [uriCollectionKeys[i] rangeOfString:@"http-get:*:video/"];
        if (position.location != NSNotFound)
            correctIndex = i;
    }
    NSArray *uriCollectionObjects = [[mediaItem uriCollection] allValues];

    if (uriCollectionObjects.count > 0)
        itemURL = [NSURL URLWithString:uriCollectionObjects[correctIndex]];

    if (![itemURL.absoluteString isSupportedFormat]) {
        UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"FILE_NOT_SUPPORTED", @"") message:[NSString stringWithFormat:NSLocalizedString(@"FILE_NOT_SUPPORTED_LONG", @""), [mediaItem uri]] delegate:self cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", @"") otherButtonTitles:nil];
        [alert show];
    } else if (itemURL) {
        NSString *fileName = [[mediaItem.title stringByAppendingString:@"."] stringByAppendingString:[[itemURL absoluteString] pathExtension]];
        [[(VLCAppDelegate*)[UIApplication sharedApplication].delegate downloadViewController] addURLToDownloadList:itemURL fileNameOfMedia:fileName];
    }
412
413
414
415
}

- (void)requestCompleted:(WRRequest *)request
{
416
    if (request == _FTPListDirRequest) {
417
418
419
420
421
422
423
424
425
426
427
        NSMutableArray *filteredList = [[NSMutableArray alloc] init];
        NSArray *rawList = [(WRRequestListDirectory*)request filesInfo];
        NSUInteger count = rawList.count;

        for (NSUInteger x = 0; x < count; x++) {
            if (![[rawList[x] objectForKey:(id)kCFFTPResourceName] hasPrefix:@"."])
                [filteredList addObject:rawList[x]];
        }

        _objectList = [NSArray arrayWithArray:filteredList];
        [self.tableView reloadData];
428
429
430
431
    } else
        APLog(@"unknown request %@ completed", request);
}

432
433
- (void)requestFailed:(WRRequest *)request
{
434
    UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"LOCAL_SERVER_CONNECTION_FAILED_TITLE", nil) message:NSLocalizedString(@"LOCAL_SERVER_CONNECTION_FAILED_MESSAGE", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", @"") otherButtonTitles:nil];
435
436
    [alert show];

Felix Paul Kühne's avatar
Felix Paul Kühne committed
437
    APLog(@"request %@ failed with error %i", request, request.error.errorCode);
438
439
}

440
441
442
#pragma mark - VLCLocalNetworkListCell delegation
- (void)triggerDownloadForCell:(VLCLocalNetworkListCell *)cell
{
443
    if (_serverType == kVLCServerTypeUPNP) {
444
445
446
447
448
449
        MediaServer1ItemObject *item;
        if ([self.searchDisplayController isActive])
            item = _searchData[[self.searchDisplayController.searchResultsTableView indexPathForCell:cell].row];
        else
            item = _mutableObjectList[[self.tableView indexPathForCell:cell].row];

450
451
        [self _downloadUPNPFileFromMediaItem:item];
        [cell.statusLabel showStatusMessage:NSLocalizedString(@"DOWNLOADING", @"")];
452
    }else if (_serverType == kVLCServerTypeFTP) {
453
        NSString *rawObjectName;
454
455
456
457
458
        NSMutableArray *ObjList = [[NSMutableArray alloc] init];
        [ObjList removeAllObjects];

        if ([self.searchDisplayController isActive]) {
            [ObjList addObjectsFromArray:_searchData];
459
            rawObjectName = [ObjList[[self.searchDisplayController.searchResultsTableView indexPathForCell:cell].row] objectForKey:(id)kCFFTPResourceName];
460
461
        } else {
            [ObjList addObjectsFromArray:_objectList];
462
            rawObjectName = [ObjList[[self.tableView indexPathForCell:cell].row] objectForKey:(id)kCFFTPResourceName];
463
464
        }

465
        NSData *flippedData = [rawObjectName dataUsingEncoding:[[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingFTPTextEncoding] intValue] allowLossyConversion:YES];
466
467
468
        NSString *properObjectName = [[NSString alloc] initWithData:flippedData encoding:NSUTF8StringEncoding];
        if (![properObjectName isSupportedFormat]) {
            UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"FILE_NOT_SUPPORTED", @"") message:[NSString stringWithFormat:NSLocalizedString(@"FILE_NOT_SUPPORTED_LONG", @""), properObjectName] delegate:self cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", @"") otherButtonTitles:nil];
469
            [alert show];
470
        } else {
471
            [self _downloadFTPFile:properObjectName];
472
473
            [cell.statusLabel showStatusMessage:NSLocalizedString(@"DOWNLOADING", @"")];
        }
474
475
476
477
    }
}

#pragma mark - communication with playback engine
478
- (void)_streamFTPFile:(NSString *)fileName
479
{
480
481
482
483
484
485
486
487
    NSString *URLofSubtitle = nil;
    NSMutableArray *SubtitlesList = [[NSMutableArray alloc] init];
    [SubtitlesList removeAllObjects];
    SubtitlesList = [self _searchSubtitle:fileName];

    if(SubtitlesList.count > 0)
       URLofSubtitle = [self _getFileSubtitleFromFtpServer:SubtitlesList[0]];

488
489
    NSURL *URLToPlay = [NSURL URLWithString:[[@"ftp" stringByAppendingFormat:@"://%@%@/%@/%@", [self _credentials], _ftpServerAddress, _ftpServerPath, fileName] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

490
    VLCAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
    [appDelegate openMovieWithExternalSubtitleFromURL:URLToPlay externalSubURL:URLofSubtitle];
}

- (NSMutableArray *)_searchSubtitle:(NSString *)url
{
    NSString *urlTemp = [[url lastPathComponent] stringByDeletingPathExtension];
    NSMutableArray *ObjList = [[NSMutableArray alloc] init];
    [ObjList removeAllObjects];
    for (int loop = 0; loop < _objectList.count; loop++)
        [ObjList addObject:[_objectList[loop] objectForKey:(id)kCFFTPResourceName]];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@", urlTemp];
    NSArray *results = [ObjList filteredArrayUsingPredicate:predicate];

    [ObjList removeAllObjects];

    for (int cnt = 0; cnt < results.count; cnt++) {
        if ([results[cnt] isSupportedSubtitleFormat])
            [ObjList addObject:results[cnt]];
    }
    return ObjList;
}

- (NSString *)_getFileSubtitleFromFtpServer:(NSString *)fileName
{
    NSURL *url = [NSURL URLWithString:[[@"ftp" stringByAppendingFormat:@"://%@%@/%@/%@", [self _credentials], _ftpServerAddress, _ftpServerPath, fileName] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    NSString *receivedSub = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:nil];
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *directoryPath = searchPaths[0];
    NSString *FileSubtitlePath = [directoryPath stringByAppendingPathComponent:[fileName lastPathComponent]];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:FileSubtitlePath]) {
        //create local subtitle file
        [fileManager createFileAtPath:FileSubtitlePath contents:nil attributes:nil];
        if (![fileManager fileExistsAtPath:FileSubtitlePath])
            APLog(@"file creation failed, no data was saved");
    }
    [receivedSub writeToFile:FileSubtitlePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    return FileSubtitlePath;
532
533
}

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
#pragma mark - Search Display Controller Delegate

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    MediaServer1BasicObject *item;
    NSInteger listCount = 0;
    [_searchData removeAllObjects];

    if (_serverType == kVLCServerTypeUPNP)
        listCount = _mutableObjectList.count;
    else if (_serverType == kVLCServerTypeFTP)
        listCount = _objectList.count;

    for (int i = 0; i < listCount; i++) {
        NSRange nameRange;
        if (_serverType == kVLCServerTypeUPNP) {
            item = _mutableObjectList[i];
            nameRange = [[item title] rangeOfString:searchString options:NSCaseInsensitiveSearch];
552
553
        } else if (_serverType == kVLCServerTypeFTP) {
            NSString *rawObjectName = [_objectList[i] objectForKey:(id)kCFFTPResourceName];
554
            NSData *flippedData = [rawObjectName dataUsingEncoding:[[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingFTPTextEncoding] intValue] allowLossyConversion:YES];
555
556
557
            NSString *properObjectName = [[NSString alloc] initWithData:flippedData encoding:NSUTF8StringEncoding];
            nameRange = [properObjectName rangeOfString:searchString options:NSCaseInsensitiveSearch];
        }
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

        if (nameRange.location != NSNotFound) {
            if (_serverType == kVLCServerTypeUPNP)
                [_searchData addObject:_mutableObjectList[i]];
            else
                [_searchData addObject:_objectList[i]];
        }
    }

    return YES;
}

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
        tableView.rowHeight = 80.0f;
    else
        tableView.rowHeight = 68.0f;

    tableView.backgroundColor = [UIColor blackColor];
}

580
@end