فهرست منبع

MacOSX/Framework/VLCMediaList.m: Cache the media list objects in a NSMutableArray. We do this because we want to use bindings. Cocoa bindings requires us to send willChangeValueForKey/didChangeValueForKey on the main thread. And that's one of the simpler way to do that without having locking problems.

Pierre d'Herbemont 17 سال پیش
والد
کامیت
a80e0bfa27
2فایلهای تغییر یافته به همراه30 افزوده شده و 48 حذف شده
  1. 1 0
      Headers/Public/VLCMediaList.h
  2. 29 48
      Sources/VLCMediaList.m

+ 1 - 0
Headers/Public/VLCMediaList.h

@@ -43,6 +43,7 @@ extern NSString * VLCMediaListItemDeleted;
 {
     void * p_mlist;                //< Internal instance of media list
     id <VLCMediaListDelegate,NSObject> delegate;                //< Delegate object
+    NSMutableArray *cachedMedia; /* We need that private copy because of Cocoa Bindings, that need to be working on first thread */
 }
 
 /* Properties */

+ 29 - 48
Sources/VLCMediaList.m

@@ -48,8 +48,6 @@ static void HandleMediaListItemAdded(const libvlc_event_t *event, void *user_dat
 {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
     id self = user_data;
-    int index = event->u.media_list_item_added.index;
-    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"Media"];
     [[VLCEventManager sharedManager] callOnMainThreadObject:self 
                                                  withMethod:@selector(mediaListItemAdded:) 
                                        withArgumentAsObject:[NSDictionary dictionaryWithObjectsAndKeys:
@@ -58,40 +56,17 @@ static void HandleMediaListItemAdded(const libvlc_event_t *event, void *user_dat
                                                           nil]];
     [pool release];
 }
-static void HandleMediaListWillAddItem(const libvlc_event_t *event, void *user_data)
-{
-    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-    id self = user_data;
-    int index = event->u.media_list_will_add_item.index;
-    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"Media"];
-    [pool release];
-}
-
 
 static void HandleMediaListItemDeleted( const libvlc_event_t * event, void * user_data)
 {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
     id self = user_data;
-    int index = event->u.media_list_will_add_item.index;
-    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"Media"];
-    // Check to see if the last item deleted is this item we're trying delete now.
-    // If no, then delete the item from the local list, otherwise, the item has already 
-    // been deleted
     [[VLCEventManager sharedManager] callOnMainThreadObject:self 
                                                  withMethod:@selector(mediaListItemRemoved:) 
                                        withArgumentAsObject:[NSNumber numberWithInt:event->u.media_list_item_deleted.index]];
     [pool release];
 }
 
-static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *user_data)
-{
-    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-    id self = user_data;
-    int index = event->u.media_list_will_add_item.index;
-    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"Media"];
-    [pool release];
-}
-
 @implementation VLCMediaList (KeyValueCodingCompliance)
 /* For the @"Media" key */
 - (int) countOfMedia
@@ -117,6 +92,7 @@ static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *use
         quit_on_exception(&p_e);
         
         // Initialize internals to defaults
+        cachedMedia = [[NSMutableArray alloc] init];
         delegate = nil;
         [self initInternalMediaList];
     }
@@ -134,9 +110,7 @@ static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *use
              * Before libvlc_event_detach. So this can't happen in dealloc */
             libvlc_event_manager_t * p_em = libvlc_media_list_event_manager(p_mlist, NULL);
             libvlc_event_detach(p_em, libvlc_MediaListItemDeleted, HandleMediaListItemDeleted, self, NULL);
-            libvlc_event_detach(p_em, libvlc_MediaListWillDeleteItem, HandleMediaListWillDeleteItem, self, NULL);
             libvlc_event_detach(p_em, libvlc_MediaListItemAdded,   HandleMediaListItemAdded,   self, NULL);
-            libvlc_event_detach(p_em, libvlc_MediaListWillAddItem, HandleMediaListWillAddItem, self, NULL);
         }
         [super release];
     }
@@ -146,7 +120,7 @@ static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *use
 {
     // Release allocated memory
     libvlc_media_list_release(p_mlist);
-    
+    [cachedMedia release];
     [super dealloc];
 }
 
