Pārlūkot izejas kodu

move TrackselectorView out of the MovieViewController

Carola Nitz 7 gadi atpakaļ
vecāks
revīzija
96f81a4f50

+ 76 - 277
Sources/VLCMovieViewController.m

@@ -22,8 +22,6 @@
 
 #import "VLCMovieViewController.h"
 #import "VLCExternalDisplayController.h"
-#import "VLCTrackSelectorTableViewCell.h"
-#import "VLCTrackSelectorHeaderView.h"
 #import "VLCEqualizerView.h"
 #import "VLCMultiSelectionMenuView.h"
 #import "VLCPlaybackController.h"
@@ -35,6 +33,7 @@
 #import "VLCMovieViewControlPanelView.h"
 #import "VLCSlider.h"
 #import "VLCLibraryViewController.h"
+#import "VLCTrackSelectorView.h"
 
 #define FORWARD_SWIPE_DURATION 30
 #define BACKWARD_SWIPE_DURATION 10
@@ -45,9 +44,6 @@
 #define MAX_FOV 150.f
 #define MIN_FOV 20.f
 
-#define TRACK_SELECTOR_TABLEVIEW_CELL @"track selector table view cell"
-#define TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER @"track selector table view section header"
-
 #define LOCKCHECK \
 if (_interfaceIsLocked) \
 return
@@ -60,7 +56,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
   VLCPanTypeProjection
 };
 
-@interface VLCMovieViewController () <UIGestureRecognizerDelegate, UITableViewDataSource, UITableViewDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate>
+@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate>
 {
     BOOL _controlsHidden;
     BOOL _videoFiltersHidden;
@@ -77,7 +73,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
     BOOL _playerIsSetup;
     BOOL _isScrubbing;
     BOOL _interfaceIsLocked;
-    BOOL _switchingTracksNotChapters;
     BOOL _audioOnly;
 
     BOOL _volumeGestureEnabled;
@@ -102,8 +97,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
     UITapGestureRecognizer *_tapOnVideoRecognizer;
     UITapGestureRecognizer *_tapToSeekRecognizer;
 
-    UIView *_trackSelectorContainer;
-    UITableView *_trackSelectorTableView;
+    VLCTrackSelectorView *_trackSelectorContainer;
 
     VLCEqualizerView *_equalizerView;
     VLCMultiSelectionMenuView *_multiSelectionView;
@@ -208,6 +202,62 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
     self.trackNameLabel.text = self.artistNameLabel.text = self.albumNameLabel.text = @"";
 
     _movieView.userInteractionEnabled = NO;
+
+    [self setupGestureRecognizers];
+
+    _isTapSeeking = NO;
+    _previousJumpState = VLCMovieJumpStateDefault;
+    _numberOfTapSeek = 0;
+
+    self.backButton.tintColor = [UIColor colorWithRed:(190.0f/255.0f) green:(190.0f/255.0f) blue:(190.0f/255.0f) alpha:1.];
+    self.toolbar.tintColor = [UIColor whiteColor];
+    self.toolbar.barStyle = UIBarStyleBlack;
+
+    rect = self.resetVideoFilterButton.frame;
+    rect.origin.y = rect.origin.y + 5.;
+    self.resetVideoFilterButton.frame = rect;
+    rect = self.toolbar.frame;
+    rect.size.height = rect.size.height + rect.origin.y;
+    rect.origin.y = 0;
+    self.toolbar.frame = rect;
+
+    _playerIsSetup = NO;
+
+    [self.movieView setAccessibilityLabel:NSLocalizedString(@"VO_VIDEOPLAYER_TITLE", nil)];
+    [self.movieView setAccessibilityHint:NSLocalizedString(@"VO_VIDEOPLAYER_DOUBLETAP", nil)];
+
+    _trackSelectorContainer = [[VLCTrackSelectorView alloc] initWithFrame:CGRectZero];
+    _trackSelectorContainer.hidden = YES;
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+        for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers)
+            [recognizer setEnabled:YES];
+        _trackSelectorContainer.hidden = YES;
+    };
+    _trackSelectorContainer.completionHandler = completionBlock;
+    _trackSelectorContainer.translatesAutoresizingMaskIntoConstraints = NO;
+    [self.view addSubview:_trackSelectorContainer];
+
+    _equalizerView = [[VLCEqualizerView alloc] initWithFrame:CGRectMake(0, 0, 450., 240.)];
+    _equalizerView.delegate = [VLCPlaybackController sharedInstance];
+    _equalizerView.UIdelegate = self;
+    _equalizerView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
+    _equalizerView.hidden = YES;
+    [self.view addSubview:_equalizerView];
+
+    //Sleep Timer initialization
+    [self sleepTimerInitializer:deviceSpeedCategory];
+    [self setupControlPanel];
+
+    CGRect screenBounds = [[UIScreen mainScreen] bounds];
+    CGFloat screenScale = [[UIScreen mainScreen] scale];
+    _screenSizePixel = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale);
+    _saveLocation = CGPointMake(-1.f, -1.f);
+
+    [self setupConstraints];
+}
+
+- (void)setupGestureRecognizers
+{
     _tapOnVideoRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleControlsVisible)];
     _tapOnVideoRecognizer.delegate = self;
     [self.view addGestureRecognizer:_tapOnVideoRecognizer];
