Browse Source

replace VLCLocalPlexFolderListViewController with VLCNetworkServerBrowserPlex

Tobias Conradi 9 years ago
parent
commit
781377d0cb

+ 0 - 21
Sources/LocalNetworkConnectivity/Plex/VLCLocalPlexFolderListViewController.h

@@ -1,21 +0,0 @@
-/*****************************************************************************
- * VLCLocalPlexFolderListViewController.h
- * VLC for iOS
- *****************************************************************************
- * Copyright (c) 2014-2015 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 authentification:(NSString *)auth;
-
-@end

+ 0 - 506
Sources/LocalNetworkConnectivity/Plex/VLCLocalPlexFolderListViewController.m

@@ -1,506 +0,0 @@
-/*****************************************************************************
- * VLCLocalPlexFolderListViewController.m
- * VLC for iOS
- *****************************************************************************
- * Copyright (c) 2014-2015 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 "VLCPlexMediaInformationViewController.h"
-#import "VLCPlexParser.h"
-#import "VLCPlexWebAPI.h"
-#import "VLCNetworkListCell.h"
-#import "VLCPlaybackController.h"
-#import "VLCLibraryViewController.h"
-#import "VLCDownloadViewController.h"
-#import "NSString+SupportedMedia.h"
-#import "VLCStatusLabel.h"
-#import "UIDevice+VLC.h"
-
-@interface VLCLocalPlexFolderListViewController () <UITableViewDataSource, UITableViewDelegate, VLCNetworkListCellDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
-{
-    NSArray *_globalObjectList;
-    NSCache *_imageCache;
-
-    NSString *_PlexServerName;
-    NSString *_PlexServerAddress;
-    NSString *_PlexServerPort;
-    NSString *_PlexServerPath;
-    NSString *_PlexAuthentification;
-
-    VLCPlexParser *_PlexParser;
-    VLCPlexWebAPI *_PlexWebAPI;
-
-    NSMutableArray *_searchData;
-    UISearchBar *_searchBar;
-    UISearchDisplayController *_searchDisplayController;
-    UIRefreshControl *_refreshControl;
-    UIBarButtonItem *_menuButton;
-    UITapGestureRecognizer *_tapTwiceGestureRecognizer;
-}
-@end
-
-@implementation VLCLocalPlexFolderListViewController
-
-- (void)dealloc
-{
-    [_tapTwiceGestureRecognizer removeTarget:self action:NULL];
-}
-
-- (void)loadView
-{
-    _tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
-    _tableView.backgroundColor = [UIColor VLCDarkBackgroundColor];
-    CGRect frame = _tableView.bounds;
-    frame.origin.y = -frame.size.height;
-    UIView *topView = [[UIView alloc] initWithFrame:frame];
-    topView.backgroundColor = [UIColor VLCDarkBackgroundColor];
-    [_tableView addSubview:topView];
-    _tableView.delegate = self;
-    _tableView.dataSource = self;
-    _tableView.rowHeight = [VLCNetworkListCell heightOfCell];
-    _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
-    _tableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
-    self.view = _tableView;
-}
-
-- (id)initWithPlexServer:(NSString *)serverName serverAddress:(NSString *)serverAddress portNumber:(NSString *)portNumber atPath:(NSString *)path authentification:(NSString *)auth
-{
-    self = [super init];
-    if (self) {
-        _PlexServerName = serverName;
-        _PlexServerAddress = serverAddress;
-        _PlexServerPort = portNumber;
-        _PlexServerPath = path;
-
-        _PlexAuthentification = auth;
-
-        _globalObjectList = [[NSArray alloc] init];
-        _imageCache = [[NSCache alloc] init];
-        [_imageCache setCountLimit:50];
-
-        _PlexParser = [[VLCPlexParser alloc] init];
-    }
-    return self;
-}
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-
-    self.tableView.separatorColor = [UIColor VLCDarkBackgroundColor];
-    self.view.backgroundColor = [UIColor VLCDarkBackgroundColor];
-
-    _PlexWebAPI = [[VLCPlexWebAPI alloc] init];
-
-    self.title = _PlexServerName;
-
-    _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
-    UINavigationBar *navBar = self.navigationController.navigationBar;
-    _searchBar.barTintColor = navBar.barTintColor;
-    _searchBar.tintColor = navBar.tintColor;
-    _searchBar.translucent = navBar.translucent;
-    _searchBar.opaque = navBar.opaque;
-    _searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
-    _searchDisplayController.delegate = self;
-    _searchDisplayController.searchResultsDataSource = self;
-    _searchDisplayController.searchResultsDelegate = self;
-    _searchDisplayController.searchBar.searchBarStyle = UIBarStyleBlack;
-    _searchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
-    _searchDisplayController.searchResultsTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
-    _searchBar.delegate = self;
-    _searchBar.hidden = YES;
-    //self.tableView.tableHeaderView = _searchBar;
-    //self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(_searchBar.frame)); // -> hide search bar to load
-
-    _tapTwiceGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self  action:@selector(tapTwiceGestureAction:)];
-    [_tapTwiceGestureRecognizer setNumberOfTapsRequired:2];
-    [self.navigationController.navigationBar addGestureRecognizer:_tapTwiceGestureRecognizer];
-
-    // Active le Pull down to refresh
-    _refreshControl = [[UIRefreshControl alloc] init];
-    _refreshControl.backgroundColor = [UIColor VLCDarkBackgroundColor];
-    _refreshControl.tintColor = [UIColor whiteColor];
-    // Call the refresh function
-    [_refreshControl addTarget:self action:@selector(handleRefresh) forControlEvents:UIControlEventValueChanged];
-    [self.tableView addSubview:_refreshControl];
-
-    _menuButton = [UIBarButtonItem themedRevealMenuButtonWithTarget:self andSelector:@selector(menuButtonAction:)];
-    self.navigationItem.rightBarButtonItem = _menuButton;
-
-    _globalObjectList = [[NSArray alloc] init];
-    _searchData = [[NSMutableArray alloc] init];
-
-    [self performSelectorInBackground:@selector(loadContents) withObject:nil];
-}
-
-- (void)loadContents
-{
-    _globalObjectList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:_PlexServerPath authentification:_PlexAuthentification];
-    NSDictionary *firstObject = [_globalObjectList firstObject];
-
-    if (_globalObjectList.count == 0 || firstObject == nil)
-        _PlexAuthentification = @"";
-    else
-        _PlexAuthentification = [firstObject objectForKey:@"authentification"];
-
-    NSString *titleValue;
-    if ([_PlexServerPath isEqualToString:@""] || _globalObjectList.count == 0 || firstObject == nil)
-        titleValue = _PlexServerName;
-    else
-        titleValue = [firstObject objectForKey:@"libTitle"];
-    self.title = titleValue;
-
-    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
-}
-
-- (BOOL)shouldAutorotate
-{
-    UIInterfaceOrientation toInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
-    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
-        return NO;
-    return YES;
-}
-
-- (IBAction)menuButtonAction:(id)sender
-{
-    [[VLCSidebarController sharedInstance] toggleSidebar];
-
-    if (self.isEditing)
-        [self setEditing:NO animated: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 _globalObjectList.count;
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    static NSString *CellIdentifier = @"PlexCellDetail";
-
-    VLCNetworkListCell *cell = (VLCNetworkListCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
-
-    if (cell == nil)
-        cell = [VLCNetworkListCell cellWithReuseIdentifier:CellIdentifier];
-
-    NSDictionary *cellObject;
-
-    if (tableView == self.searchDisplayController.searchResultsTableView)
-        cellObject = _searchData[indexPath.row];
-    else
-        cellObject = _globalObjectList[indexPath.row];
-
-    [cell setTitle:cellObject[@"title"]];
-    [cell setIcon:[UIImage imageNamed:@"blank"]];
-
-    NSString *thumbPath = cellObject[@"thumb"];
-    if (thumbPath) {
-        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
-        dispatch_async(queue, ^{
-            UIImage *img = [self getCachedImage:[self _urlAuth:thumbPath]];
-            dispatch_async(dispatch_get_main_queue(), ^{
-                if (!img)
-                    [cell setIcon:[UIImage imageNamed:@"blank"]];
-                else
-                    [cell setIcon:img];
-            });
-        });
-    }
-
-    if ([cellObject[@"container"] isEqualToString:@"item"]) {
-        UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRightGestureAction:)];
-        [swipeRight setDirection:(UISwipeGestureRecognizerDirectionRight)];
-        [cell addGestureRecognizer:swipeRight];
-        UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longTouchGestureAction:)];
-        [cell addGestureRecognizer:longPressGestureRecognizer];
-        NSInteger size = [cellObject[@"size"] integerValue];
-        NSString *mediaSize = [NSByteCountFormatter stringFromByteCount:size countStyle:NSByteCountFormatterCountStyleFile];
-        NSString *durationInSeconds = cellObject[@"duration"];
-        [cell setIsDirectory:NO];
-        [cell setSubtitle:[NSString stringWithFormat:@"%@ (%@)", mediaSize, durationInSeconds]];
-        [cell setIsDownloadable:YES];
-        [cell setDelegate:self];
-    } else {
-        [cell setIsDirectory:YES];
-        if (!thumbPath)
-            [cell setIcon:[UIImage imageNamed:@"folder"]];
-    }
-    return cell;
-}
-
-- (UIImage *)getCachedImage:(NSString *)url
-{
-    UIImage *image = [_imageCache objectForKey:url];
-    if ((image != nil) && [image isKindOfClass:[UIImage class]]) {
-        return image;
-    } else {
-        NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
-        if (imageData) {
-            image = [[UIImage alloc] initWithData:imageData];
-            if (image)
-                [_imageCache setObject:image forKey:url];
-        }
-        return image;
-    }
-}
-
-#pragma mark - Table view delegate
-
-- (void)tableView:(UITableView *)tableView willDisplayCell:(VLCNetworkListCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    UIColor *color = (indexPath.row % 2 == 0)? [UIColor blackColor]: [UIColor VLCDarkBackgroundColor];
-    cell.contentView.backgroundColor = cell.titleLabel.backgroundColor = cell.folderTitleLabel.backgroundColor = cell.subtitleLabel.backgroundColor =  color;
-}
-
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    NSArray *objectList;
-    NSString *newPath = nil;
-
-    if (tableView == self.searchDisplayController.searchResultsTableView)
-        objectList = [_searchData copy];
-    else
-        objectList = _globalObjectList;
-
-    NSDictionary *rowObject = objectList[indexPath.row];
-
-    NSString *keyValue = [rowObject objectForKey:@"key"];
-
-    if ([keyValue rangeOfString:@"library"].location == NSNotFound)
-        newPath = [_PlexServerPath stringByAppendingPathComponent:keyValue];
-    else
-        newPath = keyValue;
-
-    if ([rowObject[@"container"] isEqualToString:@"item"]) {
-        objectList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:newPath authentification:_PlexAuthentification];
-        NSString *URLofSubtitle = nil;
-
-        NSDictionary *firstObject = [objectList firstObject];
-        if (!firstObject)
-            return;
-
-        if ([firstObject objectForKey:@"keySubtitle"])
-            URLofSubtitle = [_PlexWebAPI getFileSubtitleFromPlexServer:firstObject modeStream:YES];
-
-        NSURL *itemURL = [NSURL URLWithString:[self _urlAuth:firstObject[@"keyMedia"]]];
-        if (itemURL) {
-            VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
-            [vpc playURL:itemURL subtitlesFilePath:URLofSubtitle];
-        }
-    } else {
-        VLCLocalPlexFolderListViewController *targetViewController = [[VLCLocalPlexFolderListViewController alloc] initWithPlexServer:_PlexServerName serverAddress:_PlexServerAddress portNumber:_PlexServerPort atPath:newPath authentification:_PlexAuthentification];
-        [[self navigationController] pushViewController:targetViewController animated:YES];
-    }
-    [tableView deselectRowAtIndexPath:indexPath animated:NO];
-}
-
-#pragma mark - Specifics
-
-- (NSString *)_urlAuth:(NSString *)url
-{
-    return [_PlexWebAPI urlAuth:url autentification:_PlexAuthentification];
-}
-
-- (void)_playMediaItem:(NSDictionary *)mediaObject
-{
-    NSString *newPath = nil;
-    NSString *keyValue = [mediaObject objectForKey:@"key"];
-
-    if ([keyValue rangeOfString:@"library"].location == NSNotFound)
-        newPath = [_PlexServerPath stringByAppendingPathComponent:keyValue];
-    else
-        newPath = keyValue;
-
-    if ([[mediaObject objectForKey:@"container"] isEqualToString:@"item"]) {
-        NSArray *mediaList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:newPath authentification:_PlexAuthentification];
-        NSString *URLofSubtitle = nil;
-        NSDictionary *firstObject = [mediaList firstObject];
-        if (!firstObject)
-            return;
-
-        if ([firstObject objectForKey:@"keySubtitle"])
-            URLofSubtitle = [_PlexWebAPI getFileSubtitleFromPlexServer:firstObject modeStream:YES];
-
-        NSURL *itemURL = [NSURL URLWithString:[self _urlAuth:[firstObject objectForKey:@"keyMedia"]]];
-        if (itemURL) {
-            VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
-            [vpc playURL:itemURL subtitlesFilePath:URLofSubtitle];
-        }
-    }
-}
-
-- (void)_downloadFileFromMediaItem:(NSDictionary *)mediaObject
-{
-    if (!mediaObject)
-        return;
-
-    NSURL *itemURL = [NSURL URLWithString:[mediaObject objectForKey:@"keyMedia"]];
-
-    if (![[itemURL absoluteString] isSupportedFormat]) {
-        VLCAlertView *alert = [[VLCAlertView alloc] initWithTitle:NSLocalizedString(@"FILE_NOT_SUPPORTED", nil)
-                                                         message:[NSString stringWithFormat:NSLocalizedString(@"FILE_NOT_SUPPORTED_LONG", nil), [itemURL absoluteString]]
-                                                         delegate:self
-                                                cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", nil)
-                                                otherButtonTitles:nil];
-        [alert show];
-    } else if (itemURL) {
-        NSString *fileName = [mediaObject objectForKey:@"namefile"];
-        [[VLCDownloadViewController sharedInstance] addURLToDownloadList:itemURL fileNameOfMedia:fileName];
-    }
-}
-
-- (void)swipeRightGestureAction:(UIGestureRecognizer *)recognizer
-{
-    NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:[recognizer locationInView:self.tableView]];
-    UITableViewCell *swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
-
-    VLCNetworkListCell *cell = (VLCNetworkListCell *)[[self tableView] cellForRowAtIndexPath:swipedIndexPath];
-
-    NSDictionary *cellObject = _globalObjectList[[self.tableView indexPathForCell:swipedCell].row];
-
-    NSString *ratingKey = cellObject[@"ratingKey"];
-    NSString *tag = cellObject[@"state"];
-    NSString *cellStatusLbl = nil;
-
-    NSInteger status = [_PlexWebAPI MarkWatchedUnwatchedMedia:_PlexServerAddress port:_PlexServerPort videoRatingKey:ratingKey state:tag authentification:_PlexAuthentification];
-
-    if (status == 200) {
-        if ([tag isEqualToString:@"watched"]) {
-            tag = @"unwatched";
-            cellStatusLbl = NSLocalizedString(@"PLEX_UNWATCHED", nil);
-        } else if ([tag isEqualToString:@"unwatched"]) {
-            tag = @"watched";
-            cellStatusLbl = NSLocalizedString(@"PLEX_WATCHED", nil);
-        }
-    } else
-        cellStatusLbl = NSLocalizedString(@"PLEX_ERROR_MARK", nil);
-
-    [cell.statusLabel showStatusMessage:cellStatusLbl];
-
-    [_globalObjectList[[self.tableView indexPathForCell:swipedCell].row] setObject:tag forKey:@"state"];
-}
-
-- (void)reloadTableViewPlex
-{
-    _globalObjectList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:_PlexServerPath authentification:_PlexAuthentification];
-    [self.tableView reloadData];
-}
-
-#pragma mark - VLCNetworkListCell delegation
-
-- (void)triggerDownloadForCell:(VLCNetworkListCell *)cell
-{
-    NSDictionary *cellObject;
-
-    if ([self.searchDisplayController isActive])
-        cellObject = _searchData[[self.searchDisplayController.searchResultsTableView indexPathForCell:cell].row];
-    else
-        cellObject = _globalObjectList[[self.tableView indexPathForCell:cell].row];
-
-    NSString *path = cellObject[@"key"];
-
-    NSArray *mediaList = [_PlexParser PlexMediaServerParser:_PlexServerAddress port:_PlexServerPort navigationPath:path authentification:_PlexAuthentification];
-    NSDictionary *firstObject = [mediaList firstObject];
-
-    NSInteger size = [[firstObject objectForKey:@"size"] integerValue];
-    if (size  < [[UIDevice currentDevice] freeDiskspace].longLongValue) {
-        if ([firstObject objectForKey:@"keySubtitle"])
-            [_PlexWebAPI getFileSubtitleFromPlexServer:firstObject modeStream:NO];
-
-        [self _downloadFileFromMediaItem:firstObject];
-        [cell.statusLabel showStatusMessage:NSLocalizedString(@"DOWNLOADING", nil)];
-    } else {
-        VLCAlertView *alert = [[VLCAlertView alloc] initWithTitle:NSLocalizedString(@"DISK_FULL", nil)
-                                                          message:[NSString stringWithFormat:NSLocalizedString(@"DISK_FULL_FORMAT", nil), [firstObject objectForKey:@"title"], [[UIDevice currentDevice] model]]
-                                                         delegate:self
-                                                cancelButtonTitle:NSLocalizedString(@"BUTTON_OK", nil)
-                                                otherButtonTitles:nil];
-        [alert show];
-    }
-}
-
-#pragma mark - Search Display Controller Delegate
-
-- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
-{
-    [_searchData removeAllObjects];
-
-    NSUInteger count = _globalObjectList.count;
-    for (NSUInteger i = 0; i < count; i++) {
-        NSRange nameRange;
-        nameRange = [[_globalObjectList[i] objectForKey:@"title"] rangeOfString:searchString options:NSCaseInsensitiveSearch];
-        if (nameRange.location != NSNotFound)
-            [_searchData addObject:_globalObjectList[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];
-}
-
-#pragma mark - Refresh
-
--(void)handleRefresh
-{
-    //set the title while refreshing
-    _refreshControl.attributedTitle = [[NSAttributedString alloc]initWithString:NSLocalizedString(@"LOCAL_SERVER_REFRESH", nil)];
-    //set the date and time of refreshing
-    NSDateFormatter *formattedDate = [[NSDateFormatter alloc]init];
-    [formattedDate setDateFormat:@"MMM d, h:mm a"];
-    NSString *lastupdated = [NSString stringWithFormat:NSLocalizedString(@"LOCAL_SERVER_LAST_UPDATE", nil),[formattedDate stringFromDate:[NSDate date]]];
-    NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:NSForegroundColorAttributeName];
-    _refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:lastupdated attributes:attrsDictionary];
-    //end the refreshing
-    [_refreshControl endRefreshing];
-    [self performSelector:@selector(reloadTableViewPlex) withObject:nil];
-}
-
-#pragma mark - Gesture Action
-
-- (void)tapTwiceGestureAction:(UIGestureRecognizer *)recognizer
-{
-    _searchBar.hidden = !_searchBar.hidden;
-    if (_searchBar.hidden)
-        self.tableView.tableHeaderView = nil;
-    else
-        self.tableView.tableHeaderView = _searchBar;
-
-    [self.tableView setContentOffset:CGPointMake(0.0f, -self.tableView.contentInset.top) animated:NO];
-}
-
-- (void)longTouchGestureAction:(UIGestureRecognizer *)recognizer
-{
-    if (recognizer.state == UIGestureRecognizerStateBegan) {
-        NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:[recognizer locationInView:self.tableView]];
-        UITableViewCell *swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
-        NSDictionary *cellObject = _globalObjectList[[self.tableView indexPathForCell:swipedCell].row];
-
-        VLCPlexMediaInformationViewController *targetViewController = [[VLCPlexMediaInformationViewController alloc] initPlexMediaInformation:cellObject serverAddress:_PlexServerAddress portNumber:_PlexServerPort atPath:_PlexServerPath authentification:_PlexAuthentification];
-        [[self navigationController] pushViewController:targetViewController animated:YES];
-    }
-}
-
-@end

+ 2 - 2
Sources/LocalNetworkConnectivity/Plex/VLCPlexMediaInformationViewController.m

@@ -59,7 +59,7 @@
     self.navigationController.navigationBar.translucent = NO;
 
     NSString *title = _mediaObject[@"title"];
-    NSString *thumbPath = [_PlexWebAPI urlAuth:_mediaObject[@"thumb"] autentification:_PlexAuthentification];
+    NSString *thumbPath = [_PlexWebAPI urlAuth:_mediaObject[@"thumb"] authentification:_PlexAuthentification];
     UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:thumbPath]]];
     NSInteger size = [_mediaObject[@"size"] integerValue];
     NSString *mediaSize = [NSByteCountFormatter stringFromByteCount:size countStyle:NSByteCountFormatterCountStyleFile];
@@ -134,7 +134,7 @@
         if (firstObject[@"keySubtitle"])
             URLofSubtitle = [_PlexWebAPI getFileSubtitleFromPlexServer:firstObject modeStream:YES];
 
-        NSURL *itemURL = [NSURL URLWithString:[_PlexWebAPI urlAuth:firstObject[@"keyMedia"] autentification:_PlexAuthentification]];
+        NSURL *itemURL = [NSURL URLWithString:[_PlexWebAPI urlAuth:firstObject[@"keyMedia"] authentification:_PlexAuthentification]];
         if (itemURL) {
             VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
             [vpc playURL:itemURL subtitlesFilePath:URLofSubtitle];

+ 1 - 1
Sources/LocalNetworkConnectivity/Plex/VLCPlexParser.h

@@ -12,7 +12,7 @@
 #import <UIKit/UIKit.h>
 @interface VLCPlexParser : NSObject
 
-- (NSArray *)PlexMediaServerParser:(NSString *)adress port:(NSString *)port navigationPath:(NSString *)navPath authentification:(NSString *)auth;
+- (NSArray *)PlexMediaServerParser:(NSString *)adress port:(NSNumber *)port navigationPath:(NSString *)navPath authentification:(NSString *)auth;
 - (NSArray *)PlexExtractDeviceInfo:(NSData *)data;
 
 @end

+ 25 - 13
Sources/LocalNetworkConnectivity/Plex/VLCPlexParser.m

@@ -13,8 +13,8 @@
 #import "VLCPlexWebAPI.h"
 #import "SSKeychain.h"
 
-#define kPlexMediaServerDirInit @"library/sections"
-#define kPlexVLCDeviceName @"VLC for iOS"
+static NSString *const kPlexMediaServerDirInit = @"/library/sections";
+static NSString *const kPlexVLCDeviceName = @"VLC for iOS";
 
 @interface VLCPlexParser () <NSXMLParserDelegate>
 {
@@ -26,24 +26,33 @@
 
 @implementation VLCPlexParser
 
-- (NSArray *)PlexMediaServerParser:(NSString *)address port:(NSString *)port navigationPath:(NSString *)path authentification:(NSString *)auth
+- (NSArray *)PlexMediaServerParser:(NSString *)address port:(NSNumber *)port navigationPath:(NSString *)path authentification:(NSString *)auth
 {
     _containerInfo = [[NSMutableArray alloc] init];
     _dicoInfo = [[NSMutableDictionary alloc] init];
-    _PlexMediaServerUrl = [NSString stringWithFormat:@"http://%@%@",address, port];
+    NSURLComponents *urlComponents = [[NSURLComponents alloc] init];
+    urlComponents.scheme = @"http";
+    urlComponents.host = address;
+    urlComponents.port = port;
+
+    _PlexMediaServerUrl = [urlComponents URL].absoluteString;
+
     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];
+    if ([path length] == 0) {
+        urlComponents.path = kPlexMediaServerDirInit;
+    } else {
+        if ([path rangeOfString:@"library"].location != NSNotFound) {
+            urlComponents.path = [@"/" stringByAppendingPathComponent:path];
+        } else {
+            urlComponents.path = [kPlexMediaServerDirInit stringByAppendingPathComponent:path];
+        }
     }
 
+    mediaServerUrl = [urlComponents URL].absoluteString;
+
     VLCPlexWebAPI *PlexWebAPI = [[VLCPlexWebAPI alloc] init];
-    NSURL *url = [[NSURL alloc] initWithString:[PlexWebAPI urlAuth:mediaServerUrl autentification:auth]];
+    NSURL *url = [[NSURL alloc] initWithString:[PlexWebAPI urlAuth:mediaServerUrl authentification:auth]];
 
     NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
     NSHTTPURLResponse *response = nil;
@@ -65,7 +74,7 @@
                 NSString *password = [SSKeychain passwordForService:serviceString account:username];
 
                 auth = [PlexWebAPI PlexAuthentification:username password:password];
-                url = [NSURL URLWithString:[PlexWebAPI urlAuth:mediaServerUrl autentification:auth]];
+                url = [NSURL URLWithString:[PlexWebAPI urlAuth:mediaServerUrl authentification:auth]];
                 request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
                 response = nil;
                 error = nil;
@@ -84,6 +93,9 @@
             APLog(@"PlexParser url Errors : %ld", (long)[response statusCode]);
     }
 
+    if (error) {
+        APLog(@"PlexParser url Error: %@", error);
+    }
     NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithData:data];
     [xmlparser setDelegate:self];
 

+ 3 - 1
Sources/LocalNetworkConnectivity/Plex/VLCPlexWebAPI.h

@@ -15,7 +15,7 @@
 - (BOOL)PlexCreateIdentification:(NSString *)username password:(NSString *)password;
 - (NSArray *)PlexBasicAuthentification:(NSString *)username password:(NSString *)password;
 - (NSString *)PlexAuthentification:(NSString *)username password:(NSString *)password;
-- (NSString *)urlAuth:(NSString *)url autentification:(NSString *)auth;
+- (NSString *)urlAuth:(NSString *)url authentification:(NSString *)auth;
 - (NSData *)HttpRequestWithCookie:(NSURL *)url cookies:(NSArray *)authToken HTTPMethod:(NSString *)method;
 - (NSURL *)CreatePlexStreamingURL:(NSString *)address port:(NSString *)port videoKey:(NSString *)key username:(NSString *)username deviceInfo:(NSDictionary *)deviceInfo session:(NSString *)session;
 - (void)stopSession:(NSString *)adress port:(NSString *)port session:(NSString *)session;
@@ -24,4 +24,6 @@
 - (NSString *)getSession;
 - (NSData *)PlexDeviceInfo:(NSArray *)cookies;
 
++ (NSString *)urlAuth:(NSString *)url authentification:(NSString *)auth;
+
 @end

+ 5 - 1
Sources/LocalNetworkConnectivity/Plex/VLCPlexWebAPI.m

@@ -144,7 +144,11 @@
     return authentification;
 }
 
-- (NSString *)urlAuth:(NSString *)url autentification:(NSString *)auth
+- (NSString *)urlAuth:(NSString *)url autentification:(NSString *)auth {
+    return [[self class] urlAuth:url autentification:auth];
+}
+
++ (NSString *)urlAuth:(NSString *)url autentification:(NSString *)auth
 {
     NSString *key = @"";
 

+ 34 - 0
Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserPlex.h

@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * VLCNetworkServerBrowserPlex.h
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCNetworkServerBrowser-Protocol.h"
+
+NS_ASSUME_NONNULL_BEGIN
+@interface VLCNetworkServerBrowserPlex : NSObject <VLCNetworkServerBrowser>
+- (instancetype)initWithName:(NSString *)name host:(NSString *)addressOrName portNumber:(NSNumber *)portNumber path:(NSString *)path authentificication:(NSString *)auth NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithName:(NSString *)name url:(NSURL *)url auth:(NSString *)auth;
+
+- (instancetype)init NS_UNAVAILABLE;
+@end
+
+
+@interface VLCNetworkServerBrowserItemPlex : NSObject <VLCNetworkServerBrowserItem>
+- (instancetype)initWithDictionary:(NSDictionary *)dictionary currentURL:(NSURL *)currentURL authentificication:(NSString *)auth;
+
+@property (nonatomic, readonly, nullable) NSString *duration;
+@property (nonatomic, readonly, nullable) NSURL *subtitleURL;
+@property (nonatomic, readonly, nullable) NSURL *thumbnailURL;
+
+@end
+
+
+NS_ASSUME_NONNULL_END

+ 175 - 0
Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserPlex.m

@@ -0,0 +1,175 @@
+/*****************************************************************************
+ * VLCNetworkServerBrowserPlex.m
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCNetworkServerBrowserPlex.h"
+#import "VLCPlexParser.h"
+#import "VLCPlexWebAPI.h"
+
+@interface VLCNetworkServerBrowserPlex ()
+@property (nonatomic, readonly) NSString *addressOrName;
+@property (nonatomic, readonly) NSUInteger port;
+
+@property (nonatomic, readwrite) NSString *title;
+@property (nonatomic, readonly) NSString *plexServerAddress;
+@property (nonatomic, readonly) NSNumber *plexServerPort;
+@property (nonatomic, readonly) NSString *plexServerPath;
+
+@property (nonatomic) NSString *plexAuthentification;
+
+@property (nonatomic, readonly) VLCPlexParser *plexParser;
+@property (nonatomic, readonly) VLCPlexWebAPI *plexWebAPI;
+
+@property (nonatomic, readonly) NSOperationQueue *plexQueue;
+
+@property (nonatomic, readwrite) NSArray<id<VLCNetworkServerBrowserItem>> *items;
+@end
+
+@implementation VLCNetworkServerBrowserPlex
+@synthesize title = _title, delegate = _delegate, items = _items;
+
+- (instancetype)initWithName:(NSString *)name host:(NSString *)addressOrName portNumber:(NSNumber *)portNumber path:(NSString *)path authentificication:(NSString *)auth
+{
+    self = [super init];
+    if (self) {
+        _title = name;
+        _plexServerAddress = addressOrName;
+        _plexServerPort = portNumber;
+        _plexServerPath = path;
+
+        _plexAuthentification = auth;
+
+        _plexParser = [[VLCPlexParser alloc] init];
+        _plexWebAPI = [[VLCPlexWebAPI alloc] init];
+
+        _plexQueue = [[NSOperationQueue alloc] init];
+        _plexQueue.maxConcurrentOperationCount = 1;
+        _plexQueue.name = @"org.videolan.vlc-ios.plex.update";
+
+        _items = [NSArray new];
+
+    }
+    return self;
+}
+
+- (instancetype)initWithName:(NSString *)name url:(NSURL *)url auth:(NSString *)auth {
+    return [self initWithName:name host:url.host portNumber:url.port path:url.path authentificication:auth];
+}
+
+- (void)update {
+    [self.plexQueue addOperationWithBlock:^{
+        [self loadContents];
+    }];
+}
+
+- (void)loadContents
+{
+    NSArray *dicts = [self.plexParser PlexMediaServerParser:self.plexServerAddress port:self.plexServerPort navigationPath:self.plexServerPath authentification:self.plexAuthentification];
+
+    NSDictionary *firstObject = [dicts firstObject];
+    NSString *newAuth = firstObject[@"authentification"] ?: @"";
+
+    NSURLComponents *components = [[NSURLComponents alloc] init];
+    components.scheme = @"http";
+    components.host = self.plexServerAddress;
+    components.port = self.plexServerPort;
+    components.path = self.plexServerPath;
+    NSURL *url = components.URL;
+
+    NSMutableArray *newItems = [NSMutableArray new];
+    for (NSDictionary *dict in dicts) {
+        VLCNetworkServerBrowserItemPlex *item = [[VLCNetworkServerBrowserItemPlex alloc] initWithDictionary:dict currentURL:url authentificication:newAuth];
+        [newItems addObject:item];
+    }
+
+    NSString *titleValue = firstObject[@"libTitle"];
+    if (titleValue.length) {
+        self.title = titleValue;
+    }
+    self.plexAuthentification = newAuth;
+    self.items = [newItems copy];
+    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+        [self.delegate networkServerBrowserDidUpdate:self];
+    }];
+}
+
+
+- (NSString *)_urlAuth:(NSString *)url
+{
+    return [self.plexWebAPI urlAuth:url authentification:self.plexAuthentification];
+}
+@end
+
+
+@interface VLCNetworkServerBrowserItemPlex()
+
+@property (nonatomic) NSString *plexAuthentification;
+@end
+@implementation VLCNetworkServerBrowserItemPlex
+@synthesize name = _name, URL = _URL, fileSizeBytes = _fileSizeBytes, container = _container;
+
+- (instancetype)initWithDictionary:(NSDictionary *)dictionary currentURL:(NSURL *)currentURL authentificication:(NSString *)auth
+{
+    self = [super init];
+    if (self) {
+
+        _plexAuthentification = auth;
+        
+        NSURLComponents *components = [[NSURLComponents alloc] initWithURL:currentURL resolvingAgainstBaseURL:NO];
+
+        NSString *path = components.path;
+        components.path = nil;
+        NSURL *baseURL = components.URL;
+
+        _container = ![dictionary[@"container"] isEqualToString:@"item"];
+        NSString *urlPath;
+        if (_container) {
+            NSString *keyPath = nil;
+            NSString *keyValue = dictionary[@"key"];
+            if ([keyValue rangeOfString:@"library"].location == NSNotFound) {
+                keyPath = [path stringByAppendingPathComponent:keyValue];
+            } else {
+                keyPath = keyValue;
+            }
+            urlPath = [baseURL URLByAppendingPathComponent:keyPath].absoluteString;
+        } else {
+            urlPath = dictionary[@"keyMedia"];
+        }
+
+        urlPath = [VLCPlexWebAPI urlAuth:urlPath authentification:auth];
+        _URL = [NSURL URLWithString:urlPath];
+
+        _name = dictionary[@"title"];
+        NSString *thumbPath = dictionary[@"thumb"];
+        if (thumbPath) {
+            thumbPath = [VLCPlexWebAPI urlAuth:thumbPath authentification:auth];
+        }
+        _thumbnailURL = thumbPath.length ? [baseURL URLByAppendingPathComponent:thumbPath] : nil;
+
+
+        _duration = dictionary[@"duration"];
+        _fileSizeBytes = dictionary[@"size"];
+
+        NSString *subtitleURLString = dictionary[@"keySubtitle"];
+        if (subtitleURLString) {
+            subtitleURLString = [VLCPlexWebAPI urlAuth:subtitleURLString authentification:auth];
+        }
+
+        _subtitleURL = subtitleURLString.length ? [baseURL URLByAppendingPathComponent:subtitleURLString] : nil;
+    }
+    return self;
+}
+
+- (id<VLCNetworkServerBrowser>)containerBrowser {
+    return [[VLCNetworkServerBrowserPlex alloc] initWithName:self.name url:self.URL auth:self.plexAuthentification];
+}
+
+@end

+ 7 - 4
Sources/LocalNetworkConnectivity/ServerDiscovery/VLCLocalNetworkService.m

@@ -11,6 +11,7 @@
  *****************************************************************************/
 
 #import "VLCLocalNetworkService.h"
