+
+ vlc_mutex_unlock( &p_input->lock );
+
+ return p_new_input;
+}
+
+struct item_type_entry
+{
+ const char psz_scheme[7];
+ uint8_t i_type;
+};
+
+static int typecmp( const void *key, const void *entry )
+{
+ const struct item_type_entry *type = entry;
+ const char *uri = key, *scheme = type->psz_scheme;
+
+ return strncmp( uri, scheme, strlen( scheme ) );
+}
+
+/* Guess the type of the item using the beginning of the mrl */
+static int GuessType( const input_item_t *p_item )
+{
+ static const struct item_type_entry tab[] =
+ { /* /!\ Alphabetical order /!\ */
+ /* Short match work, not just exact match */
+ { "alsa", ITEM_TYPE_CARD },
+ { "atsc", ITEM_TYPE_CARD },
+ { "bd", ITEM_TYPE_DISC },
+ { "cable", ITEM_TYPE_CARD },
+ { "cdda", ITEM_TYPE_CDDA },
+ { "dc1394", ITEM_TYPE_CARD },
+ { "dccp", ITEM_TYPE_NET },
+ { "dir", ITEM_TYPE_DIRECTORY },
+ { "dshow", ITEM_TYPE_CARD },
+ { "dv", ITEM_TYPE_CARD },
+ { "dvb", ITEM_TYPE_CARD },
+ { "dvd", ITEM_TYPE_DISC },
+ { "ftp", ITEM_TYPE_NET },
+ { "http", ITEM_TYPE_NET },
+ { "icyx", ITEM_TYPE_NET },
+ { "itpc", ITEM_TYPE_NET },
+ { "jack", ITEM_TYPE_CARD },
+ { "live", ITEM_TYPE_NET }, /* livedotcom */
+ { "mms", ITEM_TYPE_NET },
+ { "mtp", ITEM_TYPE_DISC },
+ { "ofdm", ITEM_TYPE_CARD },
+ { "oss", ITEM_TYPE_CARD },
+ { "pnm", ITEM_TYPE_NET },
+ { "pvr", ITEM_TYPE_CARD },
+ { "qam", ITEM_TYPE_CARD },
+ { "qpsk", ITEM_TYPE_CARD },
+ { "qtcapt", ITEM_TYPE_CARD }, /* qtcapture */
+ { "raw139", ITEM_TYPE_CARD }, /* raw1394 */
+ { "rt", ITEM_TYPE_NET }, /* rtp, rtsp, rtmp */
+ { "satell", ITEM_TYPE_CARD }, /* sattelite */
+ { "screen", ITEM_TYPE_CARD },
+ { "sdp", ITEM_TYPE_NET },
+ { "smb", ITEM_TYPE_NET },
+ { "svcd", ITEM_TYPE_DISC },
+ { "tcp", ITEM_TYPE_NET },
+ { "terres", ITEM_TYPE_CARD }, /* terrestrial */
+ { "udp", ITEM_TYPE_NET }, /* udplite too */
+ { "unsv", ITEM_TYPE_NET },
+ { "usdigi", ITEM_TYPE_CARD }, /* usdigital */
+ { "v4l", ITEM_TYPE_CARD },
+ { "vcd", ITEM_TYPE_DISC },
+ { "window", ITEM_TYPE_CARD },
+ };
+ const struct item_type_entry *e;
+
+ if( !strstr( p_item->psz_uri, "://" ) )
+ return ITEM_TYPE_FILE;
+
+ e = bsearch( p_item->psz_uri, tab, sizeof( tab ) / sizeof( tab[0] ),
+ sizeof( tab[0] ), typecmp );
+ return e ? e->i_type : ITEM_TYPE_FILE;
+}
+
+input_item_node_t *input_item_node_Create( input_item_t *p_input )
+{
+ input_item_node_t* p_node = malloc( sizeof( input_item_node_t ) );
+ if( !p_node )
+ return NULL;
+
+ assert( p_input );
+
+ p_node->p_item = p_input;
+ vlc_gc_incref( p_input );
+
+ p_node->p_parent = NULL;
+ p_node->i_children = 0;
+ p_node->pp_children = NULL;
+
+ return p_node;
+}
+
+static void RecursiveNodeDelete( input_item_node_t *p_node )
+{
+ for( int i = 0; i < p_node->i_children; i++ )
+ RecursiveNodeDelete( p_node->pp_children[i] );
+
+ vlc_gc_decref( p_node->p_item );
+ free( p_node->pp_children );
+ free( p_node );
+}
+
+void input_item_node_Delete( input_item_node_t *p_node )
+{
+ if( p_node->p_parent )
+ {
+ for( int i = 0; i < p_node->p_parent->i_children; i++ )
+ if( p_node->p_parent->pp_children[i] == p_node )
+ {
+ REMOVE_ELEM( p_node->p_parent->pp_children,
+ p_node->p_parent->i_children,
+ i );
+ break;
+ }
+ }
+
+ RecursiveNodeDelete( p_node );
+}
+
+input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_item_t *p_item )
+{
+ input_item_node_t *p_new_child = input_item_node_Create( p_item );
+ if( !p_new_child ) return NULL;
+ input_item_node_AppendNode( p_node, p_new_child );
+ return p_new_child;
+}
+
+void input_item_node_AppendNode( input_item_node_t *p_parent, input_item_node_t *p_child )
+{
+ assert( p_parent && p_child && p_child->p_parent == NULL );
+ INSERT_ELEM( p_parent->pp_children,
+ p_parent->i_children,
+ p_parent->i_children,
+ p_child );
+ p_child->p_parent = p_parent;
+}
+
+void input_item_node_PostAndDelete( input_item_node_t *p_root )
+{
+ post_subitems( p_root );
+
+ vlc_event_t event;
+ event.type = vlc_InputItemSubItemTreeAdded;
+ event.u.input_item_subitem_tree_added.p_root = p_root;
+ vlc_event_send( &p_root->p_item->event_manager, &event );
+
+ input_item_node_Delete( p_root );