浏览代码

playlist: implement album listing and playback (phone form factor only for now)

Felix Paul Kühne 12 年之前
父节点
当前提交
498fc2c0e3

+ 10 - 5
AspenProject/VLCMenuTableViewController.m

@@ -62,7 +62,10 @@
 	self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
 
     _sectionHeaderTexts = @[@"SECTION_HEADER_LIBRARY", @"SECTION_HEADER_NETWORK", @"Settings"];
-    _menuItemsSectionOne = @[@"LIBRARY_ALL_FILES"];
+    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
+        _menuItemsSectionOne = @[@"LIBRARY_ALL_FILES", @"LIBRARY_MUSIC"];
+    else
+        _menuItemsSectionOne = @[@"LIBRARY_ALL_FILES"];
     _menuItemsSectionTwo = @[@"LOCAL_NETWORK", @"OPEN_NETWORK", @"DOWNLOAD_FROM_HTTP", @"WiFi Upload", @"Dropbox"];
     _menuItemsSectionThree = @[@"Settings", @"ABOUT_APP"];
 
@@ -134,11 +137,11 @@
 
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     if (section == 0) // media
-        return 1;
+        return _menuItemsSectionOne.count;
     else if (section == 1) // network
-        return 5;
+        return _menuItemsSectionTwo.count;
     else if (section == 2) // settings & co
-        return 2;
+        return _menuItemsSectionThree.count;
     else
         return 0;
 }
@@ -280,8 +283,10 @@
             viewController = self.settingsController.viewController;
         } else if (itemIndex == 1)
             viewController = [[VLCAboutViewController alloc] init];
-    } else
+    } else {
         viewController = self.appDelegate.playlistViewController;
+        [self.appDelegate.playlistViewController setLibraryMode:itemIndex];
+    }
 
     if (!viewController)
         return;

+ 1 - 1
AspenProject/VLCPlaylistTableViewCell.h

@@ -21,7 +21,7 @@
 @property (nonatomic, strong) IBOutlet UILabel *artistNameLabel;
 @property (nonatomic, strong) IBOutlet UILabel *albumNameLabel;
 
-@property (nonatomic, retain) MLFile *mediaObject;
+@property (nonatomic, retain) NSManagedObject *mediaObject;
 
 + (VLCPlaylistTableViewCell *)cellWithReuseIdentifier:(NSString *)ident;
 + (CGFloat)heightOfCell;

+ 94 - 51
AspenProject/VLCPlaylistTableViewCell.m

@@ -9,6 +9,7 @@
 //
 
 #import "VLCPlaylistTableViewCell.h"
+#import <MediaLibraryKit/MLAlbum.h>
 
 #define MAX_CACHE_SIZE 21 // three times the number of items shown on iPhone 5
 
@@ -39,7 +40,12 @@
         [_mediaObject removeObserver:self forKeyPath:@"title"];
         [_mediaObject removeObserver:self forKeyPath:@"thumbnailTimeouted"];
         [_mediaObject removeObserver:self forKeyPath:@"unread"];
-        [_mediaObject didHide];
+        [_mediaObject removeObserver:self forKeyPath:@"albumTrackNumber"];
+        [_mediaObject removeObserver:self forKeyPath:@"album"];
+        [_mediaObject removeObserver:self forKeyPath:@"artist"];
+        [_mediaObject removeObserver:self forKeyPath:@"genre"];
+        if ([_mediaObject respondsToSelector:@selector(didHide)])
+            [(MLFile*)_mediaObject didHide];
 
         _mediaObject = mediaObject;
 
