浏览代码

MediaDataSource: Added a Mediatype with Category and Subctegory to show the correct content on the subviews

Carola Nitz 7 年之前
父节点
当前提交
b0f70796f7

+ 10 - 4
SharedSources/MediaDataSource.swift

@@ -1,5 +1,5 @@
 /*****************************************************************************
- * MediaDataSource.swift
+ * MediaDataSourceAndDelegate.swift
  * VLC for iOS
  *****************************************************************************
  * Copyright (c) 2018 VideoLAN. All rights reserved.
@@ -10,11 +10,16 @@
  *
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
+extension Notification.Name {
+    static let VLCTracksDidChangeNotification = Notification.Name("kTracksDidChangeNotification")
+    static let VLCAllVideosDidChangeNotification = Notification.Name("kAllVideosDidChangeNotification")
+}
 
 public class MediaDataSourceAndDelegate: NSObject, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
 
     private let cellPadding: CGFloat = 5.0
     private var services: Services
+    private var mediaType: VLCMediaType
     public weak var delegate: UICollectionViewDelegate?
 
     @available(*, unavailable)
@@ -22,18 +27,19 @@ public class MediaDataSourceAndDelegate: NSObject, UICollectionViewDataSource, U
         fatalError()
     }
 
-    init(services: Services) {
+    init(services: Services, type: VLCMediaType) {
         self.services = services
+        mediaType = type
         super.init()
     }
 
     public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return Int(services.mediaDataSource.numberOfFiles())
+            return Int(services.mediaDataSource.numberOfFiles(subcategory: mediaType.subcategory))
     }
 
     public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         if let playlistCell = collectionView.dequeueReusableCell(withReuseIdentifier: VLCPlaylistCollectionViewCell.cellIdentifier(), for: indexPath) as? VLCPlaylistCollectionViewCell {
-            playlistCell.mediaObject = services.mediaDataSource.object(at: UInt(indexPath.row))
+            playlistCell.mediaObject = services.mediaDataSource.object(at: indexPath.row, subcategory: mediaType.subcategory)
             return playlistCell
         }
         return UICollectionViewCell()

+ 24 - 16
Sources/MediaViewController.swift

@@ -20,14 +20,15 @@ import Foundation
 
 public class VLCMediaViewController: UICollectionViewController, UISearchResultsUpdating, UISearchControllerDelegate {
     private var services: Services
-    private var mediaDatasourceAndDelegate: MediaDataSourceAndDelegate?
+    private var mediaDataSourceAndDelegate: MediaDataSourceAndDelegate?
     private var searchController: UISearchController?
     private let searchDataSource = VLCLibrarySearchDisplayDataSource()
+    private var mediaType: VLCMediaType
     public weak var delegate: VLCMediaViewControllerDelegate?
 
     @available(iOS 11.0, *)
     lazy var dragAndDropManager: VLCDragAndDropManager = {
-        let dragAndDropManager = VLCDragAndDropManager()
+        let dragAndDropManager = VLCDragAndDropManager(type: mediaType)
         dragAndDropManager.delegate = services.mediaDataSource
         return dragAndDropManager
     }()
@@ -45,15 +46,26 @@ public class VLCMediaViewController: UICollectionViewController, UISearchResults
         fatalError()
     }
 
-    init(services: Services) {
+    init(services: Services, type: VLCMediaType) {
         self.services = services
+        mediaType = type
         super.init(collectionViewLayout: UICollectionViewFlowLayout())
         NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .VLCThemeDidChangeNotification, object: nil)
+        if mediaType.category == .video {
+            NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: .VLCAllVideosDidChangeNotification, object: nil)
+        } else {
+            NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: .VLCTracksDidChangeNotification, object: nil)
+        }
+    }
+
+    @objc func reloadData() {
+        collectionView?.reloadData()
+        displayEmptyViewIfNeeded()
     }
 
     @available(*, unavailable)
     required public init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
+        fatalError("init(coder: ) has not been implemented")
     }
 
     override public func viewDidLoad() {
@@ -69,14 +81,14 @@ public class VLCMediaViewController: UICollectionViewController, UISearchResults
     }
 
     func setupCollectionView() {
-        mediaDatasourceAndDelegate = MediaDataSourceAndDelegate(services: services)
-        mediaDatasourceAndDelegate?.delegate = self
+        mediaDataSourceAndDelegate = MediaDataSourceAndDelegate(services: services, type:mediaType)
+        mediaDataSourceAndDelegate?.delegate = self
         let playlistnib = UINib(nibName: "VLCPlaylistCollectionViewCell", bundle:nil)
         collectionView?.register(playlistnib, forCellWithReuseIdentifier: VLCPlaylistCollectionViewCell.cellIdentifier())
         collectionView?.backgroundColor = PresentationTheme.current.colors.background
         collectionView?.alwaysBounceVertical = true
-        collectionView?.dataSource = mediaDatasourceAndDelegate
-        collectionView?.delegate = mediaDatasourceAndDelegate
+        collectionView?.dataSource = mediaDataSourceAndDelegate
+        collectionView?.delegate = mediaDataSourceAndDelegate
         if #available(iOS 11.0, *) {
             collectionView?.dragDelegate = dragAndDropManager
             collectionView?.dropDelegate = dragAndDropManager
@@ -85,11 +97,7 @@ public class VLCMediaViewController: UICollectionViewController, UISearchResults
 
     override public func viewDidAppear(_ animated: Bool) {
         super.viewDidAppear(animated)
-        services.mediaDataSource.updateContents(forSelection: nil)
-        services.mediaDataSource.addAllFolders()
-        services.mediaDataSource.addRemainingFiles()
-        collectionView?.reloadData()
-        displayEmptyViewIfNeeded()
+        reloadData()
     }
     
     func setupSearchController() {
@@ -130,12 +138,12 @@ public class VLCMediaViewController: UICollectionViewController, UISearchResults
 
     // MARK: - MediaDatasourceAndDelegate
     override public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        delegate?.mediaViewControllerDidSelectMediaObject(self, mediaObject:services.mediaDataSource.object(at: UInt(indexPath.row)))
+        delegate?.mediaViewControllerDidSelectMediaObject(self, mediaObject: services.mediaDataSource.object(at: indexPath.row, subcategory: mediaType.subcategory))
     }
 
     // MARK: - Search
     public func updateSearchResults(for searchController: UISearchController) {
-        searchDataSource.shouldReloadTable(forSearch: searchController.searchBar.text, searchableFiles: services.mediaDataSource.allObjects())
+        searchDataSource.shouldReloadTable(forSearch: searchController.searchBar.text, searchableFiles: services.mediaDataSource.allObjects(for: mediaType.subcategory))
         collectionView?.reloadData()
     }
 
@@ -144,7 +152,7 @@ public class VLCMediaViewController: UICollectionViewController, UISearchResults
     }
 
     public func didDismissSearchController(_ searchController: UISearchController) {
-        collectionView?.dataSource = mediaDatasourceAndDelegate
+        collectionView?.dataSource = mediaDataSourceAndDelegate
     }
 
 }

+ 10 - 1
Sources/VLCDragAndDropManager.swift

@@ -36,7 +36,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
     @objc weak var delegate: VLCDragAndDropManagerDelegate?
 
     let utiTypeIdentifiers: [String] = VLCDragAndDropManager.supportedTypeIdentifiers()
-
+     var mediaType: VLCMediaType
     /// Returns the supported type identifiers that VLC can process.
     /// It fetches the identifiers in LSItemContentTypes from all the CFBundleDocumentTypes in the info.plist.
     /// Video, Audio and Subtitle formats
@@ -54,6 +54,15 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
         return typeIdentifiers
     }
 
+    @available(*, unavailable, message: "use init(category:)")
+    override init() {
+        fatalError()
+    }
+
+    init(type: VLCMediaType) {
+        mediaType = type
+        super.init()
+    }
     // MARK: - TableView
     func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool {
         return canHandleDropSession(session: session)

+ 9 - 13
Sources/VLCMediaData+VLCDragAndDrop.swift

@@ -15,31 +15,27 @@ import Foundation
 @available(iOS 11.0, *)
 extension VLCMediaDataSource: VLCDragAndDropManagerDelegate {
     func dragAndDropManagerRequestsFile(manager: VLCDragAndDropManager, atIndexPath indexPath: IndexPath) -> AnyObject? {
-        if !(indexPath.row < numberOfFiles()) {
-            return nil
-        }
-        return object(at: UInt(indexPath.row))
+        return object(at: indexPath.row, subcategory: manager.mediaType.subcategory)
     }
 
     func dragAndDropManagerInsertItem(manager: VLCDragAndDropManager, item: NSManagedObject, atIndexPath indexPath: IndexPath) {
-        if item as? MLLabel != nil && indexPath.row < numberOfFiles() {
-            removeObject(at: UInt(indexPath.row))
+        if item as? MLLabel != nil && indexPath.row < numberOfFiles(subcategory: manager.mediaType.subcategory) {
+            removeObject(at: indexPath.row, subcategory: manager.mediaType.subcategory)
         }
-        insert(item, at: UInt(indexPath.row))
+        insert(item as! MLFile, at: indexPath.row, subcategory:manager.mediaType.subcategory)
     }
 
     func dragAndDropManagerDeleteItem(manager: VLCDragAndDropManager, atIndexPath indexPath: IndexPath) {
-        if !(indexPath.row < numberOfFiles()) {
-            return
-        }
-        removeObject(at: UInt(indexPath.row))
+        return removeObject(at: indexPath.row, subcategory: manager.mediaType.subcategory)
     }
 
     func dragAndDropManagerCurrentSelection(manager: VLCDragAndDropManager) -> AnyObject? {
-        return currentSelection()
+        //  TODO:Handle playlists and Collections
+        fatalError()
     }
 
     func dragAndDropManagerRemoveFileFromFolder(manager: VLCDragAndDropManager, file: NSManagedObject) {
-        return removeMediaObject(fromFolder: file)
+        // TODO: handle removing from playlists and Collections
+        fatalError()
     }
 }

+ 0 - 34
Sources/VLCMediaDataSource.h

@@ -1,34 +0,0 @@
-//
-//  VLCMediaDatasource.h
-//  VLC
-//
-//  Created by Carola Nitz on 8/15/17.
-//  Copyright © 2017 VideoLAN. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface VLCMediaDataSource : NSObject
-
-- (NSManagedObject *)currentSelection;
-
-- (void)updateContentsForSelection:(NSManagedObject *)selection;
-- (NSUInteger)numberOfFiles;
-- (NSManagedObject *)objectAtIndex:(NSUInteger)index;
-- (NSUInteger)indexOfObject:(NSManagedObject *)object;
-
-- (void)insertObject:(NSManagedObject *)object atIndex:(NSUInteger)index;
-- (void)removeObjectAtIndex:(NSUInteger)index;
-- (void)moveObjectFromIndex:(NSUInteger)fromIdx toIndex:(NSUInteger)toIdx;
-
-//this always creates a copy that might not be good
-- (NSArray *)allObjects;
-
-- (void)addAlbumsInAllAlbumMode:(BOOL)isAllAlbumMode;
-- (void)addAllShows;
-- (void)addAllFolders;
-- (void)addRemainingFiles;
-
-- (void)removeMediaObject:(NSManagedObject *)managedObject;
-- (void)removeMediaObjectFromFolder:(NSManagedObject *)managedObject;
-@end

+ 0 - 267
Sources/VLCMediaDataSource.m

@@ -1,267 +0,0 @@
-/*****************************************************************************
- * VLCMediaDataSource.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 "VLCMediaDataSource.h"
-#import "VLCPlaybackController.h"
-#import "NSString+SupportedMedia.h"
-
-@interface VLCMediaDataSource ()
-{
-    NSMutableArray *_foundMedia;
-    NSManagedObject *_currentSelection;
-}
-@end
-
-@implementation VLCMediaDataSource
-
-- (void)updateContentsForSelection:(NSManagedObject *)selection
-{
-    NSArray *array = [NSMutableArray new];
-    if ([selection isKindOfClass:[MLAlbum class]]) {
-        array = [(MLAlbum *)selection sortedTracks];
-    } else if ([selection isKindOfClass:[MLShow class]]) {
-        array =  [(MLShow *)selection sortedEpisodes];
-    } else if ([selection isKindOfClass:[MLLabel class]]) {
-        array = [(MLLabel *)selection sortedFolderItems];
-    }
-    _currentSelection = selection;
-    _foundMedia = [NSMutableArray arrayWithArray:array];
-}
-
-- (NSManagedObject *)currentSelection
-{
-    return _currentSelection;
-}
-
-- (NSUInteger)numberOfFiles
-{
-    return [_foundMedia count];
-}
-
-- (NSManagedObject *)objectAtIndex:(NSUInteger)index
-{
-    if (index < _foundMedia.count)
-        return  _foundMedia[index];
-    return nil;
-}
-
-- (NSUInteger)indexOfObject:(NSManagedObject *)object
-{
-    return [_foundMedia indexOfObject:object];
-}
-
-- (void)insertObject:(NSManagedObject *)object atIndex:(NSUInteger)index
-{
-    [_foundMedia insertObject:object atIndex:index];
-}
-
-- (void)removeObjectAtIndex:(NSUInteger)index
-{
-    [_foundMedia removeObjectAtIndex:index];
-}
-
-- (void)moveObjectFromIndex:(NSUInteger)fromIdx toIndex:(NSUInteger)toIdx
-{
-    MLFile* object = _foundMedia[fromIdx];
-    if (![object isKindOfClass:[MLFile class]])
-        return;
-    [_foundMedia removeObjectAtIndex:fromIdx];
-    [_foundMedia insertObject:object atIndex:toIdx];
-    object.folderTrackNumber = @(toIdx - 1);
-    object = [_foundMedia objectAtIndex:fromIdx];
-    if (![object isKindOfClass:[MLFile class]])
-        return;
-    object.folderTrackNumber = @(fromIdx - 1);
-}
-
-- (void)removeAllObjects
-{
-    _foundMedia = [NSMutableArray new];
-}
-
-- (NSArray *)allObjects
-{
-    return [_foundMedia copy];
-}
-
-- (void)addObject:(NSManagedObject *)object
-{
-    [_foundMedia addObject:object];
-}
-
-- (void)addAlbumsInAllAlbumMode:(BOOL)isAllAlbumMode;
-{
-    for (MLAlbum *album in [MLAlbum allAlbums]) {
-        if (album.name.length > 0) {
-            if (isAllAlbumMode) {
-                [self addObject:album];
-            } else if ( album.tracks.count > 1) {
-                [self addObject:album];
-            }
-        }
-    }
-}
-
-- (void)addAllShows
-{
-    for (MLShow *show in [MLShow allShows]) {
-        if (show.name.length > 0 && show.episodes.count > 1) {
-            [self addObject:show];
-        }
-    }
-}
-
-- (void)addAllFolders
-{
-    for (MLLabel *folder in [MLLabel allLabels]) {
-        [self addObject:folder];
-    }
-}
-
-- (void)addRemainingFiles
-{
-    for (MLFile *file in [MLFile allFiles]) {
-        if (file.labels != nil) {
-            if (file.labels.count > 0)
-                continue;
-        }
-
-        if (!file.isShowEpisode && !file.isAlbumTrack) {
-             [self addObject:file];
-        } else if (file.isShowEpisode) {
-            if (file.showEpisode.show.episodes.count < 2) {
-                [self addObject:file];
-            }
-
-            /* older MediaLibraryKit versions don't send a show name in a popular
-             * corner case. hence, we need to work-around here and force a reload
-             * afterwards as this could lead to the 'all my shows are gone'
-             * syndrome (see #10435, #10464, #10432 et al) */
-            if (file.showEpisode.show.name.length == 0) {
-                file.showEpisode.show.name = NSLocalizedString(@"UNTITLED_SHOW", nil);
-                [self updateContentsForSelection:_currentSelection];
-            }
-        } else if (file.isAlbumTrack && file.albumTrack.album.tracks.count < 2) {
-            [self addObject:file];
-        }
-    }
-}
-
-- (void)removeMediaObjectFromFolder:(NSManagedObject *)managedObject
-{
-    NSAssert(([managedObject isKindOfClass:[MLFile class]] && ((MLFile *)managedObject).labels.count > 0), @"All media in a folder should be of type MLFile and it should be in a folder");
-
-    if (![managedObject isKindOfClass:[MLFile class]]) return;
-
-    MLFile *mediaFile = (MLFile *)managedObject;
-    [self rearrangeFolderTrackNumbersForRemovedItem:mediaFile];
-    mediaFile.labels = nil;
-    mediaFile.folderTrackNumber = nil;
-}
-
-- (void)removeMediaObject:(NSManagedObject *)managedObject
-{
-    if ([managedObject isKindOfClass:[MLAlbum class]]) {
-        MLAlbum *album = (MLAlbum *)managedObject;
-        NSSet *iterAlbumTrack = [NSSet setWithSet:album.tracks];
-
-        for (MLAlbumTrack *track in iterAlbumTrack) {
-            NSSet *iterFiles = [NSSet setWithSet:track.files];
-
-            for (MLFile *file in iterFiles)
-                [self _deleteMediaObject:file];
-        }
-        [[MLMediaLibrary sharedMediaLibrary] removeObject: album];
-        // delete all episodes from a show
-    } else if ([managedObject isKindOfClass:[MLShow class]]) {
-        MLShow *show = (MLShow *)managedObject;
-        NSSet *iterShowEpisodes = [NSSet setWithSet:show.episodes];
-
-        for (MLShowEpisode *episode in iterShowEpisodes) {
-            NSSet *iterFiles = [NSSet setWithSet:episode.files];
-
-            for (MLFile *file in iterFiles)
-                [self _deleteMediaObject:file];
-        }
-        [[MLMediaLibrary sharedMediaLibrary] removeObject: show];
-        // delete all files from an episode
-    } else if ([managedObject isKindOfClass:[MLShowEpisode class]]) {
-        MLShowEpisode *episode = (MLShowEpisode *)managedObject;
-        NSSet *iterFiles = [NSSet setWithSet:episode.files];
-
-        for (MLFile *file in iterFiles)
-            [self _deleteMediaObject:file];
-        // delete all files from a track
-        [[MLMediaLibrary sharedMediaLibrary] removeObject: episode];
-    } else if ([managedObject isKindOfClass:[MLAlbumTrack class]]) {
-        MLAlbumTrack *track = (MLAlbumTrack *)managedObject;
-        NSSet *iterFiles = [NSSet setWithSet:track.files];
-
-        for (MLFile *file in iterFiles)
-            [self _deleteMediaObject:file];
-    } else if ([managedObject isKindOfClass:[MLLabel class]]) {
-        MLLabel *folder = (MLLabel *)managedObject;
-        NSSet *iterFiles = [NSSet setWithSet:folder.files];
-        [folder removeFiles:folder.files];
-        for (MLFile *file in iterFiles)
-            [self _deleteMediaObject:file];
-        [[MLMediaLibrary sharedMediaLibrary] removeObject:folder];
-    }
-    else
-        [self _deleteMediaObject:(MLFile *)managedObject];
-}
-
-- (void)_deleteMediaObject:(MLFile *)mediaObject
-{
-    [self rearrangeFolderTrackNumbersForRemovedItem:mediaObject];
-
-    /* stop playback if needed */
-    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
-    VLCMedia *media = [vpc currentlyPlayingMedia];
-    MLFile *currentlyPlayingFile = [MLFile fileForURL:media.url].firstObject;
-    if (currentlyPlayingFile && currentlyPlayingFile == mediaObject) {
-        [vpc stopPlayback];
-    }
-
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    NSString *folderLocation = [[mediaObject.url path] stringByDeletingLastPathComponent];
-    NSArray *allfiles = [fileManager contentsOfDirectoryAtPath:folderLocation error:nil];
-    NSString *fileName = [mediaObject.path.lastPathComponent stringByDeletingPathExtension];
-    if (!fileName)
-        return;
-    NSIndexSet *indexSet = [allfiles indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
-        return ([obj rangeOfString:fileName].location != NSNotFound);
-    }];
-    NSUInteger count = indexSet.count;
-    NSString *additionalFilePath;
-    NSUInteger currentIndex = [indexSet firstIndex];
-    for (unsigned int x = 0; x < count; x++) {
-        additionalFilePath = allfiles[currentIndex];
-        if ([additionalFilePath isSupportedSubtitleFormat])
-            [fileManager removeItemAtPath:[folderLocation stringByAppendingPathComponent:additionalFilePath] error:nil];
-        currentIndex = [indexSet indexGreaterThanIndex:currentIndex];
-    }
-    [fileManager removeItemAtURL:mediaObject.url error:nil];
-}
-
-- (void)rearrangeFolderTrackNumbersForRemovedItem:(MLFile *) mediaObject
-{
-    MLLabel *label = [mediaObject.labels anyObject];
-    NSSet *allFiles = label.files;
-    for (MLFile *file in allFiles) {
-        if (file.folderTrackNumber > mediaObject.folderTrackNumber) {
-            int value = [file.folderTrackNumber intValue];
-            file.folderTrackNumber = [NSNumber numberWithInt:value - 1];
-        }
-    }
-}
-@end