+#import "VLCNetworkServerBrowserViewController.h"
 
 
 @interface VLCLocalNetworkServiceItem ()
@@ -79,7 +80,8 @@
 }
 @end
 
-#import "VLCLocalPlexFolderListViewController.h"
+#import "VLCNetworkServerBrowserPlex.h"
+
 @implementation VLCLocalNetworkServicePlex
 - (UIImage *)icon {
     return [UIImage imageNamed:@"PlexServerIcon"];
@@ -93,8 +95,10 @@
 
     NSString *name = service.name;
     NSString *hostName = service.hostName;
-    NSString *portNum = [[NSString alloc] initWithFormat:@":%ld", (long)service.port];
-    VLCLocalPlexFolderListViewController *targetViewController = [[VLCLocalPlexFolderListViewController alloc] initWithPlexServer:name serverAddress:hostName portNumber:portNum atPath:@"" authentification:@""];
+    NSUInteger portNum = service.port;
+    VLCNetworkServerBrowserPlex *serverBrowser = [[VLCNetworkServerBrowserPlex alloc] initWithName:name host:hostName portNumber:@(portNum) path:@"" authentificication:@""];
+
+    VLCNetworkServerBrowserViewController *targetViewController = [[VLCNetworkServerBrowserViewController alloc] initWithServerBrowser:serverBrowser];
     return targetViewController;
 }
 @end