@@ -240,7 +290,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
     _swipeRecognizerDown.direction = UISwipeGestureRecognizerDirectionDown;
     _swipeRecognizerDown.numberOfTouchesRequired = 2;
 
-
     [self.view addGestureRecognizer:_swipeRecognizerLeft];
     [self.view addGestureRecognizer:_swipeRecognizerRight];
     [self.view addGestureRecognizer:_swipeRecognizerUp];
@@ -261,82 +310,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
     _swipeRecognizerDown.delegate = self;
     _tapRecognizer.delegate = self;
     _tapToSeekRecognizer.delegate = self;
-
-    _isTapSeeking = NO;
-    _previousJumpState = VLCMovieJumpStateDefault;
-    _numberOfTapSeek = 0;
-
-    self.backButton.tintColor = [UIColor colorWithRed:(190.0f/255.0f) green:(190.0f/255.0f) blue:(190.0f/255.0f) alpha:1.];
-    self.toolbar.tintColor = [UIColor whiteColor];
-    self.toolbar.barStyle = UIBarStyleBlack;
-
-    rect = self.resetVideoFilterButton.frame;
-    rect.origin.y = rect.origin.y + 5.;
-    self.resetVideoFilterButton.frame = rect;
-    rect = self.toolbar.frame;
-    rect.size.height = rect.size.height + rect.origin.y;
-    rect.origin.y = 0;
-    self.toolbar.frame = rect;
-
-    _playerIsSetup = NO;
-
-    [self.movieView setAccessibilityLabel:NSLocalizedString(@"VO_VIDEOPLAYER_TITLE", nil)];
-    [self.movieView setAccessibilityHint:NSLocalizedString(@"VO_VIDEOPLAYER_DOUBLETAP", nil)];
-
-    rect = self.view.frame;
-    CGFloat width;
-    CGFloat height;
-    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
-        width = 300.;
-        height = 320.;
-    } else {
-        width = 420.;
-        height = 470.;
-    }
-
-    _trackSelectorTableView = [[UITableView alloc] initWithFrame:CGRectMake(0., 0., width, height) style:UITableViewStylePlain];
-    _trackSelectorTableView.delegate = self;
-    _trackSelectorTableView.dataSource = self;
-    _trackSelectorTableView.separatorColor = [UIColor clearColor];
-    _trackSelectorTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
-    _trackSelectorTableView.rowHeight = 44.;
-    _trackSelectorTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
-    _trackSelectorTableView.sectionHeaderHeight = 28.;
-    [_trackSelectorTableView registerClass:[VLCTrackSelectorTableViewCell class] forCellReuseIdentifier:TRACK_SELECTOR_TABLEVIEW_CELL];
-    [_trackSelectorTableView registerClass:[VLCTrackSelectorHeaderView class] forHeaderFooterViewReuseIdentifier:TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER];
-    _trackSelectorTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
-
-    _trackSelectorContainer = [[VLCFrostedGlasView alloc] initWithFrame:CGRectMake((rect.size.width - width) / 2., (rect.size.height - height) / 2., width, height)];
-    [_trackSelectorContainer addSubview:_trackSelectorTableView];
-    _trackSelectorContainer.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight;
-    _trackSelectorContainer.hidden = YES;
-
-    if (deviceSpeedCategory >= 3) {
-        _trackSelectorTableView.opaque = NO;
-        _trackSelectorTableView.backgroundColor = [UIColor clearColor];
-    } else
-        _trackSelectorTableView.backgroundColor = [UIColor blackColor];
-    _trackSelectorTableView.allowsMultipleSelection = YES;
-
-    [self.view addSubview:_trackSelectorContainer];
-
-    _equalizerView = [[VLCEqualizerView alloc] initWithFrame:CGRectMake(0, 0, 450., 240.)];
-    _equalizerView.delegate = [VLCPlaybackController sharedInstance];
-    _equalizerView.UIdelegate = self;
-    _equalizerView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
-    _equalizerView.hidden = YES;
-    [self.view addSubview:_equalizerView];
-
-    //Sleep Timer initialization
-    [self sleepTimerInitializer:deviceSpeedCategory];
-    [self setupControlPanel];
-
-    CGRect screenBounds = [[UIScreen mainScreen] bounds];
-    CGFloat screenScale = [[UIScreen mainScreen] scale];
-    _screenSizePixel = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale);
-    _saveLocation = CGPointMake(-1.f, -1.f);
-
-    [self setupConstraints];
 }
 
 - (void)setupControlPanel