+ 275 - 0
Sources/VLCMediaDataSource.swift

@@ -0,0 +1,275 @@
+/*****************************************************************************
+ * VLCMediaDataSource.swift
+ * 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 Foundation
+
+@objc enum VLCMediaCategory: Int {
+    case unknown
+    case audio
+    case video
+}
+
+@objc enum VLCMediaSubcategory: Int {
+    case unknown
+    case movies
+    case episodes
+    case artists
+    case albums
+    case tracks
+    case genres
+    case videoPlaylists
+    case audioPlaylists
+    case allVideos
+}
+
+struct VLCMediaType {
+    let category: VLCMediaCategory
+    var subcategory: VLCMediaSubcategory
+}
+
+@objc class VLCMediaDataSource: NSObject {
+
+    var foundVideos = [MLFile]()
+    var foundAudio = [MLFile]()
+
+    var movies = [MLFile]()
+    var episodes = [MLFile]()
+    var artists = [MLFile]()
+    var albums = [MLFile]()
+    var tracks = [MLFile]() // might be just foundAudio
+    var genres = [MLFile]()
+    var audioPlaylist = [MLFile]()
+    var videoPlaylist = [MLFile]()
+    var allVideos = [MLFile]() // might be just foundVideo
+
+    override init() {
+        super.init()
+        getAllVideos()
+        getAllAudio()
+    }
+
+    @objc func numberOfFiles(subcategory: VLCMediaSubcategory) -> Int {
+        return array(for: subcategory).count
+    }
+
+    private func array(for subcategory: VLCMediaSubcategory ) -> [MLFile] {
+        switch subcategory {
+        case .unknown:
+            preconditionFailure("No")
+        case .movies:
+            preconditionFailure("TODO")
+            return movies
+        case .episodes:
+            preconditionFailure("TODO")
+            return episodes
+        case .artists:
+            preconditionFailure("TODO")
+            return artists
+        case .albums:
+            preconditionFailure("TODO")
+            return albums
+        case .tracks:
+            return tracks
+        case .genres:
+            preconditionFailure("TODO")
+            return genres
+        case .audioPlaylists:
+            preconditionFailure("TODO")
+            return audioPlaylist
+        case .videoPlaylists:
+            preconditionFailure("TODO")
+            return videoPlaylist
+        case .allVideos:
+            return allVideos
+        }
+    }
+    @objc func object(at index: Int, subcategory: VLCMediaSubcategory) -> NSManagedObject {
+
+        guard index >= 0 else {
+            preconditionFailure("a negative value ? I don't think so!")
+        }
+
+        let categoryArray = array(for: subcategory)
+        if index < categoryArray.count {
+            return categoryArray[Int(index)]
+        }
+        preconditionFailure("index is taller than count")
+    }
+
+    func allObjects(for subcategory: VLCMediaSubcategory) -> [MLFile] {
+        return array(for:subcategory)
+    }
+
+    internal func removeObject(at index: Int, subcategory: VLCMediaSubcategory) {
+        guard index >= 0 else {
+            preconditionFailure("a negative value ? I don't think so!")
+        }
+        var categoryArray = array(for: subcategory)
+        if index < categoryArray.count {
+            categoryArray.remove(at: index)
+        }
+        preconditionFailure("index is taller than count")
+    }
+
+    internal func insert(_ item: MLFile, at index: Int, subcategory: VLCMediaSubcategory) {
+        guard index >= 0 else {
+            preconditionFailure("a negative value ? I don't think so!")
+        }
+        var categoryArray = array(for: subcategory)
+        if index < categoryArray.count {
+            categoryArray.insert(item, at: index)
+        }
+        categoryArray.append(item)
+    }
+
+    private func getAllVideos() {
+        let files = MLFile.allFiles() as! [MLFile]
+        foundVideos = files.filter {
+            ($0 as MLFile).isKind(ofType: kMLFileTypeMovie) ||
+                ($0 as MLFile).isKind(ofType: kMLFileTypeTVShowEpisode) ||
+                ($0 as MLFile).isKind(ofType: kMLFileTypeClip)
+        }
+        allVideosFromVideos()
+        //TODO: generate video subcategories
+    }
+
+    private func getAllAudio() {
+        let files = MLFile.allFiles() as! [MLFile]
+        foundAudio = files.filter { $0.isSupportedAudioFile() }
+        tracksFromAudio()
+        //TODO: generate remaining subcategories
+    }
+
+    private func tracksFromAudio() {
+        if tracks != foundAudio {
+            tracks = foundAudio
+            NotificationCenter.default.post(name: .VLCTracksDidChangeNotification, object: tracks)
+        }
+    }
+
+    private func allVideosFromVideos() {
+        if allVideos != foundVideos {
+            allVideos = foundVideos
+            NotificationCenter.default.post(name: .VLCAllVideosDidChangeNotification, object: allVideos)
+        }
+    }
+}
+//Todo: implement the remove
+//    - (void)removeMediaObjectFromFolder:(NSManagedObject *)managedObject
+//{
+//    NSAssert(([managedObject isKindOfClass:[MLFile class]] && ((MLFile *)managedObject).labels.count > 0), @"All media in a folder should be of type MLFile and it should be in a folder");
+//
+//    if (![managedObject isKindOfClass:[MLFile class]]) return;
+//
+//    MLFile *mediaFile = (MLFile *)managedObject;
+//    [self rearrangeFolderTrackNumbersForRemovedItem:mediaFile];
+//    mediaFile.labels = nil;
+//    mediaFile.folderTrackNumber = nil;
+//    }
+//
+//    - (void)removeMediaObject:(NSManagedObject *)managedObject
+//{
+//    if ([managedObject isKindOfClass:[MLAlbum class]]) {
+//        MLAlbum *album = (MLAlbum *)managedObject;
+//        NSSet *iterAlbumTrack = [NSSet setWithSet:album.tracks];
+//
+//        for (MLAlbumTrack *track in iterAlbumTrack) {
+//            NSSet *iterFiles = [NSSet setWithSet:track.files];
+//
+//            for (MLFile *file in iterFiles)
+//                [self _deleteMediaObject:file];
+//        }
+//        [[MLMediaLibrary sharedMediaLibrary] removeObject: album];
+//        // delete all episodes from a show
+//    } else if ([managedObject isKindOfClass:[MLShow class]]) {
+//        MLShow *show = (MLShow *)managedObject;
+//        NSSet *iterShowEpisodes = [NSSet setWithSet:show.episodes];
+//
+//        for (MLShowEpisode *episode in iterShowEpisodes) {
+//            NSSet *iterFiles = [NSSet setWithSet:episode.files];
+//
+//            for (MLFile *file in iterFiles)
+//                [self _deleteMediaObject:file];
+//        }
+//        [[MLMediaLibrary sharedMediaLibrary] removeObject: show];
+//        // delete all files from an episode
+//    } else if ([managedObject isKindOfClass:[MLShowEpisode class]]) {
+//        MLShowEpisode *episode = (MLShowEpisode *)managedObject;
+//        NSSet *iterFiles = [NSSet setWithSet:episode.files];
+//
+//        for (MLFile *file in iterFiles)
+//            [self _deleteMediaObject:file];
+//        // delete all files from a track
+//        [[MLMediaLibrary sharedMediaLibrary] removeObject: episode];
+//    } else if ([managedObject isKindOfClass:[MLAlbumTrack class]]) {
+//        MLAlbumTrack *track = (MLAlbumTrack *)managedObject;
+//        NSSet *iterFiles = [NSSet setWithSet:track.files];
+//
+//        for (MLFile *file in iterFiles)
+//            [self _deleteMediaObject:file];
+//    } else if ([managedObject isKindOfClass:[MLLabel class]]) {
+//        MLLabel *folder = (MLLabel *)managedObject;
+//        NSSet *iterFiles = [NSSet setWithSet:folder.files];
+//        [folder removeFiles:folder.files];
+//        for (MLFile *file in iterFiles)
+//            [self _deleteMediaObject:file];
+//        [[MLMediaLibrary sharedMediaLibrary] removeObject:folder];
+//    }
+//    else
+//    [self _deleteMediaObject:(MLFile *)managedObject];
+//    }
+//
+//    - (void)_deleteMediaObject:(MLFile *)mediaObject
+//{
+//    [self rearrangeFolderTrackNumbersForRemovedItem:mediaObject];
+//
+//    /* stop playback if needed */
+//    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
+//    VLCMedia *media = [vpc currentlyPlayingMedia];
+//    MLFile *currentlyPlayingFile = [MLFile fileForURL:media.url].firstObject;
+//    if (currentlyPlayingFile && currentlyPlayingFile == mediaObject) {
+//        [vpc stopPlayback];
+//    }
+//
+//    NSFileManager *fileManager = [NSFileManager defaultManager];
+//    NSString *folderLocation = [[mediaObject.url path] stringByDeletingLastPathComponent];
+//    NSArray *allfiles = [fileManager contentsOfDirectoryAtPath:folderLocation error:nil];
+//    NSString *fileName = [mediaObject.path.lastPathComponent stringByDeletingPathExtension];
+//    if (!fileName)
+//    return;
+//    NSIndexSet *indexSet = [allfiles indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
+//        return ([obj rangeOfString:fileName].location != NSNotFound);
+//        }];
+//    NSUInteger count = indexSet.count;
+//    NSString *additionalFilePath;
+//    NSUInteger currentIndex = [indexSet firstIndex];
+//    for (unsigned int x = 0; x < count; x++) {
+//        additionalFilePath = allfiles[currentIndex];
+//        if ([additionalFilePath isSupportedSubtitleFormat])
+//        [fileManager removeItemAtPath:[folderLocation stringByAppendingPathComponent:additionalFilePath] error:nil];
+//        currentIndex = [indexSet indexGreaterThanIndex:currentIndex];
+//    }
+//    [fileManager removeItemAtURL:mediaObject.url error:nil];
+//    }
+//
+//    - (void)rearrangeFolderTrackNumbersForRemovedItem:(MLFile *) mediaObject
+//{
+//    MLLabel *label = [mediaObject.labels anyObject];
+//    NSSet *allFiles = label.files;
+//    for (MLFile *file in allFiles) {
+//        if (file.folderTrackNumber > mediaObject.folderTrackNumber) {
+//            int value = [file.folderTrackNumber intValue];
+//            file.folderTrackNumber = [NSNumber numberWithInt:value - 1];
+//        }
+//    }
+//}
+//@end

