X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fcontrol%2Fmedia_list_view.c;h=5ed71d0f9d77e395fdc6ffade8eb2204261209db;hb=9d65e77152039fcb91ff55e8a590bafc17f642c0;hp=196265eb617389fcdaecd4f3222616f569ac3261;hpb=1524a416f434bfd6f370eacb1157efeaab13d553;p=vlc diff --git a/src/control/media_list_view.c b/src/control/media_list_view.c index 196265eb61..5ed71d0f9d 100644 --- a/src/control/media_list_view.c +++ b/src/control/media_list_view.c @@ -3,7 +3,7 @@ * media_list.c). ***************************************************************************** * Copyright (C) 2007 the VideoLAN team - * $Id: flat_media_list.c 21287 2007-08-20 01:28:12Z pdherbemont $ + * $Id$ * * Authors: Pierre d'Herbemont * @@ -39,53 +39,154 @@ * Private functions */ static void +media_list_item_added( const libvlc_event_t * p_event, void * p_user_data ); +static void media_list_item_removed( const libvlc_event_t * p_event, void * p_user_data ); +static void +media_list_subitem_added( const libvlc_event_t * p_event, void * p_user_data ); static void -media_list_item_added( const libvlc_event_t * p_event, void * p_user_data ) +install_md_listener( libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_md) { - libvlc_media_list_view_t * p_mlv = p_user_data; - libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item; libvlc_media_list_t * p_mlist; - if((p_mlist = libvlc_media_descriptor_subitems( p_md, NULL ))) + if((p_mlist = libvlc_media_subitems( p_md, NULL ))) { + libvlc_media_list_lock( p_mlist ); + int i, count = libvlc_media_list_count( p_mlist, NULL ); + for( i = 0; i < count; i++) + { + libvlc_event_t added_event; + libvlc_media_t * p_submd; + p_submd = libvlc_media_list_item_at_index( p_mlist, i, NULL ); + + /* Install our listeners */ + install_md_listener( p_mlv, p_submd ); + + /* For each item, send a notification to the mlv subclasses */ + added_event.u.media_list_item_added.item = p_submd; + added_event.u.media_list_item_added.index = 0; + if( p_mlv->pf_ml_item_added ) p_mlv->pf_ml_item_added( &added_event, p_mlv ); + libvlc_media_release( p_submd ); + } libvlc_event_attach( p_mlist->p_event_manager, libvlc_MediaListItemAdded, media_list_item_added, p_mlv, NULL ); libvlc_event_attach( p_mlist->p_event_manager, libvlc_MediaListItemDeleted, media_list_item_removed, p_mlv, NULL ); + libvlc_media_list_unlock( p_mlist ); + libvlc_media_list_release( p_mlist ); + } + else + { + /* No mlist, wait for a subitem added event */ + libvlc_event_attach( p_md->p_event_manager, + libvlc_MediaSubItemAdded, + media_list_subitem_added, p_mlv, NULL ); } - if( p_mlv->pf_ml_item_added ) p_mlv->pf_ml_item_added( p_event, p_user_data ); +} + +static void +uninstall_md_listener( libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_md) +{ + libvlc_media_list_t * p_mlist; + libvlc_exception_t ignored_exception; + libvlc_exception_init( &ignored_exception ); + libvlc_event_detach( p_md->p_event_manager, + libvlc_MediaSubItemAdded, + media_list_subitem_added, p_mlv, &ignored_exception ); + if( libvlc_exception_raised( &ignored_exception ) ) + libvlc_exception_clear( &ignored_exception ); /* We don't care if we encounter an exception */ + if((p_mlist = libvlc_media_subitems( p_md, NULL ))) + { + libvlc_media_list_lock( p_mlist ); + libvlc_event_detach( p_mlist->p_event_manager, + libvlc_MediaListItemAdded, + media_list_item_added, p_mlv, NULL ); + libvlc_event_detach( p_mlist->p_event_manager, + libvlc_MediaListItemDeleted, + media_list_item_removed, p_mlv, NULL ); + + int i, count = libvlc_media_list_count( p_mlist, NULL ); + for( i = 0; i < count; i++) + { + libvlc_media_t * p_submd; + p_submd = libvlc_media_list_item_at_index( p_mlist,i, NULL ); + uninstall_md_listener( p_mlv, p_submd ); + libvlc_media_release( p_submd ); + } + libvlc_media_list_unlock( p_mlist ); + libvlc_media_list_release( p_mlist ); + } +} + +static void +media_list_item_added( const libvlc_event_t * p_event, void * p_user_data ) +{ + libvlc_media_list_view_t * p_mlv = p_user_data; + libvlc_media_t * p_md = p_event->u.media_list_item_added.item; + install_md_listener( p_mlv, p_md ); + if( p_mlv->pf_ml_item_added ) p_mlv->pf_ml_item_added( p_event, p_mlv ); } static void media_list_item_removed( const libvlc_event_t * p_event, void * p_user_data ) { libvlc_media_list_view_t * p_mlv = p_user_data; - libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item; + libvlc_media_t * p_md = p_event->u.media_list_item_added.item; + uninstall_md_listener( p_mlv, p_md ); + if( p_mlv->pf_ml_item_removed ) p_mlv->pf_ml_item_removed( p_event, p_mlv ); +} + +static void +media_list_subitem_added( const libvlc_event_t * p_event, void * p_user_data ) +{ libvlc_media_list_t * p_mlist; - if((p_mlist = libvlc_media_descriptor_subitems( p_md, NULL ))) + libvlc_event_t added_event; + libvlc_media_list_view_t * p_mlv = p_user_data; + libvlc_media_t * p_submd = p_event->u.media_subitem_added.new_child; + libvlc_media_t * p_md = p_event->p_obj; + + if((p_mlist = libvlc_media_subitems( p_md, NULL ))) { + /* We have a mlist to which we're going to listen to events + * thus, no need to wait for SubItemAdded events */ + libvlc_event_detach( p_md->p_event_manager, + libvlc_MediaSubItemAdded, + media_list_subitem_added, p_mlv, NULL ); + libvlc_media_list_lock( p_mlist ); + libvlc_event_attach( p_mlist->p_event_manager, libvlc_MediaListItemAdded, media_list_item_added, p_mlv, NULL ); libvlc_event_attach( p_mlist->p_event_manager, libvlc_MediaListItemDeleted, media_list_item_removed, p_mlv, NULL ); + libvlc_media_list_unlock( p_mlist ); + libvlc_media_list_release( p_mlist ); } - if( p_mlv->pf_ml_item_removed ) p_mlv->pf_ml_item_removed( p_event, p_user_data ); -} + install_md_listener( p_mlv, p_submd ); + + added_event.u.media_list_item_added.item = p_submd; + added_event.u.media_list_item_added.index = 0; + if( p_mlv->pf_ml_item_added ) p_mlv->pf_ml_item_added( &added_event, p_mlv ); +} /* * LibVLC Internal functions */ +/************************************************************************** + * libvlc_media_list_view_set_ml_notification_callback (Internal) + * The mlist lock should be held when entered + **************************************************************************/ void libvlc_media_list_view_set_ml_notification_callback( libvlc_media_list_view_t * p_mlv, - void (*item_added)(const libvlc_event_t *, void *), - void (*item_removed)(const libvlc_event_t *, void *) ) + void (*item_added)(const libvlc_event_t *, libvlc_media_list_view_t *), + void (*item_removed)(const libvlc_event_t *, libvlc_media_list_view_t *) ) { p_mlv->pf_ml_item_added = item_added; p_mlv->pf_ml_item_removed = item_removed; @@ -95,6 +196,94 @@ libvlc_media_list_view_set_ml_notification_callback( libvlc_event_attach( p_mlv->p_mlist->p_event_manager, libvlc_MediaListItemDeleted, media_list_item_removed, p_mlv, NULL ); + int i, count = libvlc_media_list_count( p_mlv->p_mlist, NULL ); + for( i = 0; i < count; i++) + { + libvlc_media_t * p_md; + p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, NULL ); + install_md_listener( p_mlv, p_md ); + libvlc_media_release( p_md ); + } +} + +/************************************************************************** + * libvlc_media_list_view_notify_deletion (Internal) + **************************************************************************/ +void +libvlc_media_list_view_will_delete_item( + libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_item, + int index ) +{ + libvlc_event_t event; + + /* Construct the event */ + event.type = libvlc_MediaListViewWillDeleteItem; + event.u.media_list_view_will_delete_item.item = p_item; + event.u.media_list_view_will_delete_item.index = index; + + /* Send the event */ + libvlc_event_send( p_mlv->p_event_manager, &event ); +} + +/************************************************************************** + * libvlc_media_list_view_item_deleted (Internal) + **************************************************************************/ +void +libvlc_media_list_view_item_deleted( + libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_item, + int index ) +{ + libvlc_event_t event; + + /* Construct the event */ + event.type = libvlc_MediaListViewItemDeleted; + event.u.media_list_view_item_deleted.item = p_item; + event.u.media_list_view_item_deleted.index = index; + + /* Send the event */ + libvlc_event_send( p_mlv->p_event_manager, &event ); +} + +/************************************************************************** + * libvlc_media_list_view_will_add_item (Internal) + **************************************************************************/ +void +libvlc_media_list_view_will_add_item( + libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_item, + int index ) +{ + libvlc_event_t event; + + /* Construct the event */ + event.type = libvlc_MediaListViewWillAddItem; + event.u.media_list_view_will_add_item.item = p_item; + event.u.media_list_view_will_add_item.index = index; + + /* Send the event */ + libvlc_event_send( p_mlv->p_event_manager, &event ); +} + +/************************************************************************** + * libvlc_media_list_view_item_added (Internal) + **************************************************************************/ +void +libvlc_media_list_view_item_added( + libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_item, + int index ) +{ + libvlc_event_t event; + + /* Construct the event */ + event.type = libvlc_MediaListViewItemAdded; + event.u.media_list_view_item_added.item = p_item; + event.u.media_list_view_item_added.index = index; + + /* Send the event */ + libvlc_event_send( p_mlv->p_event_manager, &event ); } /************************************************************************** @@ -104,6 +293,8 @@ libvlc_media_list_view_t * libvlc_media_list_view_new( libvlc_media_list_t * p_mlist, libvlc_media_list_view_count_func_t pf_count, libvlc_media_list_view_item_at_index_func_t pf_item_at_index, + libvlc_media_list_view_children_at_index_func_t pf_children_at_index, + libvlc_media_list_view_constructor_func_t pf_constructor, libvlc_media_list_view_release_func_t pf_release, void * this_view_data, libvlc_exception_t * p_e ) @@ -117,16 +308,27 @@ libvlc_media_list_view_new( libvlc_media_list_t * p_mlist, p_mlv->p_event_manager = libvlc_event_manager_new( p_mlist, p_mlv->p_libvlc_instance, p_e ); + libvlc_event_manager_register_event_type( p_mlv->p_event_manager, + libvlc_MediaListViewItemAdded, p_e ); + libvlc_event_manager_register_event_type( p_mlv->p_event_manager, + libvlc_MediaListViewWillAddItem, p_e ); + libvlc_event_manager_register_event_type( p_mlv->p_event_manager, + libvlc_MediaListViewItemDeleted, p_e ); + libvlc_event_manager_register_event_type( p_mlv->p_event_manager, + libvlc_MediaListViewWillDeleteItem, p_e ); + libvlc_media_list_retain( p_mlist ); p_mlv->p_mlist = p_mlist; - p_mlv->pf_count = pf_count; - p_mlv->pf_item_at_index = pf_item_at_index; - p_mlv->pf_release = pf_release; + p_mlv->pf_count = pf_count; + p_mlv->pf_item_at_index = pf_item_at_index; + p_mlv->pf_children_at_index = pf_children_at_index; + p_mlv->pf_constructor = pf_constructor; + p_mlv->pf_release = pf_release; p_mlv->p_this_view_data = this_view_data; - vlc_mutex_init( p_mlv->p_libvlc_instance->p_libvlc_int, &p_mlv->object_lock ); + vlc_mutex_init( &p_mlv->object_lock ); p_mlv->i_refcount = 1; return p_mlv; @@ -141,7 +343,7 @@ libvlc_media_list_view_new( libvlc_media_list_t * p_mlist, * libvlc_media_list_view_retain (Public) **************************************************************************/ void -libvlc_media_list_view_release( libvlc_media_list_view_t * p_mlv ) +libvlc_media_list_view_retain( libvlc_media_list_view_t * p_mlv ) { vlc_mutex_lock( &p_mlv->object_lock ); p_mlv->i_refcount++; @@ -164,21 +366,29 @@ libvlc_media_list_view_release( libvlc_media_list_view_t * p_mlv ) vlc_mutex_unlock( &p_mlv->object_lock ); /* Refcount null, time to free */ + libvlc_media_list_lock( p_mlv->p_mlist ); if( p_mlv->pf_ml_item_added ) { libvlc_event_detach( p_mlv->p_mlist->p_event_manager, libvlc_MediaListItemAdded, - p_mlv->pf_ml_item_added, p_mlv, NULL ); - /* XXX: descend the whole tree and remove observer */ + media_list_item_added, p_mlv, NULL ); } if( p_mlv->pf_ml_item_removed ) { libvlc_event_detach( p_mlv->p_mlist->p_event_manager, libvlc_MediaListItemDeleted, - p_mlv->pf_ml_item_removed, p_mlv, NULL ); - /* XXX: descend the whole tree and remove observer */ + media_list_item_removed, p_mlv, NULL ); + } + int i, count = libvlc_media_list_count( p_mlv->p_mlist, NULL ); + for( i = 0; i < count; i++) + { + libvlc_media_t * p_md; + p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, NULL ); + uninstall_md_listener( p_mlv, p_md ); + libvlc_media_release( p_md ); } + libvlc_media_list_unlock( p_mlv->p_mlist ); libvlc_event_manager_release( p_mlv->p_event_manager ); @@ -187,6 +397,56 @@ libvlc_media_list_view_release( libvlc_media_list_view_t * p_mlv ) vlc_mutex_destroy( &p_mlv->object_lock ); } +/************************************************************************** + * libvlc_media_list_view_event_manager (Public) + **************************************************************************/ +libvlc_event_manager_t * +libvlc_media_list_view_event_manager( libvlc_media_list_view_t * p_mlv ) +{ + libvlc_event_manager_t * p_em; + vlc_mutex_lock( &p_mlv->object_lock ); + p_em = p_mlv->p_event_manager; + vlc_mutex_unlock( &p_mlv->object_lock ); + return p_em; +} + +/************************************************************************** + * libvlc_media_list_view_parent_media_list (Public) + **************************************************************************/ +libvlc_media_list_t * +libvlc_media_list_view_parent_media_list( libvlc_media_list_view_t * p_mlv, + libvlc_exception_t * p_e) +{ + (void)p_e; + libvlc_media_list_t * p_mlist; + vlc_mutex_lock( &p_mlv->object_lock ); + p_mlist = p_mlv->p_mlist; + libvlc_media_list_retain( p_mlv->p_mlist ); + vlc_mutex_unlock( &p_mlv->object_lock ); + return p_mlist; +} + +/************************************************************************** + * libvlc_media_list_view_children_for_item (Public) + **************************************************************************/ +libvlc_media_list_view_t * +libvlc_media_list_view_children_for_item( libvlc_media_list_view_t * p_mlv, + libvlc_media_t * p_md, + libvlc_exception_t * p_e) +{ + (void)p_e; + libvlc_media_list_t * p_mlist; + libvlc_media_list_view_t * ret; + + p_mlist = libvlc_media_subitems(p_md, p_e); + if(!p_mlist) return NULL; + + ret = p_mlv->pf_constructor( p_mlist, p_e ); + libvlc_media_list_release( p_mlist ); + + return ret; +} + /* Limited to four args, because it should be enough */ #define AN_SELECT( collapser, dec1, dec2, dec3, dec4, p, ...) p @@ -224,5 +484,6 @@ libvlc_media_list_view_release( libvlc_media_list_view_t * p_mlv ) MEDIA_LIST_VIEW_FUNCTION( count, int, 0 ) -MEDIA_LIST_VIEW_FUNCTION( item_at_index, libvlc_media_descriptor_t *, NULL, int arg1 ) +MEDIA_LIST_VIEW_FUNCTION( item_at_index, libvlc_media_t *, NULL, int arg1 ) +MEDIA_LIST_VIEW_FUNCTION( children_at_index, libvlc_media_list_view_t *, NULL, int arg1 )