Przeglądaj źródła

implement track selection for audio and subtitle tracks

Tobias Conradi 9 lat temu
rodzic
commit
10c6ad2cf5

+ 3 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTVViewController.m

@@ -13,6 +13,8 @@
 #import "VLCPlaybackInfoRateTVViewController.h"
 #import "VLCPlaybackInfoMediaInfoTVViewController.h"
 #import "VLCPlaybackInfoTVAnimators.h"
+#import "VLCPlaybackInfoTracksTVViewController.h"
+
 
 // just for appearance reasons
 @interface VLCPlaybackInfoTVTabBarController : UITabBarController
@@ -27,6 +29,7 @@
     return @[
              [[VLCPlaybackInfoRateTVViewController alloc] initWithNibName:nil bundle:nil],
              [[VLCPlaybackInfoMediaInfoTVViewController alloc] initWithNibName:nil bundle:nil],
+             [[VLCPlaybackInfoTracksTVViewController alloc] initWithNibName:nil bundle:nil],
              ];
 }
 

+ 20 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTrackTVCell.h

@@ -0,0 +1,20 @@
+/*****************************************************************************
+ * 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 <UIKit/UIKit.h>
+
+@interface VLCPlaybackInfoTrackTVCell : UICollectionViewCell
+@property (nonatomic) IBOutlet UILabel *selectionMarkerView;
+@property (nonatomic) IBOutlet UILabel *titleLabel;
+@property (nonatomic) BOOL selectionMarkerVisible;
+
++(NSString *)identifier;
+@end

+ 54 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTrackTVCell.m

@@ -0,0 +1,54 @@
+/*****************************************************************************
+ * 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 "VLCPlaybackInfoTrackTVCell.h"
+
+@implementation VLCPlaybackInfoTrackTVCell
+
++ (NSString *)identifier
+{
+    return @"VLCPlaybackInfoTrackTVCell";
+}
+
+- (void)awakeFromNib
+{
+    [super awakeFromNib];
+    [self prepareForReuse];
+}
+
+- (BOOL)selectionMarkerVisible
+{
+    return !self.selectionMarkerView.hidden;
+}
+
+- (void)setSelectionMarkerVisible:(BOOL)selectionMarkerVisible
+{
+    self.selectionMarkerView.hidden = !selectionMarkerVisible;
+}
+
+- (void)prepareForReuse
+{
+    [super prepareForReuse];
+    self.selectionMarkerVisible = NO;
+    self.titleLabel.text = nil;
+    self.selectionMarkerView.textColor = [UIColor darkGrayColor];
+    self.titleLabel.textColor = [UIColor darkGrayColor];
+}
+
+- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
+{
+    [super didUpdateFocusInContext:context withAnimationCoordinator:coordinator];
+    [coordinator addCoordinatedAnimations:^{
+        self.titleLabel.textColor = self.focused ? [UIColor whiteColor] : [UIColor darkGrayColor];
+    } completion:nil];
+}
+
+@end

+ 52 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTrackTVCell.xib

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder.AppleTV.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="VLCPlaybackInfoTrackTVCell" id="m1I-s4-RPj" customClass="VLCPlaybackInfoTrackTVCell">
+            <rect key="frame" x="0.0" y="0.0" width="460" height="56"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="460" height="56"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iNn-kk-JAL">
+                        <rect key="frame" x="48" y="0.0" width="412" height="56"/>
+                        <animations/>
+                        <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
+                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="500" text="✔︎" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YMP-ov-ixd">
+                        <rect key="frame" x="8" y="0.0" width="32" height="56"/>
+                        <animations/>
+                        <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
+                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                </subviews>
+                <animations/>
+                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+            </view>
+            <animations/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="YMP-ov-ixd" secondAttribute="bottom" id="EMu-OI-4qI"/>
+                <constraint firstItem="iNn-kk-JAL" firstAttribute="top" secondItem="m1I-s4-RPj" secondAttribute="top" id="EUZ-5I-erE"/>
+                <constraint firstItem="YMP-ov-ixd" firstAttribute="leading" secondItem="m1I-s4-RPj" secondAttribute="leading" constant="8" id="HDQ-rO-QHf"/>
+                <constraint firstAttribute="bottom" secondItem="iNn-kk-JAL" secondAttribute="bottom" id="Jfi-tb-NfI"/>
+                <constraint firstAttribute="trailing" secondItem="iNn-kk-JAL" secondAttribute="trailing" id="OTh-f4-bTz"/>
+                <constraint firstItem="iNn-kk-JAL" firstAttribute="leading" secondItem="YMP-ov-ixd" secondAttribute="trailing" constant="8" id="QUe-TA-BP4"/>
+                <constraint firstItem="YMP-ov-ixd" firstAttribute="top" secondItem="m1I-s4-RPj" secondAttribute="top" id="g0N-SR-4dY"/>
+            </constraints>
+            <size key="customSize" width="460" height="56"/>
+            <connections>
+                <outlet property="selectionMarkerView" destination="YMP-ov-ixd" id="Nq5-Gk-JHF"/>
+                <outlet property="titleLabel" destination="iNn-kk-JAL" id="l3s-MH-GSe"/>
+            </connections>
+            <point key="canvasLocation" x="649" y="-82"/>
+        </collectionViewCell>
+    </objects>
+</document>

+ 20 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTrackTVTitleView.h

@@ -0,0 +1,20 @@
+/*****************************************************************************
+ * 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 <UIKit/UIKit.h>
+
+@interface VLCPlaybackInfoTrackTVTitleView : UICollectionReusableView
+@property (nonatomic) UILabel *titleLabel;
+
++ (void)registerInCollectionView:(UICollectionView *)collectionView;
++ (NSString *)identifier;
+
+@end

+ 41 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTrackTVTitleView.m

@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * 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 "VLCPlaybackInfoTrackTVTitleView.h"
+
+@implementation VLCPlaybackInfoTrackTVTitleView
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    if (self) {
+        UILabel *label = [[UILabel alloc] initWithFrame:frame];
+        label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
+        label.textColor = [UIColor darkGrayColor];
+        label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+        [self addSubview:label];
+        _titleLabel = label;
+    }
+    return self;
+}
+
++ (void)registerInCollectionView:(UICollectionView *)collectionView
+{
+    [collectionView registerClass:self forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[self identifier]];
+}
+
++ (NSString *)identifier
+{
+    return @"VLCPlaybackInfoTrackTVTitleView";
+}
+
+
+@end

+ 17 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTracksTVViewController.h

@@ -0,0 +1,17 @@
+/*****************************************************************************
+ * 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 "VLCPlaybackInfoPanelTVViewController.h"
+
+@interface VLCPlaybackInfoTracksTVViewController : VLCPlaybackInfoPanelTVViewController
+@property (nonatomic, strong) IBOutlet UICollectionView *audioTrackCollectionView;
+@property (nonatomic, strong) IBOutlet UICollectionView *subtitleTrackCollectionView;
+@end

+ 150 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTracksTVViewController.m

@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * 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 "VLCPlaybackInfoTracksTVViewController.h"
+#import "VLCPlaybackInfoTrackTVCell.h"
+#import "VLCPlaybackInfoTrackTVTitleView.h"
+
+
+@interface VLCPlaybackInfoTracksDataSource : NSObject
+@property (nonatomic, readonly) VLCMediaPlayer *mediaPlayer;
+@property (nonatomic) NSString *title;
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
+@end
+
+@interface VLCPlaybackInfoTracksDataSourceAudio : VLCPlaybackInfoTracksDataSource <UICollectionViewDataSource, UICollectionViewDelegate>
+@end
+@interface VLCPlaybackInfoTracksDataSourceSubtitle : VLCPlaybackInfoTracksDataSource <UICollectionViewDataSource, UICollectionViewDelegate>
+@end
+
+
+@interface VLCPlaybackInfoTracksTVViewController ()
+@property (nonatomic) IBOutlet VLCPlaybackInfoTracksDataSourceAudio *audioDataSource;
+@property (nonatomic) IBOutlet VLCPlaybackInfoTracksDataSourceSubtitle *subtitleDataSource;
+@end
+
+
+@implementation VLCPlaybackInfoTracksTVViewController
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        self.title = NSLocalizedString(@"TRACK_SELECTION", nil);
+    }
+    return self;
+}
+
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    UINib *nib = [UINib nibWithNibName:@"VLCPlaybackInfoTrackTVCell" bundle:nil];
+    NSString *identifier = [VLCPlaybackInfoTrackTVCell identifier];
+    [self.audioTrackCollectionView registerNib:nib forCellWithReuseIdentifier:identifier];
+    [self.subtitleTrackCollectionView registerNib:nib forCellWithReuseIdentifier:identifier];
+    [VLCPlaybackInfoTrackTVTitleView registerInCollectionView:self.audioTrackCollectionView];
+    [VLCPlaybackInfoTrackTVTitleView registerInCollectionView:self.subtitleTrackCollectionView];
+
+    self.audioDataSource.title = NSLocalizedString(@"AUDIO", nil);
+    self.subtitleDataSource.title = NSLocalizedString(@"SUBTITLES", nil);
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaPlayerChanged) name:VLCPlaybackControllerPlaybackMetadataDidChange object:nil];
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    [super viewWillAppear:animated];
+    [self mediaPlayerChanged];
+}
+
+- (CGSize)preferredContentSize
+{
+    CGFloat prefferedHeight = MAX(self.audioTrackCollectionView.contentSize.height, self.subtitleTrackCollectionView.contentSize.height);
+    return CGSizeMake(CGRectGetWidth(self.view.bounds), prefferedHeight);
+}
+
+- (void)mediaPlayerChanged
+{
+    [self.audioTrackCollectionView reloadData];
+    [self.subtitleTrackCollectionView reloadData];
+}
+
+@end
+
+@implementation VLCPlaybackInfoTracksDataSource
+- (VLCMediaPlayer *)mediaPlayer
+{
+    return [VLCPlaybackController sharedInstance].mediaPlayer;
+}
+
+- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
+{
+    VLCPlaybackInfoTrackTVTitleView *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[VLCPlaybackInfoTrackTVTitleView identifier] forIndexPath:indexPath];
+
+    BOOL showTitle = [collectionView numberOfItemsInSection:indexPath.section] != 0;
+    header.titleLabel.text = showTitle ? self.title : nil;
+    return header;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    return [collectionView dequeueReusableCellWithReuseIdentifier:[VLCPlaybackInfoTrackTVCell identifier] forIndexPath:indexPath];
+}
+@end
+
+@implementation VLCPlaybackInfoTracksDataSourceAudio
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
+{
+    return self.mediaPlayer.numberOfAudioTracks;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    VLCPlaybackInfoTrackTVCell *trackCell = (VLCPlaybackInfoTrackTVCell*)cell;
+    BOOL isSelected = [self.mediaPlayer.audioTrackIndexes[indexPath.row] intValue] == self.mediaPlayer.currentAudioTrackIndex;
+    trackCell.selectionMarkerVisible = isSelected;
+    trackCell.titleLabel.text = self.mediaPlayer.audioTrackNames[indexPath.row];
+}
+
+-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    self.mediaPlayer.currentAudioTrackIndex = [self.mediaPlayer.audioTrackIndexes[indexPath.row] intValue];
+    [collectionView reloadData];
+}
+
+@end
+
+@implementation VLCPlaybackInfoTracksDataSourceSubtitle
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
+{
+    return self.mediaPlayer.numberOfSubtitlesTracks;
+}
+- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    VLCPlaybackInfoTrackTVCell *trackCell = (VLCPlaybackInfoTrackTVCell*)cell;
+    BOOL isSelected = [self.mediaPlayer.videoSubTitlesIndexes[indexPath.row] intValue] == self.mediaPlayer.currentVideoSubTitleIndex;
+    trackCell.selectionMarkerVisible = isSelected;
+    trackCell.titleLabel.text = self.mediaPlayer.videoSubTitlesNames[indexPath.row];
+}
+
+-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    self.mediaPlayer.currentVideoSubTitleIndex = [self.mediaPlayer.videoSubTitlesIndexes[indexPath.row] intValue];
+    [collectionView reloadData];
+}
+
+@end

+ 67 - 0
Apple-TV/Playback/Playback Info/VLCPlaybackInfoTracksTVViewController.xib

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder.AppleTV.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCPlaybackInfoTracksTVViewController">
+            <connections>
+                <outlet property="audioDataSource" destination="odX-Um-Jiy" id="FHQ-ad-anU"/>
+                <outlet property="audioTrackCollectionView" destination="rYJ-pW-rFQ" id="GXj-Ds-Ggf"/>
+                <outlet property="subtitleDataSource" destination="Z5d-WW-D76" id="AaD-El-QGo"/>
+                <outlet property="subtitleTrackCollectionView" destination="YZb-MS-8i8" id="a2J-7X-pa8"/>
+                <outlet property="view" destination="iN0-l3-epB" id="Rsf-oc-98a"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB">
+            <rect key="frame" x="0.0" y="0.0" width="1920" height="500"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="YZb-MS-8i8">
+                    <rect key="frame" x="1060" y="0.0" width="660" height="500"/>
+                    <animations/>
+                    <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="2bC-W2-ECp" customClass="VLCFullWidthCollectionViewFlowLayout">
+                        <size key="itemSize" width="660" height="50"/>
+                        <size key="headerReferenceSize" width="660" height="50"/>
+                        <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                        <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                    </collectionViewFlowLayout>
+                    <connections>
+                        <outlet property="dataSource" destination="Z5d-WW-D76" id="CEX-jp-S6S"/>
+                        <outlet property="delegate" destination="Z5d-WW-D76" id="t1D-sI-B0C"/>
+                    </connections>
+                </collectionView>
+                <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="rYJ-pW-rFQ">
+                    <rect key="frame" x="200" y="0.0" width="660" height="500"/>
+                    <animations/>
+                    <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="ceq-Lt-V8g" customClass="VLCFullWidthCollectionViewFlowLayout">
+                        <size key="itemSize" width="660" height="50"/>
+                        <size key="headerReferenceSize" width="660" height="50"/>
+                        <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                        <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                    </collectionViewFlowLayout>
+                    <connections>
+                        <outlet property="dataSource" destination="odX-Um-Jiy" id="0oK-qY-Aiz"/>
+                        <outlet property="delegate" destination="odX-Um-Jiy" id="hDT-5c-OYk"/>
+                    </connections>
+                </collectionView>
+            </subviews>
+            <animations/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="rYJ-pW-rFQ" secondAttribute="bottom" priority="500" id="5QS-de-XaJ"/>
+                <constraint firstItem="rYJ-pW-rFQ" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Grw-co-Uag"/>
+                <constraint firstItem="rYJ-pW-rFQ" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="200" id="HMO-0c-28f"/>
+                <constraint firstItem="YZb-MS-8i8" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="lJk-bE-qdA"/>
+                <constraint firstItem="YZb-MS-8i8" firstAttribute="width" secondItem="rYJ-pW-rFQ" secondAttribute="width" id="mvl-Qm-zsX"/>
+                <constraint firstAttribute="bottom" secondItem="YZb-MS-8i8" secondAttribute="bottom" priority="500" id="twj-q2-HtE"/>
+                <constraint firstAttribute="trailing" secondItem="YZb-MS-8i8" secondAttribute="trailing" constant="200" id="xiO-53-o5T"/>
+                <constraint firstItem="YZb-MS-8i8" firstAttribute="leading" secondItem="rYJ-pW-rFQ" secondAttribute="trailing" constant="200" id="xqK-zW-jRW"/>
+            </constraints>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="384" y="420"/>
+        </view>
+        <customObject id="odX-Um-Jiy" customClass="VLCPlaybackInfoTracksDataSourceAudio"/>
+        <customObject id="Z5d-WW-D76" customClass="VLCPlaybackInfoTracksDataSourceSubtitle"/>
+    </objects>
+</document>

+ 15 - 0
SharedSources/UI Elements/VLCFullWidthCollectionViewFlowLayout.h

@@ -0,0 +1,15 @@
+/*****************************************************************************
+ * 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 <UIKit/UIKit.h>
+
+@interface VLCFullWidthCollectionViewFlowLayout : UICollectionViewFlowLayout
+@end

+ 27 - 0
SharedSources/UI Elements/VLCFullWidthCollectionViewFlowLayout.m

@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * 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 "VLCFullWidthCollectionViewFlowLayout.h"
+
+@implementation VLCFullWidthCollectionViewFlowLayout
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
+{
+    return YES;
+}
+- (void)prepareLayout
+{
+    CGSize itemSize = self.itemSize;
+    itemSize.width = CGRectGetWidth(self.collectionView.bounds)-self.sectionInset.left-self.sectionInset.right;
+    self.itemSize = itemSize;
+    [super prepareLayout];
+}
+
+@end

+ 32 - 0
VLC for iOS.xcodeproj/project.pbxproj

@@ -246,6 +246,7 @@
 		D9C52A9E9D4D5AFA7EF1B45A /* libPods-vlc-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAF8927B0BE9C328466C0EA7 /* libPods-vlc-ios.a */; };
 		DD13A37B1BEE2FAA00A35554 /* VLCMaskView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD13A37A1BEE2FAA00A35554 /* VLCMaskView.m */; };
 		DD1A45FD1B676BAC00086F57 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDE1BCE41B676B8800A4B9CE /* Localizable.strings */; };