+ 2 - 2
Sources/VLCTabBarCoordinator.swift

@@ -42,7 +42,7 @@ class VLCTabbarCooordinator: NSObject, VLCMediaViewControllerDelegate {
         displayController.view.layoutMargins = UIEdgeInsets(top:0, left:0, bottom:tabBarController.tabBar.frame.size.height, right:0)
         displayController.didMove(toParentViewController: tabBarController)
 
-        let videoVC = VLCMediaViewController(services: services)
+        let videoVC = VLCMediaViewController(services: services, type:VLCMediaType(category: .video, subcategory: .allVideos))
         //this should probably not be the delegate
         videoVC.delegate = self
         videoVC.title = NSLocalizedString("VIDEO", comment: "")
@@ -53,7 +53,7 @@ class VLCTabbarCooordinator: NSObject, VLCMediaViewControllerDelegate {
         videoVC.tabBarItem.accessibilityIdentifier = VLCAccessibilityIdentifier.video
 
         // Audio
-        let audioVC = VLCMediaViewController(services: services)
+        let audioVC = VLCMediaViewController(services: services, type:VLCMediaType(category: .audio, subcategory: .tracks))
         //this should probably not be the delegate
         audioVC.delegate = self
         audioVC.title = NSLocalizedString("AUDIO", comment: "")

+ 0 - 1
VLC-iOS-Bridging-Header.h

@@ -10,7 +10,6 @@
 #import "VLCDownloadViewController.h"
 #import "VLCEmptyLibraryView.h"
 #import "VLCLibrarySearchDisplayDataSource.h"
-#import "VLCMediaDataSource.h"
 #import "VLCOpenNetworkStreamViewController.h"
 #import "VLCPlaybackController+MediaLibrary.h"
 #import "VLCPlaybackNavigationController.h"

+ 8 - 10
VLC.xcodeproj/project.pbxproj

@@ -16,6 +16,7 @@
 		41273A3D1A955C4100A2EF77 /* VLCMigrationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 41273A3B1A955C4100A2EF77 /* VLCMigrationViewController.xib */; };
 		413EC987201A329D00BF412F /* SortOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413EC986201A329D00BF412F /* SortOption.swift */; };
 		413EC98B201B4F2C00BF412F /* PresentationTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413EC98A201B4F2B00BF412F /* PresentationTheme.swift */; };
