You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

609 lines
28 KiB

/*****************************************************************************
* VLCLibraryAudioViewController.m: MacOS X interface module
*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* Authors: Claudio Cambra <claudio.cambra@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import "VLCLibraryAudioViewController.h"
#import "extensions/NSString+Helpers.h"
#import "extensions/NSWindow+VLCAdditions.h"
#import "library/VLCLibraryCollectionView.h"
#import "library/VLCLibraryCollectionViewDelegate.h"
#import "library/VLCLibraryCollectionViewFlowLayout.h"
#import "library/VLCLibraryController.h"
#import "library/VLCLibraryDataTypes.h"
#import "library/VLCLibraryModel.h"
#import "library/VLCLibrarySegment.h"
#import "library/VLCLibraryWindowNavigationSidebarViewController.h"
#import "library/VLCLibraryWindowSplitViewController.h"
#import "library/VLCLibraryTwoPaneSplitViewDelegate.h"
#import "library/VLCLibraryWindow.h"
#import "library/VLCLibraryWindowPersistentPreferences.h"
#import "library/audio-library/VLCLibraryAlbumTableCellView.h"
#import "library/audio-library/VLCLibraryAudioDataSource.h"
#import "library/audio-library/VLCLibraryAudioGroupDataSource.h"
#import "library/audio-library/VLCLibraryAudioGroupTableHeaderView.h"
#import "library/audio-library/VLCLibraryAudioGroupTableViewDelegate.h"
#import "library/audio-library/VLCLibraryAudioGroupTableHeaderCell.h"
#import "library/audio-library/VLCLibraryAudioTableViewDelegate.h"
#import "library/playlist-library/VLCLibraryPlaylistViewController.h"
#import "library/video-library/VLCLibraryVideoViewController.h"
#import "main/VLCMain.h"
#import "windows/video/VLCVoutView.h"
#import "windows/video/VLCMainVideoViewController.h"
NSString *VLCLibraryPlaceholderAudioViewIdentifier = @"VLCLibraryPlaceholderAudioViewIdentifier";
@interface VLCLibraryAudioViewController()
{
id<VLCMediaLibraryItemProtocol> _awaitingPresentingLibraryItem;
NSArray<NSLayoutConstraint *> *_internalPlaceholderImageViewSizeConstraints;
NSArray<NSString *> *_placeholderImageNames;
NSArray<NSString *> *_placeholderLabelStrings;
VLCLibraryCollectionViewDelegate *_audioLibraryCollectionViewDelegate;
VLCLibraryAudioTableViewDelegate *_audioLibraryTableViewDelegate;
VLCLibraryAudioGroupTableViewDelegate *_audioGroupLibraryTableViewDelegate;
VLCLibraryTwoPaneSplitViewDelegate *_splitViewDelegate;
}
@end
@implementation VLCLibraryAudioViewController
#pragma mark - Set up the view controller
- (instancetype)initWithLibraryWindow:(VLCLibraryWindow *)libraryWindow
{
self = [super initWithLibraryWindow:libraryWindow];
if (self) {
[self setupPropertiesFromLibraryWindow:libraryWindow];
[self setupAudioDataSource];
_audioLibraryCollectionViewDelegate = [[VLCLibraryCollectionViewDelegate alloc] init];
_audioLibraryTableViewDelegate = [[VLCLibraryAudioTableViewDelegate alloc] init];
_audioGroupLibraryTableViewDelegate = [[VLCLibraryAudioGroupTableViewDelegate alloc] init];
_splitViewDelegate = [[VLCLibraryTwoPaneSplitViewDelegate alloc] init];
[self setupAudioPlaceholderView];
[self setupAudioCollectionView];
[self setupGridModeSplitView];
[self setupAudioTableViews];
[self setupAudioLibraryViews];
NSNotificationCenter *notificationCenter = NSNotificationCenter.defaultCenter;
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelAudioMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelAudioMediaItemDeleted
object:nil];
NSString * const audioMediaResetLongLoadStartNotification = [VLCLibraryModelAudioMediaListReset stringByAppendingString:VLCLongNotificationNameStartSuffix];
NSString * const audioMediaResetLongLoadFinishNotification = [VLCLibraryModelAudioMediaListReset stringByAppendingString:VLCLongNotificationNameFinishSuffix];
NSString * const audioMediaDeletedLongLoadStartNotification = [VLCLibraryModelAudioMediaItemDeleted stringByAppendingString:VLCLongNotificationNameStartSuffix];
NSString * const audioMediaDeletedLongLoadFinishNotification = [VLCLibraryModelAudioMediaItemDeleted stringByAppendingString:VLCLongNotificationNameFinishSuffix];
[notificationCenter addObserver:self
selector:@selector(libraryModelLongLoadStarted:)
name:audioMediaResetLongLoadStartNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelLongLoadFinished:)
name:audioMediaResetLongLoadFinishNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelLongLoadStarted:)
name:audioMediaDeletedLongLoadStartNotification
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelLongLoadFinished:)
name:audioMediaDeletedLongLoadFinishNotification
object:nil];
}
return self;
}
- (void)setupPropertiesFromLibraryWindow:(VLCLibraryWindow*)libraryWindow
{
NSParameterAssert(libraryWindow);
_audioLibraryView = libraryWindow.audioLibraryView;
_audioLibrarySplitView = libraryWindow.audioLibrarySplitView;
_audioCollectionSelectionTableViewScrollView = libraryWindow.audioCollectionSelectionTableViewScrollView;
_audioCollectionSelectionTableView = libraryWindow.audioCollectionSelectionTableView;
_audioGroupSelectionTableViewScrollView = libraryWindow.audioGroupSelectionTableViewScrollView;
_audioGroupSelectionTableView = libraryWindow.audioGroupSelectionTableView;
_audioSongTableViewScrollView = libraryWindow.audioLibrarySongsTableViewScrollView;
_audioSongTableView = libraryWindow.audioLibrarySongsTableView;
_audioCollectionViewScrollView = libraryWindow.audioCollectionViewScrollView;
_audioLibraryCollectionView = libraryWindow.audioLibraryCollectionView;
_audioLibraryGridModeSplitView = libraryWindow.audioLibraryGridModeSplitView;
_audioLibraryGridModeSplitViewListTableViewScrollView = libraryWindow.audioLibraryGridModeSplitViewListTableViewScrollView;
_audioLibraryGridModeSplitViewListTableView = libraryWindow.audioLibraryGridModeSplitViewListTableView;
_audioLibraryGridModeSplitViewListSelectionCollectionViewScrollView = libraryWindow.audioLibraryGridModeSplitViewListSelectionCollectionViewScrollView;
_audioLibraryGridModeSplitViewListSelectionCollectionView = libraryWindow.audioLibraryGridModeSplitViewListSelectionCollectionView;
}
- (void)setupAudioDataSource
{
_audioDataSource = [[VLCLibraryAudioDataSource alloc] init];
_audioDataSource.libraryModel = VLCMain.sharedInstance.libraryController.libraryModel;
_audioDataSource.collectionSelectionTableView = _audioCollectionSelectionTableView;
_audioDataSource.songsTableView = _audioSongTableView;
_audioDataSource.collectionView = _audioLibraryCollectionView;
_audioDataSource.gridModeListTableView = _audioLibraryGridModeSplitViewListTableView;
_audioDataSource.headerDelegate = self;
[_audioDataSource setup];
_audioGroupDataSource = [[VLCLibraryAudioGroupDataSource alloc] init];
_audioGroupDataSource.tableViews = @[_audioGroupSelectionTableView];
_audioGroupDataSource.collectionViews = @[_audioLibraryGridModeSplitViewListSelectionCollectionView];
_audioDataSource.audioGroupDataSource = _audioGroupDataSource;
}
- (void)setupAudioCollectionView
{
_audioLibraryCollectionView.dataSource = _audioDataSource;
_audioLibraryCollectionView.delegate = _audioLibraryCollectionViewDelegate;
_audioLibraryCollectionView.selectable = YES;
_audioLibraryCollectionView.allowsMultipleSelection = NO;
_audioLibraryCollectionView.allowsEmptySelection = YES;
_audioLibraryCollectionView.collectionViewLayout = VLCLibraryCollectionViewFlowLayout.standardLayout;
}
- (void)setupAudioTableViews
{
_audioLibrarySplitView.delegate = _splitViewDelegate;
_audioCollectionSelectionTableView.dataSource = _audioDataSource;
_audioCollectionSelectionTableView.delegate = _audioLibraryTableViewDelegate;
CGFloat headerHeight = VLCLibraryAudioGroupTableHeaderViewHeight;
if (@available(macOS 26.0, *)) {
headerHeight += VLCLibraryUIUnits.largeSpacing * 2;
}
const NSRect headerFrame = NSMakeRect(0.f,
0.f,
_audioGroupSelectionTableView.bounds.size.width,
headerHeight);
_audioCollectionHeaderView = [[VLCLibraryAudioGroupTableHeaderView alloc] initWithFrame:headerFrame withInternalPaddingAddedForContentView:YES];
_audioCollectionHeaderView.autoresizingMask = NSViewWidthSizable;
_audioGroupSelectionTableView.headerView = self.audioCollectionHeaderView;
_audioGroupSelectionTableView.tableColumns.firstObject.headerCell = [VLCLibraryAudioGroupTableHeaderCell new];
_audioGroupSelectionTableView.dataSource = _audioGroupDataSource;
_audioGroupSelectionTableView.delegate = _audioGroupLibraryTableViewDelegate;
if(@available(macOS 11.0, *)) {
_audioGroupSelectionTableView.style = NSTableViewStyleFullWidth;
}
_audioSongTableView.dataSource = _audioDataSource;
_audioSongTableView.delegate = _audioLibraryTableViewDelegate;
[_audioDataSource applySelectionForTableView:_audioCollectionSelectionTableView];
}
- (void)setupGridModeSplitView
{
_audioLibraryGridModeSplitView.delegate = _splitViewDelegate;
_audioLibraryGridModeSplitViewListTableView.dataSource = _audioDataSource;
_audioLibraryGridModeSplitViewListTableView.delegate = _audioLibraryTableViewDelegate;
_audioLibraryGridModeSplitViewListSelectionCollectionView.dataSource = _audioGroupDataSource;
_audioLibraryGridModeSplitViewListSelectionCollectionView.delegate = _audioLibraryCollectionViewDelegate;
_audioLibraryGridModeSplitViewListSelectionCollectionView.selectable = YES;
_audioLibraryGridModeSplitViewListSelectionCollectionView.allowsMultipleSelection = NO;
_audioLibraryGridModeSplitViewListSelectionCollectionView.allowsEmptySelection = YES;
VLCLibraryCollectionViewFlowLayout * const audioLibraryGridModeListSelectionCollectionViewLayout =
VLCLibraryCollectionViewFlowLayout.standardLayout;
_audioLibraryGridModeSplitViewListSelectionCollectionView.collectionViewLayout = audioLibraryGridModeListSelectionCollectionViewLayout;
audioLibraryGridModeListSelectionCollectionViewLayout.headerReferenceSize =
NSMakeSize(self.audioCollectionViewScrollView.documentView.frame.size.width, VLCLibraryAudioGroupTableHeaderViewHeight);
if (@available(macOS 10.12, *)) {
audioLibraryGridModeListSelectionCollectionViewLayout.sectionHeadersPinToVisibleBounds = YES;
}
[VLCLibraryAudioDataSource setupCollectionView:_audioLibraryGridModeSplitViewListSelectionCollectionView];
[VLCLibraryAudioGroupDataSource setupCollectionView:_audioLibraryGridModeSplitViewListSelectionCollectionView];
}
- (void)setupAudioPlaceholderView
{
_internalPlaceholderImageViewSizeConstraints = @[
[NSLayoutConstraint constraintWithItem:self.placeholderImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.f
constant:149.f],
[NSLayoutConstraint constraintWithItem:self.placeholderImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.f
constant:149.f],
];
_placeholderImageNames = @[@"placeholder-group2", @"placeholder-music", @"placeholder-music", @"placeholder-music"];
_placeholderLabelStrings = @[
_NS("Your music artists will appear here.\nGo to the Browse section to add artists you love."),
_NS("Your music albums will appear here.\nGo to the Browse section to add albums you love."),
_NS("Your music tracks will appear here.\nGo to the Browse section to add tracks you love."),
_NS("Your music genres will appear here.\nGo to the Browse section to add genres you love."),
];
}
- (void)setupAudioLibraryViews
{
_audioCollectionSelectionTableView.rowHeight = VLCLibraryUIUnits.mediumTableViewRowHeight;
_audioLibraryGridModeSplitViewListTableView.rowHeight = VLCLibraryUIUnits.mediumTableViewRowHeight;
_audioGroupSelectionTableView.rowHeight = VLCLibraryAlbumTableCellView.defaultHeight;
const NSEdgeInsets audioScrollViewContentInsets = VLCLibraryUIUnits.libraryViewScrollViewContentInsets;
const NSEdgeInsets audioScrollViewScrollerInsets = VLCLibraryUIUnits.libraryViewScrollViewScrollerInsets;
_audioCollectionViewScrollView.automaticallyAdjustsContentInsets = NO;
_audioCollectionViewScrollView.contentInsets = audioScrollViewContentInsets;
_audioCollectionViewScrollView.scrollerInsets = audioScrollViewScrollerInsets;
_audioCollectionSelectionTableViewScrollView.automaticallyAdjustsContentInsets = NO;
_audioCollectionSelectionTableViewScrollView.contentInsets = audioScrollViewContentInsets;
_audioCollectionSelectionTableViewScrollView.scrollerInsets = audioScrollViewScrollerInsets;
_audioGroupSelectionTableViewScrollView.automaticallyAdjustsContentInsets = NO;
NSEdgeInsets adjustedInsets = audioScrollViewContentInsets;
adjustedInsets.top -= VLCLibraryUIUnits.largeSpacing;
_audioGroupSelectionTableViewScrollView.contentInsets = adjustedInsets;
_audioGroupSelectionTableViewScrollView.scrollerInsets = audioScrollViewScrollerInsets;
_audioLibraryGridModeSplitViewListTableViewScrollView.automaticallyAdjustsContentInsets = NO;
_audioLibraryGridModeSplitViewListTableViewScrollView.contentInsets = audioScrollViewContentInsets;
_audioLibraryGridModeSplitViewListTableViewScrollView.scrollerInsets = audioScrollViewScrollerInsets;
_audioLibraryGridModeSplitViewListSelectionCollectionViewScrollView.automaticallyAdjustsContentInsets = NO;
_audioLibraryGridModeSplitViewListSelectionCollectionViewScrollView.contentInsets = audioScrollViewContentInsets;
_audioLibraryGridModeSplitViewListSelectionCollectionViewScrollView.scrollerInsets = audioScrollViewScrollerInsets;
// Songs table view needs bottom padding for controls bar
const CGFloat controlsBarHeight = VLCLibraryUIUnits.libraryWindowControlsBarHeight;
const CGFloat controlsBarPadding = VLCLibraryUIUnits.largeSpacing * 2;
NSClipView * const clipView = _audioSongTableViewScrollView.contentView;
const CGFloat topInset = self.libraryWindow.titlebarHeight + self.audioSongTableView.headerView.frame.size.height;
clipView.automaticallyAdjustsContentInsets = NO;
clipView.contentInsets = NSEdgeInsetsMake(topInset, 0, controlsBarHeight + controlsBarPadding, 0);
}
#pragma mark - Superclass property overrides
- (NSArray<NSLayoutConstraint *> *)placeholderImageViewSizeConstraints
{
return _internalPlaceholderImageViewSizeConstraints;
}
- (id<VLCLibraryDataSource>)currentDataSource
{
return self.audioDataSource;
}
#pragma mark - Show the audio view
- (void)presentAudioView
{
[self updatePresentedView];
}
- (void)presentPlaceholderAudioView
{
const NSInteger selectedLibrarySegment = self.audioDataSource.audioLibrarySegment;
NSAssert(selectedLibrarySegment != VLCAudioLibraryRecentsSegment &&
selectedLibrarySegment != VLCAudioLibraryUnknownSegment,
@"Received invalid audio library segment from audio data source!");
[self.libraryWindow displayLibraryPlaceholderViewWithImage:[NSImage imageNamed:_placeholderImageNames[selectedLibrarySegment]]
usingConstraints:self.placeholderImageViewSizeConstraints
displayingMessage:_placeholderLabelStrings[selectedLibrarySegment]];
}
- (void)hideAllViews
{
_audioLibrarySplitView.hidden = YES;
_audioLibraryGridModeSplitView.hidden = YES;
_audioSongTableViewScrollView.hidden = YES;
_audioCollectionViewScrollView.hidden = YES;
}
- (void)presentAudioGridModeView
{
const VLCLibrarySegmentType selectedSegment = self.libraryWindow.librarySegmentType;
if (selectedSegment == VLCLibrarySongsMusicSubSegmentType ||
selectedSegment == VLCLibraryAlbumsMusicSubSegmentType) {
[_audioLibraryCollectionView deselectAll:self];
[(VLCLibraryCollectionViewFlowLayout *)_audioLibraryCollectionView.collectionViewLayout resetLayout];
_audioCollectionViewScrollView.hidden = NO;
} else {
_audioLibraryGridModeSplitView.hidden = NO;
[_splitViewDelegate resetDefaultSplitForSplitView:self.audioLibraryGridModeSplitView];
}
}
- (void)presentAudioTableView
{
if (self.libraryWindow.librarySegmentType == VLCLibrarySongsMusicSubSegmentType) {
_audioSongTableViewScrollView.hidden = NO;
} else {
_audioLibrarySplitView.hidden = NO;
[_splitViewDelegate resetDefaultSplitForSplitView:self.audioLibrarySplitView];
}
}
- (VLCLibraryViewModeSegment)viewModeSegmentForCurrentLibrarySegment
{
VLCLibraryWindowPersistentPreferences * const libraryWindowPrefs = VLCLibraryWindowPersistentPreferences.sharedInstance;
switch (self.libraryWindow.librarySegmentType) {
case VLCLibraryArtistsMusicSubSegmentType:
return libraryWindowPrefs.artistLibraryViewMode;
case VLCLibraryGenresMusicSubSegmentType:
return libraryWindowPrefs.genreLibraryViewMode;
case VLCLibrarySongsMusicSubSegmentType:
return libraryWindowPrefs.songsLibraryViewMode;
case VLCLibraryAlbumsMusicSubSegmentType:
return libraryWindowPrefs.albumLibraryViewMode;
default:
return VLCLibraryGridViewModeSegment;
}
}
- (VLCAudioLibrarySegment)currentLibrarySegmentToAudioLibrarySegment
{
switch (self.libraryWindow.librarySegmentType) {
case VLCLibraryMusicSegmentType:
case VLCLibraryArtistsMusicSubSegmentType:
return VLCAudioLibraryArtistsSegment;
case VLCLibraryAlbumsMusicSubSegmentType:
return VLCAudioLibraryAlbumsSegment;
case VLCLibrarySongsMusicSubSegmentType:
return VLCAudioLibrarySongsSegment;
case VLCLibraryGenresMusicSubSegmentType:
return VLCAudioLibraryGenresSegment;
default:
NSAssert(false, @"Non-audio or unknown library subsegment received");
return VLCAudioLibraryUnknownSegment;
}
}
- (void)updatePresentedView
{
self.audioDataSource.audioLibrarySegment = [self currentLibrarySegmentToAudioLibrarySegment];
const BOOL anyAudioMedia = self.audioDataSource.libraryModel.numberOfAudioMedia > 0;
if (anyAudioMedia) {
[self.libraryWindow displayLibraryView:self.audioLibraryView];
[self hideAllViews];
const VLCLibraryViewModeSegment viewModeSegment = [self viewModeSegmentForCurrentLibrarySegment];
if (viewModeSegment == VLCLibraryListViewModeSegment) {
[self presentAudioTableView];
} else if (viewModeSegment == VLCLibraryGridViewModeSegment) {
[self presentAudioGridModeView];
} else {
NSAssert(false, @"View mode must be grid or list mode");
}
[VLCMain.sharedInstance.libraryWindow updateGridVsListViewModeSegmentedControl];
} else if (self.audioDataSource.libraryModel.filterString.length > 0) {
[self.libraryWindow displayNoResultsMessage];
} else {
[self presentPlaceholderAudioView];
}
}
- (void)reloadData
{
[_audioDataSource reloadData];
}
- (void)presentLibraryItemInTableView:(id<VLCMediaLibraryItemProtocol>)libraryItem
{
if (libraryItem == nil) {
return;
}
NSTableView *targetMainTableView;
if ([libraryItem isKindOfClass:VLCMediaLibraryMediaItem.class]) {
targetMainTableView = self.audioSongTableView;
} else if ([self viewModeSegmentForCurrentLibrarySegment] == VLCLibraryGridViewModeSegment) {
targetMainTableView = self.audioLibraryGridModeSplitViewListTableView;
} else {
targetMainTableView = self.audioCollectionSelectionTableView;
}
NSAssert(targetMainTableView != nil, @"Target tableview for presenting audio library view is nil");
NSAssert(targetMainTableView.dataSource == self.audioDataSource, @"Target tableview data source is unexpected");
const NSInteger rowForLibraryItem = [self.audioDataSource rowForLibraryItem:libraryItem];
if (rowForLibraryItem != NSNotFound) {
NSIndexSet * const indexSet = [NSIndexSet indexSetWithIndex:rowForLibraryItem];
[self.audioDataSource tableView:targetMainTableView selectRowIndices:indexSet];
}
}
- (void)presentLibraryItemInCollectionView:(id<VLCMediaLibraryItemProtocol>)libraryItem
{
if (libraryItem == nil) {
return;
}
// If we are handling a library item that is shown in one of the split view modes,
// with a table view on the left and the collection view on the right, defer back
// to presentLibraryItemInTabelView
if ([libraryItem isKindOfClass:VLCMediaLibraryGenre.class] ||
[libraryItem isKindOfClass:VLCMediaLibraryArtist.class]) {
[self presentLibraryItemInTableView:libraryItem];
}
NSIndexPath * const indexPathForLibraryItem = [self.audioDataSource indexPathForLibraryItem:libraryItem];
if (indexPathForLibraryItem) {
NSSet<NSIndexPath *> * const indexPathSet = [NSSet setWithObject:indexPathForLibraryItem];
NSCollectionView * const collectionView = self.audioLibraryCollectionView;
VLCLibraryCollectionViewFlowLayout * const expandableFlowLayout = (VLCLibraryCollectionViewFlowLayout *)collectionView.collectionViewLayout;
[collectionView selectItemsAtIndexPaths:indexPathSet
scrollPosition:NSCollectionViewScrollPositionTop];
[expandableFlowLayout expandDetailSectionAtIndex:indexPathForLibraryItem];
}
}
- (void)presentLibraryItemWaitForDataSourceFinished:(nullable NSNotification *)aNotification
{
if ((NSUInteger)self.audioDataSource.displayedCollectionCount < self.audioDataSource.collectionToDisplayCount) {
return;
}
[NSNotificationCenter.defaultCenter removeObserver:self
name:VLCLibraryAudioDataSourceDisplayedCollectionChangedNotification
object:self.audioDataSource];
const VLCLibraryViewModeSegment viewModeSegment = [self viewModeSegmentForCurrentLibrarySegment];
if (viewModeSegment == VLCLibraryListViewModeSegment) {
[self presentLibraryItemInTableView:_awaitingPresentingLibraryItem];
} else if (viewModeSegment == VLCLibraryGridViewModeSegment) {
[self presentLibraryItemInCollectionView:_awaitingPresentingLibraryItem];
} else {
NSAssert(NO, @"No valid view mode segment acquired, cannot present item!");
}
_awaitingPresentingLibraryItem = nil;
}
- (void)presentLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
{
if (libraryItem == nil) {
return;
}
_awaitingPresentingLibraryItem = libraryItem;
// If the library item is a media item, we need to select the corresponding segment
// in the segmented control. We then need to update the presented view.
VLCLibrarySegmentType segmentType;
if ([libraryItem isKindOfClass:VLCMediaLibraryAlbum.class]) {
segmentType = VLCLibraryAlbumsMusicSubSegmentType;
} else if ([libraryItem isKindOfClass:VLCMediaLibraryArtist.class]) {
segmentType = VLCLibraryArtistsMusicSubSegmentType;
} else if ([libraryItem isKindOfClass:VLCMediaLibraryGenre.class]) {
segmentType = VLCLibraryGenresMusicSubSegmentType;
} else {
segmentType = VLCLibrarySongsMusicSubSegmentType;
}
VLCLibraryWindow * const libraryWindow = self.libraryWindow;
if (segmentType == libraryWindow.librarySegmentType) {
[self presentLibraryItemWaitForDataSourceFinished:nil];
return;
}
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(presentLibraryItemWaitForDataSourceFinished:)
name:VLCLibraryAudioDataSourceDisplayedCollectionChangedNotification
object:self.audioDataSource];
libraryWindow.librarySegmentType = segmentType;
[libraryWindow.splitViewController.navSidebarViewController selectSegment:segmentType];
}
- (void)libraryModelUpdated:(NSNotification *)aNotification
{
VLCLibraryModel * const model = VLCMain.sharedInstance.libraryController.libraryModel;
const NSUInteger audioCount = model.numberOfAudioMedia;
if ((self.libraryWindow.librarySegmentType == VLCLibraryMusicSegmentType ||
self.libraryWindow.librarySegmentType == VLCLibrarySongsMusicSubSegmentType ||
self.libraryWindow.librarySegmentType == VLCLibraryArtistsMusicSubSegmentType ||
self.libraryWindow.librarySegmentType == VLCLibraryAlbumsMusicSubSegmentType ||
self.libraryWindow.librarySegmentType == VLCLibraryGenresMusicSubSegmentType) &&
((audioCount == 0 && ![self.libraryTargetView.subviews containsObject:self.emptyLibraryView]) ||
(audioCount > 0 && ![self.libraryTargetView.subviews containsObject:_audioLibraryView])) &&
!self.libraryWindow.embeddedVideoPlaybackActive) {
[self updatePresentedView];
}
}
- (void)libraryModelLongLoadStarted:(NSNotification *)notification
{
if (self.connected) {
[self.audioDataSource disconnect];
[self.audioGroupDataSource disconnect];
}
[self.libraryWindow showLoadingOverlay];
}
- (void)libraryModelLongLoadFinished:(NSNotification *)notification
{
if (self.connected) {
[self.audioDataSource connect];
[self.audioGroupDataSource connect];
}
[self.libraryWindow hideLoadingOverlay];
}
- (void)updateHeaderForTableView:(NSTableView *)tableView
withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
fallbackTitle:(NSString *)fallbackTitle
fallbackDetail:(NSString *)fallbackDetail
{
if (tableView != self.audioCollectionSelectionTableView &&
tableView != self.audioGroupSelectionTableView &&
![self.audioGroupDataSource.tableViews containsObject:tableView])
return;
if (representedItem != nil) {
self.audioCollectionHeaderView.representedItem = representedItem;
} else {
[self.audioCollectionHeaderView updateWithRepresentedItem:nil
fallbackTitle:fallbackTitle
fallbackDetail:fallbackDetail];
}
}
@end