+		DD1B31F41BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1B31F21BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.m */; };
 		DD1CB0321BB9E005006EDDE6 /* VLCMovieViewControlPanelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAD5C2D1BB9A1E6006AFD3B /* VLCMovieViewControlPanelViewController.m */; };
 		DD1CB05A1BBAC549006EDDE6 /* VLCVolumeView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1CB0591BBAC549006EDDE6 /* VLCVolumeView.m */; };
 		DD2789DD1B67A5C400CED769 /* VLCThumbnailsCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D37849D183A98DD009EE944 /* VLCThumbnailsCache.m */; };
@@ -319,6 +320,11 @@
 		DD3EFF5B1BDEBCE500B68579 /* VLCNetworkServerBrowserUPnP.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EFF271BDEBCE500B68579 /* VLCNetworkServerBrowserUPnP.m */; };
 		DD3EFF5D1BDEBCE500B68579 /* VLCLocalServerDiscoveryController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EFF2B1BDEBCE500B68579 /* VLCLocalServerDiscoveryController.m */; };
 		DD3EFF5E1BDEBCE500B68579 /* VLCLocalServerDiscoveryController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3EFF2B1BDEBCE500B68579 /* VLCLocalServerDiscoveryController.m */; };
+		DD4089E91BF63AD00022745E /* VLCPlaybackInfoTracksTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD4089E81BF63AD00022745E /* VLCPlaybackInfoTracksTVViewController.xib */; };
+		DD4089EF1BF646540022745E /* VLCPlaybackInfoTrackTVCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD4089EE1BF646540022745E /* VLCPlaybackInfoTrackTVCell.xib */; };
+		DD4089F21BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4089F11BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.m */; };
+		DD4089F51BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4089F41BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.m */; };
+		DD4089FA1BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4089F91BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.m */; };
 		DD490B171BE6BA580010F335 /* VLCIRTVTapGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = DD490B161BE6BA580010F335 /* VLCIRTVTapGestureRecognizer.m */; };
 		DD490B1F1BE95B5C0010F335 /* VLCSiriRemoteGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = DD490B1E1BE95B5C0010F335 /* VLCSiriRemoteGestureRecognizer.m */; };
 		DD510B701B14E564003BA71C /* VLCPlayerDisplayController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD510B6F1B14E564003BA71C /* VLCPlayerDisplayController.m */; };