@@ -378,6 +351,16 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
                                                                       views:@{@"panel":_controllerPanel}];
     [self.view addConstraints:hConstraints];
     [self.view addConstraints:vConstraints];
+
+    CGFloat width = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ? 300.0 : 420.0;
+    //constraint within _trackSelectorContainer is setting it's height to the tableviews contentview
+    NSArray *constraints = @[
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorContainer attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0],
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorContainer attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0],
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorContainer attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1 constant:width],
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorContainer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:2.0/3.0 constant:0],
+                             ];
+    [NSLayoutConstraint activateConstraints:constraints];
 }
 
 - (void)viewWillAppear:(BOOL)animated
@@ -1039,13 +1022,13 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 {
     LOCKCHECK;
 
-    if (_trackSelectorContainer.hidden == YES || _switchingTracksNotChapters == NO) {
-        _switchingTracksNotChapters = YES;
+    if (_trackSelectorContainer.hidden == YES || _trackSelectorContainer.switchingTracksNotChapters == NO) {
+        _trackSelectorContainer.switchingTracksNotChapters = YES;
 
         _trackSelectorContainer.hidden = NO;
         _trackSelectorContainer.alpha = 1.;
 
-        [_trackSelectorTableView reloadData];
+        [_trackSelectorContainer updateView];
 
         if (_equalizerView.hidden == NO)
             _equalizerView.hidden = YES;
@@ -1068,7 +1051,7 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 
     } else {
         _trackSelectorContainer.hidden = YES;
-        _switchingTracksNotChapters = NO;
+        _trackSelectorContainer.switchingTracksNotChapters = NO;
     }
 }
 
@@ -1204,10 +1187,10 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
 {
     LOCKCHECK;
 
-    if (_trackSelectorContainer.hidden == YES || _switchingTracksNotChapters == YES) {
-        _switchingTracksNotChapters = NO;
+    if (_trackSelectorContainer.hidden == YES || _trackSelectorContainer.switchingTracksNotChapters == YES) {
+        _trackSelectorContainer.switchingTracksNotChapters = NO;
+        [_trackSelectorContainer updateView];
 
-        [_trackSelectorTableView reloadData];
         _trackSelectorContainer.hidden = NO;
         _trackSelectorContainer.alpha = 1.;
 
@@ -1270,190 +1253,6 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
     [self _resetIdleTimer];
 }
 
-#pragma mark - track selector table view
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-{
-    NSInteger ret = 0;
-    VLCMediaPlayer *mediaPlayer = _vpc.mediaPlayer;
-
-    if (_switchingTracksNotChapters == YES) {
-        if (mediaPlayer.audioTrackIndexes.count > 2)
-            ret++;
-
-        if (mediaPlayer.videoSubTitlesIndexes.count > 1)
-            ret++;
-    } else {
-        if ([mediaPlayer numberOfTitles] > 1)
-            ret++;
-
-        if ([mediaPlayer numberOfChaptersForTitle:mediaPlayer.currentTitleIndex] > 1)
-            ret++;
-    }
-
-    return ret;
-}
-
-- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
-{
-    UITableViewHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER];
-
-    if (!view)
-        view = [[VLCTrackSelectorHeaderView alloc] initWithReuseIdentifier:TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER];
-
-    return view;
-}
-
-- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
-{
-    VLCMediaPlayer *mediaPlayer = _vpc.mediaPlayer;
-
-    if (_switchingTracksNotChapters == YES) {
-        if (mediaPlayer.audioTrackIndexes.count > 2 && section == 0)
-            return NSLocalizedString(@"CHOOSE_AUDIO_TRACK", nil);
-
-        if (mediaPlayer.videoSubTitlesIndexes.count > 1)
-            return NSLocalizedString(@"CHOOSE_SUBTITLE_TRACK", nil);
-    } else {
-        if ([mediaPlayer numberOfTitles] > 1 && section == 0)
-            return NSLocalizedString(@"CHOOSE_TITLE", nil);
-
-        if ([mediaPlayer numberOfChaptersForTitle:mediaPlayer.currentTitleIndex] > 1)
-            return NSLocalizedString(@"CHOOSE_CHAPTER", nil);
-    }
-
-    return @"unknown track type";
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    VLCTrackSelectorTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TRACK_SELECTOR_TABLEVIEW_CELL];
-
-    if (!cell)
-        cell = [[VLCTrackSelectorTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TRACK_SELECTOR_TABLEVIEW_CELL];
-
-    NSInteger row = indexPath.row;
-    NSInteger section = indexPath.section;
-    VLCMediaPlayer *mediaPlayer = _vpc.mediaPlayer;
-    BOOL cellShowsCurrentTrack = NO;
-
-    if (_switchingTracksNotChapters == YES) {
-        NSArray *indexArray;
-        NSString *trackName;
-        if ([mediaPlayer numberOfAudioTracks] > 2 && section == 0) {
-            indexArray = mediaPlayer.audioTrackIndexes;
-
-            if ([indexArray indexOfObject:[NSNumber numberWithInt:mediaPlayer.currentAudioTrackIndex]] == row)
-                cellShowsCurrentTrack = YES;
-
-            NSArray *audioTrackNames = mediaPlayer.audioTrackNames;
-            if (row < audioTrackNames.count) {
-                trackName = audioTrackNames[row];
-            }
-        } else {
-            indexArray = mediaPlayer.videoSubTitlesIndexes;
-
-            if ([indexArray indexOfObject:[NSNumber numberWithInt:mediaPlayer.currentVideoSubTitleIndex]] == row)
-                cellShowsCurrentTrack = YES;
-
-            NSArray *videoSubtitlesNames = mediaPlayer.videoSubTitlesNames;
-            if (row < videoSubtitlesNames.count) {
-                trackName = mediaPlayer.videoSubTitlesNames[row];
-            }
-        }
-
-        if (trackName != nil) {
-            if ([trackName isEqualToString:@"Disable"])
-                cell.textLabel.text = NSLocalizedString(@"DISABLE_LABEL", nil);
-            else
-                cell.textLabel.text = trackName;
-        }
-    } else {
-        if ([mediaPlayer numberOfTitles] > 1 && section == 0) {
-            NSArray *titleDescriptions = mediaPlayer.titleDescriptions;
-            if (row < titleDescriptions.count) {
-                NSDictionary *description = titleDescriptions[row];
-                cell.textLabel.text = [NSString stringWithFormat:@"%@ (%@)", description[VLCTitleDescriptionName], [[VLCTime timeWithNumber:description[VLCTitleDescriptionDuration]] stringValue]];
-            }
-
-            if (row == mediaPlayer.currentTitleIndex)
-                cellShowsCurrentTrack = YES;
-        } else {
-            NSArray *chapterDescriptions = [mediaPlayer chapterDescriptionsOfTitle:mediaPlayer.currentTitleIndex];
-            if (row < chapterDescriptions.count) {
-                NSDictionary *description = chapterDescriptions[row];
-                cell.textLabel.text = [NSString stringWithFormat:@"%@ (%@)", description[VLCChapterDescriptionName], [[VLCTime timeWithNumber:description[VLCChapterDescriptionDuration]] stringValue]];
-            }
-
-            if (row == mediaPlayer.currentChapterIndex)
-                cellShowsCurrentTrack = YES;
-        }
-    }
-    [cell setShowsCurrentTrack:cellShowsCurrentTrack];
-
-    return cell;
-}
-
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-{
-    VLCMediaPlayer *mediaPlayer = _vpc.mediaPlayer;
-
-    if (_switchingTracksNotChapters == YES) {
-        NSInteger audioTrackCount = mediaPlayer.audioTrackIndexes.count;
-
-        if (audioTrackCount > 2 && section == 0)
-            return audioTrackCount;
-
-        return mediaPlayer.videoSubTitlesIndexes.count;
-    } else {
-        if ([mediaPlayer numberOfTitles] > 1 && section == 0)
-            return [mediaPlayer numberOfTitles];
-        else
-            return [mediaPlayer numberOfChaptersForTitle:mediaPlayer.currentTitleIndex];
-    }
-}
-
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    [tableView deselectRowAtIndexPath:indexPath animated:NO];
-    NSInteger index = indexPath.row;
-    VLCMediaPlayer *mediaPlayer = _vpc.mediaPlayer;
-
-    if (_switchingTracksNotChapters == YES) {
-        NSArray *indexArray;
-        if (mediaPlayer.audioTrackIndexes.count > 2 && indexPath.section == 0) {
-            indexArray = mediaPlayer.audioTrackIndexes;
-            if (index <= indexArray.count)
-                mediaPlayer.currentAudioTrackIndex = [indexArray[index] intValue];
-
-        } else {
-            indexArray = mediaPlayer.videoSubTitlesIndexes;
-            if (index <= indexArray.count)
-                mediaPlayer.currentVideoSubTitleIndex = [indexArray[index] intValue];
-        }
-    } else {
-        if ([mediaPlayer numberOfTitles] > 1 && indexPath.section == 0)
-            mediaPlayer.currentTitleIndex = (int)index;
-        else
-            mediaPlayer.currentChapterIndex = (int)index;
-    }
-
-    CGFloat alpha = 0.0f;
-    _trackSelectorContainer.alpha = 1.0f;
-
-    void (^animationBlock)() = ^() {
-        _trackSelectorContainer.alpha = alpha;
-    };
-
-    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
-        for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers)
-            [recognizer setEnabled:YES];
-        _trackSelectorContainer.hidden = YES;
-    };
-
-    NSTimeInterval animationDuration = .3;
-    [UIView animateWithDuration:animationDuration animations:animationBlock completion:completionBlock];
-}
-
 #pragma mark - multi-touch gestures
 
 - (void)tapRecognized

