[vlc-commits] macosx/library: show list of videos known to the library
Felix Paul Kühne
git at videolan.org
Mon Apr 29 19:26:40 CEST 2019
vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Fri Apr 19 18:36:41 2019 +0200| [787defaa5ed5f5b1179edd40a41a2dd3d0e1f9fc] | committer: Felix Paul Kühne
macosx/library: show list of videos known to the library
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=787defaa5ed5f5b1179edd40a41a2dd3d0e1f9fc
---
.../gui/macosx/UI/VLCLibraryCollectionViewItem.xib | 16 +-
.../macosx/library/VLCLibraryCollectionViewItem.h | 1 +
modules/gui/macosx/library/VLCLibraryController.m | 2 +-
modules/gui/macosx/library/VLCLibraryDataSource.h | 4 +
modules/gui/macosx/library/VLCLibraryDataSource.m | 21 ++-
modules/gui/macosx/library/VLCLibraryModel.h | 71 ++++++++
modules/gui/macosx/library/VLCLibraryModel.m | 178 +++++++++++++++++++++
modules/gui/macosx/library/VLCLibraryWindow.m | 17 +-
8 files changed, 303 insertions(+), 7 deletions(-)
diff --git a/modules/gui/macosx/UI/VLCLibraryCollectionViewItem.xib b/modules/gui/macosx/UI/VLCLibraryCollectionViewItem.xib
index d87148cb57..44805042a4 100644
--- a/modules/gui/macosx/UI/VLCLibraryCollectionViewItem.xib
+++ b/modules/gui/macosx/UI/VLCLibraryCollectionViewItem.xib
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="VLCLibraryCollectionViewItem">
<connections>
+ <outlet property="durationTextField" destination="VAn-gF-QiZ" id="U8T-Cs-HaL"/>
<outlet property="mediaImageView" destination="vP5-5j-rVa" id="YJb-5w-9sW"/>
<outlet property="mediaTitleTextField" destination="OBS-Eh-1mT" id="h1n-PU-IAx"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
@@ -35,12 +36,23 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
+ <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VAn-gF-QiZ">
+ <rect key="frame" x="420" y="20" width="42" height="19"/>
+ <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="LSS-jh-llZ">
+ <font key="font" size="15" name=".AppleSystemUIFont"/>
+ <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
</subviews>
<constraints>
+ <constraint firstItem="VAn-gF-QiZ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="OBS-Eh-1mT" secondAttribute="trailing" constant="20" id="2di-oZ-tsC"/>
<constraint firstItem="A5y-ue-y7t" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="NpD-8l-D5s"/>
+ <constraint firstAttribute="trailing" secondItem="VAn-gF-QiZ" secondAttribute="trailing" constant="20" id="Ol6-wf-2dJ"/>
<constraint firstAttribute="bottom" secondItem="A5y-ue-y7t" secondAttribute="bottom" id="cnQ-bx-Fmn"/>
<constraint firstAttribute="bottom" secondItem="OBS-Eh-1mT" secondAttribute="bottom" constant="20" id="dy4-gP-Sdi"/>
<constraint firstAttribute="trailing" secondItem="A5y-ue-y7t" secondAttribute="trailing" id="rKQ-WW-oC6"/>
+ <constraint firstItem="VAn-gF-QiZ" firstAttribute="bottom" secondItem="OBS-Eh-1mT" secondAttribute="bottom" id="ukj-ba-ask"/>
<constraint firstItem="A5y-ue-y7t" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="x7v-58-kKz"/>
<constraint firstItem="OBS-Eh-1mT" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" id="yvp-xr-geN"/>
</constraints>
diff --git a/modules/gui/macosx/library/VLCLibraryCollectionViewItem.h b/modules/gui/macosx/library/VLCLibraryCollectionViewItem.h
index 337acf1fee..8b413bcc3d 100644
--- a/modules/gui/macosx/library/VLCLibraryCollectionViewItem.h
+++ b/modules/gui/macosx/library/VLCLibraryCollectionViewItem.h
@@ -29,6 +29,7 @@ extern NSString *VLCLibraryCellIdentifier;
@interface VLCLibraryCollectionViewItem : NSCollectionViewItem
@property (readwrite, assign) IBOutlet NSTextField *mediaTitleTextField;
+ at property (readwrite, assign) IBOutlet NSTextField *durationTextField;
@property (readwrite, assign) IBOutlet NSImageView *mediaImageView;
@end
diff --git a/modules/gui/macosx/library/VLCLibraryController.m b/modules/gui/macosx/library/VLCLibraryController.m
index cb75184549..837ef837f7 100644
--- a/modules/gui/macosx/library/VLCLibraryController.m
+++ b/modules/gui/macosx/library/VLCLibraryController.m
@@ -41,7 +41,7 @@
self = [super init];
if (self) {
_p_libraryInstance = vlc_ml_instance_get(getIntf());
- _libraryModel = [[VLCLibraryModel alloc] init];
+ _libraryModel = [[VLCLibraryModel alloc] initWithLibrary:_p_libraryInstance];
NSNotificationCenter *defaultNotificationCenter = [NSNotificationCenter defaultCenter];
[defaultNotificationCenter addObserver:self
diff --git a/modules/gui/macosx/library/VLCLibraryDataSource.h b/modules/gui/macosx/library/VLCLibraryDataSource.h
index 94ef80572e..abb4daed9e 100644
--- a/modules/gui/macosx/library/VLCLibraryDataSource.h
+++ b/modules/gui/macosx/library/VLCLibraryDataSource.h
@@ -24,8 +24,12 @@
NS_ASSUME_NONNULL_BEGIN
+ at class VLCLibraryModel;
+
@interface VLCLibraryDataSource : NSObject <NSCollectionViewDataSource, NSCollectionViewDelegate>
+ at property (readwrite, assign) VLCLibraryModel *libraryModel;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/modules/gui/macosx/library/VLCLibraryDataSource.m b/modules/gui/macosx/library/VLCLibraryDataSource.m
index 19c7604f06..0a2f9a1893 100644
--- a/modules/gui/macosx/library/VLCLibraryDataSource.m
+++ b/modules/gui/macosx/library/VLCLibraryDataSource.m
@@ -23,20 +23,35 @@
#import "VLCLibraryDataSource.h"
#import "library/VLCLibraryCollectionViewItem.h"
+#import "library/VLCLibraryModel.h"
+
+#import "extensions/NSString+Helpers.h"
@implementation VLCLibraryDataSource
- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
- return 2;
+ return [_libraryModel numberOfVideoMedia];
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath
{
VLCLibraryCollectionViewItem *viewItem = [collectionView makeItemWithIdentifier:VLCLibraryCellIdentifier forIndexPath:indexPath];
- viewItem.mediaTitleTextField.stringValue = @"Custom Cell Label Text";
- viewItem.mediaImageView.image = [NSImage imageNamed: @"noart.png"];
+ NSArray *videoMedia = [_libraryModel listOfVideoMedia];
+ VLCMediaLibraryMediaItem *mediaItem = videoMedia[indexPath.item];
+
+ viewItem.mediaTitleTextField.stringValue = mediaItem.title;
+ viewItem.durationTextField.stringValue = [NSString stringWithTime:mediaItem.duration];
+
+ NSImage *image;
+ if (mediaItem.artworkGenerated) {
+ image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:mediaItem.artworkMRL]];
+ }
+ if (!image) {
+ image = [NSImage imageNamed: @"noart.png"];
+ }
+ viewItem.mediaImageView.image = image;
return viewItem;
}
diff --git a/modules/gui/macosx/library/VLCLibraryModel.h b/modules/gui/macosx/library/VLCLibraryModel.h
index abbf186089..3c362e2872 100644
--- a/modules/gui/macosx/library/VLCLibraryModel.h
+++ b/modules/gui/macosx/library/VLCLibraryModel.h
@@ -26,10 +26,81 @@
NS_ASSUME_NONNULL_BEGIN
+ at class VLCMediaLibraryMediaItem;
+
+extern NSString *VLCLibraryModelVideoMediaListUpdated;
+
@interface VLCLibraryModel : NSObject
- (instancetype)initWithLibrary:(vlc_medialibrary_t *)library;
+ at property (readonly) size_t numberOfVideoMedia;
+ at property (readonly) NSArray <VLCMediaLibraryMediaItem *> *listOfVideoMedia;
+
+- (nullable VLCMediaLibraryMediaItem *)mediaItemAtIndexPath:(NSIndexPath *)index;
+
+ at end
+
+ at interface VLCMediaLibraryFile : NSObject
+
+- (instancetype)initWithFile:(struct vlc_ml_file_t *)file;
+
+ at property (readonly) NSString *MRL;
+ at property (readonly) vlc_ml_file_type_t fileType;
+ at property (readonly) BOOL external;
+ at property (readonly) BOOL removable;
+ at property (readonly) BOOL present;
+
+ at end
+
+ at interface VLCMediaLibraryTrack : NSObject
+
+- (instancetype)initWithTrack:(struct vlc_ml_media_track_t *)track;
+
+ at property (readonly) NSString *codec;
+ at property (readonly) NSString *language;
+ at property (readonly) NSString *trackDescription;
+ at property (readonly) vlc_ml_track_type_t trackType;
+ at property (readonly) uint32_t bitrate;
+
+ at property (readonly) uint32_t numberOfAudioChannels;
+ at property (readonly) uint32_t audioSampleRate;
+
+ at property (readonly) uint32_t videoHeight;
+ at property (readonly) uint32_t videoWidth;
+ at property (readonly) uint32_t sourceAspectRatio;
+ at property (readonly) uint32_t sourceAspectRatioDenominator;
+ at property (readonly) uint32_t frameRate;
+ at property (readonly) uint32_t frameRateDenominator;
+
+ at end
+
+ at interface VLCMediaLibraryMediaItem : NSObject
+
+- (instancetype)initWithMediaItem:(struct vlc_ml_media_t *)mediaItem;
+
+ at property (readonly) int64_t libraryID;
+ at property (readonly) vlc_ml_media_type_t mediaType;
+ at property (readonly) vlc_ml_media_subtype_t mediaSubType;
+
+ at property (readonly) NSArray <VLCMediaLibraryFile *> *files;
+ at property (readonly) NSArray <VLCMediaLibraryTrack *> *tracks;
+
+ at property (readonly) int32_t year;
+ at property (readonly) int64_t duration; /* Duration in milliseconds */
+ at property (readonly) uint32_t playCount;
+ at property (readonly) time_t lastPlayedDate;
+ at property (readonly) NSString *title;
+
+ at property (readonly) NSString *artworkMRL;
+
+ at property (readonly) BOOL artworkGenerated;
+ at property (readonly) BOOL favorited;
+
+ at property (readonly) vlc_ml_show_episode_t showEpisode;
+ at property (readonly) vlc_ml_movie_t movie;
+ at property (readonly) vlc_ml_album_track_t albumTrack;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/modules/gui/macosx/library/VLCLibraryModel.m b/modules/gui/macosx/library/VLCLibraryModel.m
index a4544b1598..cea1843b3e 100644
--- a/modules/gui/macosx/library/VLCLibraryModel.m
+++ b/modules/gui/macosx/library/VLCLibraryModel.m
@@ -21,13 +21,40 @@
*****************************************************************************/
#import "VLCLibraryModel.h"
+#import "extensions/NSString+Helpers.h"
+
+NSString *VLCLibraryModelVideoMediaListUpdated = @"VLCLibraryModelVideoMediaListUpdated";
@interface VLCLibraryModel ()
{
vlc_medialibrary_t *_p_mediaLibrary;
+ vlc_ml_event_callback_t *_p_eventCallback;
+
+ NSArray *_cachedVideoMedia;
+ NSNotificationCenter *_defaultNotificationCenter;
}
+
+- (void)updateCachedListOfVideoMedia;
+
@end
+static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
+{
+ switch(p_event->i_type)
+ {
+ case VLC_ML_EVENT_MEDIA_ADDED:
+ case VLC_ML_EVENT_MEDIA_UPDATED:
+ case VLC_ML_EVENT_MEDIA_DELETED:
+ dispatch_async(dispatch_get_main_queue(), ^{
+ VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
+ [libraryModel updateCachedListOfVideoMedia];
+ });
+ break;
+ default:
+ break;
+ }
+}
+
@implementation VLCLibraryModel
- (instancetype)initWithLibrary:(vlc_medialibrary_t *)library
@@ -35,8 +62,159 @@
self = [super init];
if (self) {
_p_mediaLibrary = library;
+ _p_eventCallback = vlc_ml_event_register_callback(_p_mediaLibrary, libraryCallback, (__bridge void *)self);
+ _defaultNotificationCenter = [[NSNotificationCenter alloc] init];
}
return self;
}
+- (void)dealloc
+{
+ if (_p_eventCallback) {
+ vlc_ml_event_unregister_callback(_p_mediaLibrary, _p_eventCallback);
+ }
+}
+
+- (size_t)numberOfVideoMedia
+{
+ if (!_cachedVideoMedia) {
+ [self updateCachedListOfVideoMedia];
+ }
+
+ return _cachedVideoMedia.count;
+}
+
+- (void)updateCachedListOfVideoMedia
+{
+ vlc_ml_media_list_t *p_media_list = vlc_ml_list_video_media(_p_mediaLibrary, NULL);
+ NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:p_media_list->i_nb_items];
+ for (size_t x = 0; x < p_media_list->i_nb_items; x++) {
+ VLCMediaLibraryMediaItem *mediaItem = [[VLCMediaLibraryMediaItem alloc] initWithMediaItem:&p_media_list->p_items[x]];
+ [mutableArray addObject:mediaItem];
+ }
+ _cachedVideoMedia = [mutableArray copy];
+ vlc_ml_media_list_release(p_media_list);
+ [_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListUpdated object:self];
+}
+
+- (nullable VLCMediaLibraryMediaItem *)mediaItemAtIndexPath:(NSIndexPath *)indexPath
+{
+ // FIXME: the scope needs be larger than just the video list
+ if (!_cachedVideoMedia) {
+ return nil;
+ }
+ return _cachedVideoMedia[indexPath.item];
+}
+
+- (NSArray<VLCMediaLibraryMediaItem *> *)listOfVideoMedia
+{
+ if (!_cachedVideoMedia) {
+ [self updateCachedListOfVideoMedia];
+ }
+
+ return _cachedVideoMedia;
+}
+
+ at end
+
+ at implementation VLCMediaLibraryFile
+
+- (instancetype)initWithFile:(struct vlc_ml_file_t *)file
+{
+ self = [super init];
+ if (self && file != NULL) {
+ _MRL = toNSStr(file->psz_mrl);
+ _fileType = file->i_type;
+ _external = file->b_external;
+ _removable = file->b_removable;
+ _present = file->b_present;
+ }
+ return self;
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"%@ — type: %i, MRL: %@", NSStringFromClass([self class]), _fileType, _MRL];
+}
+
+ at end
+
+ at implementation VLCMediaLibraryTrack
+
+- (instancetype)initWithTrack:(struct vlc_ml_media_track_t *)track
+{
+ self = [super init];
+ if (self && track != NULL) {
+ _codec = toNSStr(track->psz_codec);
+ _language = toNSStr(track->psz_language);
+ _trackDescription = toNSStr(track->psz_description);
+ _trackType = track->i_type;
+ _bitrate = track->i_bitrate;
+
+ _numberOfAudioChannels = track->a.i_nbChannels;
+ _audioSampleRate = track->a.i_sampleRate;
+
+ _videoHeight = track->v.i_height;
+ _videoWidth = track->v.i_width;
+ _sourceAspectRatio = track->v.i_sarNum;
+ _sourceAspectRatioDenominator = track->v.i_sarDen;
+ _frameRate = track->v.i_fpsNum;
+ _frameRateDenominator = track->v.i_fpsDen;
+ }
+ return self;
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"%@ — type: %i, codec %@", NSStringFromClass([self class]), _trackType, _codec];
+}
+
+ at end
+
+ at implementation VLCMediaLibraryMediaItem
+
+- (instancetype)initWithMediaItem:(struct vlc_ml_media_t *)p_mediaItem
+{
+ self = [super init];
+ if (self) {
+ _libraryID = p_mediaItem->i_id;
+ _mediaType = p_mediaItem->i_type;
+ _mediaSubType = p_mediaItem->i_subtype;
+ NSMutableArray *mutArray = [[NSMutableArray alloc] initWithCapacity:p_mediaItem->p_files->i_nb_items];
+ for (size_t x = 0; x < p_mediaItem->p_files->i_nb_items; x++) {
+ VLCMediaLibraryFile *file = [[VLCMediaLibraryFile alloc] initWithFile:&p_mediaItem->p_files->p_items[x]];
+ if (file) {
+ [mutArray addObject:file];
+ }
+ }
+ _files = [mutArray copy];
+ mutArray = [[NSMutableArray alloc] initWithCapacity:p_mediaItem->p_tracks->i_nb_items];
+ for (size_t x = 0; x < p_mediaItem->p_tracks->i_nb_items; x++) {
+ VLCMediaLibraryTrack *track = [[VLCMediaLibraryTrack alloc] initWithTrack:&p_mediaItem->p_tracks->p_items[x]];
+ if (track) {
+ [mutArray addObject:track];
+ }
+ }
+ _tracks = [mutArray copy];
+ _year = p_mediaItem->i_year;
+ _duration = p_mediaItem->i_duration;
+ _playCount = p_mediaItem->i_playcount;
+ _lastPlayedDate = p_mediaItem->i_last_played_date;
+ _title = toNSStr(p_mediaItem->psz_title);
+ _artworkMRL = toNSStr(p_mediaItem->psz_artwork_mrl);
+ _artworkGenerated = p_mediaItem->b_artwork_generated;
+ _favorited = p_mediaItem->b_is_favorite;
+ _showEpisode = p_mediaItem->show_episode;
+ _movie = p_mediaItem->movie;
+ _albumTrack = p_mediaItem->album_track;
+ }
+ return self;
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"%@ — title: %@, ID: %lli, type: %i, artwork: %@",
+ NSStringFromClass([self class]), _title, _libraryID, _mediaType, _artworkMRL];
+}
+
@end
diff --git a/modules/gui/macosx/library/VLCLibraryWindow.m b/modules/gui/macosx/library/VLCLibraryWindow.m
index c0067170a6..d650ca07a2 100644
--- a/modules/gui/macosx/library/VLCLibraryWindow.m
+++ b/modules/gui/macosx/library/VLCLibraryWindow.m
@@ -28,8 +28,10 @@
#import "playlist/VLCPlaylistController.h"
#import "playlist/VLCPlaylistDataSource.h"
+#import "library/VLCLibraryController.h"
#import "library/VLCLibraryDataSource.h"
#import "library/VLCLibraryCollectionViewItem.h"
+#import "library/VLCLibraryModel.h"
#import "windows/mainwindow/VLCControlsBarCommon.h"
#import "windows/video/VLCFSPanelController.h"
@@ -59,6 +61,10 @@ static const float f_playlist_row_height = 72.;
selector:@selector(shouldShowFullscreenController:)
name:VLCVideoWindowShouldShowFullscreenController
object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(updateLibraryRepresentation:)
+ name:VLCLibraryModelVideoMediaListUpdated
+ object:nil];
_fspanel = [[VLCFSPanelController alloc] init];
[_fspanel showWindow:self];
@@ -71,7 +77,9 @@ static const float f_playlist_row_height = 72.;
[_segmentedTitleControl setLabel:_NS("Network") forSegment:2];
[_segmentedTitleControl sizeToFit];
- VLCPlaylistController *playlistController = [[VLCMain sharedInstance] playlistController];
+ VLCMain *mainInstance = [VLCMain sharedInstance];
+
+ VLCPlaylistController *playlistController = [mainInstance playlistController];
_playlistDataSource = [[VLCPlaylistDataSource alloc] init];
_playlistDataSource.playlistController = playlistController;
_playlistDataSource.tableView = _playlistTableView;
@@ -83,6 +91,7 @@ static const float f_playlist_row_height = 72.;
[_playlistTableView reloadData];
_libraryDataSource = [[VLCLibraryDataSource alloc] init];
+ _libraryDataSource.libraryModel = mainInstance.libraryController.libraryModel;
_libraryCollectionView.dataSource = _libraryDataSource;
_libraryCollectionView.delegate = _libraryDataSource;
[_libraryCollectionView registerClass:[VLCLibraryCollectionViewItem class] forItemWithIdentifier:VLCLibraryCellIdentifier];
@@ -158,6 +167,12 @@ static const float f_playlist_row_height = 72.;
}
}
+#pragma mark - library representation and interaction
+- (void)updateLibraryRepresentation:(NSNotification *)aNotification
+{
+ [_libraryCollectionView reloadData];
+}
+
#pragma mark -
#pragma mark Fullscreen support
More information about the vlc-commits
mailing list