@@ -866,6 +872,8 @@
 		DD13A3791BEE2FAA00A35554 /* VLCMaskView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMaskView.h; path = "UI Elements/VLCMaskView.h"; sourceTree = "<group>"; };
 		DD13A37A1BEE2FAA00A35554 /* VLCMaskView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMaskView.m; path = "UI Elements/VLCMaskView.m"; sourceTree = "<group>"; };
 		DD1A45FC1B676BAC00086F57 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
+		DD1B31F11BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackInfoTracksTVViewController.h; sourceTree = "<group>"; };
+		DD1B31F21BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackInfoTracksTVViewController.m; sourceTree = "<group>"; };
 		DD1CB0581BBAC549006EDDE6 /* VLCVolumeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCVolumeView.h; path = Sources/VLCVolumeView.h; sourceTree = SOURCE_ROOT; };
 		DD1CB0591BBAC549006EDDE6 /* VLCVolumeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCVolumeView.m; path = Sources/VLCVolumeView.m; sourceTree = SOURCE_ROOT; };
 		DD2789E01B67A7BE00CED769 /* VLCWatchCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCWatchCommunication.h; path = Sources/VLCWatchCommunication.h; sourceTree = SOURCE_ROOT; };
@@ -962,6 +970,14 @@
 		DD3EFF2A1BDEBCE500B68579 /* VLCLocalServerDiscoveryController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCLocalServerDiscoveryController.h; sourceTree = "<group>"; };
 		DD3EFF2B1BDEBCE500B68579 /* VLCLocalServerDiscoveryController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCLocalServerDiscoveryController.m; sourceTree = "<group>"; };
 		DD3EFF2C1BDEBCE500B68579 /* VLCNetworkServerBrowser-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "VLCNetworkServerBrowser-Protocol.h"; sourceTree = "<group>"; };
+		DD4089E81BF63AD00022745E /* VLCPlaybackInfoTracksTVViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCPlaybackInfoTracksTVViewController.xib; path = "Playback/Playback Info/VLCPlaybackInfoTracksTVViewController.xib"; sourceTree = "<group>"; };
+		DD4089EE1BF646540022745E /* VLCPlaybackInfoTrackTVCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCPlaybackInfoTrackTVCell.xib; path = "Playback/Playback Info/VLCPlaybackInfoTrackTVCell.xib"; sourceTree = "<group>"; };
+		DD4089F01BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackInfoTrackTVCell.h; sourceTree = "<group>"; };
+		DD4089F11BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackInfoTrackTVCell.m; sourceTree = "<group>"; };
+		DD4089F31BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCFullWidthCollectionViewFlowLayout.h; path = "UI Elements/VLCFullWidthCollectionViewFlowLayout.h"; sourceTree = "<group>"; };
+		DD4089F41BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCFullWidthCollectionViewFlowLayout.m; path = "UI Elements/VLCFullWidthCollectionViewFlowLayout.m"; sourceTree = "<group>"; };
+		DD4089F81BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackInfoTrackTVTitleView.h; sourceTree = "<group>"; };
+		DD4089F91BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackInfoTrackTVTitleView.m; sourceTree = "<group>"; };
 		DD490B151BE6BA580010F335 /* VLCIRTVTapGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCIRTVTapGestureRecognizer.h; sourceTree = "<group>"; };
 		DD490B161BE6BA580010F335 /* VLCIRTVTapGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCIRTVTapGestureRecognizer.m; sourceTree = "<group>"; };
 		DD490B1D1BE95B5C0010F335 /* VLCSiriRemoteGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCSiriRemoteGestureRecognizer.h; sourceTree = "<group>"; };
@@ -1696,6 +1712,8 @@
 				7D7EF3D91BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.xib */,
 				DDEAECF51BDFEAFA00756C83 /* VLCLocalNetworkServerTVCell.xib */,
 				7D51B3AF1BF0EEF4005AF4D5 /* VLCPlaybackInfoMediaInfoTVViewController.xib */,