@@ -201,24 +175,12 @@ static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *use
 
 - (VLCMedia *)mediaAtIndex:(int)index
 {
-    libvlc_exception_t p_e;
-    libvlc_exception_init( &p_e );
-    libvlc_media_descriptor_t *p_md = libvlc_media_list_item_at_index( p_mlist, index, &p_e );
-    quit_on_exception( &p_e );
-    
-    // Returns local object for media descriptor, searchs for user data first.  If not found it creates a 
-    // new cocoa object representation of the media descriptor.
-    return [VLCMedia mediaWithLibVLCMediaDescriptor:p_md];
+    return [cachedMedia objectAtIndex:index];
 }
 
 - (int)count
 {
-    libvlc_exception_t p_e;
-    libvlc_exception_init( &p_e );
-    int result = libvlc_media_list_count( p_mlist, &p_e );
-    quit_on_exception( &p_e );
-
-    return result;
+    return [cachedMedia count];
 }
 
 - (int)indexOfMedia:(VLCMedia *)media
@@ -264,7 +226,17 @@ static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *use
     {
         p_mlist = p_new_mlist;
         libvlc_media_list_retain(p_mlist);
+        libvlc_media_list_lock(p_mlist);
+        cachedMedia = [[NSMutableArray alloc] initWithCapacity:libvlc_media_list_count(p_mlist, NULL)];
+        int i, count = libvlc_media_list_count(p_mlist, NULL);
+        for( i = 0; i < count; i++ )
+        {
+            libvlc_media_descriptor_t * p_md = libvlc_media_list_item_at_index(p_mlist, i, NULL);
+            [cachedMedia addObject:[VLCMedia mediaWithLibVLCMediaDescriptor: p_md]];
+            libvlc_media_descriptor_release(p_md);
+        }
         [self initInternalMediaList];
+        libvlc_media_list_unlock(p_mlist);
     }
     return self;
 }
@@ -285,35 +257,44 @@ static void HandleMediaListWillDeleteItem(const libvlc_event_t *event, void *use
 
     libvlc_event_manager_t *p_em = libvlc_media_list_event_manager( p_mlist, &p_e );
     libvlc_event_attach( p_em, libvlc_MediaListItemAdded,   HandleMediaListItemAdded,   self, &p_e );
-    libvlc_event_attach( p_em, libvlc_MediaListWillAddItem, HandleMediaListWillAddItem, self, &p_e );
     libvlc_event_attach( p_em, libvlc_MediaListItemDeleted, HandleMediaListItemDeleted, self, &p_e );
-    libvlc_event_attach( p_em, libvlc_MediaListWillDeleteItem, HandleMediaListWillDeleteItem, self, &p_e );
     [self unlock];
     
     quit_on_exception( &p_e );
 }
 
 - (void)mediaListItemAdded:(NSDictionary *)args
-{    
+{
+    int index = [[args objectForKey:@"index"] intValue];
+    VLCMedia * media = [args objectForKey:@"media"];
+
+    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"Media"];
+    [cachedMedia insertObject:media atIndex:index];
+    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"Media"];
+
     // Post the notification
     [[NSNotificationCenter defaultCenter] postNotificationName:VLCMediaListItemAdded
                                                         object:self
                                                       userInfo:args];
-    
+
     // Let the delegate know that the item was added
     if (delegate && [delegate respondsToSelector:@selector(mediaList:mediaAdded:atIndex:)])
-        [delegate mediaList:self mediaAdded:[args objectForKey:@"media"] atIndex:[[args objectForKey:@"index"] intValue]];
+        [delegate mediaList:self mediaAdded:media atIndex:index];
 }
 
 - (void)mediaListItemRemoved:(NSNumber *)index
 {
+    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:[index intValue]] forKey:@"Media"];
+    [cachedMedia removeObjectAtIndex:[index intValue]];
+    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:[index intValue]] forKey:@"Media"];
+
     // Post the notification
     [[NSNotificationCenter defaultCenter] postNotificationName:VLCMediaListItemDeleted 
                                                         object:self
                                                       userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
                                                           index, @"index",
                                                           nil]];
-    
+
     // Let the delegate know that the item is being removed
     if (delegate && [delegate respondsToSelector:@selector(mediaList:mediaRemovedAtIndex:)])
         [delegate mediaList:self mediaRemovedAtIndex:[index intValue]];