Commit d0eeb1ef authored by Pierre SAGASPE's avatar Pierre SAGASPE Committed by Felix Paul Kühne
Browse files

LocalServer: Add Plex web server support for stream or download with external subtitle


Signed-off-by: Felix Paul Kühne's avatarFelix Paul Kühne <fkuehne@videolan.org>
parent 62d94a16
/*****************************************************************************
* VLCLocalPlexFolderListViewController.h
* VLC for iOS
*****************************************************************************
* Copyright (c) 2014 VideoLAN. All rights reserved.
*
* 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.
*****************************************************************************/
#import <UIKit/UIKit.h>
@interface VLCLocalPlexFolderListViewController : UIViewController
@property (nonatomic, strong) UITableView *tableView;
- (id)initWithPlexServer:(NSString *)serverName serverAddress:(NSString *)serverAddress portNumber:(NSString *)portNumber atPath:(NSString *)path;
@end
/*****************************************************************************
* VLCLocalPlexFolderListViewController.m
* VLC for iOS
*****************************************************************************
* Copyright (c) 2014 VideoLAN. All rights reserved.
*
* 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.
*****************************************************************************/
#import "VLCLocalPlexFolderListViewController.h"
#import "VLCPlexParser.h"
#import "VLCLocalNetworkListCell.h"
#import "VLCAppDelegate.h"
#import "VLCPlaylistViewController.h"
#import "UINavigationController+Theme.h"
#import "VLCDownloadViewController.h"
#import "NSString+SupportedMedia.h"
#import "VLCStatusLabel.h"
@interface VLCLocalPlexFolderListViewController () <UITableViewDataSource, UITableViewDelegate, VLCLocalNetworkListCell, UISearchBarDelegate, UISearchDisplayDelegate>
{
UIBarButtonItem *_backButton;
NSMutableArray *_mutableObjectList;
NSString *_PlexServerName;
NSString *_PlexServerAddress;
NSString *_PlexServerPort;
NSString *_PlexServerPath;
VLCPlexParser *_PlexParser;
NSMutableArray *_searchData;
UISearchBar *_searchBar;
UISearchDisplayController *_searchDisplayController;
}
@end
@implementation VLCLocalPlexFolderListViewController
- (void)loadView
{
_tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
_tableView.backgroundColor = [UIColor colorWithWhite:.122 alpha:1.];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.rowHeight = [VLCLocalNetworkListCell heightOfCell];
self.view = _tableView;
}
- (id)initWithPlexServer:(NSString *)serverName serverAddress:(NSString *)serverAddress portNumber:(NSString *)portNumber atPath:(NSString *)path
{
self = [super init];
if (self) {
_PlexServerName = serverName;
_PlexServerAddress = serverAddress;
_PlexServerPort = portNumber;
_PlexServerPath = path;
_mutableObjectList = [[NSMutableArray alloc] init];
_PlexParser = [[VLCPlexParser alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[_mutableObjectList removeAllObjects];
_mutableObjectList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:_PlexServerPath];
self.tableView.separatorColor = [UIColor colorWithWhite:.122 alpha:1.];
self.view.backgroundColor = [UIColor colorWithWhite:.122 alpha:1.];
NSString *titleValue;
if ([_PlexServerPath isEqualToString:@""])
titleValue = _PlexServerName;
else
titleValue = [_PlexServerPath lastPathComponent];
self.title = titleValue;
_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;
if (SYSTEM_RUNS_IOS7_OR_LATER)
_searchDisplayController.searchBar.searchBarStyle = UIBarStyleBlack;
_searchBar.delegate = self;
self.tableView.tableHeaderView = _searchBar;
_searchData = [[NSMutableArray alloc] init];
[_searchData removeAllObjects];
}
- (BOOL)shouldAutorotate
{
UIInterfaceOrientation toInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
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
{
if (tableView == self.searchDisplayController.searchResultsTableView)
return _searchData.count;
else
return _mutableObjectList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"PlexCellDetail";
VLCLocalNetworkListCell *cell = (VLCLocalNetworkListCell *)[[self tableView] dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [VLCLocalNetworkListCell cellWithReuseIdentifier:CellIdentifier];
NSMutableArray *ObjList = [[NSMutableArray alloc] init];
[ObjList removeAllObjects];
if (tableView == self.searchDisplayController.searchResultsTableView)
[ObjList addObjectsFromArray:_searchData];
else
[ObjList addObjectsFromArray:_mutableObjectList];
[cell setTitle:[[ObjList objectAtIndex:indexPath.row] objectForKey:@"title"]];
NSString *thumbPath = [[ObjList objectAtIndex:indexPath.row] objectForKey:@"thumb"];
if (thumbPath)
[cell setIconURL:[NSURL URLWithString:thumbPath]];
if ([[[ObjList objectAtIndex:indexPath.row] objectForKey:@"container"] isEqualToString:@"item"]) {
NSInteger size = [[[ObjList objectAtIndex:indexPath.row] objectForKey:@"size"] integerValue];
NSString *mediaSize = [NSByteCountFormatter stringFromByteCount:size countStyle:NSByteCountFormatterCountStyleFile];
NSString *durationInSeconds = [[ObjList objectAtIndex:indexPath.row] objectForKey:@"duration"];
[cell setIsDirectory:NO];
[cell setIcon:[UIImage imageNamed:@"blank"]];
[cell setSubtitle:[NSString stringWithFormat:@"%@ (%@)", mediaSize, durationInSeconds]];
[cell setIsDownloadable:YES];
[cell setDelegate:self];
} else {
[cell setIsDirectory:YES];
[cell setIcon:[UIImage imageNamed:@"folder"]];
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(VLCLocalNetworkListCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIColor *color = (indexPath.row % 2 == 0)? [UIColor blackColor]: [UIColor colorWithWhite:.122 alpha:1.];
cell.contentView.backgroundColor = cell.titleLabel.backgroundColor = cell.folderTitleLabel.backgroundColor = cell.subtitleLabel.backgroundColor = color;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *ObjList = [[NSMutableArray alloc] init];
[ObjList removeAllObjects];
NSString *newPath = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
[ObjList addObjectsFromArray:_searchData];
else
[ObjList addObjectsFromArray:_mutableObjectList];
NSString *keyValue = [[ObjList objectAtIndex:indexPath.row] objectForKey:@"key"];
if ([keyValue rangeOfString:@"library"].location == NSNotFound)
newPath = [_PlexServerPath stringByAppendingPathComponent:keyValue];
else
newPath = keyValue;
if ([[[ObjList objectAtIndex:indexPath.row] objectForKey:@"container"] isEqualToString:@"item"]) {
[ObjList removeAllObjects];
ObjList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:newPath];
NSString *URLofSubtitle = nil;
if ([[ObjList objectAtIndex:0] objectForKey:@"keySubtitle"])
URLofSubtitle = [self _getFileSubtitleFromPlexServer:ObjList modeStream:YES];
NSURL *itemURL = [NSURL URLWithString:[[ObjList objectAtIndex:0] objectForKey:@"keyMedia"]];
if (itemURL) {
VLCAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate openMovieWithExternalSubtitleFromURL:itemURL externalSubURL:URLofSubtitle];
}
} else {
VLCLocalPlexFolderListViewController *targetViewController = [[VLCLocalPlexFolderListViewController alloc] initWithPlexServer:_PlexServerName serverAddress:_PlexServerAddress portNumber:_PlexServerPort atPath:newPath];
[[self navigationController] pushViewController:targetViewController animated:YES];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
#pragma mark - Specifics
- (void)_downloadFileFromMediaItem:(NSMutableArray *)mutableMediaObject
{
NSURL *itemURL = [NSURL URLWithString:[[mutableMediaObject objectAtIndex:0] objectForKey:@"keyMedia"]];
if (![[itemURL absoluteString] isSupportedFormat]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"FILE_NOT_SUPPORTED", @"") message:[NSString stringWithFormat:NSLocalizedString(@"FILE_NOT_SUPPORTED_LONG", @""), [itemURL absoluteString]] delegate:self cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", @"") otherButtonTitles:nil];
[alert show];
} else if (itemURL) {
NSString *fileName = [[mutableMediaObject objectAtIndex:0] objectForKey:@"namefile"];
[[(VLCAppDelegate *)[UIApplication sharedApplication].delegate downloadViewController] addURLToDownloadList:itemURL fileNameOfMedia:fileName];
}
}
- (NSString *)_getFileSubtitleFromPlexServer:(NSMutableArray *)mutableMediaObject modeStream:(BOOL)modeStream
{
NSURL *url = [NSURL URLWithString:[[mutableMediaObject objectAtIndex:0] objectForKey:@"keySubtitle"]];
NSString *receivedSub = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSArray *searchPaths = nil;
if (modeStream)
searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
else
searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directoryPath = [searchPaths objectAtIndex:0];
NSString *FileSubtitlePath = [[directoryPath stringByAppendingPathComponent:[[[mutableMediaObject objectAtIndex:0] objectForKey:@"namefile"] stringByDeletingPathExtension]] stringByAppendingPathExtension:[[mutableMediaObject objectAtIndex:0] objectForKey:@"codecSubtitle"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:FileSubtitlePath]) {
[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;
}
#pragma mark - VLCLocalNetworkListCell delegation
- (void)triggerDownloadForCell:(VLCLocalNetworkListCell *)cell
{
NSMutableArray *ObjList = [[NSMutableArray alloc] init];
[ObjList removeAllObjects];
if ([self.searchDisplayController isActive])
[ObjList addObject:_searchData[[self.searchDisplayController.searchResultsTableView indexPathForCell:cell].row]];
else
[ObjList addObject:_mutableObjectList[[self.tableView indexPathForCell:cell].row]];
NSString *path = [[ObjList objectAtIndex:0] objectForKey:@"key"];
[ObjList removeAllObjects];
ObjList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:path];
if ([[ObjList objectAtIndex:0] objectForKey:@"keySubtitle"])
[self _getFileSubtitleFromPlexServer:ObjList modeStream:NO];
[self _downloadFileFromMediaItem:ObjList];
[cell.statusLabel showStatusMessage:NSLocalizedString(@"DOWNLOADING", @"")];
}
#pragma mark - Search Display Controller Delegate
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[_searchData removeAllObjects];
for (int i = 0; i < [_mutableObjectList count]; i++) {
NSRange nameRange;
nameRange = [[[_mutableObjectList objectAtIndex:i] objectForKey:@"title"] rangeOfString:searchString options:NSCaseInsensitiveSearch];
if (nameRange.location != NSNotFound)
[_searchData addObject:_mutableObjectList[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];
}
@end
......@@ -18,6 +18,7 @@
#import "UPnPManager.h"
#import "VLCLocalNetworkListCell.h"
#import "VLCLocalServerFolderListViewController.h"
#import "VLCLocalPlexFolderListViewController.h"
#import <QuartzCore/QuartzCore.h>
#import "GHRevealViewController.h"
#import "VLCNetworkLoginViewController.h"
......@@ -304,9 +305,12 @@
[self.navigationController pushViewController:targetViewController animated:YES];
}
} else if (section == 1) {
//target Plex servers here
APLog(@"Hello I'm a Plex Media Server, my name is %@ my adress is %@%@", [_PlexServicesInfo[row] objectForKey:@"name"], [_PlexServicesInfo[row] objectForKey:@"hostName"], [_PlexServicesInfo[row] objectForKey:@"port"]);
} else if (section == 2) {
NSString *name = [_PlexServicesInfo[row] objectForKey:@"name"];
NSString *hostName = [_PlexServicesInfo[row] objectForKey:@"hostName"];
NSString *portNum = [_PlexServicesInfo[row] objectForKey:@"port"];
VLCLocalPlexFolderListViewController *targetViewController = [[VLCLocalPlexFolderListViewController alloc] initWithPlexServer:name serverAddress:hostName portNumber:portNum atPath:@""];
[[self navigationController] pushViewController:targetViewController animated:YES];
} else if (section == 2) {
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_loginViewController];
[navCon loadTheme];
navCon.navigationBarHidden = NO;
......@@ -328,7 +332,7 @@
else
_loginViewController.hostname = @"";
} else if (section == 3) {
VLCAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
VLCAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate openMovieFromURL:[[_sapDiscoverer.discoveredMedia mediaAtIndex:row] url]];
}
}
......
/*****************************************************************************
* VLCPlexParser.h
* VLC for iOS
*****************************************************************************
* Copyright (c) 2014 VideoLAN. All rights reserved.
*
* Authors: Pierre Sagaspe <pierre.sagaspe # me.com>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <UIKit/UIKit.h>
@interface VLCPlexParser : NSObject
- (NSMutableArray *)PlexMediaServerParser:(NSString *)adress port:(NSString *)port navigationPath:(NSString *)navPath;
@end
/*****************************************************************************
* VLCPlexParser.m
* VLC for iOS
*****************************************************************************
* Copyright (c) 2014 VideoLAN. All rights reserved.
*
* Authors: Pierre Sagaspe <pierre.sagaspe # me.com>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "VLCPlexParser.h"
#define kPlexMediaServerDirInit @"library/sections"
@interface VLCPlexParser () <NSXMLParserDelegate>
{
NSMutableArray *_containerInfo;
NSMutableDictionary *_dicoInfo;
NSString *_PlexMediaServerUrl;
}
@end
@implementation VLCPlexParser
- (NSMutableArray *)PlexMediaServerParser:(NSString *)adress port:(NSString *)port navigationPath:(NSString *)path
{
_containerInfo = [[NSMutableArray alloc] init];
[_containerInfo removeAllObjects];
_dicoInfo = [[NSMutableDictionary alloc] init];
_PlexMediaServerUrl = [NSString stringWithFormat:@"http://%@%@",adress, port];
NSString *mediaServerUrl;
if ([path isEqualToString:@""])
mediaServerUrl = [NSString stringWithFormat:@"%@/%@",_PlexMediaServerUrl, kPlexMediaServerDirInit];
else {
if ([path rangeOfString:@"library"].location != NSNotFound)
mediaServerUrl = [NSString stringWithFormat:@"%@%@",_PlexMediaServerUrl, path];
else
mediaServerUrl = [NSString stringWithFormat:@"%@/%@/%@",_PlexMediaServerUrl, kPlexMediaServerDirInit, path];
}
NSURL *url = [[NSURL alloc] initWithString:mediaServerUrl];
NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[xmlparser setDelegate:self];
if (![xmlparser parse])
APLog(@"PlexParser url Errors : %@", url);
return _containerInfo;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"MediaContainer"]) {
if ([attributeDict objectForKey:@"friendlyName"])
[_dicoInfo setObject:[attributeDict objectForKey:@"friendlyName"] forKey:@"libTitle"];
else if ([attributeDict objectForKey:@"title1"])
[_dicoInfo setObject:[attributeDict objectForKey:@"title1"] forKey:@"libTitle"];
} else if([elementName isEqualToString:@"Directory"]) {
[_dicoInfo setObject:@"directory" forKey:@"container"];
[_dicoInfo setObject:[attributeDict objectForKey:@"key"] forKey:@"key"];
[_dicoInfo setObject:[attributeDict objectForKey:@"title"] forKey:@"title"];
} else if([elementName isEqualToString:@"Video"]) {
[_dicoInfo setObject:@"item" forKey:@"container"];
[_dicoInfo setObject:[attributeDict objectForKey:@"key"] forKey:@"key"];
[_dicoInfo setObject:[attributeDict objectForKey:@"title"] forKey:@"title"];
} else if([elementName isEqualToString:@"Part"]) {
[_dicoInfo setObject:[NSString stringWithFormat:@"%@%@",_PlexMediaServerUrl, [attributeDict objectForKey:@"key"]] forKey:@"keyMedia"];
if([attributeDict objectForKey:@"file"])
[_dicoInfo setObject:[[attributeDict objectForKey:@"file"] lastPathComponent] forKey:@"namefile"];
NSString *duration = [self timeFormatted:[[attributeDict objectForKey:@"duration"] intValue]];
[_dicoInfo setObject:duration forKey:@"duration"];
NSString *sizeFile = (NSString *)[attributeDict objectForKey:@"size"];
[_dicoInfo setObject:sizeFile forKey:@"size"];
} else if([elementName isEqualToString:@"Stream"]) {
if([attributeDict objectForKey:@"key"]){
[_dicoInfo setObject:[NSString stringWithFormat:@"%@%@",_PlexMediaServerUrl, [attributeDict objectForKey:@"key"]] forKey:@"keySubtitle"];
[_dicoInfo setObject:[attributeDict objectForKey:@"codec"] forKey:@"codecSubtitle"];
[_dicoInfo setObject:[attributeDict objectForKey:@"language"] forKey:@"languageSubtitle"];
}
}
if ([attributeDict objectForKey:@"thumb"] && ([elementName isEqualToString:@"Video"] || [elementName isEqualToString:@"Directory"] || [elementName isEqualToString:@"Part"]))
[_dicoInfo setObject:[NSString stringWithFormat:@"%@%@", _PlexMediaServerUrl, [attributeDict objectForKey:@"thumb"]] forKey:@"thumb"];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if(([elementName isEqualToString:@"Video"] || [elementName isEqualToString:@"Directory"] || [elementName isEqualToString:@"MediaContainer"]) && [_dicoInfo count] > 0) {
[_containerInfo addObject:_dicoInfo];
_dicoInfo = [[NSMutableDictionary alloc] init];
}
}
- (NSString *)timeFormatted:(int)mSeconds
{
mSeconds = (int)(mSeconds / 1000);
int seconds = (int)(mSeconds % 60);
int minutes = (int)((mSeconds / 60) % 60);
int hours = (int)(mSeconds / 3600);
return [NSString stringWithFormat:@"%02d:%02d:%02d",hours, minutes, seconds];
}
@end
\ No newline at end of file
......@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
265D511C1922746C00E38383 /* VLCLocalPlexFolderListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 265D51191922746C00E38383 /* VLCLocalPlexFolderListViewController.m */; };
265D511D1922746C00E38383 /* VLCPlexParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 265D511B1922746C00E38383 /* VLCPlexParser.m */; };
29125E5617492219003F03E5 /* index.html in Resources */ = {isa = PBXBuildFile; fileRef = 29125E5417492219003F03E5 /* index.html */; };
2915540117490A1E00B86CAD /* DDData.m in Sources */ = {isa = PBXBuildFile; fileRef = 291553EB17490A1E00B86CAD /* DDData.m */; };
2915540217490A1E00B86CAD /* DDNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 291553ED17490A1E00B86CAD /* DDNumber.m */; };
......@@ -405,6 +407,10 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
265D51181922746C00E38383 /* VLCLocalPlexFolderListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCLocalPlexFolderListViewController.h; path = Sources/VLCLocalPlexFolderListViewController.h; sourceTree = SOURCE_ROOT; };
265D51191922746C00E38383 /* VLCLocalPlexFolderListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCLocalPlexFolderListViewController.m; path = Sources/VLCLocalPlexFolderListViewController.m; sourceTree = SOURCE_ROOT; };
265D511A1922746C00E38383 /* VLCPlexParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCPlexParser.h; path = Sources/VLCPlexParser.h; sourceTree = SOURCE_ROOT; };
265D511B1922746C00E38383 /* VLCPlexParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlexParser.m; path = Sources/VLCPlexParser.m; sourceTree = SOURCE_ROOT; };
29125E5417492219003F03E5 /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = "<group>"; };
291553EA17490A1E00B86CAD /* DDData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDData.h; sourceTree = "<group>"; };
291553EB17490A1E00B86CAD /* DDData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDData.m; sourceTree = "<group>"; };
......@@ -1488,10 +1494,14 @@
7D31002117B676D500E6516D /* Local Network Connectivity */ = {
isa = PBXGroup;
children = (
265D511A1922746C00E38383 /* VLCPlexParser.h */,
265D511B1922746C00E38383 /* VLCPlexParser.m */,
7D30F3D1183AB2F100FFC021 /* VLCLocalNetworkListCell.h */,
7D30F3D2183AB2F100FFC021 /* VLCLocalNetworkListCell.m */,
7D30F3D3183AB2F100FFC021 /* VLCLocalServerFolderListViewController.h */,
7D30F3D4183AB2F100FFC021 /* VLCLocalServerFolderListViewController.m */,
265D51181922746C00E38383 /* VLCLocalPlexFolderListViewController.h */,
265D51191922746C00E38383 /* VLCLocalPlexFolderListViewController.m */,
7D30F3D5183AB2F100FFC021 /* VLCLocalServerListViewController.h */,
7D30F3D6183AB2F100FFC021 /* VLCLocalServerListViewController.m */,
7D30F3DA183AB2F900FFC021 /* VLCNetworkLoginViewController.h */,
......@@ -2691,7 +2701,9 @@
7D30F3CA183AB27A00FFC021 /* VLCDownloadViewController.m in Sources */,
7D30F3CD183AB29300FFC021 /* VLCMenuTableViewController.m in Sources */,
7D30F3D0183AB2AC00FFC021 /* VLCMediaFileDiscoverer.m in Sources */,
265D511D1922746C00E38383 /* VLCPlexParser.m in Sources */,
7D30F3D7183AB2F100FFC021 /* VLCLocalNetworkListCell.m in Sources */,
265D511C1922746C00E38383 /* VLCLocalPlexFolderListViewController.m in Sources */,
7D30F3D8183AB2F100FFC021 /* VLCLocalServerFolderListViewController.m in Sources */,
7D30F3D9183AB2F100FFC021 /* VLCLocalServerListViewController.m in Sources */,
7D30F3DC183AB2F900FFC021 /* VLCNetworkLoginViewController.m in Sources */,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment