sd: add proper item tree support

This adds explicit tree support to the SD callback and the
corresponding playlist back-end.
This commit is contained in:
Rémi Denis-Courmont 2017-05-14 11:22:28 +03:00
parent 1144801418
commit a995ddeef7
3 changed files with 50 additions and 20 deletions

View File

@ -43,8 +43,8 @@ extern "C" {
struct services_discovery_owner_t
{
void *sys; /**< Private data for the owner callbacks */
void (*item_added)(struct services_discovery_t *sd, input_item_t *item,
const char *category);
void (*item_added)(struct services_discovery_t *sd, input_item_t *parent,
input_item_t *item, const char *category);
void (*item_removed)(struct services_discovery_t *sd, input_item_t *item);
};
@ -147,23 +147,41 @@ VLC_USED;
VLC_API void vlc_sd_Destroy( services_discovery_t * );
/**
* Added top-level service callback.
*
* This is a convenience wrapper for services_discovery_AddSubItem().
* It covers the most comomn case wherby the added item is a top-level service,
* i.e. it has no parent node.
*/
static inline void services_discovery_AddItem(services_discovery_t *sd,
input_item_t *item)
{
return sd->owner.item_added(sd, NULL, item, NULL);
}
/**
* Added service callback.
*
* A services discovery module invokes this function when it "discovers" a new
* service, i.e. a new input item.
*
* @note The function does not take ownership of the input item; it might
* however add one of more references. The caller is responsible for releasing
* its reference to the input item.
* @note This callback does not take ownership of the input item; it might
* however (and most probably will) add one of more references to the item.
*
* The caller is responsible for releasing its own reference(s) eventually.
* Keeping a reference is necessary to call services_discovery_RemoveItem() or
* to alter the item later. However, if the caller will never remove nor alter
* the item, it can drop its reference(s) immediately.
*
* @param sd services discoverer / services discovery module instance
* @param item input item to add
*/
static inline void services_discovery_AddItem(services_discovery_t *sd,
input_item_t *item)
static inline void services_discovery_AddSubItem(services_discovery_t *sd,
input_item_t *parent,
input_item_t *item)
{
return sd->owner.item_added(sd, item, NULL);
return sd->owner.item_added(sd, parent, item, NULL);
}
/**
@ -177,7 +195,7 @@ static inline void services_discovery_AddItemCat(services_discovery_t *sd,
input_item_t *item,
const char *category)
{
return sd->owner.item_added(sd, item, category);
return sd->owner.item_added(sd, item, NULL, category);
}
/**

View File

@ -58,6 +58,7 @@ struct libvlc_media_discoverer_t
**************************************************************************/
static void services_discovery_item_added( services_discovery_t *sd,
input_item_t *parent,
input_item_t *p_item,
const char *psz_cat )
{
@ -68,6 +69,11 @@ static void services_discovery_item_added( services_discovery_t *sd,
p_md = libvlc_media_new_from_input_item( p_mdis->p_libvlc_instance,
p_item );
if( parent != NULL )
{
/* Flatten items list for now. TODO: tree support. */
}
else
/* If we have a category, that mean we have to group the items having
* that category in a media_list. */
if( psz_cat )

View File

@ -40,11 +40,14 @@ struct vlc_sd_internal_t
/* A new item has been added to a certain sd */
static void playlist_sd_item_added(services_discovery_t *sd,
input_item_t *p_input, const char *psz_cat)
input_item_t *parent, input_item_t *p_input,
const char *psz_cat)
{
assert(parent == NULL || psz_cat == NULL);
vlc_sd_internal_t *sds = sd->owner.sys;
playlist_t *playlist = (playlist_t *)sd->obj.parent;
playlist_item_t *parent;
playlist_item_t *node;
const char *longname = (sd->description != NULL) ? sd->description : "?";
msg_Dbg(sd, "adding %s", p_input->psz_name ? p_input->psz_name : "(null)");
@ -55,18 +58,21 @@ static void playlist_sd_item_added(services_discovery_t *sd,
PLAYLIST_END,
PLAYLIST_RO_FLAG|PLAYLIST_SKIP_FLAG);
/* If p_parent is in root category (this is clearly a hack) and we have a cat */
if (psz_cat == NULL)
parent = sds->node;
if (parent != NULL)
node = playlist_ItemGetByInput(playlist, parent);
else
{
parent = playlist_ChildSearchName(sds->node, psz_cat);
if (parent == NULL)
parent = playlist_NodeCreate(playlist, psz_cat, sds->node,
PLAYLIST_END, PLAYLIST_RO_FLAG);
if (psz_cat == NULL)
node = sds->node;
else
{ /* Parent is NULL (root) and category is specified.
* This is clearly a hack. TODO: remove this. */
node = playlist_ChildSearchName(sds->node, psz_cat);
if (node == NULL)
node = playlist_NodeCreate(playlist, psz_cat, sds->node,
PLAYLIST_END, PLAYLIST_RO_FLAG);
}
playlist_NodeAddInput(playlist, p_input, parent, 0, PLAYLIST_END);
playlist_NodeAddInput(playlist, p_input, node, 0, PLAYLIST_END);
playlist_Unlock(playlist);
}