@@ -112,7 +116,6 @@
 @end
 
 #import "VLCNetworkServerBrowserSharedLibrary.h"
-#import "VLCNetworkServerBrowserViewController.h"
 @implementation VLCLocalNetworkServiceHTTP
 - (UIImage *)icon {
     return [UIImage imageNamed:@"menuCone"];

+ 14 - 9
Sources/LocalNetworkConnectivity/VLCServerListViewController.m

@@ -20,11 +20,11 @@
 #import "VLCNetworkListCell.h"
 #import "VLCNetworkLoginViewController.h"
 #import "VLCUPnPServerListViewController.h"
-#import "VLCLocalPlexFolderListViewController.h"
 #import "VLCNetworkServerBrowserViewController.h"
 
 #import "VLCNetworkServerBrowserFTP.h"
 #import "VLCNetworkServerBrowserVLCMedia.h"
+#import "VLCNetworkServerBrowserPlex.h"
 
 @interface VLCServerListViewController () <UITableViewDataSource, UITableViewDelegate, VLCLocalServerDiscoveryControllerDelegate>
 {
@@ -222,14 +222,19 @@ confirmedWithUsername:(NSString *)username
         }
         case VLCServerProtocolPLEX:
         {
-            if (port == nil || port.length == 0)
-                port = @"32400";
-            VLCLocalPlexFolderListViewController *targetViewController = [[VLCLocalPlexFolderListViewController alloc]
-                                                                          initWithPlexServer:server
-                                                                          serverAddress:server
-                                                                          portNumber:[NSString stringWithFormat:@":%@", port] atPath:@""
-                                                                          authentification:username];
-            [[self navigationController] pushViewController:targetViewController animated:YES];
+
+            NSNumber *portNumber;
+            NSUInteger portInteger = 0;
+            if (port.length) {
+                portInteger = [port integerValue];
+            }
+            portNumber = portInteger != 0 ? @(portInteger) : @(32400);
+
+            serverBrowser = [[VLCNetworkServerBrowserPlex alloc] initWithName:server
+                                                                         host:server
+                                                                   portNumber:@([port integerValue])
+                                                                         path:@""
+                                                           authentificication:@""];
             break;
         }
         case VLCServerProtocolSMB:

+ 7 - 7
VLC for iOS.xcodeproj/project.pbxproj

@@ -9,7 +9,6 @@
 /* Begin PBXBuildFile section */
 		262C71591A98FA9200F7ED34 /* VLCPlexMediaInformationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 262C71581A98FA9200F7ED34 /* VLCPlexMediaInformationViewController.m */; };
 		2640FAE61B01477A00E359D6 /* VLCPlexWebAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 2640FAE51B01477A00E359D6 /* VLCPlexWebAPI.m */; };