+ 10 - 0
VLC.xcodeproj/project.pbxproj

@@ -53,6 +53,9 @@
 		41F5C07D1F42E567005EB9CB /* VLCMediaDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F5C07A1F42E567005EB9CB /* VLCMediaDataSource.m */; };
 		41F5C07E1F42E572005EB9CB /* VLCLibrarySearchDisplayDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F5C0771F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.m */; };
 		41F5C07F1F42E573005EB9CB /* VLCLibrarySearchDisplayDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F5C0771F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.m */; };
+		41F9BC7C1F4F20E400268461 /* VLCTrackSelectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */; };
+		41FF73C11F50526400B6CF0B /* VLCTrackSelectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */; };
+		41FF73C21F50526400B6CF0B /* VLCTrackSelectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */; };
 		6A804FA9706D38FB40A4136A /* libPods-VLC-watchOS-Extension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F82CE64560C0AD3059DAAFC /* libPods-VLC-watchOS-Extension.a */; };
 		6B4E33D11BF2A39400A35255 /* playerControl.css in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E33CF1BF2A39400A35255 /* playerControl.css */; };
 		6B4E33D21BF2A39400A35255 /* playerControl.js in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E33D01BF2A39400A35255 /* playerControl.js */; };
@@ -1168,6 +1171,8 @@
 		41F5C0771F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = VLCLibrarySearchDisplayDataSource.m; path = Sources/VLCLibrarySearchDisplayDataSource.m; sourceTree = SOURCE_ROOT; };
 		41F5C0791F42E567005EB9CB /* VLCMediaDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCMediaDataSource.h; sourceTree = SOURCE_ROOT; };
 		41F5C07A1F42E567005EB9CB /* VLCMediaDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCMediaDataSource.m; sourceTree = SOURCE_ROOT; };
+		41F9BC7A1F4F20E400268461 /* VLCTrackSelectorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCTrackSelectorView.h; sourceTree = SOURCE_ROOT; };
+		41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCTrackSelectorView.m; sourceTree = SOURCE_ROOT; };
 		4EB2A836EBC6DE6E89855975 /* Pods-VLC-watchOS-Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-watchOS-Extension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-watchOS-Extension/Pods-VLC-watchOS-Extension.debug.xcconfig"; sourceTree = "<group>"; };
 		5B343E4F4D971F5A169EB864 /* 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>"; };
 		633AEC92459BCABEC8671A34 /* Pods-VLC-tvOS-Debug.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-tvOS-Debug.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-tvOS-Debug/Pods-VLC-tvOS-Debug.debug.xcconfig"; sourceTree = "<group>"; };
@@ -2299,6 +2304,8 @@
 				7D1276611AADA0E600F0260C /* VLCMultiSelectionMenuView.m */,
 				DDAD5C2C1BB9A1E6006AFD3B /* VLCMovieViewControlPanelView.h */,
 				DDAD5C2D1BB9A1E6006AFD3B /* VLCMovieViewControlPanelView.m */,
