Commit 9b2b94d9 authored by Tobias's avatar Tobias

refactor VLCLocalServerDiscoveryController and VLCServerListView

reduce number of switches with magic numbers
add enum for LocalServerSections
introduce VLCLocalNetworkService as a wrapper around different network services
parent b3e16226
/*****************************************************************************
* VLCLocalNetworkService.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 <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol VLCLocalNetworkService <NSObject>
@required
@property (nonatomic, readonly, nullable) UIImage *icon;
@property (nonatomic, readonly) NSString *title;
@optional
- (nullable UIViewController *)detailViewController;
typedef void (^VLCLocalNetworkServiceActionBlock)(void);
@property (nonatomic, readonly) VLCLocalNetworkServiceActionBlock action;
@end
#pragma mark - item
@interface VLCLocalNetworkServiceItem : NSObject <VLCLocalNetworkService>
- (instancetype)initWithTile:(NSString *)title icon:(nullable UIImage *)icon;
@end
@interface VLCLocalNetworkServiceItemLogin : VLCLocalNetworkServiceItem
- (instancetype)init;
@end
#pragma mark - NetService based services
@interface VLCLocalNetworkServiceNetService : NSObject <VLCLocalNetworkService>
@property (nonatomic, readonly, strong) NSNetService *netService;
- (instancetype)initWithNetService:(NSNetService *)service;
@end
@interface VLCLocalNetworkServicePlex : VLCLocalNetworkServiceNetService
@end
@interface VLCLocalNetworkServiceFTP : VLCLocalNetworkServiceNetService
@end
@interface VLCLocalNetworkServiceHTTP : VLCLocalNetworkServiceNetService
@property (nonatomic, strong) NSDictionary *seviceDescription;
@end
#pragma mark - VLCMedia based services
@interface VLCLocalNetworkServiceVLCMedia : NSObject <VLCLocalNetworkService>
- (instancetype)initWithMediaItem:(VLCMedia *)mediaItem;
@end
@interface VLCLocalNetworkServiceDSM: VLCLocalNetworkServiceVLCMedia
@end
@interface VLCLocalNetworkServiceSAP: VLCLocalNetworkServiceVLCMedia
@end
#pragma mark - UPnP
@class BasicUPnPDevice;
@interface VLCLocalNetworkServiceUPnP : NSObject <VLCLocalNetworkService>
- (instancetype)initWithUPnPDevice:(BasicUPnPDevice *)device;
@end
NS_ASSUME_NONNULL_END
/*****************************************************************************
* VLCLocalNetworkService.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 "VLCLocalNetworkService.h"
@interface VLCLocalNetworkServiceItem ()
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong, nullable) UIImage *icon;
@end
@implementation VLCLocalNetworkServiceItem
- (instancetype)initWithTile:(NSString *)title icon:(UIImage *)icon
{
self = [super init];
if (self) {
_title = title;
_icon = icon;
}
return self;
}
@end
#import "VLCNetworkLoginViewController.h"
@implementation VLCLocalNetworkServiceItemLogin
- (instancetype)init
{
self = [super initWithTile:NSLocalizedString(@"CONNECT_TO_SERVER", nil)
icon:[UIImage imageNamed:@"menuCone"]];
if (self) {
}
return self;
}
- (UIViewController *)detailViewController {
VLCNetworkLoginViewController *loginViewController = [[VLCNetworkLoginViewController alloc] initWithNibName:@"VLCNetworkLoginViewController" bundle:nil];
loginViewController.serverProtocol = VLCServerProtocolUndefined;
return loginViewController;
}
@end
#pragma mark - NetService based services
@interface VLCLocalNetworkServiceNetService()
@property (nonatomic, strong) NSNetService *netService;
@end
@implementation VLCLocalNetworkServiceNetService
- (instancetype)initWithNetService:(NSNetService *)service
{
self = [super init];
if (self) {
_netService = service;
}
return self;
}
- (NSString *)title {
return self.netService.name;
}
- (UIImage *)icon {
return nil;
}
- (UIViewController *)detailViewController {
return nil;
}
@end
#import "VLCLocalPlexFolderListViewController.h"
@implementation VLCLocalNetworkServicePlex
- (UIImage *)icon {
return [UIImage imageNamed:@"PlexServerIcon"];
}
- (UIViewController *)detailViewController {
NSNetService *service = self.netService;
if (service.hostName == nil || service.port == 0) {
return nil;
}
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:@""];
return targetViewController;
}
@end
@implementation VLCLocalNetworkServiceFTP
- (UIImage *)icon {
return [UIImage imageNamed:@"serverIcon"];
}
- (UIViewController *)detailViewController {
VLCNetworkLoginViewController *loginViewController = [[VLCNetworkLoginViewController alloc] initWithNibName:@"VLCNetworkLoginViewController" bundle:nil];
loginViewController.serverProtocol = VLCServerProtocolFTP;
loginViewController.hostname = self.netService.hostName;
return loginViewController;
}
@end
#import "VLCSharedLibraryListViewController.h"
@implementation VLCLocalNetworkServiceHTTP
- (UIImage *)icon {
return [UIImage imageNamed:@"menuCone"];
}
- (UIViewController *)detailViewController {
NSDictionary *serviceDescription = self.seviceDescription;
if (serviceDescription == nil) {
return nil;
}
NSString *name = serviceDescription[@"name"];
NSString *hostName = serviceDescription[@"hostName"];
NSString *portNum = serviceDescription[@"port"];
VLCSharedLibraryListViewController *targetViewController = [[VLCSharedLibraryListViewController alloc]
initWithHttpServer:name
serverAddress:hostName
portNumber:portNum];
return targetViewController;
}
@end
#pragma mark - VLCMedia based services
@interface VLCLocalNetworkServiceVLCMedia()
@property (nonatomic, strong) VLCMedia *mediaItem;
@end
@implementation VLCLocalNetworkServiceVLCMedia
- (instancetype)initWithMediaItem:(VLCMedia *)mediaItem
{
self = [super init];
if (self) {
_mediaItem = mediaItem;
}
return self;
}
- (NSString *)title {
return [self.mediaItem metadataForKey:VLCMetaInformationTitle];
}
- (UIImage *)icon {
return nil;
}
@end
#import "VLCDiscoveryListViewController.h"
@implementation VLCLocalNetworkServiceDSM
- (UIImage *)icon {
return [UIImage imageNamed:@"serverIcon"];
}
- (UIViewController *)detailViewController {
VLCMedia *cellMedia = self.mediaItem;
if (cellMedia.mediaType != VLCMediaTypeDirectory)
return nil;
NSDictionary *mediaOptions = @{@"smb-user" : @"",
@"smb-pwd" : @"",
@"smb-domain" : @""};
[cellMedia addOptions:mediaOptions];
VLCDiscoveryListViewController *targetViewController = [[VLCDiscoveryListViewController alloc]
initWithMedia:cellMedia
options:mediaOptions];
return targetViewController;
}
@end
#import "VLCPlaybackController.h"
@implementation VLCLocalNetworkServiceSAP
- (UIImage *)icon {
return [UIImage imageNamed:@"TVBroadcastIcon"];
}
- (VLCLocalNetworkServiceActionBlock)action {
__weak typeof(self) weakSelf = self;
return ^{
VLCMedia *cellMedia = weakSelf.mediaItem;
VLCMediaType mediaType = cellMedia.mediaType;
if (cellMedia && mediaType != VLCMediaTypeDirectory && mediaType != VLCMediaTypeDisc) {
VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
[vpc playURL:[cellMedia url] successCallback:nil errorCallback:nil];
}
};
}
@end
#pragma mark - UPnP
#import "UPnPManager.h"
#import "VLCUPnPServerListViewController.h"
@interface VLCLocalNetworkServiceUPnP ()
@property (nonatomic, strong) BasicUPnPDevice *device;
@end
@implementation VLCLocalNetworkServiceUPnP
- (instancetype)initWithUPnPDevice:(BasicUPnPDevice *)device
{
self = [super init];
if (self) {
_device = device;
}
return self;
}
- (NSString *)title {
return [self.device friendlyName];
}
- (UIImage *)icon {
return [self.device smallIcon] ?: [UIImage imageNamed:@"serverIcon"];
}
- (UIViewController *)detailViewController {
BasicUPnPDevice *device = self.device;
if (device != nil) {
if ([[device urn] isEqualToString:@"urn:schemas-upnp-org:device:MediaServer:1"]) {
MediaServer1Device *server = (MediaServer1Device*)device;
VLCUPnPServerListViewController *targetViewController = [[VLCUPnPServerListViewController alloc] initWithUPNPDevice:server header:[device friendlyName] andRootID:@"0"];
return targetViewController;
}
}
return nil;
}
@end
......@@ -6,6 +6,7 @@
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne # videolan.org>
* Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
......@@ -13,6 +14,8 @@
#import <Foundation/Foundation.h>
#import "UPnPManager.h"
#import "VLCLocalNetworkService.h"
@protocol VLCLocalServerDiscoveryControllerDelegate <NSObject>
@required
......@@ -25,17 +28,9 @@
@property (nonatomic, readwrite, weak) id delegate;
@property (nonatomic, readonly) NSArray *sectionHeaderTexts;
- (NSInteger)numberOfItemsInSection:(NSInteger)section;
- (NSString *)titleForIndexPath:(NSIndexPath *)indexPath;
- (UIImage *)iconForIndexPath:(NSIndexPath *)indexPath;
- (id<VLCLocalNetworkService>)networkServiceForIndexPath:(NSIndexPath *)indexPath;
- (BasicUPnPDevice *)upnpDeviceForIndexPath:(NSIndexPath *)indexPath;
- (NSDictionary *)plexServiceDescriptionForIndexPath:(NSIndexPath *)indexPath;
- (NSString *)ftpHostnameForIndexPath:(NSIndexPath *)indexPath;
- (NSDictionary *)httpServiceDescriptionForIndexPath:(NSIndexPath *)indexPath;
- (VLCMedia *)dsmDiscoveryForIndexPath:(NSIndexPath *)indexPath;
- (VLCMedia *)sapDiscoveryForIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)numberOfItemsInSection:(NSInteger)section;
- (void)stopDiscovery;
- (BOOL)refreshDiscoveredData;
......
......@@ -7,6 +7,7 @@
*
* Authors: Felix Paul Kühne <fkuehne # videolan.org>
* Pierre SAGASPE <pierre.sagaspe # me.com>
* Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
......@@ -33,19 +34,58 @@
#define kPlexServiceType @"_plexmediasvr._tcp."
typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
VLCLocalServerSectionGeneric = 0,
VLCLocalServerSectionUPnP,
VLCLocalServerSectionPlex,
VLCLocalServerSectionFTP,
VLCLocalServerSectionVLCiOS,
VLCLocalServerSectionSMB,
VLCLocalServerSectionSAP
};
@interface NSMutableArray(VLCLocalNetworkServiceNetService)
-(NSUInteger)vlc_indexOfServiceWithNetService:(NSNetService*)netService;
-(void)vlc_removeServiceWithNetService:(NSNetService*)netService;
@end
@implementation NSMutableArray (VLCLocalNetworkServiceNetService)
- (NSUInteger)vlc_indexOfServiceWithNetService:(NSNetService *)netService {
NSUInteger index = [self indexOfObjectPassingTest:^BOOL(VLCLocalNetworkServiceNetService *obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (![obj respondsToSelector:@selector(netService)]) return false;
BOOL equal = [obj.netService isEqual:netService];
if (equal) {
*stop = YES;
}
return equal;
}];
return index;
}
-(void)vlc_removeServiceWithNetService:(NSNetService *)netService {
NSUInteger index = [self vlc_indexOfServiceWithNetService:netService];
if (index != NSNotFound) {
[self removeObjectAtIndex:index];
}
}
@end
@interface VLCLocalServerDiscoveryController () <NSNetServiceBrowserDelegate, NSNetServiceDelegate, VLCMediaListDelegate, UPnPDBObserver>
{
NSNetServiceBrowser *_ftpNetServiceBrowser;
NSNetServiceBrowser *_PlexNetServiceBrowser;
NSNetServiceBrowser *_httpNetServiceBrowser;
NSMutableArray *_plexServices;
NSMutableArray *_PlexServicesInfo;
NSMutableArray *_httpServices;
NSMutableArray *_httpServicesInfo;
NSMutableArray<VLCLocalNetworkServicePlex*> *_plexServices;
NSMutableArray<VLCLocalNetworkServiceHTTP*> *_httpVLCServices;
NSMutableArray<VLCLocalNetworkServiceFTP*> *_ftpServices;
// to keep strong references while resolving
NSMutableArray *_rawNetServices;
NSMutableArray *_ftpServices;
NSArray *_filteredUPNPDevices;
NSArray<VLCLocalNetworkServiceUPnP*> *_filteredUPNPDevices;
NSArray *_UPNPdevices;
VLCMediaDiscoverer *_sapDiscoverer;
......@@ -98,7 +138,13 @@
- (NSArray *)sectionHeaderTexts
{
return @[@"Generic", @"Universal Plug'n'Play (UPnP)", @"Plex Media Server (via Bonjour)", @"File Transfer Protocol (FTP)", NSLocalizedString(@"SHARED_VLC_IOS_LIBRARY", nil), NSLocalizedString(@"SMB_CIFS_FILE_SERVERS", nil), @"SAP"];
return @[@"Generic",
@"Universal Plug'n'Play (UPnP)",
@"Plex Media Server (via Bonjour)",
@"File Transfer Protocol (FTP)",
NSLocalizedString(@"SHARED_VLC_IOS_LIBRARY", nil),
NSLocalizedString(@"SMB_CIFS_FILE_SERVERS", nil),
@"SAP"];
}
- (instancetype)init
......@@ -132,12 +178,10 @@
_ftpNetServiceBrowser.delegate = self;
_plexServices = [[NSMutableArray alloc] init];
_PlexServicesInfo = [[NSMutableArray alloc] init];
_PlexNetServiceBrowser = [[NSNetServiceBrowser alloc] init];
_PlexNetServiceBrowser.delegate = self;
_httpServices = [[NSMutableArray alloc] init];
_httpServicesInfo = [[NSMutableArray alloc] init];
_httpVLCServices = [[NSMutableArray alloc] init];
_httpNetServiceBrowser = [[NSNetServiceBrowser alloc] init];
_httpNetServiceBrowser.delegate = self;
......@@ -185,178 +229,87 @@
#pragma mark - table view handling
- (NSInteger)numberOfItemsInSection:(NSInteger)section
{
switch (section) {
case 0:
return 1;
case 1:
return _filteredUPNPDevices.count;
case 2:
return _plexServices.count;
case 3:
return _ftpServices.count;
case 4:
return _httpServices.count;
case 5:
return _dsmDiscoverer.discoveredMedia.count;
case 6:
return _sapDiscoverer.discoveredMedia.count;
default:
return 0;
}
}
- (NSString *)titleForIndexPath:(NSIndexPath *)indexPath
- (id<VLCLocalNetworkService>)networkServiceForIndexPath:(NSIndexPath *)indexPath
{
VLCLocalServerSections section = indexPath.section;
NSUInteger row = indexPath.row;
NSUInteger section = indexPath.section;
switch (section) {
case 0:
case VLCLocalServerSectionGeneric:
{
return NSLocalizedString(@"CONNECT_TO_SERVER", nil);
return [[VLCLocalNetworkServiceItemLogin alloc] init];
}
case 1:
case VLCLocalServerSectionUPnP:
{
if (_filteredUPNPDevices.count > row) {
BasicUPnPDevice *device = _filteredUPNPDevices[row];
return [device friendlyName];
return _filteredUPNPDevices[row];
}
return @"";
}
case 2:
case VLCLocalServerSectionPlex:
{
return [_plexServices[row] name];
return _plexServices[row];
}
case 3:
case VLCLocalServerSectionFTP:
{
return [_ftpServices[row] name];
return _ftpServices[row];
}
case 4:
case VLCLocalServerSectionVLCiOS:
{
return [_httpServices[row] name];
return _httpVLCServices[row];
}
case 5:
case VLCLocalServerSectionSMB:
{
return [[_dsmDiscoverer.discoveredMedia mediaAtIndex:row] metadataForKey: VLCMetaInformationTitle];
return [[VLCLocalNetworkServiceDSM alloc] initWithMediaItem:[_dsmDiscoverer.discoveredMedia mediaAtIndex:row]];
}
case 6:
case VLCLocalServerSectionSAP:
{
return [[_sapDiscoverer.discoveredMedia mediaAtIndex:row] metadataForKey: VLCMetaInformationTitle];
return [[VLCLocalNetworkServiceSAP alloc] initWithMediaItem:[_sapDiscoverer.discoveredMedia mediaAtIndex:row]];
}
default:
return @"";
break;
}
return [[VLCLocalNetworkServiceItem alloc] initWithTile:@"FAIL"
icon:nil];
}
- (UIImage *)iconForIndexPath:(NSIndexPath *)indexPath
- (NSInteger)numberOfItemsInSection:(NSInteger)section
{
NSUInteger row = indexPath.row;
NSUInteger section = indexPath.section;
switch (section) {
case 0:
{
return [UIImage imageNamed:@"menuCone"];
}
case VLCLocalServerSectionGeneric:
return 1;
case 1:
{
UIImage *icon;
if (_filteredUPNPDevices.count > row) {
BasicUPnPDevice *device = _filteredUPNPDevices[row];
icon = [device smallIcon];
}
return icon != nil ? icon : [UIImage imageNamed:@"serverIcon"];
}
case VLCLocalServerSectionUPnP:
return _filteredUPNPDevices.count;
case 2:
{
return [UIImage imageNamed:@"PlexServerIcon"];
}
case VLCLocalServerSectionPlex:
return _plexServices.count;
case 3:
{
return [UIImage imageNamed:@"serverIcon"];
}
case VLCLocalServerSectionFTP:
return _ftpServices.count;
case 4:
{
return [UIImage imageNamed:@"menuCone"];
}
case VLCLocalServerSectionVLCiOS:
return _httpVLCServices.count;
case 5:
{
return [UIImage imageNamed:@"serverIcon"];
}
case VLCLocalServerSectionSMB:
return _dsmDiscoverer.discoveredMedia.count;
case 6: