]> git.sesse.net Git - vlc/blobdiff - projects/macosx/framework/Sources/VLCMediaListAspect.m
Merge branch 'master' of ssh://git@git.videolan.org/vlc
[vlc] / projects / macosx / framework / Sources / VLCMediaListAspect.m
index aa7411b98ca13854a892be9405cfe515211e08cc..e58fb5a07dfa08b2dcd3314488990c47cf32bfa5 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * VLCMediaList.m: VLC.framework VLCMediaList implementation
+ * VLCMediaListAspect.m: VLCKit.framework VLCMediaListAspect implementation
  *****************************************************************************
  * Copyright (C) 2007 Pierre d'Herbemont
  * Copyright (C) 2007 the VideoLAN team
 @end
 
 @implementation VLCMediaListAspectNode
+- (id)init
+{
+    if(self = [super init])
+    {
+        media = nil;
+        children = nil;
+    }
+    return self;
+}
+- (void)dealloc
+{
+    [media release];
+    [children release];
+    [super dealloc];
+}
+
 @synthesize media;
 @synthesize children;
 
 - (BOOL)isLeaf
 {
-    return self.children == NULL;
+    return self.children == nil;
 }
 
--(void)dealloc
-{
-    [self.children release];
-    [super dealloc];
-}
 @end
 
 @implementation VLCMediaListAspect (KeyValueCodingCompliance)
 /* For the @"media" key */
-- (int) countOfMedia
+- (NSInteger) countOfMedia
 {
     return [cachedNode count];
 }
-- (id) objectInMediaAtIndex:(int)i
+- (id) objectInMediaAtIndex:(NSInteger)i
 {
     return [[cachedNode objectAtIndex:i] media];
 }
 /* For the @"node" key */
-- (int) countOfNode
+- (NSInteger) countOfNode
 {
     return [cachedNode count];
 }
-- (id) objectInNodeAtIndex:(int)i
+- (id) objectInNodeAtIndex:(NSInteger)i
 {
     return [cachedNode objectAtIndex:i];
 }
@@ -84,8 +95,8 @@ static void HandleMediaListViewItemAdded(const libvlc_event_t * event, void * us
 {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
     id self = user_data;
-    [[VLCEventManager sharedManager] callOnMainThreadObject:self 
-                                                 withMethod:@selector(mediaListViewItemAdded:) 
+    [[VLCEventManager sharedManager] callOnMainThreadObject:self
+                                                 withMethod:@selector(mediaListViewItemAdded:)
                                        withArgumentAsObject:[NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
                                                           [VLCMedia mediaWithLibVLCMediaDescriptor:event->u.media_list_item_added.item], @"media",
                                                           [NSNumber numberWithInt:event->u.media_list_item_added.index], @"index",
@@ -97,8 +108,8 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
 {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
     id self = user_data;
-    [[VLCEventManager sharedManager] callOnMainThreadObject:self 
-                                                 withMethod:@selector(mediaListViewItemRemoved:) 
+    [[VLCEventManager sharedManager] callOnMainThreadObject:self
+                                                 withMethod:@selector(mediaListViewItemRemoved:)
                                        withArgumentAsObject:[NSNumber numberWithInt:event->u.media_list_item_deleted.index]];
     [pool release];
 }
@@ -113,10 +124,28 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
         [parentMediaList release];
     [super dealloc];
 }
+
+- (void)release
+{
+    @synchronized(self)
+    {
+        if([self retainCount] <= 1)
+        {
+            /* We must make sure we won't receive new event after an upcoming dealloc
+             * We also may receive a -retain in some event callback that may occcur
+             * Before libvlc_event_detach. So this can't happen in dealloc */
+            libvlc_event_manager_t * p_em = libvlc_media_list_view_event_manager(p_mlv);
+            libvlc_event_detach(p_em, libvlc_MediaListViewItemDeleted, HandleMediaListViewItemDeleted, self);
+            libvlc_event_detach(p_em, libvlc_MediaListViewItemAdded,   HandleMediaListViewItemAdded,   self);
+        }
+        [super release];
+    }
+}
+
 - (NSString *)description
 {
     NSMutableString * content = [NSMutableString string];
-    int i;
+    NSUInteger i;
     for( i = 0; i < [self count]; i++)
     {
         [content appendFormat:@"%@\n", [self mediaAtIndex: i]];
@@ -124,19 +153,19 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
     return [NSString stringWithFormat:@"<%@ %p> {\n%@}", [self className], self, content];
 }
 
-- (VLCMedia *)mediaAtIndex:(int)index
+- (VLCMedia *)mediaAtIndex:(NSInteger)index
 {
     libvlc_exception_t p_e;
     libvlc_exception_init( &p_e );
-    libvlc_media_descriptor_t * p_md = libvlc_media_list_view_item_at_index( p_mlv, index, &p_e );
+    libvlc_media_t * p_md = libvlc_media_list_view_item_at_index( p_mlv, index, &p_e );
     catch_exception( &p_e );
-    
-    // Returns local object for media descriptor, searchs for user data first.  If not found it creates a 
+
+    // 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];
 }
 
-- (VLCMediaListAspect *)childrenAtIndex:(int)index
+- (VLCMediaListAspect *)childrenAtIndex:(NSInteger)index
 {
     libvlc_exception_t p_e;
     libvlc_exception_init( &p_e );
@@ -146,23 +175,29 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
     if( !p_sub_mlv )
         return nil;
 
-    // Returns local object for media descriptor, searchs for user data first.  If not found it creates a 
+    // 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 [VLCMediaListAspect mediaListAspectWithLibVLCMediaListView:p_sub_mlv];
 }
 
-- (VLCMediaListAspectNode *)nodeAtIndex:(int)index
+- (VLCMediaListAspectNode *)nodeAtIndex:(NSInteger)index
 {
     VLCMediaListAspectNode * node = [[[VLCMediaListAspectNode alloc] init] autorelease];
     [node setMedia:[self mediaAtIndex: index]];
+    libvlc_media_list_view_t * p_sub_mlv = libvlc_media_list_view_children_for_item([self libVLCMediaListView], [node.media libVLCMediaDescriptor], NULL);
+    if( p_sub_mlv )
+    {
+        [node setChildren:[VLCMediaListAspect mediaListAspectWithLibVLCMediaListView: p_sub_mlv]];
+        libvlc_media_list_view_release(p_sub_mlv);
+    }
     return node;
 }
 
-- (int)count
+- (NSInteger)count
 {
     libvlc_exception_t p_e;
     libvlc_exception_init( &p_e );
-    int result = libvlc_media_list_view_count( p_mlv, &p_e );
+    NSInteger result = libvlc_media_list_view_count( p_mlv, &p_e );
     catch_exception( &p_e );
 
     return result;
@@ -210,16 +245,18 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
         libvlc_media_list_t * p_mlist;
         p_mlist = libvlc_media_list_view_parent_media_list( p_mlv, NULL );
         libvlc_media_list_lock( p_mlist );
-        int i, count = libvlc_media_list_view_count(p_mlv, NULL);
+        NSUInteger i, count = libvlc_media_list_view_count(p_mlv, NULL);
         for( i = 0; i < count; i++ )
         {
-            libvlc_media_descriptor_t * p_md = libvlc_media_list_view_item_at_index(p_mlv, i, NULL);
+            libvlc_media_t * p_md = libvlc_media_list_view_item_at_index(p_mlv, i, NULL);
             libvlc_media_list_view_t * p_sub_mlv = libvlc_media_list_view_children_at_index(p_mlv, i, NULL);
             VLCMediaListAspectNode * node = [[[VLCMediaListAspectNode alloc] init] autorelease];
             [node setMedia:[VLCMedia mediaWithLibVLCMediaDescriptor: p_md]];
             [node setChildren: p_sub_mlv ? [VLCMediaListAspect mediaListAspectWithLibVLCMediaListView: p_sub_mlv] : nil];
+            if( p_sub_mlv ) NSAssert(![node isLeaf], @"Not leaf");
+
             [cachedNode addObject:node];
-            libvlc_media_descriptor_release(p_md);
+            libvlc_media_release(p_md);
             if( p_sub_mlv ) libvlc_media_list_view_release(p_sub_mlv);
         }
         [self initInternalMediaListView];
@@ -238,15 +275,11 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
 @implementation VLCMediaListAspect (Private)
 - (void)initInternalMediaListView
 {
-    libvlc_exception_t e;
-    libvlc_exception_init( &e );
-
-    libvlc_event_manager_t * p_em = libvlc_media_list_event_manager( p_mlv, &e );
+    libvlc_event_manager_t * p_em = libvlc_media_list_event_manager(p_mlv);
 
     /* Add internal callback */
-    libvlc_event_attach( p_em, libvlc_MediaListViewItemAdded,   HandleMediaListViewItemAdded,   self, &e );
-    libvlc_event_attach( p_em, libvlc_MediaListViewItemDeleted, HandleMediaListViewItemDeleted, self, &e );
-    catch_exception( &e );
+    libvlc_event_attach(p_em, libvlc_MediaListViewItemAdded,   HandleMediaListViewItemAdded,   self);
+    libvlc_event_attach(p_em, libvlc_MediaListViewItemDeleted, HandleMediaListViewItemDeleted, self);
 }
 
 - (void)mediaListViewItemAdded:(NSArray *)arrayOfArgs
@@ -254,19 +287,29 @@ static void HandleMediaListViewItemDeleted( const libvlc_event_t * event, void *
     NSAssert([NSThread isMainThread], @"We are not on main thread");
 
     /* We hope to receive index in a nide range, that could change one day */
-    int start = [[[arrayOfArgs objectAtIndex: 0] objectForKey:@"index"] intValue];
-    int end = [[[arrayOfArgs objectAtIndex: [arrayOfArgs count]-1] objectForKey:@"index"] intValue];
+    NSInteger start = [[[arrayOfArgs objectAtIndex: 0] objectForKey:@"index"] intValue];
+    NSInteger end = [[[arrayOfArgs objectAtIndex: [arrayOfArgs count]-1] objectForKey:@"index"] intValue];
     NSRange range = NSMakeRange(start, end-start);
 
     [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndexesInRange:range] forKey:@"media"];
     [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndexesInRange:range] forKey:@"node"];
     for( NSDictionary * args in arrayOfArgs )
     {
-        int index = [[args objectForKey:@"index"] intValue];
+        NSInteger index = [[args objectForKey:@"index"] intValue];
         VLCMedia * media = [args objectForKey:@"media"];
         VLCMediaListAspectNode * node = [[[VLCMediaListAspectNode alloc] init] autorelease];
         [node setMedia:media];
-        [node setChildren:[self childrenAtIndex:index]];
+
+        /* Set the sub media list view we enventually have */
+        libvlc_media_list_view_t * p_sub_mlv = libvlc_media_list_view_children_for_item([self libVLCMediaListView], [media libVLCMediaDescriptor], NULL);
+
+        if( p_sub_mlv )
+        {
+            [node setChildren:[VLCMediaListAspect mediaListAspectWithLibVLCMediaListView: p_sub_mlv]];
+            libvlc_media_list_view_release(p_sub_mlv);
+            NSAssert(![node isLeaf], @"Not leaf");
+        }
+
         /* Sanity check */
         if( index && index > [cachedNode count] )
             index = [cachedNode count];