-		265D511C1922746C00E38383 /* VLCLocalPlexFolderListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 265D51191922746C00E38383 /* VLCLocalPlexFolderListViewController.m */; };
 		265D511D1922746C00E38383 /* VLCPlexParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 265D511B1922746C00E38383 /* VLCPlexParser.m */; };
 		266DB8EB1B447E5000EA415E /* VLCPlexMediaInformationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 266DB8EA1B447E5000EA415E /* VLCPlexMediaInformationViewController.xib */; };
 		268BDA7E1B4FE1E200D622DD /* backArrow_black.png in Resources */ = {isa = PBXBuildFile; fileRef = 268BDA7D1B4FE1E200D622DD /* backArrow_black.png */; };
@@ -286,6 +285,7 @@
 		DD3EA6311AF50CFE007FF096 /* VLCWatchMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EA6301AF50CFE007FF096 /* VLCWatchMessage.m */; };
 		DD3EFE301BDA813F00B68579 /* VLCNetworkServerBrowserVLCMedia.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EFE2F1BDA813F00B68579 /* VLCNetworkServerBrowserVLCMedia.m */; };
 		DD3EFE361BDAACD400B68579 /* VLCNetworkServerBrowserSharedLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EFE351BDAACD400B68579 /* VLCNetworkServerBrowserSharedLibrary.m */; };