+		4142AB4520A31EC500039380 /* VLCMediaDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4142AB4420A31EC500039380 /* VLCMediaDataSource.swift */; };
 		414396C22023316C005E3FAF /* AppearanceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414396C12023316C005E3FAF /* AppearanceManager.swift */; };
 		4144C4661A0ED6C700918C89 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D3784E6183A99E1009EE944 /* Reachability.m */; };
 		4152F1621FEF19BD00F1908B /* KeychainCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */; };
@@ -32,7 +33,7 @@
 		418B145620179DF2000447AA /* VLCMediaData+VLCDragAndDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418B145520179DF2000447AA /* VLCMediaData+VLCDragAndDrop.swift */; };
 		418B145920179E50000447AA /* VLCDragAndDropManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418B145820179E50000447AA /* VLCDragAndDropManager.swift */; };
 		4195747D206A92ED00393A42 /* RemoteNetworkDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4195747C206A92ED00393A42 /* RemoteNetworkDataSource.swift */; };
-		419794C3206B9E7A009E081A /* MediaDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 419794C2206B9E7A009E081A /* MediaDataSource.swift */; };
+		419794C3206B9E7A009E081A /* MediaDataSourceAndDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 419794C2206B9E7A009E081A /* MediaDataSourceAndDelegate.swift */; };
 		419A2C661F37A4B70069D224 /* VLCStringsForLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 419A2C651F37A4B70069D224 /* VLCStringsForLocalization.m */; };
 		419A2C681F37A4B70069D224 /* VLCStringsForLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 419A2C651F37A4B70069D224 /* VLCStringsForLocalization.m */; };
 		419D7F051F54176900AF69A2 /* VLCTimeNavigationTitleView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 419D7F041F54176900AF69A2 /* VLCTimeNavigationTitleView.xib */; };
