Commit cc48dbcb authored by Tobias's avatar Tobias

add UPnP ServiceBrowser

parent baf9ad8c
/*****************************************************************************
* VLCLocalNetworkServiceBrowserUPnP.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 "VLCLocalNetworkServiceBrowser-Protocol.h"
@interface VLCLocalNetworkServiceBrowserUPnP : NSObject <VLCLocalNetworkServiceBrowser>
@end
/*****************************************************************************
* VLCLocalNetworkServiceBrowserUPnP.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 "VLCLocalNetworkServiceBrowserUPnP.h"
#import "UPnPManager.h"
@interface VLCLocalNetworkServiceBrowserUPnP () <UPnPDBObserver>{
BOOL _udnpDiscoveryRunning;
NSTimer *_searchTimer;
BOOL _setup;
}
@property (nonatomic) NSArray<VLCLocalNetworkServiceUPnP*> *filteredUPNPDevices;
@property (nonatomic) NSArray *UPNPdevices;
@end
@implementation VLCLocalNetworkServiceBrowserUPnP
@synthesize name = _name, delegate = _delegate;
- (instancetype)init
{
self = [super init];
if (self) {
_name = @"Universal Plug'n'Play (UPnP)";
}
return self;
}
#pragma mark - VLCLocalNetworkServiceBrowser Protocol
- (NSUInteger)numberOfItems {
return _filteredUPNPDevices.count;
}
- (id<VLCLocalNetworkService>)networkServiceForIndex:(NSUInteger)index {
return _filteredUPNPDevices[index];
}
- (void)startDiscovery {
[self _startUPNPDiscovery];
}
- (void)stopDiscovery {
[self _stopUPNPDiscovery];
}
#pragma mark -
#pragma mark - UPNP discovery
- (void)_startUPNPDiscovery
{
UPnPManager *managerInstance = [UPnPManager GetInstance];
_UPNPdevices = [[managerInstance DB] rootDevices];
if (_UPNPdevices.count > 0)
[self UPnPDBUpdated:nil];
[[managerInstance DB] addObserver:self];
//Optional; set User Agent
if (!_setup) {
[[managerInstance SSDP] setUserAgentProduct:[NSString stringWithFormat:@"VLCforiOS/%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]] andOS:[NSString stringWithFormat:@"iOS/%@", [[UIDevice currentDevice] systemVersion]]];
_setup = YES;
}
//Search for UPnP Devices
[[managerInstance SSDP] startSSDP];
[[managerInstance SSDP] notifySSDPAlive];
_searchTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1.0] interval:10.0 target:self selector:@selector(_performSSDPSearch) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:_searchTimer forMode:NSRunLoopCommonModes];
_udnpDiscoveryRunning = YES;
}
- (void)_performSSDPSearch
{
UPnPManager *managerInstance = [UPnPManager GetInstance];
[[managerInstance SSDP] searchSSDP];
[[managerInstance SSDP] searchForMediaServer];
[[managerInstance SSDP] performSelectorInBackground:@selector(SSDPDBUpdate) withObject:nil];
}
- (void)_stopUPNPDiscovery
{
if (_udnpDiscoveryRunning) {
UPnPManager *managerInstance = [UPnPManager GetInstance];
[[managerInstance SSDP] notifySSDPByeBye];
[_searchTimer invalidate];
_searchTimer = nil;
[[managerInstance DB] removeObserver:self];
[[managerInstance SSDP] stopSSDP];
_udnpDiscoveryRunning = NO;
}
}
#pragma mark - UPnPDBObserver protocol
- (void)UPnPDBWillUpdate:(UPnPDB*)sender
{
}
- (void)UPnPDBUpdated:(UPnPDB*)sender
{
NSUInteger count = _UPNPdevices.count;
BasicUPnPDevice *device;
NSMutableArray<VLCLocalNetworkServiceUPnP*> *mutArray = [[NSMutableArray alloc] init];
for (NSUInteger x = 0; x < count; x++) {
device = _UPNPdevices[x];
if ([[device urn] isEqualToString:@"urn:schemas-upnp-org:device:MediaServer:1"])
[mutArray addObject:[[VLCLocalNetworkServiceUPnP alloc] initWithUPnPDevice:device]];
else
APLog(@"found device '%@' with unsupported urn '%@'", [device friendlyName], [device urn]);
}
_filteredUPNPDevices = nil;
_filteredUPNPDevices = [NSArray arrayWithArray:mutArray];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.delegate localNetworkServiceBrowserDidUpdateServices:self];
}];
}
@end
......@@ -16,7 +16,6 @@
#import "VLCServerListViewController.h"
#import "VLCPlaybackController.h"
#import "UPnPManager.h"
#import "VLCNetworkListCell.h"
#import "VLCLocalPlexFolderListViewController.h"
......@@ -34,6 +33,7 @@
#import "VLCLocalNetworkServiceBrowserNetService.h"
#import "VLCLocalNetworkServiceBrowserMediaDiscoverer.h"
#import "VLCLocalNetworkServiceBrowserManualConnect.h"
#import "VLCLocalNetworkServiceBrowserUPnP.h"
typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
VLCLocalServerSectionGeneric = 0,
......@@ -47,25 +47,20 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
@interface VLCLocalServerDiscoveryController () <VLCLocalNetworkServiceBrowserDelegate, VLCMediaListDelegate, UPnPDBObserver>
@interface VLCLocalServerDiscoveryController () <VLCLocalNetworkServiceBrowserDelegate>
{
id<VLCLocalNetworkServiceBrowser> _manualConnectBrowser;
id<VLCLocalNetworkServiceBrowser> _plexBrowser;
id<VLCLocalNetworkServiceBrowser> _FTPBrowser;
id<VLCLocalNetworkServiceBrowser> _HTTPBrowser;
NSArray<VLCLocalNetworkServiceUPnP*> *_filteredUPNPDevices;
NSArray *_UPNPdevices;
id<VLCLocalNetworkServiceBrowser> _UPnPBrowser;
id<VLCLocalNetworkServiceBrowser> _sapBrowser;
id<VLCLocalNetworkServiceBrowser> _dsmBrowser;
VLCSharedLibraryParser *_httpParser;
Reachability *_reachability;
BOOL _udnpDiscoveryRunning;
NSTimer *_searchTimer;
BOOL _setup;
}
......@@ -83,7 +78,7 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
- (void)stopDiscovery
{
[self _stopUPNPDiscovery];
[_UPnPBrowser stopDiscovery];
[_sapBrowser stopDiscovery];
[_dsmBrowser stopDiscovery];
......@@ -94,8 +89,11 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
- (void)startDiscovery
{
if (_reachability.currentReachabilityStatus != ReachableViaWiFi) {
return;
}
[self _startUPNPDiscovery];
[_UPnPBrowser startDiscovery];
[_sapBrowser startDiscovery];
[_dsmBrowser startDiscovery];
......@@ -107,7 +105,7 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
- (NSArray *)sectionHeaderTexts
{
return @[_manualConnectBrowser.name,
@"Universal Plug'n'Play (UPnP)",
_UPnPBrowser.name,
_plexBrowser.name,
_FTPBrowser.name,
_HTTPBrowser.name,
......@@ -148,6 +146,8 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
_dsmBrowser = [[VLCLocalNetworkServiceBrowserDSM alloc] init];
_dsmBrowser.delegate = self;
_UPnPBrowser = [[VLCLocalNetworkServiceBrowserUPnP alloc] init];
_UPnPBrowser.delegate = self;
_reachability = [Reachability reachabilityForLocalWiFi];
[_reachability startNotifier];
......@@ -168,22 +168,6 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
}
}
- (IBAction)goBack:(id)sender
{
[self _stopUPNPDiscovery];
[self stopDiscovery];
[[VLCSidebarController sharedInstance] toggleSidebar];
}
- (BOOL)shouldAutorotate
{
UIInterfaceOrientation toInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
return NO;
return YES;
}
#pragma mark - table view handling
- (id<VLCLocalNetworkService>)networkServiceForIndexPath:(NSIndexPath *)indexPath
......@@ -200,9 +184,7 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
case VLCLocalServerSectionUPnP:
{
if (_filteredUPNPDevices.count > row) {
return _filteredUPNPDevices[row];
}
return [_UPnPBrowser networkServiceForIndex:row];
}
case VLCLocalServerSectionPlex:
......@@ -245,7 +227,7 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
return _manualConnectBrowser.numberOfItems;
case VLCLocalServerSectionUPnP:
return _filteredUPNPDevices.count;
return _UPnPBrowser.numberOfItems;
case VLCLocalServerSectionPlex:
return _plexBrowser.numberOfItems;
......@@ -272,11 +254,8 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
if (_reachability.currentReachabilityStatus != ReachableViaWiFi)
return NO;
UPnPManager *managerInstance = [UPnPManager GetInstance];
[[managerInstance DB] removeObserver:self];
[[managerInstance SSDP] stopSSDP];
[self _startUPNPDiscovery];
[self stopDiscovery];
[self startDiscovery];
return YES;
}
......@@ -288,82 +267,4 @@ typedef NS_ENUM(NSUInteger, VLCLocalServerSections) {
}
}
#pragma mark - UPNP discovery
- (void)_startUPNPDiscovery
{
if (_reachability.currentReachabilityStatus != ReachableViaWiFi)
return;
UPnPManager *managerInstance = [UPnPManager GetInstance];
_UPNPdevices = [[managerInstance DB] rootDevices];
if (_UPNPdevices.count > 0)
[self UPnPDBUpdated:nil];
[[managerInstance DB] addObserver:self];
//Optional; set User Agent
if (!_setup) {
[[managerInstance SSDP] setUserAgentProduct:[NSString stringWithFormat:@"VLCforiOS/%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]] andOS:[NSString stringWithFormat:@"iOS/%@", [[UIDevice currentDevice] systemVersion]]];
_setup = YES;
}
//Search for UPnP Devices
[[managerInstance SSDP] startSSDP];
[[managerInstance SSDP] notifySSDPAlive];
_searchTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1.0] interval:10.0 target:self selector:@selector(_performSSDPSearch) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:_searchTimer forMode:NSRunLoopCommonModes];
_udnpDiscoveryRunning = YES;
}
- (void)_performSSDPSearch
{
UPnPManager *managerInstance = [UPnPManager GetInstance];
[[managerInstance SSDP] searchSSDP];
[[managerInstance SSDP] searchForMediaServer];
[[managerInstance SSDP] performSelectorInBackground:@selector(SSDPDBUpdate) withObject:nil];
}
- (void)_stopUPNPDiscovery
{
if (_udnpDiscoveryRunning) {
UPnPManager *managerInstance = [UPnPManager GetInstance];
[[managerInstance SSDP] notifySSDPByeBye];
[_searchTimer invalidate];
_searchTimer = nil;
[[managerInstance DB] removeObserver:self];
[[managerInstance SSDP] stopSSDP];
_udnpDiscoveryRunning = NO;
}
}
//protocol UPnPDBObserver
- (void)UPnPDBWillUpdate:(UPnPDB*)sender
{
}
- (void)UPnPDBUpdated:(UPnPDB*)sender
{
NSUInteger count = _UPNPdevices.count;
BasicUPnPDevice *device;
NSMutableArray<VLCLocalNetworkServiceUPnP*> *mutArray = [[NSMutableArray alloc] init];
for (NSUInteger x = 0; x < count; x++) {
device = _UPNPdevices[x];
if ([[device urn] isEqualToString:@"urn:schemas-upnp-org:device:MediaServer:1"])
[mutArray addObject:[[VLCLocalNetworkServiceUPnP alloc] initWithUPnPDevice:device]];
else
APLog(@"found device '%@' with unsupported urn '%@'", [device friendlyName], [device urn]);
}
_filteredUPNPDevices = nil;
_filteredUPNPDevices = [NSArray arrayWithArray:mutArray];
if (self.delegate) {
if ([self.delegate respondsToSelector:@selector(discoveryFoundSomethingNew)]) {
[self.delegate performSelectorOnMainThread:@selector(discoveryFoundSomethingNew) withObject:nil waitUntilDone:NO];
}
}
}
@end
......@@ -264,6 +264,7 @@
DDE3C8DA1BD1323800C03B8B /* VLCLocalNetworkService.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE3C8CF1BD0246500C03B8B /* VLCLocalNetworkService.m */; };
DDE3C8DD1BD246DD00C03B8B /* VLCLocalNetworkServiceBrowserMediaDiscoverer.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE3C8DC1BD246DD00C03B8B /* VLCLocalNetworkServiceBrowserMediaDiscoverer.m */; };
DDE3C8E01BD24FAC00C03B8B /* VLCLocalNetworkServiceBrowserManualConnect.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE3C8DF1BD24FAC00C03B8B /* VLCLocalNetworkServiceBrowserManualConnect.m */; };
DDE3C8E31BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE3C8E21BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.m */; };
E0C04F951A25B4410080331A /* VLCDocumentPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C04F941A25B4410080331A /* VLCDocumentPickerController.m */; };
/* End PBXBuildFile section */
......@@ -818,6 +819,8 @@
DDE3C8DC1BD246DD00C03B8B /* VLCLocalNetworkServiceBrowserMediaDiscoverer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCLocalNetworkServiceBrowserMediaDiscoverer.m; path = Sources/LocalNetworkConnectivity/VLCLocalNetworkServiceBrowserMediaDiscoverer.m; sourceTree = SOURCE_ROOT; };
DDE3C8DE1BD24FAC00C03B8B /* VLCLocalNetworkServiceBrowserManualConnect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCLocalNetworkServiceBrowserManualConnect.h; path = Sources/LocalNetworkConnectivity/VLCLocalNetworkServiceBrowserManualConnect.h; sourceTree = SOURCE_ROOT; };
DDE3C8DF1BD24FAC00C03B8B /* VLCLocalNetworkServiceBrowserManualConnect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCLocalNetworkServiceBrowserManualConnect.m; path = Sources/LocalNetworkConnectivity/VLCLocalNetworkServiceBrowserManualConnect.m; sourceTree = SOURCE_ROOT; };
DDE3C8E11BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCLocalNetworkServiceBrowserUPnP.h; path = Sources/LocalNetworkConnectivity/VLCLocalNetworkServiceBrowserUPnP.h; sourceTree = SOURCE_ROOT; };
DDE3C8E21BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCLocalNetworkServiceBrowserUPnP.m; path = Sources/LocalNetworkConnectivity/VLCLocalNetworkServiceBrowserUPnP.m; sourceTree = SOURCE_ROOT; };
DDF157B31ACB169B00AAFBC6 /* WatchKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WatchKit.framework; path = System/Library/Frameworks/WatchKit.framework; sourceTree = SDKROOT; };
E09EACF57CDD22ABAE66CDD0 /* Pods-vlc-ios.distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-vlc-ios.distribution.xcconfig"; path = "Pods/Target Support Files/Pods-vlc-ios/Pods-vlc-ios.distribution.xcconfig"; sourceTree = "<group>"; };
E0C04F931A25B4410080331A /* VLCDocumentPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCDocumentPickerController.h; path = Sources/VLCDocumentPickerController.h; sourceTree = SOURCE_ROOT; };
......@@ -1145,6 +1148,8 @@
DDE3C8DC1BD246DD00C03B8B /* VLCLocalNetworkServiceBrowserMediaDiscoverer.m */,
DDE3C8DE1BD24FAC00C03B8B /* VLCLocalNetworkServiceBrowserManualConnect.h */,
DDE3C8DF1BD24FAC00C03B8B /* VLCLocalNetworkServiceBrowserManualConnect.m */,
DDE3C8E11BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.h */,
DDE3C8E21BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.m */,
7D37E3981BC93F7500AFA70E /* VLCLocalServerDiscoveryController.h */,
7D37E3991BC93F7500AFA70E /* VLCLocalServerDiscoveryController.m */,
7D30F3DA183AB2F900FFC021 /* VLCNetworkLoginViewController.h */,
......@@ -2161,6 +2166,7 @@
7DC19B0C1868D21800810BF7 /* VLCFirstStepsSixthPageViewController.m in Sources */,
2915540717490A1E00B86CAD /* HTTPServer.m in Sources */,
2915540817490A1E00B86CAD /* MultipartFormDataParser.m in Sources */,
DDE3C8E31BD2592300C03B8B /* VLCLocalNetworkServiceBrowserUPnP.m in Sources */,
2915540917490A1E00B86CAD /* MultipartMessageHeader.m in Sources */,
2915540A17490A1E00B86CAD /* MultipartMessageHeaderField.m in Sources */,
2915542217490A9C00B86CAD /* GCDAsyncSocket.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