+		DD3EFE5A1BDC268D00B68579 /* VLCNetworkServerBrowserPlex.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EFE591BDC268D00B68579 /* VLCNetworkServerBrowserPlex.m */; };
 		DD510B701B14E564003BA71C /* VLCPlayerDisplayController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD510B6F1B14E564003BA71C /* VLCPlayerDisplayController.m */; };
 		DD7110F01AF38B2B00854776 /* MLMediaLibrary+playlist.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7110EF1AF38B2B00854776 /* MLMediaLibrary+playlist.m */; };
 		DD7BA2631B680C8E002D9F54 /* MediaLibraryKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD7BA2601B680C1B002D9F54 /* MediaLibraryKit.framework */; };
@@ -432,9 +432,7 @@
 		262C71581A98FA9200F7ED34 /* VLCPlexMediaInformationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlexMediaInformationViewController.m; path = Sources/LocalNetworkConnectivity/Plex/VLCPlexMediaInformationViewController.m; sourceTree = SOURCE_ROOT; };
 		2640FAE41B01477A00E359D6 /* VLCPlexWebAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCPlexWebAPI.h; path = Sources/LocalNetworkConnectivity/Plex/VLCPlexWebAPI.h; sourceTree = SOURCE_ROOT; };
 		2640FAE51B01477A00E359D6 /* VLCPlexWebAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlexWebAPI.m; path = Sources/LocalNetworkConnectivity/Plex/VLCPlexWebAPI.m; sourceTree = SOURCE_ROOT; };
-		265D51181922746C00E38383 /* VLCLocalPlexFolderListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCLocalPlexFolderListViewController.h; path = Sources/LocalNetworkConnectivity/Plex/VLCLocalPlexFolderListViewController.h; sourceTree = SOURCE_ROOT; };
-		265D51191922746C00E38383 /* VLCLocalPlexFolderListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCLocalPlexFolderListViewController.m; path = Sources/LocalNetworkConnectivity/Plex/VLCLocalPlexFolderListViewController.m; sourceTree = SOURCE_ROOT; };
-		265D511A1922746C00E38383 /* VLCPlexParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlexParser.h; sourceTree = "<group>"; };
+		265D511A1922746C00E38383 /* VLCPlexParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCPlexParser.h; path = Sources/LocalNetworkConnectivity/Plex/VLCPlexParser.h; sourceTree = SOURCE_ROOT; };
 		265D511B1922746C00E38383 /* VLCPlexParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlexParser.m; path = Sources/LocalNetworkConnectivity/Plex/VLCPlexParser.m; sourceTree = SOURCE_ROOT; };
 		266DB8EA1B447E5000EA415E /* VLCPlexMediaInformationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCPlexMediaInformationViewController.xib; path = Resources/VLCPlexMediaInformationViewController.xib; sourceTree = SOURCE_ROOT; };
 		268BDA7D1B4FE1E200D622DD /* backArrow_black.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = backArrow_black.png; path = ImportedSources/OneDrive/src/LiveSDK/Library/Internal/Resources/backArrow_black.png; sourceTree = SOURCE_ROOT; };
@@ -896,6 +894,8 @@
 		DD3EFE2F1BDA813F00B68579 /* VLCNetworkServerBrowserVLCMedia.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCNetworkServerBrowserVLCMedia.m; path = Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserVLCMedia.m; sourceTree = SOURCE_ROOT; };
 		DD3EFE341BDAACD400B68579 /* VLCNetworkServerBrowserSharedLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCNetworkServerBrowserSharedLibrary.h; path = Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserSharedLibrary.h; sourceTree = SOURCE_ROOT; };
 		DD3EFE351BDAACD400B68579 /* VLCNetworkServerBrowserSharedLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCNetworkServerBrowserSharedLibrary.m; path = Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserSharedLibrary.m; sourceTree = SOURCE_ROOT; };
+		DD3EFE581BDC268D00B68579 /* VLCNetworkServerBrowserPlex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCNetworkServerBrowserPlex.h; path = Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserPlex.h; sourceTree = SOURCE_ROOT; };
+		DD3EFE591BDC268D00B68579 /* VLCNetworkServerBrowserPlex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCNetworkServerBrowserPlex.m; path = Sources/LocalNetworkConnectivity/ServerBrowsing/VLCNetworkServerBrowserPlex.m; sourceTree = SOURCE_ROOT; };
 		DD510B6E1B14E564003BA71C /* VLCPlayerDisplayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCPlayerDisplayController.h; path = Sources/VLCPlayerDisplayController.h; sourceTree = SOURCE_ROOT; };
 		DD510B6F1B14E564003BA71C /* VLCPlayerDisplayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlayerDisplayController.m; path = Sources/VLCPlayerDisplayController.m; sourceTree = SOURCE_ROOT; };
 		DD7110EE1AF38B2B00854776 /* MLMediaLibrary+playlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MLMediaLibrary+playlist.h"; sourceTree = "<group>"; };
@@ -1644,6 +1644,8 @@
 				DD3EFE2F1BDA813F00B68579 /* VLCNetworkServerBrowserVLCMedia.m */,
 				DD3EFE341BDAACD400B68579 /* VLCNetworkServerBrowserSharedLibrary.h */,
 				DD3EFE351BDAACD400B68579 /* VLCNetworkServerBrowserSharedLibrary.m */,