@@ -46,7 +47,6 @@
 		41EB91DD1F7BFF8500821AA5 /* VLCMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 41EB91DC1F7BFF8400821AA5 /* VLCMetadata.m */; };
 		41EB91DE1F7BFF8500821AA5 /* VLCMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 41EB91DC1F7BFF8400821AA5 /* VLCMetadata.m */; };
 		41F5C0781F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F5C0771F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.m */; };
-		41F5C07B1F42E567005EB9CB /* VLCMediaDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F5C07A1F42E567005EB9CB /* VLCMediaDataSource.m */; };
 		41F9BC7C1F4F20E400268461 /* VLCTrackSelectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */; };
 		6B4E33D11BF2A39400A35255 /* playerControl.css in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E33CF1BF2A39400A35255 /* playerControl.css */; };
 		6B4E33D21BF2A39400A35255 /* playerControl.js in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E33D01BF2A39400A35255 /* playerControl.js */; };
@@ -488,6 +488,7 @@
 		412BE7521FC4947400ACCC42 /* VLCMediaData+VLCDragAndDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "VLCMediaData+VLCDragAndDrop.swift"; path = "Sources/VLCMediaData+VLCDragAndDrop.swift"; sourceTree = SOURCE_ROOT; };
 		413EC986201A329D00BF412F /* SortOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SortOption.swift; path = SharedSources/Coordinators/SortOption.swift; sourceTree = SOURCE_ROOT; };
 		413EC98A201B4F2B00BF412F /* PresentationTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentationTheme.swift; sourceTree = "<group>"; };
+		4142AB4420A31EC500039380 /* VLCMediaDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VLCMediaDataSource.swift; path = Sources/VLCMediaDataSource.swift; sourceTree = "<group>"; };
 		414396C12023316C005E3FAF /* AppearanceManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppearanceManager.swift; path = Sources/AppearanceManager.swift; sourceTree = SOURCE_ROOT; };
 		4152F1611FEF19BD00F1908B /* KeychainCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = KeychainCoordinator.swift; path = Sources/KeychainCoordinator.swift; sourceTree = "<group>"; };
 		416DEFF51FEEA76A00F4FC59 /* LayoutAnchorContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LayoutAnchorContainer.swift; path = Sources/LayoutAnchorContainer.swift; sourceTree = "<group>"; };
@@ -551,7 +552,7 @@
 		418B145520179DF2000447AA /* VLCMediaData+VLCDragAndDrop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "VLCMediaData+VLCDragAndDrop.swift"; path = "Sources/VLCMediaData+VLCDragAndDrop.swift"; sourceTree = "<group>"; };
 		418B145820179E50000447AA /* VLCDragAndDropManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VLCDragAndDropManager.swift; path = Sources/VLCDragAndDropManager.swift; sourceTree = "<group>"; };
 		4195747C206A92ED00393A42 /* RemoteNetworkDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteNetworkDataSource.swift; sourceTree = "<group>"; };
-		419794C2206B9E7A009E081A /* MediaDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaDataSource.swift; sourceTree = "<group>"; };
+		419794C2206B9E7A009E081A /* MediaDataSourceAndDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaDataSourceAndDelegate.swift; sourceTree = "<group>"; };
 		419A2C651F37A4B70069D224 /* VLCStringsForLocalization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCStringsForLocalization.m; sourceTree = "<group>"; };
 		419D7F041F54176900AF69A2 /* VLCTimeNavigationTitleView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = VLCTimeNavigationTitleView.xib; path = Resources/VLCTimeNavigationTitleView.xib; sourceTree = SOURCE_ROOT; };
 		41B0BC861F73ED7D0063BA26 /* VLC for iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "VLC for iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -572,8 +573,6 @@
 		41EB91DC1F7BFF8400821AA5 /* VLCMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCMetadata.m; sourceTree = "<group>"; };
 		41F5C0761F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VLCLibrarySearchDisplayDataSource.h; path = Sources/VLCLibrarySearchDisplayDataSource.h; sourceTree = SOURCE_ROOT; };
 		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; name = VLCMediaDataSource.h; path = Sources/VLCMediaDataSource.h; sourceTree = SOURCE_ROOT; };
-		41F5C07A1F42E567005EB9CB /* VLCMediaDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = VLCMediaDataSource.m; path = Sources/VLCMediaDataSource.m; sourceTree = SOURCE_ROOT; };
 		41F9BC7A1F4F20E400268461 /* VLCTrackSelectorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VLCTrackSelectorView.h; path = Sources/VLCTrackSelectorView.h; sourceTree = SOURCE_ROOT; };
 		41F9BC7B1F4F20E400268461 /* VLCTrackSelectorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = VLCTrackSelectorView.m; path = Sources/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>"; };
@@ -1522,6 +1521,7 @@
 		7D5F7AB81752658E006CCCFA /* Everything Playlist */ = {
 			isa = PBXGroup;
 			children = (
+				4142AB4420A31EC500039380 /* VLCMediaDataSource.swift */,
 				418B145520179DF2000447AA /* VLCMediaData+VLCDragAndDrop.swift */,
 				418B145820179E50000447AA /* VLCDragAndDropManager.swift */,
 				41251ECB1FD0C5C100099110 /* VLC-iOS-Bridging-Header.h */,
@@ -1535,8 +1535,6 @@
 				8F91EC78195CEC7900F5BCBA /* VLCOpenInActivity.m */,
 				41F5C0761F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.h */,
 				41F5C0771F41ED55005EB9CB /* VLCLibrarySearchDisplayDataSource.m */,
-				41F5C0791F42E567005EB9CB /* VLCMediaDataSource.h */,
-				41F5C07A1F42E567005EB9CB /* VLCMediaDataSource.m */,
 			);
 			name = "Everything Playlist";
 			sourceTree = "<group>";
@@ -1921,7 +1919,7 @@
 				7D37849D183A98DD009EE944 /* VLCThumbnailsCache.m */,
 				DD7110EE1AF38B2B00854776 /* MLMediaLibrary+playlist.h */,
 				DD7110EF1AF38B2B00854776 /* MLMediaLibrary+playlist.m */,
-				419794C2206B9E7A009E081A /* MediaDataSource.swift */,
+				419794C2206B9E7A009E081A /* MediaDataSourceAndDelegate.swift */,
 			);
 			name = Library;
 			sourceTree = "<group>";