+				DD4089E81BF63AD00022745E /* VLCPlaybackInfoTracksTVViewController.xib */,
+				DD4089EE1BF646540022745E /* VLCPlaybackInfoTrackTVCell.xib */,
 			);
 			name = xibs;
 			sourceTree = "<group>";
@@ -1751,6 +1769,8 @@
 				DD3EAC031BE153B4003668DA /* VLCNetworkImageView.m */,
 				DD13A3791BEE2FAA00A35554 /* VLCMaskView.h */,
 				DD13A37A1BEE2FAA00A35554 /* VLCMaskView.m */,
+				DD4089F31BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.h */,
+				DD4089F41BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.m */,
 			);
 			name = "UI Elements";
 			sourceTree = "<group>";
@@ -2176,6 +2196,12 @@
 				DD8095E91BE4F04E0065D8E1 /* VLCPlaybackInfoRateTVViewController.m */,
 				7D51B3AD1BF0EEF4005AF4D5 /* VLCPlaybackInfoMediaInfoTVViewController.h */,
 				7D51B3AE1BF0EEF4005AF4D5 /* VLCPlaybackInfoMediaInfoTVViewController.m */,
+				DD1B31F11BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.h */,
+				DD1B31F21BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.m */,
+				DD4089F01BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.h */,
+				DD4089F11BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.m */,
+				DD4089F81BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.h */,
+				DD4089F91BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.m */,
 			);
 			path = "Playback Info";
 			sourceTree = "<group>";
