Commit 88ffe158 authored by Thomas Guillem's avatar Thomas Guillem

access: refactor pf_readdir

The main advantage is to move the management of the input_item_node_t from all
accesses to the directory demux.
parent 5fe33893
......@@ -92,7 +92,11 @@ struct access_t
* XXX A access should set one and only one of them */
ssize_t (*pf_read) ( access_t *, uint8_t *, size_t ); /* Return -1 if no data yet, 0 if no more data, else real data read */
block_t *(*pf_block) ( access_t * ); /* Return a block of data in his 'natural' size, NULL if not yet data or eof */
int (*pf_readdir)( access_t *, input_item_node_t * );/* Fills the provided item_node, see doc/browsing.txt for details */
/* pf_readdir: Read the next input_item_t from the directory stream. It
* returns the next input item on success or NULL in case of error or end
* of stream. The item must be released with input_item_Release. */
input_item_t *(*pf_readdir)( access_t * );
/* Called for each seek.
* XXX can be null */
......
......@@ -67,7 +67,7 @@ struct stream_t
/* */
int (*pf_read) ( stream_t *, void *p_read, unsigned int i_read );
int (*pf_peek) ( stream_t *, const uint8_t **pp_peek, unsigned int i_peek );
int (*pf_readdir)( stream_t *, input_item_node_t * );
input_item_t *(*pf_readdir)( stream_t * );
int (*pf_control)( stream_t *, int i_query, va_list );
/* */
......@@ -134,7 +134,7 @@ VLC_API int stream_Control( stream_t *s, int i_query, ... );
VLC_API block_t * stream_Block( stream_t *s, int i_size );
VLC_API block_t * stream_BlockRemaining( stream_t *s, int i_max_size );
VLC_API char * stream_ReadLine( stream_t * );
VLC_API int stream_ReadDir( stream_t *, input_item_node_t * );
VLC_API input_item_t *stream_ReadDir( stream_t * );
/**
* Get the current position in a stream
......@@ -230,7 +230,7 @@ VLC_API stream_t* stream_FilterNew( stream_t *p_source, const char *psz_stream_f
* Default ReadDir implementation for stream Filter. This implementation just
* forward the pf_readdir call to the p_source stream.
*/
VLC_API int stream_FilterDefaultReadDir( stream_t *s, input_item_node_t *p_node );
VLC_API input_item_t *stream_FilterDefaultReadDir( stream_t *s );
/**
* Sets stream_FilterDefaultReadDir as the pf_readdir callback for this stream filter
......
......@@ -132,39 +132,34 @@ static ssize_t SeekCallback(struct archive *p_archive, void *p_object, ssize_t i
return stream_Tell(p_stream->p_source);
}
static int Browse(stream_t *p_stream, input_item_node_t *p_node)
static input_item_t *Browse(stream_t *p_stream)
{
stream_sys_t *p_sys = p_stream->p_sys;
struct archive_entry *p_entry;
input_item_t *p_item = NULL;
while(archive_read_next_header(p_sys->p_archive, &p_entry) == ARCHIVE_OK)
if (archive_read_next_header(p_sys->p_archive, &p_entry) == ARCHIVE_OK)
{
char *psz_uri = NULL;
char *psz_access_uri = NULL;
int i_ret = asprintf(&psz_access_uri, "%s://%s%c%s", p_stream->psz_access,
p_stream->psz_path, ARCHIVE_SEP_CHAR, archive_entry_pathname(p_entry));
if (i_ret == -1)
goto error;
return NULL;
i_ret = asprintf(&psz_uri, "archive://%s", psz_access_uri);
free(psz_access_uri);
if( i_ret == -1 )
goto error;
return NULL;
input_item_t *p_item = input_item_New(psz_uri, archive_entry_pathname(p_entry));
free( psz_uri );
if(p_item == NULL)
goto error;
return NULL;
input_item_CopyOptions(p_node->p_item, p_item);
input_item_node_AppendItem(p_node, p_item);
msg_Dbg(p_stream, "declaring playlist entry %s", archive_entry_pathname(p_entry));
input_item_Release(p_item);
}
return VLC_SUCCESS;
error:
return VLC_ENOITEM;
return p_item;
}
int StreamOpen(vlc_object_t *p_object)
......
......@@ -353,27 +353,19 @@ void DirClose( vlc_object_t * p_this )
/* This function is a little bit too complex for what it seems to do, but the
* point is to de-recursify directory recusion to avoid overruning the stack
* in case there's a high directory depth */
int DirRead (access_t *p_access, input_item_node_t *p_current_node)
input_item_t* DirRead (access_t *p_access)
{
access_sys_t *p_sys = p_access->p_sys;
input_item_t *p_item = NULL;
while (p_sys->current != NULL
while (!p_item && p_sys->current != NULL
&& p_sys->current->i <= p_sys->current->filec)
{
directory *p_current = p_sys->current;
/* End of the current folder, let's pop directory and node */
if (p_current->i == p_current->filec)
{
directory_pop (p_sys);
p_current_node = p_current_node->p_parent;
continue;
}
char *psz_entry = p_current->filev[p_current->i++];
char *psz_full_uri, *psz_uri;
DIR *handle;
input_item_t *p_new = NULL;
int i_res;
/* Check if it is a directory or even readable */
......@@ -383,7 +375,6 @@ int DirRead (access_t *p_access, input_item_node_t *p_current_node)
|| (i_res == ENTRY_ENOTDIR && has_ext (p_sys->ignored_exts, psz_entry)))
continue;
/* Create an input item for the current entry */
psz_uri = encode_URI_component (psz_entry);
if (psz_uri == NULL
......@@ -398,21 +389,16 @@ int DirRead (access_t *p_access, input_item_node_t *p_current_node)
}
int i_type = i_res == ENTRY_DIR ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
p_new = input_item_NewWithType (psz_full_uri, psz_entry,
0, NULL, 0, 0, i_type);
if (p_new == NULL)
p_item = input_item_NewWithType (psz_full_uri, psz_entry,
0, NULL, 0, 0, i_type);
if (p_item == NULL)
{
free (psz_full_uri);
closedir (handle);
continue;
}
input_item_CopyOptions (p_current_node->p_item, p_new);
input_item_node_AppendItem (p_current_node, p_new);
free (psz_full_uri);
input_item_Release (p_new);
}
return VLC_SUCCESS;
return p_item;
}
......@@ -107,8 +107,7 @@ static void login_dialog( access_t *p_access );
static int login( access_t *p_access );
static void backslash_path( vlc_url_t *p_url );
static bool get_path( access_t *p_access );
static int add_item( access_t *p_access, input_item_node_t *p_node,
const char *psz_name, int i_type );
static input_item_t* new_item( access_t *p_access, const char *psz_name, int i_type );
struct access_sys_t
{
......@@ -126,6 +125,11 @@ struct access_sys_t
smb_fd i_fd; /**< SMB fd for the file we're reading */
smb_tid i_tid; /**< SMB Tree ID we're connected to */
bool b_is_browsing;
size_t i_browse_count;
size_t i_browse_idx;
smb_share_list shares;
smb_stat_list files;
};
/*****************************************************************************
......@@ -240,6 +244,10 @@ static void Close( vlc_object_t *p_this )
if( p_sys->p_session )
smb_session_destroy( p_sys->p_session );
vlc_UrlClean( &p_sys->url );
if( p_sys->shares )
smb_share_list_destroy( p_sys->shares );
if( p_sys->files )
smb_stat_list_destroy( p_sys->files );
free( p_sys->creds.login );
free( p_sys->creds.password );
free( p_sys->creds.domain );
......@@ -559,137 +567,120 @@ static int Control( access_t *p_access, int i_query, va_list args )
return VLC_SUCCESS;
}
static int add_item( access_t *p_access, input_item_node_t *p_node,
const char *psz_name, int i_type )
static input_item_t *new_item( access_t *p_access, const char *psz_name,
int i_type )
{
access_sys_t *p_sys = p_access->p_sys;
input_item_t *p_item;
char *psz_uri, *psz_option;
char *psz_uri, *psz_option = NULL;
int i_ret;
i_ret = asprintf( &psz_uri, "%s/%s", p_node->p_item->psz_uri, psz_name );
i_ret = asprintf( &psz_uri, "smb://%s/%s", p_access->psz_location, psz_name );
if( i_ret == -1 )
return VLC_ENOMEM;
return NULL;
p_item = input_item_NewWithTypeExt( psz_uri, psz_name, 0, NULL, 0, -1,
i_type, 1 );
free( psz_uri );
if( p_item == NULL )
return VLC_ENOMEM;
return NULL;
/* Here we save on the node the credentials that allowed us to login.
* That way the user isn't prompted more than once for credentials */
i_ret = asprintf( &psz_option, "smb-user=%s", p_sys->creds.login );
if( i_ret == -1 )
return VLC_ENOMEM;
goto bailout;
input_item_AddOption( p_item, psz_option, VLC_INPUT_OPTION_TRUSTED );
free( psz_option );
i_ret = asprintf( &psz_option, "smb-pwd=%s", p_sys->creds.password );
if( i_ret == -1 )
return VLC_ENOMEM;
goto bailout;
input_item_AddOption( p_item, psz_option, VLC_INPUT_OPTION_TRUSTED );
free( psz_option );
i_ret = asprintf( &psz_option, "smb-domain=%s", p_sys->creds.domain );
if( i_ret == -1 )
return VLC_ENOMEM;
goto bailout;
input_item_AddOption( p_item, psz_option, VLC_INPUT_OPTION_TRUSTED );
free( psz_option );
input_item_CopyOptions( p_node->p_item, p_item );
i_ret = input_item_node_AppendItem( p_node, p_item ) != NULL ? VLC_SUCCESS
: VLC_EGENERIC;
input_item_Release( p_item );
return i_ret;
return p_item;
bailout:
if( p_item )
input_item_Release( p_item );
free( psz_option );
return NULL;
}
static int BrowseShare( access_t *p_access, input_item_node_t *p_node )
static input_item_t* BrowseShare( access_t *p_access )
{
access_sys_t *p_sys = p_access->p_sys;
smb_share_list shares;
const char *psz_name;
size_t share_count;
int i_ret;
input_item_t *p_item = NULL;
share_count = smb_share_get_list( p_sys->p_session, &shares );
if( !share_count )
return VLC_ENOITEM;
for( size_t i = 0; i < share_count; i++ )
if( !p_sys->i_browse_count )
p_sys->i_browse_count = smb_share_get_list( p_sys->p_session,
&p_sys->shares );
for( ; !p_item && p_sys->i_browse_idx < p_sys->i_browse_count
; p_sys->i_browse_idx++ )
{
psz_name = smb_share_list_at( shares, i );
psz_name = smb_share_list_at( p_sys->shares, p_sys->i_browse_idx );
if( psz_name[strlen( psz_name ) - 1] == '$')
continue;
i_ret = add_item( p_access, p_node, psz_name, ITEM_TYPE_DIRECTORY );
if( i_ret != VLC_SUCCESS )
goto error;
p_item = new_item( p_access, psz_name, ITEM_TYPE_DIRECTORY );
if( !p_item )
return NULL;
}
smb_share_list_destroy( shares );
return VLC_SUCCESS;
error:
smb_share_list_destroy( shares );
return i_ret;
return p_item;
}
static int BrowseDirectory( access_t *p_access, input_item_node_t *p_node )
static input_item_t* BrowseDirectory( access_t *p_access )
{
access_sys_t *p_sys = p_access->p_sys;
smb_stat_list files;
smb_stat st;
input_item_t *p_item = NULL;
char *psz_query;
const char *psz_name;
size_t files_count;
int i_ret;
if( p_sys->psz_path != NULL )
if( !p_sys->i_browse_count )
{
i_ret = asprintf( &psz_query, "%s\\*", p_sys->psz_path );
if( i_ret == -1 )
return VLC_ENOMEM;
files = smb_find( p_sys->p_session, p_sys->i_tid, psz_query );
free( psz_query );
if( p_sys->psz_path != NULL )
{
i_ret = asprintf( &psz_query, "%s\\*", p_sys->psz_path );
if( i_ret == -1 )
return NULL;
p_sys->files = smb_find( p_sys->p_session, p_sys->i_tid, psz_query );
free( psz_query );
}
else
p_sys->files = smb_find( p_sys->p_session, p_sys->i_tid, "\\*" );
if( p_sys->files == NULL )
return NULL;
p_sys->i_browse_count = smb_stat_list_count( p_sys->files );
}
else
files = smb_find( p_sys->p_session, p_sys->i_tid, "\\*" );
if( files == NULL )
return VLC_ENOITEM;
files_count = smb_stat_list_count( files );
for( size_t i = 0; i < files_count; i++ )
if( p_sys->i_browse_idx < p_sys->i_browse_count )
{
int i_type;
st = smb_stat_list_at( files, i );
st = smb_stat_list_at( p_sys->files, p_sys->i_browse_idx++ );
if( st == NULL ) {
i_ret = VLC_ENOITEM;
goto error;
}
if( st == NULL )
return NULL;
psz_name = smb_stat_name( st );
/* Avoid infinite loop */
if( !strcmp( psz_name, ".") || !strcmp( psz_name, "..") )
continue;
i_type = smb_stat_get( st, SMB_STAT_ISDIR ) ?
ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
i_ret = add_item( p_access, p_node, psz_name, i_type );
if( i_ret != VLC_SUCCESS )
goto error;
p_item = new_item( p_access, psz_name, i_type );
if( !p_item )
return NULL;
}
smb_stat_list_destroy( files );
return VLC_SUCCESS;
error:
smb_stat_list_destroy( files );
return i_ret;
return p_item;
}
static int BrowserInit( access_t *p_access )
......
......@@ -25,6 +25,6 @@ void FileClose (vlc_object_t *);
int DirOpen (vlc_object_t *);
int DirInit (access_t *p_access, DIR *handle);
int DirRead (access_t *, input_item_node_t *);
input_item_t* DirRead (access_t *);
int DirControl (access_t *, int, va_list);
void DirClose (vlc_object_t *);
......@@ -106,7 +106,7 @@ vlc_module_end ()
static ssize_t Read( access_t *, uint8_t *, size_t );
static int Seek( access_t *, uint64_t );
static int Control( access_t *, int, va_list );
static int DirRead( access_t *, input_item_node_t * );
static input_item_t* DirRead( access_t * );
#ifdef ENABLE_SOUT
static int OutSeek( sout_access_out_t *, off_t );
static ssize_t Write( sout_access_out_t *, block_t * );
......@@ -839,9 +839,10 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
/*****************************************************************************
* DirRead:
*****************************************************************************/
static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
static input_item_t* DirRead( access_t *p_access )
{
access_sys_t *p_sys = p_access->p_sys;
input_item_t *p_item = NULL;
assert( p_sys->data.fd != -1 );
assert( !p_sys->out );
......@@ -863,23 +864,13 @@ static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
p_sys->url.psz_path ? p_sys->url.psz_path : "",
psz_line ) != -1 )
{
input_item_t *p_item;
p_item = input_item_NewWithTypeExt( psz_uri, psz_line, 0, NULL,
0, -1, ITEM_TYPE_UNKNOWN, 1 );
free( psz_uri );
if( !p_item )
{
free( psz_line );
return VLC_ENOMEM;
}
input_item_CopyOptions( p_current_node->p_item, p_item );
input_item_node_AppendItem( p_current_node, p_item );
input_item_Release( p_item );
}
free( psz_line );
}
return VLC_SUCCESS;
return p_item;
}
/*****************************************************************************
......
......@@ -83,8 +83,7 @@ static block_t* Block( access_t * );
static int Seek( access_t *, uint64_t );
static int Control( access_t *, int, va_list );
static int DirControl( access_t *, int, va_list );
static int DirRead( access_t *p_access, input_item_node_t *p_current_node );
static input_item_t* DirRead( access_t *p_access );
struct access_sys_t
{
......@@ -451,10 +450,11 @@ static int Control( access_t* p_access, int i_query, va_list args )
* Directory access
*****************************************************************************/
static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
static input_item_t* DirRead( access_t *p_access )
{
access_sys_t *p_sys = p_access->p_sys;
LIBSSH2_SFTP_ATTRIBUTES attrs;
input_item_t *p_item = NULL;
int err;
/* Allocate 1024 bytes for file name. Longer names are skipped.
* libssh2 does not support seeking in directory streams.
......@@ -465,9 +465,9 @@ static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
char *psz_file = malloc( i_size );
if( !psz_file )
return VLC_ENOMEM;
return NULL;
while( 0 != ( err = libssh2_sftp_readdir( p_sys->file, psz_file, i_size, &attrs ) ) )
while( !p_item && 0 != ( err = libssh2_sftp_readdir( p_sys->file, psz_file, i_size, &attrs ) ) )
{
if( err < 0 )
{
......@@ -506,29 +506,25 @@ static int DirRead (access_t *p_access, input_item_node_t *p_current_node)
free( psz_uri );
int i_type = LIBSSH2_SFTP_S_ISDIR( attrs.permissions ) ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
input_item_t *p_new = input_item_NewWithTypeExt( psz_full_uri, psz_file,
0, NULL, 0, 0, i_type, 1 );
p_item = input_item_NewWithTypeExt( psz_full_uri, psz_file,
0, NULL, 0, 0, i_type, 1 );
if( p_new == NULL )
if( p_item == NULL )
{
free( psz_full_uri );
continue;
break;
}
/* Here we save on the node the credentials that allowed us to login.
* That way the user isn't prompted more than once for credentials */
if( p_sys->psz_password_opt )
input_item_AddOption( p_new, p_sys->psz_password_opt, VLC_INPUT_OPTION_TRUSTED );
input_item_AddOption( p_item, p_sys->psz_password_opt, VLC_INPUT_OPTION_TRUSTED );
if( p_sys->psz_username_opt )
input_item_AddOption( p_new, p_sys->psz_username_opt, VLC_INPUT_OPTION_TRUSTED );
input_item_CopyOptions( p_current_node->p_item, p_new );
input_item_node_AppendItem( p_current_node, p_new );
input_item_AddOption( p_item, p_sys->psz_username_opt, VLC_INPUT_OPTION_TRUSTED );
free( psz_full_uri );
input_item_Release( p_new );
}
free( psz_file );
return VLC_SUCCESS;
return p_item;
}
......@@ -63,17 +63,37 @@ void Close_Dir ( vlc_object_t *p_this )
static int Demux( demux_t *p_demux )
{
int i_ret = VLC_SUCCESS;
input_item_t *p_input = GetCurrentItem(p_demux);
input_item_node_t *p_node = input_item_node_Create( p_input );
input_item_t *p_item;
input_item_Release(p_input);
if( stream_ReadDir( p_demux->s, p_node ) )
while( !i_ret && ( p_item = stream_ReadDir( p_demux->s ) ) )
{
int i_name_len = p_item->psz_name ? strlen( p_item->psz_name ) : 0;
/* skip "." and ".." items */
if( ( i_name_len == 1 && p_item->psz_name[0] == '.' ) ||
( i_name_len == 2 && p_item->psz_name[0] == '.' &&
p_item->psz_name[1] == '.' ) )
goto skip_item;
input_item_CopyOptions( p_node->p_item, p_item );
if( !input_item_node_AppendItem( p_node, p_item ) )
i_ret = VLC_ENOMEM;
skip_item:
input_item_Release( p_item );
}
if( i_ret )
{
msg_Warn( p_demux, "unable to read directory" );
input_item_node_Delete( p_node );
return VLC_EGENERIC;
return i_ret;
} else
{
input_item_node_PostAndDelete( p_node );
return VLC_SUCCESS;
}
input_item_node_PostAndDelete( p_node );
return VLC_SUCCESS;
}
......@@ -57,6 +57,7 @@ struct services_discovery_sys_t
struct access_sys_t
{
UpnpInstanceWrapper* p_upnp;
Access::MediaServer* p_server;
};
UpnpInstanceWrapper* UpnpInstanceWrapper::s_instance;
......@@ -523,14 +524,25 @@ int MediaServerList::Callback( Upnp_EventType event_type, void* p_event, void* p
namespace Access
{
MediaServer::MediaServer(const char *psz_url, access_t *p_access, input_item_node_t *node)
MediaServer::MediaServer(const char *psz_url, access_t *p_access)
: url_( psz_url )
, access_( p_access )
, node_( node )
, xmlDocument_( NULL )
, containerNodeList_( NULL )
, containerNodeIndex_( 0 )
, itemNodeList_( NULL )
, itemNodeIndex_( 0 )
{
}
void MediaServer::addItem(const char *objectID, const char *title )
MediaServer::~MediaServer()
{
ixmlNodeList_free( containerNodeList_ );
ixmlNodeList_free( itemNodeList_ );
ixmlDocument_free( xmlDocument_ );
}
input_item_t* MediaServer::newItem(const char *objectID, const char *title )
{
vlc_url_t url;
vlc_UrlParse( &url, url_.c_str(), '?' );
......@@ -540,27 +552,21 @@ void MediaServer::addItem(const char *objectID, const char *title )
url.psz_host, url.i_port ? url.i_port : 80, url.psz_path, objectID ) < 0 )
{
vlc_UrlClean( &url );
return ;
return NULL;
}
vlc_UrlClean( &url );
input_item_t* p_item = input_item_NewWithTypeExt( psz_url, title, 0, NULL,
0, -1, ITEM_TYPE_DIRECTORY, 1 );
free( psz_url);
if ( !p_item )
return;
input_item_CopyOptions( node_->p_item, p_item );
input_item_node_AppendItem( node_, p_item );
input_item_Release( p_item );
return p_item;
}
void MediaServer::addItem(const char* title, const char*, const char*,
mtime_t duration, const char* psz_url)
input_item_t* MediaServer::newItem(const char* title, const char*, const char*,
mtime_t duration, const char* psz_url)
{
input_item_t* p_item = input_item_NewWithTypeExt( psz_url, title, 0, NULL, 0,
duration, ITEM_TYPE_FILE, 1 );
input_item_node_AppendItem( node_, p_item );
input_item_Release( p_item );
return input_item_NewWithTypeExt( psz_url, title, 0, NULL, 0,
duration, ITEM_TYPE_FILE, 1 );
}
/* Access part */
......@@ -665,7 +671,7 @@ browseActionCleanup:
/*
* Fetches and parses the UPNP response
*/
bool MediaServer::fetchContents()
void MediaServer::fetchContents()
{
const char* objectID = "";
vlc_url_t url;
......@@ -688,31 +694,45 @@ bool MediaServer::fetchContents()
if ( !p_response )
{
msg_Err( access_, "No response from browse() action" );
return false;
return;
}
IXML_Document* p_result = parseBrowseResult( p_response );
xmlDocument_ = parseBrowseResult( p_response );
ixmlDocument_free( p_response );
if ( !p_result )
if ( !xmlDocument_ )
{
msg_Err( access_, "browse() response parsing failed" );
return false;
return;
}
#ifndef NDEBUG
msg_Dbg( access_, "Got DIDL document: %s", ixmlPrintDocument( p_result ) );
msg_Dbg( access_, "Got DIDL document: %s", ixmlPrintDocument( xmlDocument_ ) );
#endif
IXML_NodeList* containerNodeList =
ixmlDocument_getElementsByTagName( p_result, "container" );
containerNodeList_ = ixmlDocument_getElementsByTagName( xmlDocument_, "container" );
itemNodeList_ = ixmlDocument_getElementsByTagName( xmlDocument_, "item" );
}
input_item_t* MediaServer::getNextItem()
{
input_item_t *p_item = NULL;
if( !xmlDocument_ )
{
fetchContents();
if( !xmlDocument_ )
return NULL;
}
if ( containerNodeList )
if ( containerNodeList_ )
{
for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ )
for ( ; !p_item && containerNodeIndex_ < ixmlNodeList_length( containerNodeList_ )
; containerNodeIndex_++ )
{
IXML_Element* containerElement = (IXML_Element*)ixmlNodeList_item( containerNodeList, i );
IXML_Element* containerElement = (IXML_Element*)ixmlNodeList_item( containerNodeList_,
containerNodeIndex_ );
const char* objectID = ixmlElement_getAttribute( containerElement,
"id" );
......@@ -723,19 +743,18 @@ bool MediaServer::fetchContents()
"dc:title" );
if ( !title )
continue;
addItem(objectID, title);
p_item = newItem(objectID, title);
}
ixmlNodeList_free( containerNodeList );
}
IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( p_result,
"item" );
if ( itemNodeList )
if( itemNodeList_ )
{
for ( unsigned int i = 0; i < ixmlNodeList_length( itemNodeList ); i++ )
for ( ; !p_item && itemNodeIndex_ < ixmlNodeList_length( itemNodeList_ )
; itemNodeIndex_++ )
{
IXML_Element* itemElement =
( IXML_Element* )ixmlNodeList_item( itemNodeList, i );
( IXML_Element* )ixmlNodeList_item( itemNodeList_,
itemNodeIndex_ );
const char* objectID =
ixmlElement_getAttribute( itemElement, "id" );
......@@ -781,24 +800,19 @@ bool MediaServer::fetchContents()
i_seconds );
}
addItem( title, objectID, psz_subtitles, i_duration, psz_resource_url );
p_item = newItem( title, objectID, psz_subtitles, i_duration,
psz_resource_url );
}
ixmlNodeList_free( p_resource_list );
}
ixmlNodeList_free( itemNodeList );