+				41F9BC7A1F4F20E400268461 /* VLCTrackSelectorView.h */,
+				41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */,
 			);
 			name = Playback;
 			sourceTree = "<group>";
@@ -4558,6 +4565,7 @@
 				7D787F731D40FDE70003CFA1 /* VLCOpenNetworkStreamViewController.m in Sources */,
 				7D787F741D40FDE70003CFA1 /* VLCVolumeView.m in Sources */,
 				7D787F751D40FDE70003CFA1 /* VLCTrackSelectorHeaderView.m in Sources */,
+				41FF73C21F50526400B6CF0B /* VLCTrackSelectorView.m in Sources */,
 				7DE7D2CD1D42900200B3AD27 /* VLCNetworkLoginDataSource.m in Sources */,
 				7D787F761D40FDE70003CFA1 /* VLCFolderCollectionViewFlowLayout.m in Sources */,
 				7D787F771D40FDE70003CFA1 /* VLCLocalNetworkServiceBrowserBonjour.m in Sources */,
@@ -4641,6 +4649,7 @@
 				DD3EFF4D1BDEBCE500B68579 /* VLCNetworkServerBrowserPlex.m in Sources */,
 				DDF908E41CFCD97400108B70 /* VLCNetworkLoginDataSourceProtocol.m in Sources */,
 				7D378492183A98BF009EE944 /* VLCExternalDisplayController.m in Sources */,