@@ -3158,7 +3156,6 @@
 				4184AA151A5492070063DF5A /* VLCCloudStorageController.m in Sources */,
 				9BE4D1CE183D76950006346C /* VLCCloudStorageTableViewCell.m in Sources */,
 				413EC98B201B4F2C00BF412F /* PresentationTheme.swift in Sources */,
-				41F5C07B1F42E567005EB9CB /* VLCMediaDataSource.m in Sources */,
 				DD1CB0321BB9E005006EDDE6 /* VLCMovieViewControlPanelView.m in Sources */,
 				DDF908D01CF4CCAA00108B70 /* VLCNetworkLoginViewButtonCell.m in Sources */,
 				DD3EFF3D1BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserHTTP.m in Sources */,
@@ -3171,6 +3168,7 @@
 				DD3EFEED1BDEBA3800B68579 /* VLCNetworkServerBrowserViewController.m in Sources */,
 				DD3EABFC1BE14C4B003668DA /* UIViewController+VLCAlert.m in Sources */,
 				7D9289751877459B009108FD /* VLCFirstStepsThirdPageViewController.m in Sources */,
+				4142AB4520A31EC500039380 /* VLCMediaDataSource.swift in Sources */,
 				7D95610B1AF3E9E800779745 /* VLCMiniPlaybackView.m in Sources */,
 				DD3EFF451BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserManualConnect.m in Sources */,
 				7DC19B051868D1C400810BF7 /* VLCFirstStepsFifthPageViewController.m in Sources */,
@@ -3237,7 +3235,7 @@
 				7D3784C8183A9972009EE944 /* NSString+SupportedMedia.m in Sources */,
 				417E68B91F321EFF00DB9BB2 /* VLCActivityViewControllerVendor.m in Sources */,
 				DD3EFF5B1BDEBCE500B68579 /* VLCNetworkServerBrowserUPnP.m in Sources */,
-				419794C3206B9E7A009E081A /* MediaDataSource.swift in Sources */,
+				419794C3206B9E7A009E081A /* MediaDataSourceAndDelegate.swift in Sources */,
 				418B144D20179C75000447AA /* VLCTabBarCoordinator.swift in Sources */,
 				DD3EABF81BE14BD6003668DA /* BasicUPnPDevice+VLC.m in Sources */,
 				DD3EAC091BE2192A003668DA /* VLCServerBrowsingController.m in Sources */,