+				DD3EFE581BDC268D00B68579 /* VLCNetworkServerBrowserPlex.h */,
+				DD3EFE591BDC268D00B68579 /* VLCNetworkServerBrowserPlex.m */,
 			);
 			name = "Server browsing";
 			sourceTree = "<group>";
@@ -1737,8 +1739,6 @@
 				265D511B1922746C00E38383 /* VLCPlexParser.m */,
 				2640FAE41B01477A00E359D6 /* VLCPlexWebAPI.h */,
 				2640FAE51B01477A00E359D6 /* VLCPlexWebAPI.m */,
-				265D51181922746C00E38383 /* VLCLocalPlexFolderListViewController.h */,
-				265D51191922746C00E38383 /* VLCLocalPlexFolderListViewController.m */,
 				262C71571A98FA9200F7ED34 /* VLCPlexMediaInformationViewController.h */,
 				262C71581A98FA9200F7ED34 /* VLCPlexMediaInformationViewController.m */,
 			);
@@ -2645,9 +2645,9 @@
 				7D1052E91A4DCC1100295F08 /* VLCOneDriveTableViewController.m in Sources */,
 				7DBB788A1B30423B00894467 /* VLCKeychainCoordinator.m in Sources */,
 				7D30F3D7183AB2F100FFC021 /* VLCNetworkListCell.m in Sources */,
-				265D511C1922746C00E38383 /* VLCLocalPlexFolderListViewController.m in Sources */,
 				7D1052EE1A4DCD1E00295F08 /* VLCOneDriveController.m in Sources */,
 				7DAE0C371B2EF85B00C53996 /* VLCSidebarController.m in Sources */,
+				DD3EFE5A1BDC268D00B68579 /* VLCNetworkServerBrowserPlex.m in Sources */,
 				7D30F3D9183AB2F100FFC021 /* VLCServerListViewController.m in Sources */,
 				7D30F3DC183AB2F900FFC021 /* VLCNetworkLoginViewController.m in Sources */,
 				DDB959421AFBB30500BB8CFF /* MappingModel_2_5_to_2_6.xcmappingmodel in Sources */,