@@ -50,7 +56,13 @@
         [_mediaObject addObserver:self forKeyPath:@"title" options:0 context:nil];
         [_mediaObject addObserver:self forKeyPath:@"thumbnailTimeouted" options:0 context:nil];
         [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
-        [_mediaObject willDisplay];
+        [_mediaObject addObserver:self forKeyPath:@"albumTrackNumber" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
+
+        if ([_mediaObject respondsToSelector:@selector(willDisplay)])
+            [(MLFile*)_mediaObject willDisplay];
     }
 
     [self _updatedDisplayedInformationForKeyPath:NULL];
@@ -64,59 +76,90 @@
 
 - (void)_updatedDisplayedInformationForKeyPath:(NSString *)keyPath
 {
-    MLFile *mediaObject = self.mediaObject;
-
-    self.albumNameLabel.text = self.artistNameLabel.text = @"";
-
-    if (mediaObject.isAlbumTrack) {
-        self.artistNameLabel.text = mediaObject.albumTrack.artist;
-        self.albumNameLabel.text = mediaObject.albumTrack.album.name;
-        self.titleLabel.text = (mediaObject.albumTrack.title.length > 1) ? mediaObject.albumTrack.title : mediaObject.title;
-    } else
-        self.titleLabel.text = mediaObject.title;
-
-    if (self.isEditing)
-        self.subtitleLabel.text = [NSString stringWithFormat:@"%@ — %i MB", [VLCTime timeWithNumber:[mediaObject duration]], (int)([mediaObject fileSizeInBytes] / 1e6)];
-    else {
-        self.subtitleLabel.text = [NSString stringWithFormat:@"%@", [VLCTime timeWithNumber:[mediaObject duration]]];
-        if (mediaObject.videoTrack) {
-            NSString *width = [[mediaObject videoTrack] valueForKey:@"width"];
-            NSString *height = [[mediaObject videoTrack] valueForKey:@"height"];
-            if (width.intValue > 0 && height.intValue > 0)
-                self.subtitleLabel.text = [self.subtitleLabel.text stringByAppendingFormat:@" — %@x%@", width, height];
+    if ([self.mediaObject isKindOfClass:[MLFile class]]) {
+        MLFile *mediaObject = (MLFile*)self.mediaObject;
+
+        self.albumNameLabel.text = self.artistNameLabel.text = @"";
+
+        if (mediaObject.isAlbumTrack) {
+            self.artistNameLabel.text = mediaObject.albumTrack.artist;
+            self.albumNameLabel.text = mediaObject.albumTrack.album.name;
+            self.titleLabel.text = (mediaObject.albumTrack.title.length > 1) ? mediaObject.albumTrack.title : mediaObject.title;
+        } else
+            self.titleLabel.text = mediaObject.title;
+
+        if (self.isEditing)
+            self.subtitleLabel.text = [NSString stringWithFormat:@"%@ — %i MB", [VLCTime timeWithNumber:[mediaObject duration]], (int)([mediaObject fileSizeInBytes] / 1e6)];
+        else {
+            self.subtitleLabel.text = [NSString stringWithFormat:@"%@", [VLCTime timeWithNumber:[mediaObject duration]]];
+            if (mediaObject.videoTrack) {
+                NSString *width = [[mediaObject videoTrack] valueForKey:@"width"];
+                NSString *height = [[mediaObject videoTrack] valueForKey:@"height"];
+                if (width.intValue > 0 && height.intValue > 0)
+                    self.subtitleLabel.text = [self.subtitleLabel.text stringByAppendingFormat:@" — %@x%@", width, height];
+            }
         }
-    }
-    if ([keyPath isEqualToString:@"computedThumbnail"] || !keyPath) {
-        static NSMutableArray *_thumbnailCacheIndex;
-        static NSMutableDictionary *_thumbnailCache;
-        if (!_thumbnailCache)
-            _thumbnailCache = [[NSMutableDictionary alloc] initWithCapacity:MAX_CACHE_SIZE];
-        if (!_thumbnailCacheIndex)
-            _thumbnailCacheIndex = [[NSMutableArray alloc] initWithCapacity:MAX_CACHE_SIZE];
-
-        NSManagedObjectID *objID = mediaObject.objectID;
-        UIImage *displayedImage;
-        if ([_thumbnailCacheIndex containsObject:objID]) {
-            [_thumbnailCacheIndex removeObject:objID];
-            [_thumbnailCacheIndex insertObject:objID atIndex:0];
-            displayedImage = [_thumbnailCache objectForKey:objID];
-        } else {
-            if (_thumbnailCacheIndex.count >= MAX_CACHE_SIZE) {
-                [_thumbnailCache removeObjectForKey:[_thumbnailCacheIndex lastObject]];
-                [_thumbnailCacheIndex removeLastObject];
+        if ([keyPath isEqualToString:@"computedThumbnail"] || !keyPath) {
+            static NSMutableArray *_thumbnailCacheIndex;
+            static NSMutableDictionary *_thumbnailCache;
+            if (!_thumbnailCache)
+                _thumbnailCache = [[NSMutableDictionary alloc] initWithCapacity:MAX_CACHE_SIZE];
+            if (!_thumbnailCacheIndex)
+                _thumbnailCacheIndex = [[NSMutableArray alloc] initWithCapacity:MAX_CACHE_SIZE];
+
+            NSManagedObjectID *objID = mediaObject.objectID;
+            UIImage *displayedImage;
+            if ([_thumbnailCacheIndex containsObject:objID]) {
+                [_thumbnailCacheIndex removeObject:objID];
+                [_thumbnailCacheIndex insertObject:objID atIndex:0];
+                displayedImage = [_thumbnailCache objectForKey:objID];
+            } else {
+                if (_thumbnailCacheIndex.count >= MAX_CACHE_SIZE) {
+                    [_thumbnailCache removeObjectForKey:[_thumbnailCacheIndex lastObject]];
+                    [_thumbnailCacheIndex removeLastObject];
+                }
+                displayedImage = mediaObject.computedThumbnail;
+                if (displayedImage)
+                    [_thumbnailCache setObject:displayedImage forKey:objID];
+                [_thumbnailCacheIndex insertObject:objID atIndex:0];
             }
-            displayedImage = mediaObject.computedThumbnail;
-            if (displayedImage)
-                [_thumbnailCache setObject:displayedImage forKey:objID];
-            [_thumbnailCacheIndex insertObject:objID atIndex:0];
+            self.thumbnailView.image = displayedImage;
         }
-        self.thumbnailView.image = displayedImage;
+        CGFloat position = mediaObject.lastPosition.floatValue;
+        self.progressIndicator.progress = position;
+        self.progressIndicator.hidden = ((position < .1f) || (position > .95f)) ? YES : NO;
+        [self.progressIndicator setNeedsDisplay];
+        self.mediaIsUnreadView.hidden = !mediaObject.unread.intValue;
+    } else if ([self.mediaObject isKindOfClass:[MLAlbum class]]) {
+        MLAlbum *mediaObject = (MLAlbum *)self.mediaObject;
+        self.titleLabel.text = mediaObject.name;
+        MLAlbumTrack *anyTrack = [mediaObject.tracks anyObject];
+        if (anyTrack)
+            self.artistNameLabel.text = anyTrack.artist;
+        else
+            self.artistNameLabel.text = @"";
+        self.albumNameLabel.text = mediaObject.releaseYear;
+        self.thumbnailView.image = nil;
+        NSUInteger count = mediaObject.tracks.count;
+        self.subtitleLabel.text = [NSString stringWithFormat:(count > 1) ? @"%i Tracks" : @"%i Track", count];
+        self.mediaIsUnreadView.hidden = YES;
+        self.progressIndicator.hidden = YES;
+    } else if ([self.mediaObject isKindOfClass:[MLAlbumTrack class]]) {
+        MLAlbumTrack *mediaObject = (MLAlbumTrack *)self.mediaObject;
+        self.artistNameLabel.text = mediaObject.artist;
+        self.albumNameLabel.text = mediaObject.album.name;
+        self.titleLabel.text = mediaObject.title;
+        self.thumbnailView.image = nil;
+
+        MLFile *anyFileFromTrack = mediaObject.files.anyObject;
+        self.subtitleLabel.text = [NSString stringWithFormat:@"%@", [VLCTime timeWithNumber:[anyFileFromTrack duration]]];
+
+        CGFloat position = anyFileFromTrack.lastPosition.floatValue;
+        self.progressIndicator.progress = position;
+        self.progressIndicator.hidden = ((position < .1f) || (position > .95f)) ? YES : NO;
+        [self.progressIndicator setNeedsDisplay];
+        self.mediaIsUnreadView.hidden = !anyFileFromTrack.unread.intValue;
     }
-    CGFloat position = mediaObject.lastPosition.floatValue;
-    self.progressIndicator.progress = position;
-    self.progressIndicator.hidden = ((position < .1f) || (position > .95f)) ? YES : NO;
-    [self.progressIndicator setNeedsDisplay];
-    self.mediaIsUnreadView.hidden = !mediaObject.unread.intValue;
 
     [self setNeedsDisplay];
 }

+ 8 - 1
AspenProject/VLCPlaylistViewController.h

@@ -11,6 +11,12 @@
 #import <UIKit/UIKit.h>
 #import "AQGridView.h"
 
+#define EXPERIMENTAL_LIBRARY 1
+
+#define kVLCLibraryModeAllFiles 0
+#define kVLCLibraryModeAllAlbums 1
+#define kVLCLibraryModeAllSeries 2
+
 @class VLCMovieViewController;
 @class EmptyLibraryView;
 
@@ -25,13 +31,14 @@
 
 @property (nonatomic, strong) EmptyLibraryView *emptyLibraryView;
 
-
 - (IBAction)leftButtonAction:(id)sender;
 
 - (void)updateViewContents;
 - (void)openMovieFromURL:(NSURL *)url;
 - (void)removeMediaObject:(MLFile *)mediaObject;
 
+- (void)setLibraryMode:(NSUInteger)mode;
+
 @end
 
 @interface EmptyLibraryView: UIView

+ 47 - 12
AspenProject/VLCPlaylistViewController.m

@@ -21,9 +21,9 @@
 @implementation EmptyLibraryView
 @end
 
-@interface VLCPlaylistViewController () <AQGridViewDataSource, AQGridViewDelegate,
-                                         UITableViewDataSource, UITableViewDelegate> {
+@interface VLCPlaylistViewController () <AQGridViewDataSource, AQGridViewDelegate, UITableViewDataSource, UITableViewDelegate> {
     NSMutableArray *_foundMedia;
+    NSUInteger _libraryMode;
 }
 @end
 
@@ -44,6 +44,8 @@
         self.view = _gridView;
     }
 
+    _libraryMode = kVLCLibraryModeAllFiles;
+
     self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
     self.emptyLibraryView = [[[NSBundle mainBundle] loadNibNamed:@"VLCEmptyLibraryView" owner:self options:nil] lastObject];
 }
@@ -99,7 +101,7 @@
 
 - (void)viewDidAppear:(BOOL)animated
 {
-    [self performSelector:@selector(updateViewContents) withObject:nil afterDelay:.0];
+    [self performSelector:@selector(reloadContents) withObject:nil afterDelay:.0];
     [[MLMediaLibrary sharedMediaLibrary] performSelector:@selector(libraryDidAppear) withObject:nil afterDelay:1.];
 
     [super viewDidAppear:animated];
@@ -142,7 +144,7 @@
     }
     [fileManager removeItemAtPath:[[NSURL URLWithString:mediaObject.url] path] error:nil];
     [[MLMediaLibrary sharedMediaLibrary] updateMediaDatabase];
-    [self updateViewContents];
+    [self reloadContents];
 }
 
 - (void)_displayEmptyLibraryViewIfNeeded
@@ -164,10 +166,28 @@
     }
 }
 
-- (void)updateViewContents
+- (void)reloadContents
 {
-    _foundMedia = [NSMutableArray arrayWithArray:[MLFile allFiles]];
+    if (_libraryMode == kVLCLibraryModeAllAlbums) {
+        NSArray *rawAlbums = [MLAlbum allAlbums];
+        _foundMedia = [[NSMutableArray alloc] init];
+        NSUInteger count = rawAlbums.count;
+        MLAlbum *album;
+
+        for (NSUInteger x = 0; x < count; x++) {
+            album = rawAlbums[x];
+            if (album.name.length > 0 && album.tracks.count > 0)
+                [_foundMedia addObject:album];
+        }
+        rawAlbums = nil;
+    } else
+        _foundMedia = [NSMutableArray arrayWithArray:[MLFile allFiles]];
+
+    [self updateViewContents];
+}
 
+- (void)updateViewContents
+{
     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
         [self.tableView reloadData];
     else {
@@ -178,7 +198,6 @@
     [self _displayEmptyLibraryViewIfNeeded];
 }
 
-
 #pragma mark - Table View
 
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
@@ -224,12 +243,22 @@
 
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
-    MLFile *mediaObject = _foundMedia[indexPath.row];
-    if (!self.movieViewController)
-        self.movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];
+    NSManagedObject *currentObject = _foundMedia[indexPath.row];
+    if ([currentObject isKindOfClass:[MLAlbum class]]) {
+        _foundMedia = [NSMutableArray arrayWithArray:[[(MLAlbum *)currentObject tracks] allObjects]];
+        NSLog(@"current item is an album with %i kids", _foundMedia.count);
+        [self updateViewContents];
+    } else {
+        if (!self.movieViewController)
+            self.movieViewController = [[VLCMovieViewController alloc] initWithNibName:nil bundle:nil];
 
-    self.movieViewController.mediaItem = mediaObject;
-    [self.navigationController pushViewController:self.movieViewController animated:YES];
+        if ([currentObject isKindOfClass:[MLFile class]])
+            self.movieViewController.mediaItem = (MLFile *)currentObject;
+        else
+            self.movieViewController.mediaItem = [(MLAlbumTrack*)currentObject files].anyObject;
+
+        [self.navigationController pushViewController:self.movieViewController animated:YES];
+    }
 }
 
 #pragma mark - AQGridView
@@ -340,4 +369,10 @@
     self.movieViewController.url = url;
 }
 
+- (void)setLibraryMode:(NSUInteger)mode
+{
+    _libraryMode = mode;
+    [self reloadContents];
+}
+
 @end