Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (45)
Showing
with 726 additions and 166 deletions
......@@ -92,8 +92,8 @@ const CGFloat VLCLibraryCollectionViewItemMaximumDisplayedProgress = 0.95;
if (self) {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(mediaItemUpdated:)
name:VLCLibraryModelMediaItemUpdated
selector:@selector(mediaItemThumbnailGenerated:)
name:VLCLibraryModelMediaItemThumbnailGenerated
object:nil];
[notificationCenter addObserver:self
selector:@selector(updateFontBasedOnSetting:)
......@@ -211,7 +211,7 @@ const CGFloat VLCLibraryCollectionViewItemMaximumDisplayedProgress = 0.95;
_highlightBox.hidden = !selected;
}
- (void)mediaItemUpdated:(NSNotification *)aNotification
- (void)mediaItemThumbnailGenerated:(NSNotification *)aNotification
{
VLCMediaLibraryMediaItem *updatedMediaItem = aNotification.object;
if (updatedMediaItem == nil || _representedItem == nil || ![_representedItem isKindOfClass:[VLCMediaLibraryMediaItem class]]) {
......
......@@ -32,17 +32,28 @@ NS_ASSUME_NONNULL_BEGIN
@class VLCMediaLibraryGenre;
@class VLCMediaLibraryEntryPoint;
extern NSString *VLCLibraryModelAudioMediaListUpdated;
extern NSString *VLCLibraryModelArtistListUpdated;
extern NSString *VLCLibraryModelAlbumListUpdated;
extern NSString *VLCLibraryModelGenreListUpdated;
extern NSString *VLCLibraryModelVideoMediaListUpdated;
extern NSString *VLCLibraryModelRecentMediaListUpdated;
extern NSString *VLCLibraryModelListOfMonitoredFoldersUpdated;
extern NSString *VLCLibraryModelMediaItemUpdated;
extern NSString *VLCLibraryModelMediaItemThumbnailGenerated;
extern NSString *VLCLibraryModelAudioMediaListReset;
extern NSString *VLCLibraryModelVideoMediaListReset;
extern NSString *VLCLibraryModelRecentsMediaListReset;
extern NSString *VLCLibraryModelAudioMediaItemDeleted;
extern NSString *VLCLibraryModelVideoMediaItemDeleted;
extern NSString *VLCLibraryModelRecentsMediaItemDeleted;
extern NSString *VLCLibraryModelAudioMediaItemUpdated;
extern NSString *VLCLibraryModelVideoMediaItemUpdated;
extern NSString *VLCLibraryModelRecentsMediaItemUpdated;
@interface VLCLibraryModel : NSObject
+ (NSUInteger)modelIndexFromModelItemNotification:(NSNotification * const)aNotification;
- (instancetype)initWithLibrary:(vlc_medialibrary_t *)library;
@property (readonly) size_t numberOfAudioMedia;
......
......@@ -26,14 +26,23 @@
#import "library/VLCLibraryDataTypes.h"
#import "extensions/NSString+Helpers.h"
NSString *VLCLibraryModelAudioMediaListUpdated = @"VLCLibraryModelAudioMediaListUpdated";
NSString *VLCLibraryModelArtistListUpdated = @"VLCLibraryModelArtistListUpdated";
NSString *VLCLibraryModelAlbumListUpdated = @"VLCLibraryModelAlbumListUpdated";
NSString *VLCLibraryModelGenreListUpdated = @"VLCLibraryModelGenreListUpdated";
NSString *VLCLibraryModelVideoMediaListUpdated = @"VLCLibraryModelVideoMediaListUpdated";
NSString *VLCLibraryModelRecentMediaListUpdated = @"VLCLibraryModelRecentMediaListUpdated";
NSString *VLCLibraryModelListOfMonitoredFoldersUpdated = @"VLCLibraryModelListOfMonitoredFoldersUpdated";
NSString *VLCLibraryModelMediaItemUpdated = @"VLCLibraryModelMediaItemUpdated";
NSString *VLCLibraryModelMediaItemThumbnailGenerated = @"VLCLibraryModelMediaItemThumbnailGenerated";
NSString *VLCLibraryModelAudioMediaListReset = @"VLCLibraryModelAudioMediaListReset";
NSString *VLCLibraryModelVideoMediaListReset = @"VLCLibraryModelVideoMediaListReset";
NSString *VLCLibraryModelRecentsMediaListReset = @"VLCLibraryModelRecentsMediaListReset";
NSString *VLCLibraryModelAudioMediaItemDeleted = @"VLCLibraryModelAudioMediaItemDeleted";
NSString *VLCLibraryModelVideoMediaItemDeleted = @"VLCLibraryModelVideoMediaItemDeleted";
NSString *VLCLibraryModelRecentsMediaItemDeleted = @"VLCLibraryModelRecentsMediaItemDeleted";
NSString *VLCLibraryModelAudioMediaItemUpdated = @"VLCLibraryModelAudioMediaItemUpdated";
NSString *VLCLibraryModelVideoMediaItemUpdated = @"VLCLibraryModelVideoMediaItemUpdated";
NSString *VLCLibraryModelRecentsMediaItemUpdated = @"VLCLibraryModelRecentsMediaItemUpdated";
@interface VLCLibraryModel ()
{
......@@ -55,16 +64,26 @@ NSString *VLCLibraryModelMediaItemUpdated = @"VLCLibraryModelMediaItemUpdated";
size_t _initialVideoCount;
size_t _initialAudioCount;
dispatch_queue_t _mediaItemCacheModificationQueue;
}
- (void)updateCachedListOfAudioMedia;
- (void)updateCachedListOfVideoMedia;
- (void)updateCachedListOfRecentMedia;
- (void)updateCachedListOfArtists;
- (void)updateCachedListOfAlbums;
- (void)updateCachedListOfGenres;
- (void)updateCachedListOfMonitoredFolders;
- (void)mediaItemWasUpdated:(VLCMediaLibraryMediaItem *)mediaItem;
@property (readwrite, atomic) NSArray *cachedAudioMedia;
@property (readwrite, atomic) NSArray *cachedArtists;
@property (readwrite, atomic) NSArray *cachedAlbums;
@property (readwrite, atomic) NSArray *cachedGenres;
@property (readwrite, atomic) NSArray *cachedVideoMedia;
@property (readwrite, atomic) NSArray *cachedRecentMedia;
@property (readwrite, atomic) NSArray *cachedListOfMonitoredFolders;
- (void)resetCachedMediaItemLists;
- (void)resetCachedListOfArtists;
- (void)resetCachedListOfAlbums;
- (void)resetCachedListOfGenres;
- (void)resetCachedListOfMonitoredFolders;
- (void)mediaItemThumbnailGenerated:(VLCMediaLibraryMediaItem *)mediaItem;
- (void)handleMediaItemDeletionEvent:(const vlc_ml_event_t * const)p_event;
- (void)handleMediaItemUpdateEvent:(const vlc_ml_event_t * const)p_event;
@end
......@@ -73,15 +92,23 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
switch(p_event->i_type)
{
case VLC_ML_EVENT_MEDIA_ADDED:
{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel resetCachedMediaItemLists];
break;
}
case VLC_ML_EVENT_MEDIA_UPDATED:
{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel handleMediaItemUpdateEvent:p_event];
break;
}
case VLC_ML_EVENT_MEDIA_DELETED:
dispatch_async(dispatch_get_main_queue(), ^{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel updateCachedListOfRecentMedia];
[libraryModel updateCachedListOfAudioMedia];
[libraryModel updateCachedListOfVideoMedia];
});
{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel handleMediaItemDeletionEvent:p_event];
break;
}
case VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED:
if (p_event->media_thumbnail_generated.b_success) {
VLCMediaLibraryMediaItem *mediaItem = [[VLCMediaLibraryMediaItem alloc] initWithMediaItem:(struct vlc_ml_media_t *)p_event->media_thumbnail_generated.p_media];
......@@ -90,7 +117,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
dispatch_async(dispatch_get_main_queue(), ^{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel mediaItemWasUpdated:mediaItem];
[libraryModel mediaItemThumbnailGenerated:mediaItem];
});
}
break;
......@@ -98,40 +125,33 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
case VLC_ML_EVENT_ARTIST_UPDATED:
case VLC_ML_EVENT_ARTIST_DELETED:
{
dispatch_async(dispatch_get_main_queue(), ^{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel updateCachedListOfArtists];
});
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel resetCachedListOfArtists];
break;
}
case VLC_ML_EVENT_ALBUM_ADDED:
case VLC_ML_EVENT_ALBUM_UPDATED:
case VLC_ML_EVENT_ALBUM_DELETED:
{
dispatch_async(dispatch_get_main_queue(), ^{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel updateCachedListOfAlbums];
});
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel resetCachedListOfAlbums];
break;
}
case VLC_ML_EVENT_GENRE_ADDED:
case VLC_ML_EVENT_GENRE_UPDATED:
case VLC_ML_EVENT_GENRE_DELETED:
{
dispatch_async(dispatch_get_main_queue(), ^{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel updateCachedListOfGenres];
});
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel resetCachedListOfGenres];
break;
}
case VLC_ML_EVENT_FOLDER_ADDED:
case VLC_ML_EVENT_FOLDER_UPDATED:
case VLC_ML_EVENT_FOLDER_DELETED:
{
dispatch_async(dispatch_get_main_queue(), ^{
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel updateCachedListOfMonitoredFolders];
});
VLCLibraryModel *libraryModel = (__bridge VLCLibraryModel *)p_data;
[libraryModel resetCachedListOfMonitoredFolders];
break;
}
default:
break;
......@@ -140,6 +160,18 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
@implementation VLCLibraryModel
+ (NSUInteger)modelIndexFromModelItemNotification:(NSNotification * const)aNotification
{
NSParameterAssert(aNotification);
NSDictionary * const notificationUserInfo = aNotification.userInfo;
NSAssert(notificationUserInfo != nil, @"Video item-related notification should carry valid user info");
NSNumber * const modelIndexNumber = (NSNumber * const)[notificationUserInfo objectForKey:@"index"];
NSAssert(modelIndexNumber != nil, @"Video item notification user info should carry index for updated item");
return modelIndexNumber.longLongValue;
}
- (instancetype)initWithLibrary:(vlc_medialibrary_t *)library
{
self = [super init];
......@@ -149,15 +181,18 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
_filterString = @"";
_p_mediaLibrary = library;
_p_eventCallback = vlc_ml_event_register_callback(_p_mediaLibrary, libraryCallback, (__bridge void *)self);
_mediaItemCacheModificationQueue = dispatch_queue_create("mediaItemCacheModificationQueue", 0);
_defaultNotificationCenter = [NSNotificationCenter defaultCenter];
[_defaultNotificationCenter addObserver:self
selector:@selector(applicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:nil];
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParameters = {};
// Preload video and audio count for gui
self->_initialVideoCount = vlc_ml_count_video_media(self->_p_mediaLibrary, &queryParameters);
self->_initialAudioCount = vlc_ml_count_audio_media(self->_p_mediaLibrary, &queryParameters);
......@@ -178,18 +213,16 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
[_defaultNotificationCenter removeObserver:self];
}
- (void)mediaItemWasUpdated:(VLCMediaLibraryMediaItem *)mediaItem
- (void)mediaItemThumbnailGenerated:(VLCMediaLibraryMediaItem *)mediaItem
{
[_defaultNotificationCenter postNotificationName:VLCLibraryModelMediaItemUpdated object:mediaItem];
[_defaultNotificationCenter postNotificationName:VLCLibraryModelMediaItemThumbnailGenerated object:mediaItem];
}
- (size_t)numberOfAudioMedia
{
if (!_cachedAudioMedia) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateCachedListOfAudioMedia];
});
[self resetCachedListOfAudioMedia];
// Return initial count here, otherwise it will return 0 on the first time
return _initialAudioCount;
}
......@@ -204,7 +237,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
return queryParams;
}
- (void)updateCachedListOfAudioMedia
- (void)resetCachedListOfAudioMedia
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParams = [self queryParams];
......@@ -222,8 +255,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
vlc_ml_media_list_release(p_media_list);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedAudioMedia = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListUpdated object:self];
self.cachedAudioMedia = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListReset object:self];
});
});
}
......@@ -231,7 +264,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (NSArray<VLCMediaLibraryMediaItem *> *)listOfAudioMedia
{
if (!_cachedAudioMedia) {
[self updateCachedListOfAudioMedia];
[self resetCachedListOfAudioMedia];
}
return _cachedAudioMedia;
}
......@@ -239,12 +272,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (size_t)numberOfArtists
{
if (!_cachedArtists) {
[self updateCachedListOfArtists];
[self resetCachedListOfArtists];
}
return _cachedArtists.count;
}
- (void)updateCachedListOfArtists
- (void)resetCachedListOfArtists
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParams = [self queryParams];
......@@ -258,7 +291,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
vlc_ml_artist_list_release(p_artist_list);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedArtists = [mutableArray copy];
self.cachedArtists = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelArtistListUpdated object:self];
});
});
......@@ -267,7 +300,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (NSArray<VLCMediaLibraryArtist *> *)listOfArtists
{
if (!_cachedArtists) {
[self updateCachedListOfArtists];
[self resetCachedListOfArtists];
}
return _cachedArtists;
}
......@@ -275,12 +308,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (size_t)numberOfAlbums
{
if (!_cachedAlbums) {
[self updateCachedListOfAlbums];
[self resetCachedListOfAlbums];
}
return _cachedAlbums.count;
}
- (void)updateCachedListOfAlbums
- (void)resetCachedListOfAlbums
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParams = [self queryParams];
......@@ -292,7 +325,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
vlc_ml_album_list_release(p_album_list);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedAlbums = [mutableArray copy];
self.cachedAlbums = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAlbumListUpdated object:self];
});
});
......@@ -301,7 +334,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (NSArray<VLCMediaLibraryAlbum *> *)listOfAlbums
{
if (!_cachedAlbums) {
[self updateCachedListOfAlbums];
[self resetCachedListOfAlbums];
}
return _cachedAlbums;
}
......@@ -309,12 +342,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (size_t)numberOfGenres
{
if (!_cachedGenres) {
[self updateCachedListOfGenres];
[self resetCachedListOfGenres];
}
return _cachedGenres.count;
}
- (void)updateCachedListOfGenres
- (void)resetCachedListOfGenres
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParams = [self queryParams];
......@@ -326,7 +359,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
vlc_ml_genre_list_release(p_genre_list);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedGenres = [mutableArray copy];
self.cachedGenres = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelGenreListUpdated object:self];
});
});
......@@ -335,7 +368,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (NSArray<VLCMediaLibraryMediaItem *> *)listOfGenres
{
if (!_cachedGenres) {
[self updateCachedListOfGenres];
[self resetCachedListOfGenres];
}
return _cachedGenres;
}
......@@ -343,17 +376,15 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (size_t)numberOfVideoMedia
{
if (!_cachedVideoMedia) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateCachedListOfVideoMedia];
});
[self resetCachedListOfVideoMedia];
// Return initial count here, otherwise it will return 0 on the first time
return _initialVideoCount;
}
return _cachedVideoMedia.count;
}
- (void)updateCachedListOfVideoMedia
- (void)resetCachedListOfVideoMedia
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParameters = [self queryParams];
......@@ -370,8 +401,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
vlc_ml_media_list_release(p_media_list);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedVideoMedia = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListUpdated object:self];
self.cachedVideoMedia = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListReset object:self];
});
});
}
......@@ -379,14 +410,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (NSArray<VLCMediaLibraryMediaItem *> *)listOfVideoMedia
{
if (!_cachedVideoMedia) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateCachedListOfVideoMedia];
});
[self resetCachedListOfVideoMedia];
}
return _cachedVideoMedia;
}
- (void)updateCachedListOfRecentMedia
- (void)resetCachedListOfRecentMedia
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
const vlc_ml_query_params_t queryParameters = { .i_nbResults = 20 };
......@@ -405,8 +434,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
}
vlc_ml_media_list_release(p_media_list);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedRecentMedia = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentMediaListUpdated object:self];
self.cachedRecentMedia = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentsMediaListReset object:self];
});
});
}
......@@ -415,7 +444,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
{
if (!_cachedRecentMedia) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateCachedListOfRecentMedia];
[self resetCachedListOfRecentMedia];
});
}
return _cachedRecentMedia.count;
......@@ -425,13 +454,20 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
{
if (!_cachedRecentMedia) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateCachedListOfRecentMedia];
[self resetCachedListOfRecentMedia];
});
}
return _cachedRecentMedia;
}
- (void)updateCachedListOfMonitoredFolders
- (void)resetCachedMediaItemLists
{
[self resetCachedListOfRecentMedia];
[self resetCachedListOfAudioMedia];
[self resetCachedListOfVideoMedia];
}
- (void)resetCachedListOfMonitoredFolders
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
vlc_ml_folder_list_t *pp_entrypoints = vlc_ml_list_entry_points(self->_p_mediaLibrary, NULL);
......@@ -451,7 +487,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
vlc_ml_folder_list_release(pp_entrypoints);
dispatch_async(dispatch_get_main_queue(), ^{
self->_cachedListOfMonitoredFolders = [mutableArray copy];
self.cachedListOfMonitoredFolders = [mutableArray copy];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelListOfMonitoredFoldersUpdated object:self];
});
});
......@@ -460,9 +496,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (NSArray<VLCMediaLibraryEntryPoint *> *)listOfMonitoredFolders
{
if(!_cachedListOfMonitoredFolders) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateCachedListOfMonitoredFolders];
});
[self resetCachedListOfMonitoredFolders];
}
return _cachedListOfMonitoredFolders;
......@@ -513,8 +547,125 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
_cachedArtists = nil;
_cachedAudioMedia = nil;
[_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListUpdated object:self];
[_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListUpdated object:self];
[_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaListReset object:self];
[_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaListReset object:self];
}
- (void)performActionOnMediaItemInCache:(const int64_t)libraryId action:(void (^)(const NSMutableArray*, const NSUInteger, const NSMutableArray*, const NSUInteger))action
{
dispatch_async(_mediaItemCacheModificationQueue, ^{
BOOL (^idCheckBlock)(VLCMediaLibraryMediaItem * const, const NSUInteger, BOOL * const) = ^BOOL(VLCMediaLibraryMediaItem * const mediaItem, const NSUInteger idx, BOOL * const stop) {
NSAssert(mediaItem != nil, @"Cache list should not contain nil media items");
return mediaItem.libraryID == libraryId;
};
// Recents can contain media items the other two do
NSMutableArray * const recentsMutable = [self.cachedRecentMedia mutableCopy];
const NSUInteger recentsIndex = [recentsMutable indexOfObjectPassingTest:idCheckBlock];
BOOL isInRecents = recentsIndex != NSNotFound;
NSMutableArray * const videoMutable = [self.cachedVideoMedia mutableCopy];
const NSUInteger videoIndex = [videoMutable indexOfObjectPassingTest:idCheckBlock];
if (videoIndex != NSNotFound) {
dispatch_sync(dispatch_get_main_queue(), ^{
action(videoMutable, videoIndex, recentsMutable, recentsIndex);
self.cachedVideoMedia = [videoMutable copy];
self.cachedRecentMedia = [recentsMutable copy];
});
return;
}
NSMutableArray * const audioMutable = [self.cachedAudioMedia mutableCopy];
const NSUInteger audioIndex = [self.cachedAudioMedia indexOfObjectPassingTest:idCheckBlock];
if (audioIndex != NSNotFound) {
dispatch_sync(dispatch_get_main_queue(), ^{
action(audioMutable, audioIndex, recentsMutable, recentsIndex);
self.cachedAudioMedia = [audioMutable copy];
self.cachedRecentMedia = [recentsMutable copy];
});
return;
}
action(nil, NSNotFound, nil, NSNotFound);
});
}
- (void)handleMediaItemUpdateEvent:(const vlc_ml_event_t * const)p_event
{
NSParameterAssert(p_event != NULL);
const int64_t itemId = p_event->modification.i_entity_id;
VLCMediaLibraryMediaItem * const mediaItem = [VLCMediaLibraryMediaItem mediaItemForLibraryID:itemId];
if (mediaItem == nil) {
NSLog(@"Could not find a library media item with this ID. Can't handle update.");
return;
}
[self performActionOnMediaItemInCache:itemId action:^(NSMutableArray * const cachedMediaArray, const NSUInteger cachedMediaIndex, NSMutableArray * const recentMediaArray, const NSUInteger recentMediaIndex) {
if (cachedMediaArray == nil || cachedMediaIndex == NSNotFound) {
NSLog(@"Could not handle update for media library item with id %lld in model", itemId);
return;
}
// Notify what happened
[cachedMediaArray replaceObjectAtIndex:cachedMediaIndex withObject:mediaItem];
if (recentMediaArray != nil && recentMediaIndex != NSNotFound) {
[cachedMediaArray replaceObjectAtIndex:recentMediaIndex withObject:mediaItem];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentsMediaItemUpdated object:mediaItem];
}
switch (mediaItem.mediaType) {
case VLC_ML_MEDIA_TYPE_VIDEO:
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaItemUpdated object:mediaItem];
break;
case VLC_ML_MEDIA_TYPE_AUDIO:
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaItemUpdated object:mediaItem];
break;
case VLC_ML_MEDIA_TYPE_UNKNOWN:
NSLog(@"Unknown type of media type encountered, don't know what to do in update");
break;
}
}];
}
- (void)handleMediaItemDeletionEvent:(const vlc_ml_event_t * const)p_event
{
NSParameterAssert(p_event != NULL);
const int64_t itemId = p_event->modification.i_entity_id;
NSLog(@"Deleting %lli", itemId);
[self performActionOnMediaItemInCache:itemId action:^(NSMutableArray * const cachedMediaArray, const NSUInteger cachedMediaIndex, NSMutableArray * const recentMediaArray, const NSUInteger recentMediaIndex) {
if (cachedMediaArray == nil || cachedMediaIndex == NSNotFound) {
NSLog(@"Could not handle deletion for media library item with id %lld in model", itemId);
return;
}
VLCMediaLibraryMediaItem * mediaItem = cachedMediaArray[cachedMediaIndex];
// Notify what happened
[cachedMediaArray removeObjectAtIndex:cachedMediaIndex];
if (recentMediaArray != nil && recentMediaIndex != NSNotFound) {
[recentMediaArray removeObjectAtIndex:recentMediaIndex];
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelRecentsMediaItemDeleted object:mediaItem];
}
switch (mediaItem.mediaType) {
case VLC_ML_MEDIA_TYPE_VIDEO:
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelVideoMediaItemDeleted object:mediaItem];
break;
case VLC_ML_MEDIA_TYPE_AUDIO:
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelAudioMediaItemDeleted object:mediaItem];
break;
case VLC_ML_MEDIA_TYPE_UNKNOWN:
NSLog(@"Unknown type of media type encountered, don't know what to do in deletion");
break;
}
}];
}
@end
......@@ -89,8 +89,17 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelAudioMediaListUpdated
name:VLCLibraryModelAudioMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelAudioItemUpdated:)
name:VLCLibraryModelAudioMediaItemUpdated
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelAudioItemDeleted:)
name:VLCLibraryModelAudioMediaItemDeleted
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelArtistListUpdated
......@@ -152,44 +161,55 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
}
}
- (void)libraryModelUpdated:(NSNotification *)aNotification
- (NSArray *)collectionToDisplay
{
if(self.libraryModel == nil) {
return;
}
NSArray *collectionToDisplay;
switch(_currentParentType) {
case VLC_ML_PARENT_UNKNOWN:
collectionToDisplay = [self.libraryModel listOfAudioMedia];
break;
return [_libraryModel listOfAudioMedia];
case VLC_ML_PARENT_ALBUM:
collectionToDisplay = [self.libraryModel listOfAlbums];
break;
return [_libraryModel listOfAlbums];
case VLC_ML_PARENT_ARTIST:
collectionToDisplay = [self.libraryModel listOfArtists];
break;
return [_libraryModel listOfArtists];
case VLC_ML_PARENT_GENRE:
collectionToDisplay = [self.libraryModel listOfGenres];
break;
return [_libraryModel listOfGenres];
default:
return;
return nil;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
NSSet* originalCollectionSet = [[NSSet alloc] initWithArray:self->_displayedCollection];
NSSet* newCollectionSet = [[NSSet alloc] initWithArray:collectionToDisplay];
- (void)libraryModelUpdated:(NSNotification * const)aNotification
{
if(_libraryModel == nil) {
return;
}
if([originalCollectionSet isEqual:newCollectionSet]) {
return;
}
[self reloadData];
}
- (void)libraryModelAudioItemUpdated:(NSNotification * const)aNotification
{
if(_libraryModel == nil) {
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem * const mediaItem = (VLCMediaLibraryMediaItem * const)aNotification.object;
NSAssert(mediaItem != nil, @"Audio item-related notification should carry valid media item");
[self retainSelectedMediaItem];
self->_displayedCollection = collectionToDisplay;
[self reloadData];
[self restoreSelectionState];
});
[self reloadDataForMediaLibraryItem:mediaItem];
}
- (void)libraryModelAudioItemDeleted:(NSNotification * const)aNotification
{
if(_libraryModel == nil) {
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem * const mediaItem = (VLCMediaLibraryMediaItem * const)aNotification.object;
NSAssert(mediaItem != nil, @"Audio item-related notification should carry valid media item");
[self deleteDataForMediaLibraryItem:mediaItem];
}
- (void)retainSelectedMediaItem
......@@ -420,14 +440,7 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
return VLCLibraryTitleSortDescriptorKey;
}
- (void)reloadData
{
[self retainSelectedMediaItem];
[self reloadViews];
[self restoreSelectionState];
}
- (void)reloadViews
- (void)resetLayoutsForOperation:(void(^)(void))operation
{
VLCLibraryCollectionViewFlowLayout *collectionViewFlowLayout = (VLCLibraryCollectionViewFlowLayout *)_collectionView.collectionViewLayout;
if (collectionViewFlowLayout) {
......@@ -439,15 +452,87 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
[gridModeListSelectionCollectionViewFlowLayout resetLayout];
}
[self.collectionView reloadData];
[self.gridModeListTableView reloadData];
[self.gridModeListSelectionCollectionView reloadData];
[self.collectionSelectionTableView reloadData];
[self.groupSelectionTableView reloadData];
[self.songsTableView reloadData];
operation();
[self setupExistingSortForTableView:_songsTableView];
}
- (void)reloadData
{
[self retainSelectedMediaItem];
self->_displayedCollection = [self collectionToDisplay];
[self resetLayoutsForOperation:^{
[self.collectionView reloadData];
[self.gridModeListTableView reloadData];
[self.gridModeListSelectionCollectionView reloadData];
[self.collectionSelectionTableView reloadData];
[self.groupSelectionTableView reloadData];
[self.songsTableView reloadData];
}];
[self restoreSelectionState];
}
- (NSUInteger)indexForMediaLibraryItemWithId:(const int64_t)itemId
{
return [_displayedCollection indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem * const mediaItem, const NSUInteger idx, BOOL * const stop) {
NSAssert(mediaItem != nil, @"Cache list should not contain nil media items");
return mediaItem.libraryID == itemId;
}];
}
- (void)reloadDataForMediaLibraryItem:(VLCMediaLibraryMediaItem * const)mediaItem
{
[self resetLayoutsForOperation:^{
const NSUInteger index = [self indexForMediaLibraryItemWithId:mediaItem.libraryID];
if (index == NSNotFound) {
return;
}
NSMutableArray * const mutableCollectionCopy = [self->_displayedCollection mutableCopy];
[mutableCollectionCopy replaceObjectAtIndex:index withObject:mediaItem];
self->_displayedCollection = [mutableCollectionCopy copy];
NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:index inSection:0];
NSIndexSet * const rowIndexSet = [NSIndexSet indexSetWithIndex:index];
NSRange songsTableColumnRange = NSMakeRange(0, self->_songsTableView.numberOfColumns);
NSIndexSet * const songsTableColumnIndexSet = [NSIndexSet indexSetWithIndexesInRange:songsTableColumnRange];
[self.collectionView reloadItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
[self.songsTableView reloadDataForRowIndexes:rowIndexSet columnIndexes:songsTableColumnIndexSet];
// Don't update gridModeListSelectionCollectionView, let its VLCLibraryAudioGroupDataSource do it.
// TODO: Stop splitting functionality for these audio source selection views between this data source
// TODO: and the VLCLibraryAudioGroupDataSource, it is super confusing
// Also don't update:
// - gridModeListTableView, as this will only show artists/genres
// - collectionSelectionTableView, as this will only show artists/genres/albums
// - groupSelectionTableView, as this shows cells for albums (and each cell has its own data source with media items)
}];
}
- (void)deleteDataForMediaLibraryItem:(VLCMediaLibraryMediaItem * const)mediaItem
{
[self resetLayoutsForOperation:^{
const NSUInteger index = [self indexForMediaLibraryItemWithId:mediaItem.libraryID];
if (index == NSNotFound) {
return;
}
NSMutableArray * const mutableCollectionCopy = [self->_displayedCollection mutableCopy];
[mutableCollectionCopy removeObjectAtIndex:index];
self->_displayedCollection = [mutableCollectionCopy copy];
NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:index inSection:0];
NSIndexSet * const rowIndexSet = [NSIndexSet indexSetWithIndex:index];
[self.collectionView deleteItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
[self.songsTableView removeRowsAtIndexes:rowIndexSet withAnimation:NSTableViewAnimationSlideUp];
// Comment in reloadDataForMediaLibraryItem will be informative
}];
}
- (void)setAudioLibrarySegment:(VLCAudioLibrarySegment)audioLibrarySegment
{
if (audioLibrarySegment == _audioLibrarySegment) {
......
......@@ -82,7 +82,11 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = @"VLCLibraryPlaceholderAudi
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelAudioMediaListUpdated
name:VLCLibraryModelAudioMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelAudioMediaItemDeleted
object:nil];
}
......
......@@ -36,10 +36,12 @@
@interface VLCLibraryVideoCollectionViewContainerViewDataSource ()
{
NSArray *_collectionArray;
VLCLibraryCollectionViewFlowLayout *_collectionViewFlowLayout;
VLCLibraryModel *_libraryModel;
}
@property (readwrite, atomic) NSArray *collectionArray;
@end
@implementation VLCLibraryVideoCollectionViewContainerViewDataSource
......@@ -50,23 +52,115 @@
if(self) {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelVideoMediaListUpdated
selector:@selector(libraryModelVideoListReset:)
name:VLCLibraryModelVideoMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelVideoItemUpdated:)
name:VLCLibraryModelVideoMediaItemUpdated
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelVideoItemDeleted:)
name:VLCLibraryModelVideoMediaItemDeleted
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelRecentsListReset:)
name:VLCLibraryModelRecentsMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelRecentMediaListUpdated
selector:@selector(libraryModelRecentsItemUpdated:)
name:VLCLibraryModelRecentsMediaItemUpdated
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelRecentsItemDeleted:)
name:VLCLibraryModelRecentsMediaItemDeleted
object:nil];
_libraryModel = [VLCMain sharedInstance].libraryController.libraryModel;
self.collectionArray = [NSArray array];
}
return self;
}
- (void)libraryModelUpdated:(NSNotification *)aNotification
- (NSUInteger)indexOfMediaItemInCollection:(const NSUInteger)libraryId
{
return [self.collectionArray indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem * const findMediaItem, const NSUInteger idx, BOOL * const stop) {
NSAssert(findMediaItem != nil, @"Collection should not contain nil media items");
return findMediaItem.libraryID == libraryId;
}];
}
- (void)libraryModelVideoListReset:(NSNotification * const)aNotification
{
if (_groupDescriptor.group != VLCLibraryVideoLibraryGroup) {
return;
}
[self reloadData];
}
- (void)libraryModelVideoItemUpdated:(NSNotification * const)aNotification
{
if (_groupDescriptor.group != VLCLibraryVideoLibraryGroup) {
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
[self reloadDataForMediaItem:notificationMediaItem];
}
- (void)libraryModelVideoItemDeleted:(NSNotification * const)aNotification
{
if (_groupDescriptor.group != VLCLibraryVideoLibraryGroup) {
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
[self deleteDataForMediaItem:notificationMediaItem];
}
- (void)libraryModelRecentsListReset:(NSNotification * const)aNotification
{
if (_groupDescriptor.group != VLCLibraryVideoRecentsGroup) {
return;
}
[self reloadData];
}
- (void)libraryModelRecentsItemUpdated:(NSNotification * const)aNotification
{
if (_groupDescriptor.group != VLCLibraryVideoRecentsGroup) {
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
[self reloadDataForMediaItem:notificationMediaItem];
}
- (void)libraryModelRecentsItemDeleted:(NSNotification * const)aNotification
{
if (_groupDescriptor.group != VLCLibraryVideoRecentsGroup) {
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
[self deleteDataForMediaItem:notificationMediaItem];
}
- (void)reloadData
{
if(!_collectionView || !_groupDescriptor) {
......@@ -74,18 +168,54 @@
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
NSAssert(self->_groupDescriptor.libraryModelDataMethodSignature, @"Group descriptor's library model data method signature cannot be nil");
NSInvocation *modelDataInvocation = [NSInvocation invocationWithMethodSignature:self->_groupDescriptor.libraryModelDataMethodSignature];
modelDataInvocation.selector = self->_groupDescriptor.libraryModelDataSelector;
[modelDataInvocation invokeWithTarget:self->_libraryModel];
[modelDataInvocation getReturnValue:&self->_collectionArray];
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
switch(self->_groupDescriptor.group) {
case VLCLibraryVideoLibraryGroup:
self.collectionArray = self->_libraryModel.listOfVideoMedia;
break;
case VLCLibraryVideoRecentsGroup:
self.collectionArray = self->_libraryModel.listOfRecentMedia;
break;
default:
return;
}
[self->_collectionView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
[self->_collectionView reloadData];
});
});
}
- (void)reloadDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
{
NSUInteger mediaItemIndex = [self indexOfMediaItemInCollection:mediaItem.libraryID];
if (mediaItemIndex == NSNotFound) {
return;
}
NSMutableArray * const mutableCollectionCopy = [self.collectionArray mutableCopy];
[mutableCollectionCopy replaceObjectAtIndex:mediaItemIndex withObject:mediaItem];
self.collectionArray = [mutableCollectionCopy copy];
NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:mediaItemIndex inSection:0];
[self->_collectionView reloadItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
}
- (void)deleteDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
{
NSUInteger mediaItemIndex = [self indexOfMediaItemInCollection:mediaItem.libraryID];
if (mediaItemIndex == NSNotFound) {
return;
}
NSMutableArray * const mutableCollectionCopy = [self.collectionArray mutableCopy];
[mutableCollectionCopy removeObjectAtIndex:mediaItemIndex];
self.collectionArray = [mutableCollectionCopy copy];
NSIndexPath * const indexPath = [NSIndexPath indexPathForItem:mediaItemIndex inSection:0];
[self->_collectionView deleteItemsAtIndexPaths:[NSSet setWithObject:indexPath]];
}
- (void)setGroupDescriptor:(VLCLibraryVideoCollectionViewGroupDescriptor *)groupDescriptor
{
if(!groupDescriptor) {
......@@ -130,14 +260,14 @@
return 0;
}
return _collectionArray.count;
return self.collectionArray.count;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView
itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath
{
VLCLibraryCollectionViewItem *viewItem = [collectionView makeItemWithIdentifier:VLCLibraryCellIdentifier forIndexPath:indexPath];
viewItem.representedItem = _collectionArray[indexPath.item];
viewItem.representedItem = self.collectionArray[indexPath.item];
return viewItem;
}
......@@ -156,7 +286,7 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
} else if ([kind isEqualToString:VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind]) {
VLCLibraryCollectionViewMediaItemSupplementaryDetailView* mediaItemSupplementaryDetailView = [collectionView makeSupplementaryViewOfKind:kind withIdentifier:VLCLibraryCollectionViewMediaItemSupplementaryDetailViewKind forIndexPath:indexPath];
mediaItemSupplementaryDetailView.representedMediaItem = _collectionArray[indexPath.item];
mediaItemSupplementaryDetailView.representedMediaItem = self.collectionArray[indexPath.item];
mediaItemSupplementaryDetailView.selectedItem = [collectionView itemAtIndexPath:indexPath];
return mediaItemSupplementaryDetailView;
}
......@@ -167,7 +297,7 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
- (id<VLCMediaLibraryItemProtocol>)libraryItemAtIndexPath:(NSIndexPath *)indexPath
forCollectionView:(NSCollectionView *)collectionView
{
return _collectionArray[indexPath.item];
return self.collectionArray[indexPath.item];
}
@end
......@@ -38,7 +38,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) VLCLibraryVideoGroup group;
@property (readonly) SEL libraryModelDataSelector;
@property (readonly) NSMethodSignature *libraryModelDataMethodSignature;
@property (readonly) NSNotificationName libraryModelUpdatedNotificationName;
@property (readonly) NSString *name;
@property (readonly) BOOL isHorizontalBarCollectionView;
......
......@@ -37,13 +37,11 @@
switch (_group) {
case VLCLibraryVideoRecentsGroup:
_libraryModelUpdatedNotificationName = VLCLibraryModelRecentMediaListUpdated;
_libraryModelDataSelector = @selector(listOfRecentMedia);
_isHorizontalBarCollectionView = YES;
_name = _NS("Recents");
break;
case VLCLibraryVideoLibraryGroup:
_libraryModelUpdatedNotificationName = VLCLibraryModelVideoMediaListUpdated;
_libraryModelDataSelector = @selector(listOfVideoMedia);
_isHorizontalBarCollectionView = NO;
_name = _NS("Library");
......
......@@ -54,22 +54,128 @@
if(self) {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelVideoMediaListUpdated
selector:@selector(libraryModelVideoListReset:)
name:VLCLibraryModelVideoMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelRecentMediaListUpdated
selector:@selector(libraryModelVideoItemUpdated:)
name:VLCLibraryModelVideoMediaItemUpdated
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelVideoItemDeleted:)
name:VLCLibraryModelVideoMediaItemDeleted
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelRecentsListReset:)
name:VLCLibraryModelRecentsMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelRecentsItemUpdated:)
name:VLCLibraryModelRecentsMediaItemUpdated
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelRecentsItemDeleted:)
name:VLCLibraryModelRecentsMediaItemDeleted
object:nil];
}
return self;
}
- (void)libraryModelUpdated:(NSNotification *)aNotification
- (NSUInteger)indexOfMediaItem:(const NSUInteger)libraryId inArray:(NSArray const *)array
{
return [array indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem * const findMediaItem, const NSUInteger idx, BOOL * const stop) {
NSAssert(findMediaItem != nil, @"Collection should not contain nil media items");
return findMediaItem.libraryID == libraryId;
}];
}
- (void)libraryModelVideoListReset:(NSNotification * const)aNotification
{
if (_groupsTableView.selectedRow == -1 ||
_groupsTableView.selectedRow != VLCLibraryVideoLibraryGroup - 1) { // Row 0 == second value in enum, so compensate
return;
}
[self reloadData];
}
- (void)libraryModelVideoItemUpdated:(NSNotification * const)aNotification
{
if (_groupsTableView.selectedRow == -1 ||
_groupsTableView.selectedRow != VLCLibraryVideoLibraryGroup - 1) { // Row 0 == second value in enum, so compensate
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
[self reloadDataForMediaItem:notificationMediaItem
inVideoGroup:VLCLibraryVideoLibraryGroup];
}
- (void)libraryModelVideoItemDeleted:(NSNotification * const)aNotification
{
if (_groupsTableView.selectedRow == -1 ||
_groupsTableView.selectedRow != VLCLibraryVideoLibraryGroup - 1) { // Row 0 == second value in enum, so compensate
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
[self deleteDataForMediaItem:notificationMediaItem
inVideoGroup:VLCLibraryVideoLibraryGroup];
}
- (void)libraryModelRecentsListReset:(NSNotification * const)aNotification
{
if (_groupsTableView.selectedRow == -1 ||
_groupsTableView.selectedRow != VLCLibraryVideoRecentsGroup - 1) { // Row 0 == second value in enum, so compensate
return;
}
[self reloadData];
}
- (void)libraryModelRecentsItemUpdated:(NSNotification * const)aNotification
{
if (_groupsTableView.selectedRow == -1 ||
_groupsTableView.selectedRow != VLCLibraryVideoRecentsGroup - 1) { // Row 0 == second value in enum, so compensate
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item updated notification should carry valid media item");
[self reloadDataForMediaItem:notificationMediaItem
inVideoGroup:VLCLibraryVideoRecentsGroup];
}
- (void)libraryModelRecentsItemDeleted:(NSNotification * const)aNotification
{
if (_groupsTableView.selectedRow == -1 ||
_groupsTableView.selectedRow != VLCLibraryVideoRecentsGroup - 1) { // Row 0 == second value in enum, so compensate
return;
}
NSParameterAssert(aNotification);
VLCMediaLibraryMediaItem *notificationMediaItem = aNotification.object;
NSAssert(notificationMediaItem != nil, @"Media item deleted notification should carry valid media item");
[self deleteDataForMediaItem:notificationMediaItem
inVideoGroup:VLCLibraryVideoRecentsGroup];
}
- (void)reloadData
{
if(!_libraryModel) {
......@@ -78,12 +184,85 @@
[_collectionViewFlowLayout resetLayout];
dispatch_async(dispatch_get_main_queue(), ^{
self->_recentsArray = [self->_libraryModel listOfRecentMedia];
self->_libraryArray = [self->_libraryModel listOfVideoMedia];
[self->_groupsTableView reloadData];
[self->_groupSelectionTableView reloadData];
});
self->_recentsArray = [self.libraryModel listOfRecentMedia];
self->_libraryArray = [self.libraryModel listOfVideoMedia];
[self->_groupSelectionTableView reloadData];
}
- (void)changeDataForSpecificMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
inVideoGroup:(VLCLibraryVideoGroup)group
arrayOperation:(void(^)(const NSMutableArray*, const NSUInteger))arrayOperation
completionHandler:(void(^)(const NSIndexSet*))completionHandler
{
NSMutableArray *groupMutableCopyArray;
switch(group) {
case VLCLibraryVideoLibraryGroup:
groupMutableCopyArray = [_libraryArray mutableCopy];
break;
case VLCLibraryVideoRecentsGroup:
groupMutableCopyArray = [_recentsArray mutableCopy];
break;
default:
return;
}
NSUInteger mediaItemIndex = [self indexOfMediaItem:mediaItem.libraryID inArray:groupMutableCopyArray];
if (mediaItemIndex == NSNotFound) {
return;
}
arrayOperation(groupMutableCopyArray, mediaItemIndex);
switch(group) {
case VLCLibraryVideoLibraryGroup:
_libraryArray = [groupMutableCopyArray copy];
break;
case VLCLibraryVideoRecentsGroup:
_recentsArray = [groupMutableCopyArray copy];
break;
default:
return;
}
NSIndexSet * const rowIndexSet = [NSIndexSet indexSetWithIndex:mediaItemIndex];
completionHandler(rowIndexSet);
}
- (void)reloadDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
inVideoGroup:(VLCLibraryVideoGroup)group
{
[self changeDataForSpecificMediaItem:mediaItem
inVideoGroup:group
arrayOperation:^(NSMutableArray * const mediaArray, const NSUInteger mediaItemIndex) {
[mediaArray replaceObjectAtIndex:mediaItemIndex withObject:mediaItem];
} completionHandler:^(NSIndexSet * const rowIndexSet) {
// Don't regenerate the groups by index as these do not change according to the notification
// Stick to the selection table view
NSRange columnRange = NSMakeRange(0, self->_groupsTableView.numberOfColumns);
NSIndexSet * const columnIndexSet = [NSIndexSet indexSetWithIndexesInRange:columnRange];
[self->_groupSelectionTableView reloadDataForRowIndexes:rowIndexSet columnIndexes:columnIndexSet];
}];
}
- (void)deleteDataForMediaItem:(VLCMediaLibraryMediaItem * const)mediaItem
inVideoGroup:(VLCLibraryVideoGroup)group
{
[self changeDataForSpecificMediaItem:mediaItem
inVideoGroup:group
arrayOperation:^(NSMutableArray * const mediaArray, const NSUInteger mediaItemIndex) {
[mediaArray removeObjectAtIndex:mediaItemIndex];
} completionHandler:^(NSIndexSet * const rowIndexSet){
// Don't regenerate the groups by index as these do not change according to the notification
// Stick to the selection table view
[self->_groupSelectionTableView removeRowsAtIndexes:rowIndexSet withAnimation:NSTableViewAnimationSlideUp];
}];
}
#pragma mark - table view data source and delegation
......
......@@ -65,7 +65,11 @@
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelVideoMediaListUpdated
name:VLCLibraryModelVideoMediaListReset
object:nil];
[notificationCenter addObserver:self
selector:@selector(libraryModelUpdated:)
name:VLCLibraryModelVideoMediaItemDeleted
object:nil];
}
......@@ -218,8 +222,7 @@
- (void)libraryModelUpdated:(NSNotification *)aNotification
{
NSParameterAssert(aNotification);
VLCLibraryModel *model = (VLCLibraryModel *)aNotification.object;
NSAssert(model, @"Notification object should be a VLCLibraryModel");
VLCLibraryModel *model = VLCMain.sharedInstance.libraryController.libraryModel;
NSArray<VLCMediaLibraryMediaItem *> * videoList = model.listOfVideoMedia;
if (_segmentedTitleControl.selectedSegment == VLCLibraryVideoSegment &&
......