VLCOpenNetworkStreamViewController.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*****************************************************************************
  2. * VLCOpenNetworkStreamViewController.m
  3. * VLC for iOS
  4. *****************************************************************************
  5. * Copyright (c) 2013 VideoLAN. All rights reserved.
  6. * $Id$
  7. *
  8. * Authors: Felix Paul Kühne <fkuehne # videolan.org>
  9. * Gleb Pinigin <gpinigin # gmail.com>
  10. * Pierre Sagaspe <pierre.sagaspe # me.com>
  11. *
  12. * Refer to the COPYING file of the official project for license.
  13. *****************************************************************************/
  14. #import "VLCOpenNetworkStreamViewController.h"
  15. #import "VLCAppDelegate.h"
  16. #import "VLCPlaylistViewController.h"
  17. #import "UIBarButtonItem+Theme.h"
  18. #import "UINavigationController+Theme.h"
  19. #import "VLCMenuTableViewController.h"
  20. @interface VLCOpenNetworkStreamViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>
  21. {
  22. NSMutableArray *_recentURLs;
  23. }
  24. @end
  25. @implementation VLCOpenNetworkStreamViewController
  26. + (void)initialize
  27. {
  28. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  29. NSDictionary *appDefaults = @{kVLCRecentURLs : @[], kVLCPrivateWebStreaming : @(NO)};
  30. [defaults registerDefaults:appDefaults];
  31. }
  32. - (void)applicationDidBecomeActive:(NSNotification *)notification
  33. {
  34. [self updatePasteboardTextInURLField];
  35. }
  36. - (void)dealloc
  37. {
  38. [[NSNotificationCenter defaultCenter] removeObserver:self
  39. name:UIApplicationDidBecomeActiveNotification
  40. object:[UIApplication sharedApplication]];
  41. }
  42. - (void)viewDidLoad
  43. {
  44. [super viewDidLoad];
  45. /*
  46. * Observe changes to the pasteboard so we can automatically paste it into the URL field.
  47. * Do not use UIPasteboardChangedNotification because we have copy actions that will trigger it on this screen.
  48. * Instead when the user comes back to the application from the background (or the inactive state by pulling down notification center), update the URL field.
  49. * Using the 'active' rather than 'foreground' notification for future proofing if iOS ever allows running multiple apps on the same screen (which would allow the pasteboard to be changed without truly backgrounding the app).
  50. */
  51. [[NSNotificationCenter defaultCenter] addObserver:self
  52. selector:@selector(applicationDidBecomeActive:)
  53. name:UIApplicationDidBecomeActiveNotification
  54. object:[UIApplication sharedApplication]];
  55. if (SYSTEM_RUNS_IOS7_OR_LATER)
  56. [self.openButton setTitle:NSLocalizedString(@"OPEN_NETWORK", @"") forState:UIControlStateNormal];
  57. else
  58. [self.openButton setTitle:NSLocalizedString(@"BUTTON_OPEN", @"") forState:UIControlStateNormal];
  59. [self.privateModeLabel setText:NSLocalizedString(@"PRIVATE_PLAYBACK_TOGGLE", @"")];
  60. [self.ScanSubModeLabel setText:NSLocalizedString(@"SCAN_SUBTITLE_TOGGLE", @"")];
  61. [self.ScanSubModeLabel setAdjustsFontSizeToFitWidth:YES];
  62. [self.ScanSubModeLabel setNumberOfLines:0];
  63. self.title = NSLocalizedString(@"OPEN_NETWORK", @"");
  64. self.navigationItem.leftBarButtonItem = [UIBarButtonItem themedRevealMenuButtonWithTarget:self andSelector:@selector(goBack:)];
  65. [self.whatToOpenHelpLabel setText:NSLocalizedString(@"OPEN_NETWORK_HELP", @"")];
  66. self.urlField.delegate = self;
  67. self.urlField.keyboardType = UIKeyboardTypeURL;
  68. if (SYSTEM_RUNS_IOS7_OR_LATER) {
  69. NSAttributedString *coloredAttributedPlaceholder = [[NSAttributedString alloc] initWithString:@"http://myserver.com/file.mkv" attributes:@{NSForegroundColorAttributeName: [UIColor VLCLightTextColor]}];
  70. self.urlField.attributedPlaceholder = coloredAttributedPlaceholder;
  71. self.edgesForExtendedLayout = UIRectEdgeNone;
  72. }
  73. // This will be called every time this VC is opened by the side menu controller
  74. [self updatePasteboardTextInURLField];
  75. }
  76. - (void)updatePasteboardTextInURLField
  77. {
  78. if ([[UIPasteboard generalPasteboard] containsPasteboardTypes:@[@"public.url", @"public.text"]]) {
  79. NSURL *pasteURL = [[UIPasteboard generalPasteboard] valueForPasteboardType:@"public.url"];
  80. if (!pasteURL || [[pasteURL absoluteString] isEqualToString:@""]) {
  81. NSString *pasteString = [[UIPasteboard generalPasteboard] valueForPasteboardType:@"public.text"];
  82. pasteURL = [NSURL URLWithString:pasteString];
  83. }
  84. if (pasteURL && ![[pasteURL scheme] isEqualToString:@""] && ![[pasteURL absoluteString] isEqualToString:@""])
  85. self.urlField.text = [pasteURL absoluteString];
  86. }
  87. }
  88. - (void)viewWillAppear:(BOOL)animated
  89. {
  90. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  91. _recentURLs = [NSMutableArray arrayWithArray:[defaults objectForKey:kVLCRecentURLs]];
  92. self.privateToggleSwitch.on = [defaults boolForKey:kVLCPrivateWebStreaming];
  93. self.ScanSubToggleSwitch.on = [defaults boolForKey:kVLChttpScanSubtitle];
  94. [super viewWillAppear:animated];
  95. }
  96. - (void)viewWillDisappear:(BOOL)animated
  97. {
  98. [[NSNotificationCenter defaultCenter] removeObserver:self
  99. name:UIApplicationDidBecomeActiveNotification
  100. object:[UIApplication sharedApplication]];
  101. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  102. [defaults setObject:[NSArray arrayWithArray:_recentURLs] forKey:kVLCRecentURLs];
  103. [defaults setBool:self.privateToggleSwitch.on forKey:kVLCPrivateWebStreaming];
  104. [defaults setBool:self.ScanSubToggleSwitch.on forKey:kVLChttpScanSubtitle];
  105. [defaults synchronize];
  106. [super viewWillDisappear:animated];
  107. }
  108. - (CGSize)contentSizeForViewInPopover {
  109. return [self.view sizeThatFits:CGSizeMake(320, 800)];
  110. }
  111. #pragma mark - UI interaction
  112. - (BOOL)shouldAutorotate
  113. {
  114. UIInterfaceOrientation toInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
  115. if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
  116. return NO;
  117. return YES;
  118. }
  119. - (IBAction)goBack:(id)sender
  120. {
  121. [[(VLCAppDelegate*)[UIApplication sharedApplication].delegate revealController] toggleSidebar:![(VLCAppDelegate*)[UIApplication sharedApplication].delegate revealController].sidebarShowing duration:kGHRevealSidebarDefaultAnimationDuration];
  122. }
  123. - (IBAction)openButtonAction:(id)sender
  124. {
  125. if ([self.urlField.text length] > 0) {
  126. if (!self.privateToggleSwitch.on) {
  127. if ([_recentURLs indexOfObject:self.urlField.text] != NSNotFound)
  128. [_recentURLs removeObject:self.urlField.text];
  129. if (_recentURLs.count >= 15)
  130. [_recentURLs removeLastObject];
  131. [_recentURLs addObject:self.urlField.text];
  132. [self.historyTableView reloadData];
  133. }
  134. [self _openURLStringAndDismiss:self.urlField.text];
  135. }
  136. }
  137. #pragma mark - table view data source
  138. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  139. {
  140. return 1;
  141. }
  142. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  143. {
  144. return _recentURLs.count;
  145. }
  146. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  147. {
  148. static NSString *CellIdentifier = @"StreamingHistoryCell";
  149. UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  150. if (cell == nil) {
  151. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
  152. cell.textLabel.textColor = [UIColor whiteColor];
  153. cell.textLabel.highlightedTextColor = [UIColor blackColor];
  154. cell.detailTextLabel.textColor = [UIColor VLCLightTextColor];
  155. cell.detailTextLabel.highlightedTextColor = [UIColor blackColor];
  156. }
  157. NSInteger row = indexPath.row;
  158. cell.textLabel.text = [_recentURLs[row] lastPathComponent];
  159. cell.detailTextLabel.text = _recentURLs[row];
  160. return cell;
  161. }
  162. #pragma mark - table view delegate
  163. - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
  164. {
  165. cell.backgroundColor = (indexPath.row % 2 == 0)? [UIColor blackColor]: [UIColor VLCDarkBackgroundColor];
  166. }
  167. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
  168. {
  169. return YES;
  170. }
  171. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
  172. {
  173. if (editingStyle == UITableViewCellEditingStyleDelete) {
  174. [_recentURLs removeObjectAtIndex:indexPath.row];
  175. [tableView reloadData];
  176. }
  177. }
  178. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  179. {
  180. [self _openURLStringAndDismiss:_recentURLs[indexPath.row]];
  181. [self.historyTableView deselectRowAtIndexPath:indexPath animated:NO];
  182. }
  183. - (void)tableView:(UITableView *)tableView
  184. performAction:(SEL)action
  185. forRowAtIndexPath:(NSIndexPath *)indexPath
  186. withSender:(id)sender
  187. {
  188. NSString *actionText = NSStringFromSelector(action);
  189. if ([actionText isEqualToString:@"copy:"])
  190. {
  191. [UIPasteboard generalPasteboard].string = _recentURLs[indexPath.row];
  192. }
  193. }
  194. - (BOOL)tableView:(UITableView *)tableView
  195. canPerformAction:(SEL)action
  196. forRowAtIndexPath:(NSIndexPath *)indexPath
  197. withSender:(id)sender
  198. {
  199. NSString *actionText = NSStringFromSelector(action);
  200. if ([actionText isEqualToString:@"copy:"])
  201. {
  202. return YES;
  203. }
  204. return NO;
  205. }
  206. - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
  207. {
  208. return YES;
  209. }
  210. #pragma mark - internals
  211. - (void)_openURLStringAndDismiss:(NSString *)url
  212. {
  213. NSURL *URLscheme = [NSURL URLWithString:url];
  214. NSString *URLofSubtitle = nil;
  215. if ([URLscheme.scheme isEqualToString:@"http"])
  216. if (self.ScanSubToggleSwitch.on)
  217. URLofSubtitle = [self _checkURLofSubtitle:url];
  218. [(VLCAppDelegate*)[UIApplication sharedApplication].delegate openMovieWithExternalSubtitleFromURL:[NSURL URLWithString:url] externalSubURL:URLofSubtitle];
  219. }
  220. - (NSString *)_checkURLofSubtitle:(NSString *)url
  221. {
  222. NSString *SubtitleFileExtensions = kSupportedSubtitleFileExtensions;
  223. NSCharacterSet *characterFilter = [NSCharacterSet characterSetWithCharactersInString:@"\\.():$"];
  224. SubtitleFileExtensions = [[SubtitleFileExtensions componentsSeparatedByCharactersInSet:characterFilter] componentsJoinedByString:@""];
  225. NSArray *arraySubtitleFileExtensions = [SubtitleFileExtensions componentsSeparatedByString:@"|"];
  226. NSString *urlTemp = [[url stringByDeletingPathExtension] stringByAppendingString:@"."];
  227. for (int cnt = 0; cnt < arraySubtitleFileExtensions.count; cnt++) {
  228. NSString *CheckURL = [urlTemp stringByAppendingString:arraySubtitleFileExtensions[cnt]];
  229. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:CheckURL]];
  230. NSURLResponse *response = nil;
  231. NSError *error = nil;
  232. NSData *receivedData = [[NSData alloc] initWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]];
  233. NSInteger httpStatus = [(NSHTTPURLResponse *)response statusCode];
  234. receivedData = nil;
  235. if (httpStatus == 200) {
  236. NSString *receivedSub = [NSString stringWithContentsOfURL:[NSURL URLWithString:CheckURL] encoding:NSASCIIStringEncoding error:nil];
  237. NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  238. NSString *directoryPath = searchPaths[0];
  239. NSString *FileSubtitlePath = [directoryPath stringByAppendingPathComponent:[CheckURL lastPathComponent]];
  240. NSFileManager *fileManager = [NSFileManager defaultManager];
  241. if (![fileManager fileExistsAtPath:FileSubtitlePath]) {
  242. //create local subtitle file
  243. [fileManager createFileAtPath:FileSubtitlePath contents:nil attributes:nil];
  244. if (![fileManager fileExistsAtPath:FileSubtitlePath])
  245. APLog(@"file creation failed, no data was saved");
  246. }
  247. [receivedSub writeToFile:FileSubtitlePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
  248. return FileSubtitlePath;
  249. }
  250. }
  251. return nil;
  252. }
  253. #pragma mark - text view delegate
  254. - (BOOL)textFieldShouldReturn:(UITextField *)textField
  255. {
  256. [self.urlField resignFirstResponder];
  257. return NO;
  258. }
  259. @end