@@ -2447,6 +2473,7 @@
 				DD8095E51BE3F4240065D8E1 /* VLCPlaybackInfoTVViewController.xib in Resources */,
 				7D405ED91BEA1F56006ED886 /* jquery.ui.widget.js in Resources */,
 				7D405ED71BEA1F56006ED886 /* jquery.fileupload.js in Resources */,
+				DD4089E91BF63AD00022745E /* VLCPlaybackInfoTracksTVViewController.xib in Resources */,
 				7DEC8BDF1BD67899006E1093 /* VLCFullscreenMovieTVViewController.xib in Resources */,
 				7DEDD38C1BE936130053802C /* About Contents.html in Resources */,
 				7DF383AE1BF206FB00D71A5C /* VLCRemoteBrowsingCollectionViewController.xib in Resources */,
@@ -2460,6 +2487,7 @@
 				7D405ED51BEA1F56006ED886 /* Raleway.woff in Resources */,
 				6B4E33D21BF2A39400A35255 /* playerControl.js in Resources */,
 				7D405ED81BEA1F56006ED886 /* jquery.iframe-transport.js in Resources */,
+				DD4089EF1BF646540022745E /* VLCPlaybackInfoTrackTVCell.xib in Resources */,
 				DD3EAC131BE26166003668DA /* VLCRemoteBrowsingTVCell.xib in Resources */,
 				7D3E528C1BD7B5E100309D15 /* VLCCloudServicesTVViewController.xib in Resources */,
 				7D405EDA1BEA1F56006ED886 /* style.css in Resources */,