+				41F9BC7C1F4F20E400268461 /* VLCTrackSelectorView.m in Sources */,
 				7D378499183A98D1009EE944 /* VLCPlaylistCollectionViewCell.m in Sources */,
 				DD8F84311B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m in Sources */,
 				DD3EFF551BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserDSM.m in Sources */,
@@ -4770,6 +4779,7 @@
 				7DC54FD41C046615007B4E42 /* VLCNetworkServerBrowserPlex.m in Sources */,
 				7DC54FD51C046615007B4E42 /* VLCExternalDisplayController.m in Sources */,
 				7DC54FD61C046615007B4E42 /* VLCPlaylistCollectionViewCell.m in Sources */,
+				41FF73C11F50526400B6CF0B /* VLCTrackSelectorView.m in Sources */,
 				41F5C07E1F42E572005EB9CB /* VLCLibrarySearchDisplayDataSource.m in Sources */,
 				7DC54FD71C046615007B4E42 /* VLCPlaybackController+MediaLibrary.m in Sources */,
 				7DC54FD81C046615007B4E42 /* VLCLocalNetworkServiceBrowserDSM.m in Sources */,

+ 21 - 0
VLCTrackSelectorView.h

@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * VLCTrackSelectorView.h
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2017 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Carola Nitz <caro # videolan.org>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCFrostedGlasView.h"
+
+@interface VLCTrackSelectorView : VLCFrostedGlasView
+
+@property (nonatomic, assign) BOOL switchingTracksNotChapters;
+@property(nonatomic, copy) void (^completionHandler)(BOOL finished);
+
+- (void)updateView;
+@end

+ 266 - 0
VLCTrackSelectorView.m

