vlc | branch: master | Felix Paul Kühne <[email protected]> | 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; +@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 +@class VLCLibraryModel; + @interface VLCLibraryDataSource : NSObject <NSCollectionViewDataSource, NSCollectionViewDelegate> +@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 +@class VLCMediaLibraryMediaItem; + +extern NSString *VLCLibraryModelVideoMediaListUpdated; + @interface VLCLibraryModel : NSObject - (instancetype)initWithLibrary:(vlc_medialibrary_t *)library; +@property (readonly) size_t numberOfVideoMedia; +@property (readonly) NSArray <VLCMediaLibraryMediaItem *> *listOfVideoMedia; + +- (nullable VLCMediaLibraryMediaItem *)mediaItemAtIndexPath:(NSIndexPath *)index; + +@end + +@interface VLCMediaLibraryFile : NSObject + +- (instancetype)initWithFile:(struct vlc_ml_file_t *)file; + +@property (readonly) NSString *MRL; +@property (readonly) vlc_ml_file_type_t fileType; +@property (readonly) BOOL external; +@property (readonly) BOOL removable; +@property (readonly) BOOL present; + +@end + +@interface VLCMediaLibraryTrack : NSObject + +- (instancetype)initWithTrack:(struct vlc_ml_media_track_t *)track; + +@property (readonly) NSString *codec; +@property (readonly) NSString *language; +@property (readonly) NSString *trackDescription; +@property (readonly) vlc_ml_track_type_t trackType; +@property (readonly) uint32_t bitrate; + +@property (readonly) uint32_t numberOfAudioChannels; +@property (readonly) uint32_t audioSampleRate; + +@property (readonly) uint32_t videoHeight; +@property (readonly) uint32_t videoWidth; +@property (readonly) uint32_t sourceAspectRatio; +@property (readonly) uint32_t sourceAspectRatioDenominator; +@property (readonly) uint32_t frameRate; +@property (readonly) uint32_t frameRateDenominator; + +@end + +@interface VLCMediaLibraryMediaItem : NSObject + +- (instancetype)initWithMediaItem:(struct vlc_ml_media_t *)mediaItem; + +@property (readonly) int64_t libraryID; +@property (readonly) vlc_ml_media_type_t mediaType; +@property (readonly) vlc_ml_media_subtype_t mediaSubType; + +@property (readonly) NSArray <VLCMediaLibraryFile *> *files; +@property (readonly) NSArray <VLCMediaLibraryTrack *> *tracks; + +@property (readonly) int32_t year; +@property (readonly) int64_t duration; /* Duration in milliseconds */ +@property (readonly) uint32_t playCount; +@property (readonly) time_t lastPlayedDate; +@property (readonly) NSString *title; + +@property (readonly) NSString *artworkMRL; + +@property (readonly) BOOL artworkGenerated; +@property (readonly) BOOL favorited; + +@property (readonly) vlc_ml_show_episode_t showEpisode; +@property (readonly) vlc_ml_movie_t movie; +@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; +} + +@end + +@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]; +} + +@end + +@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]; +} + +@end + +@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 _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