@@ -2677,6 +2705,8 @@
 				7D13347F1BE132ED0012E919 /* VLCLocalNetworkServiceUPnP.m in Sources */,
 				DD3EFF4A1BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserPlex.m in Sources */,
 				DD3EABEF1BE14720003668DA /* VLCPlaybackControlsFocusView.m in Sources */,
+				DD1B31F41BF637D500A369B6 /* VLCPlaybackInfoTracksTVViewController.m in Sources */,
+				DD4089F51BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.m in Sources */,
 				DD3EFF3A1BDEBCE500B68579 /* VLCLocalNetworkServiceVLCMedia.m in Sources */,
 				7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */,
 				DD3EFF521BDEBCE500B68579 /* VLCPlexWebAPI.m in Sources */,
@@ -2716,6 +2746,7 @@
 				DD490B1F1BE95B5C0010F335 /* VLCSiriRemoteGestureRecognizer.m in Sources */,
 				DD3EFF3C1BDEBCE500B68579 /* VLCNetworkServerBrowserVLCMedia.m in Sources */,
 				7D1334801BE132F10012E919 /* VLCNetworkServerBrowserUPnP.m in Sources */,
+				DD4089FA1BF659030022745E /* VLCPlaybackInfoTrackTVTitleView.m in Sources */,
 				7DF383D01BF24BB100D71A5C /* VLCBoxCollectionViewController.m in Sources */,
 				DDEAECC71BDEC79D00756C83 /* VLCLocalNetworkServiceBrowserSAP.m in Sources */,
 				7D1329441BA1F10100BE647E /* AppleTVAppDelegate.m in Sources */,
@@ -2723,6 +2754,7 @@
 				7DC71D291BC83590001FACAA /* UIColor+Presets.m in Sources */,
 				DD8095DB1BE3C42F0065D8E1 /* VLCBufferingBar.m in Sources */,
 				7D4408591BDA8DCA0080FB42 /* VLCBoxController.m in Sources */,
+				DD4089F21BF6467E0022745E /* VLCPlaybackInfoTrackTVCell.m in Sources */,
 				DD3EAC0A1BE2192A003668DA /* VLCServerBrowsingController.m in Sources */,
 				DD3EFF341BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserMediaDiscoverer.m in Sources */,
 				DD3EFF421BDEBCE500B68579 /* VLCNetworkServerBrowserSharedLibrary.m in Sources */,