@@ -0,0 +1,266 @@
+/*****************************************************************************
+ * VLCTrackSelectorView.m
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2017 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Carola Nitz <caro # videolan.org>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCTrackSelectorView.h"
+
+#import "VLCPlaybackController.h"
+#import "VLCTrackSelectorHeaderView.h"
+#import "VLCTrackSelectorTableViewCell.h"
+
+#import "UIDevice+VLC.h"
+
+#define TRACK_SELECTOR_TABLEVIEW_CELL @"track selector table view cell"
+#define TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER @"track selector table view section header"
+
+@interface VLCTrackSelectorView() <UITableViewDataSource, UITableViewDelegate>
+{
+    UITableView *_trackSelectorTableView;
+    NSLayoutConstraint *_heightConstraint;
+}
+@end
+
+@implementation VLCTrackSelectorView
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    if(self){
+        _trackSelectorTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        _trackSelectorTableView.delegate = self;
+        _trackSelectorTableView.dataSource = self;
+        _trackSelectorTableView.separatorColor = [UIColor clearColor];
+        _trackSelectorTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
+        _trackSelectorTableView.rowHeight = 44.;
+        _trackSelectorTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        _trackSelectorTableView.sectionHeaderHeight = 28.;
+        [_trackSelectorTableView registerClass:[VLCTrackSelectorTableViewCell class] forCellReuseIdentifier:TRACK_SELECTOR_TABLEVIEW_CELL];
+        [_trackSelectorTableView registerClass:[VLCTrackSelectorHeaderView class] forHeaderFooterViewReuseIdentifier:TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER];
+        _trackSelectorTableView.translatesAutoresizingMaskIntoConstraints = NO;
+        [self addSubview:_trackSelectorTableView];
+        [self setupConstraints];
+        [self configureForDeviceCategory];
+    }
+    return self;
+}
+
+- (void)configureForDeviceCategory {
+    if ([[UIDevice currentDevice] VLCSpeedCategory] >= 3) {
+        _trackSelectorTableView.opaque = NO;
+        _trackSelectorTableView.backgroundColor = [UIColor clearColor];
+    } else {
+        _trackSelectorTableView.backgroundColor = [UIColor blackColor];
+    }
+    _trackSelectorTableView.allowsMultipleSelection = YES;
+}
+- (void)layoutSubviews
+{
+    CGFloat height = _trackSelectorTableView.contentSize.height;
+    _heightConstraint.constant = height;
+    [super layoutSubviews];
+}
+
+- (void)setupConstraints
+{
+    _heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
+    _heightConstraint.priority = UILayoutPriorityDefaultHigh;
+    NSArray *constraints = @[
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorTableView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:0],
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorTableView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0],
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorTableView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0],
+                             [NSLayoutConstraint constraintWithItem:_trackSelectorTableView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0],
+                             _heightConstraint,
+                             ];
+    [NSLayoutConstraint activateConstraints:constraints];
+}
+#pragma mark - track selector table view
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+    NSInteger ret = 0;
+    VLCMediaPlayer *mediaPlayer = [VLCPlaybackController sharedInstance].mediaPlayer;
+
+    if (_switchingTracksNotChapters) {
+        if (mediaPlayer.audioTrackIndexes.count > 2)
+            ret++;
+
+        if (mediaPlayer.videoSubTitlesIndexes.count > 1)
+            ret++;
+    } else {
+        if ([mediaPlayer numberOfTitles] > 1)
+            ret++;
+
+        if ([mediaPlayer numberOfChaptersForTitle:mediaPlayer.currentTitleIndex] > 1)
+            ret++;
+    }
+
+    return ret;
+}
+
+- (void)updateView
+{
+    [_trackSelectorTableView reloadData];
+}
+
+- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
+{
+    UITableViewHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER];
+
+    if (!view) {
+        view = [[VLCTrackSelectorHeaderView alloc] initWithReuseIdentifier:TRACK_SELECTOR_TABLEVIEW_SECTIONHEADER];
+    }
+    return view;
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
+{
+    VLCMediaPlayer *mediaPlayer =  [VLCPlaybackController sharedInstance].mediaPlayer;
+
+    if (_switchingTracksNotChapters == YES) {
+        if (mediaPlayer.audioTrackIndexes.count > 2 && section == 0)
+            return NSLocalizedString(@"CHOOSE_AUDIO_TRACK", nil);
+
+        if (mediaPlayer.videoSubTitlesIndexes.count > 1)
+            return NSLocalizedString(@"CHOOSE_SUBTITLE_TRACK", nil);
+    } else {
+        if ([mediaPlayer numberOfTitles] > 1 && section == 0)
+            return NSLocalizedString(@"CHOOSE_TITLE", nil);
+
+        if ([mediaPlayer numberOfChaptersForTitle:mediaPlayer.currentTitleIndex] > 1)
+            return NSLocalizedString(@"CHOOSE_CHAPTER", nil);
+    }
+
+    return @"unknown track type";
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    VLCTrackSelectorTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TRACK_SELECTOR_TABLEVIEW_CELL];
+
+    if (!cell) {
+        cell = [[VLCTrackSelectorTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TRACK_SELECTOR_TABLEVIEW_CELL];
+    }
+    NSInteger row = indexPath.row;
+    NSInteger section = indexPath.section;
+    VLCMediaPlayer *mediaPlayer =  [VLCPlaybackController sharedInstance].mediaPlayer;
+    BOOL cellShowsCurrentTrack = NO;
+
+    if (_switchingTracksNotChapters) {
+        NSArray *indexArray;
+        NSString *trackName;
+        if ([mediaPlayer numberOfAudioTracks] > 2 && section == 0) {
+            indexArray = mediaPlayer.audioTrackIndexes;
+
+            if ([indexArray indexOfObject:[NSNumber numberWithInt:mediaPlayer.currentAudioTrackIndex]] == row)
+                cellShowsCurrentTrack = YES;
+
+            NSArray *audioTrackNames = mediaPlayer.audioTrackNames;
+            if (row < audioTrackNames.count) {
+                trackName = audioTrackNames[row];
+            }
+        } else {
+            indexArray = mediaPlayer.videoSubTitlesIndexes;
+
+            if ([indexArray indexOfObject:[NSNumber numberWithInt:mediaPlayer.currentVideoSubTitleIndex]] == row)
+                cellShowsCurrentTrack = YES;
+
+            NSArray *videoSubtitlesNames = mediaPlayer.videoSubTitlesNames;
+            if (row < videoSubtitlesNames.count) {
+                trackName = mediaPlayer.videoSubTitlesNames[row];
+            }
+        }
+
+        if (trackName != nil) {
+            if ([trackName isEqualToString:@"Disable"]) {
+                cell.textLabel.text = NSLocalizedString(@"DISABLE_LABEL", nil);
+            } else {
+                cell.textLabel.text = trackName;
+            }
+        }
+    } else {
+        if ([mediaPlayer numberOfTitles] > 1 && section == 0) {
+            NSArray *titleDescriptions = mediaPlayer.titleDescriptions;
+            if (row < titleDescriptions.count) {
+                NSDictionary *description = titleDescriptions[row];
+                cell.textLabel.text = [NSString stringWithFormat:@"%@ (%@)", description[VLCTitleDescriptionName], [[VLCTime timeWithNumber:description[VLCTitleDescriptionDuration]] stringValue]];
+            }
+
+            if (row == mediaPlayer.currentTitleIndex)
+                cellShowsCurrentTrack = YES;
+        } else {
+            NSArray *chapterDescriptions = [mediaPlayer chapterDescriptionsOfTitle:mediaPlayer.currentTitleIndex];
+            if (row < chapterDescriptions.count) {
+                NSDictionary *description = chapterDescriptions[row];
+                cell.textLabel.text = [NSString stringWithFormat:@"%@ (%@)", description[VLCChapterDescriptionName], [[VLCTime timeWithNumber:description[VLCChapterDescriptionDuration]] stringValue]];
+            }
+
+            if (row == mediaPlayer.currentChapterIndex)
+                cellShowsCurrentTrack = YES;
+        }
+    }
+    [cell setShowsCurrentTrack:cellShowsCurrentTrack];
+
+    return cell;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    VLCMediaPlayer *mediaPlayer =  [VLCPlaybackController sharedInstance].mediaPlayer;
+
+    if (_switchingTracksNotChapters == YES) {
+        NSInteger audioTrackCount = mediaPlayer.audioTrackIndexes.count;
+
+        if (audioTrackCount > 2 && section == 0)
+            return audioTrackCount;
+
+        return mediaPlayer.videoSubTitlesIndexes.count;
+    } else {
+        if ([mediaPlayer numberOfTitles] > 1 && section == 0)
+            return [mediaPlayer numberOfTitles];
+        else
+            return [mediaPlayer numberOfChaptersForTitle:mediaPlayer.currentTitleIndex];
+    }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    [tableView deselectRowAtIndexPath:indexPath animated:NO];
+    NSInteger index = indexPath.row;
+    VLCMediaPlayer *mediaPlayer =  [VLCPlaybackController sharedInstance].mediaPlayer;
+
+    if (_switchingTracksNotChapters) {
+        NSArray *indexArray;
+        if (mediaPlayer.audioTrackIndexes.count > 2 && indexPath.section == 0) {
+            indexArray = mediaPlayer.audioTrackIndexes;
+            if (index <= indexArray.count)
+                mediaPlayer.currentAudioTrackIndex = [indexArray[index] intValue];
+
+        } else {
+            indexArray = mediaPlayer.videoSubTitlesIndexes;
+            if (index <= indexArray.count)
+                mediaPlayer.currentVideoSubTitleIndex = [indexArray[index] intValue];
+        }
+    } else {
+        if ([mediaPlayer numberOfTitles] > 1 && indexPath.section == 0)
+            mediaPlayer.currentTitleIndex = (int)index;
+        else
+            mediaPlayer.currentChapterIndex = (int)index;
+    }
+
+    self.alpha = 1.0f;
+    void (^animationBlock)() = ^() {
+        self.alpha =  0.0f;;
+    };
+
+    NSTimeInterval animationDuration = .3;
+    [UIView animateWithDuration:animationDuration animations:animationBlock completion:_completionHandler];
+}
+@end