item.c 19.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*****************************************************************************
 * item.c: input_item management
 *****************************************************************************
 * Copyright (C) 1998-2004 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

24 25 26
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
27
#include <assert.h>
28

29
#include <vlc_common.h>
30 31 32
#include "vlc_playlist.h"
#include "vlc_interface.h"

33
#include "item.h"
34

35 36
static void GuessType( input_item_t *p_item );

37 38
/** Stuff moved out of vlc_input.h -- FIXME: should probably not be inline
 * anyway. */
39
static inline void input_item_Init( vlc_object_t *p_o, input_item_t *p_i )
40 41
{
    memset( p_i, 0, sizeof(input_item_t) );
42

43 44 45 46 47 48 49 50
    p_i->psz_name = NULL;
    p_i->psz_uri = NULL;
    TAB_INIT( p_i->i_es, p_i->es );
    TAB_INIT( p_i->i_options, p_i->ppsz_options );
    p_i->optflagv = NULL, p_i->optflagc = 0;
    TAB_INIT( p_i->i_categories, p_i->pp_categories );

    p_i->i_type = ITEM_TYPE_UNKNOWN;
51
    p_i->b_fixed_name = true;
52 53 54 55

    p_i->p_stats = NULL;
    p_i->p_meta = NULL;

56
    vlc_mutex_init( &p_i->lock );
57 58 59 60 61 62 63 64 65
    vlc_event_manager_t * p_em = &p_i->event_manager;
    vlc_event_manager_init( p_em, p_i, p_o );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemMetaChanged );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemSubItemAdded );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemDurationChanged );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemPreparsedChanged );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemNameChanged );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemInfoChanged );
    vlc_event_manager_register_event_type( p_em, vlc_InputItemErrorWhenReadingChanged );
66 67
}

68
static inline void input_item_Clean( input_item_t *p_i )
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
{
    int i;

    vlc_event_manager_fini( &p_i->event_manager );

    free( p_i->psz_name );
    free( p_i->psz_uri );
    if( p_i->p_stats )
    {
        vlc_mutex_destroy( &p_i->p_stats->lock );
        free( p_i->p_stats );
    }

    if( p_i->p_meta )
        vlc_meta_Delete( p_i->p_meta );

    for( i = 0; i < p_i->i_options; i++ )
        free( p_i->ppsz_options[i] );
    TAB_CLEAN( p_i->i_options, p_i->ppsz_options );
    free( p_i->optflagv);

    for( i = 0; i < p_i->i_es; i++ )
    {
        es_format_Clean( p_i->es[i] );
        free( p_i->es[i] );
    }
    TAB_CLEAN( p_i->i_es, p_i->es );

    for( i = 0; i < p_i->i_categories; i++ )
    {
        info_category_t *p_category = p_i->pp_categories[i];
        int j;

        for( j = 0; j < p_category->i_infos; j++ )
        {
            struct info_t *p_info = p_category->pp_infos[j];

            free( p_info->psz_name);
            free( p_info->psz_value );
            free( p_info );
        }
        TAB_CLEAN( p_category->i_infos, p_category->pp_infos );

        free( p_category->psz_name );
        free( p_category );
    }
    TAB_CLEAN( p_i->i_categories, p_i->pp_categories );

    vlc_mutex_destroy( &p_i->lock );
}
119 120 121 122 123 124 125 126 127 128
void input_item_SetErrorWhenReading( input_item_t *p_i, bool b_error )
{
    bool b_changed;

    vlc_mutex_lock( &p_i->lock );

    b_changed = p_i->b_error_when_reading != b_error;
    p_i->b_error_when_reading = b_error;

    vlc_mutex_unlock( &p_i->lock );
129

130 131 132 133 134 135 136 137 138 139
    if( b_changed )
    {
        vlc_event_t event;

        event.type = vlc_InputItemErrorWhenReadingChanged;
        event.u.input_item_error_when_reading_changed.new_value = b_error;
        vlc_event_send( &p_i->event_manager, &event );
    }
}
void input_item_SetPreparsed( input_item_t *p_i, bool b_preparsed )
140
{
141
    bool b_send_event = false;
142

143
    vlc_mutex_lock( &p_i->lock );
144

145 146
    if( !p_i->p_meta )
        p_i->p_meta = vlc_meta_New();
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
    int i_new_status;
    if( b_preparsed )
        i_new_status = p_i->p_meta->i_status | ITEM_PREPARSED;
    else
        i_new_status = p_i->p_meta->i_status & ~ITEM_PREPARSED;
    if( p_i->p_meta->i_status != i_new_status )
    {
        p_i->p_meta->i_status = i_new_status;
        b_send_event = true;
    }

    vlc_mutex_unlock( &p_i->lock );

    if( b_send_event )
    {
        vlc_event_t event;
        event.type = vlc_InputItemPreparsedChanged;
        event.u.input_item_preparsed_changed.new_status = i_new_status;
        vlc_event_send( &p_i->event_manager, &event );
    }
}
void input_item_SetArtNotFound( input_item_t *p_i, bool b_not_found )
{
    vlc_mutex_lock( &p_i->lock );

    if( !p_i->p_meta )
        p_i->p_meta = vlc_meta_New();

    if( b_not_found )
        p_i->p_meta->i_status |= ITEM_ART_NOTFOUND;
    else
        p_i->p_meta->i_status &= ~ITEM_ART_NOTFOUND;

    vlc_mutex_unlock( &p_i->lock );
}
void input_item_SetArtFetched( input_item_t *p_i, bool b_art_fetched )
{
    vlc_mutex_lock( &p_i->lock );

    if( !p_i->p_meta )
        p_i->p_meta = vlc_meta_New();

    if( b_art_fetched )
        p_i->p_meta->i_status |= ITEM_ART_FETCHED;
    else
        p_i->p_meta->i_status &= ~ITEM_ART_FETCHED;

    vlc_mutex_unlock( &p_i->lock );
196 197
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
void input_item_SetMeta( input_item_t *p_i, vlc_meta_type_t meta_type, const char *psz_val )
{
    vlc_event_t event;

    vlc_mutex_lock( &p_i->lock );
    if( !p_i->p_meta )
        p_i->p_meta = vlc_meta_New();
    vlc_meta_Set( p_i->p_meta, meta_type, psz_val );
    vlc_mutex_unlock( &p_i->lock );

    /* Notify interested third parties */
    event.type = vlc_InputItemMetaChanged;
    event.u.input_item_meta_changed.meta_type = meta_type;
    vlc_event_send( &p_i->event_manager, &event );
}

214 215
/* FIXME GRRRRRRRRRR args should be in the reverse order to be 
 * consistant with (nearly?) all or copy funcs */
216
void input_item_CopyOptions( input_item_t *p_parent,
217
                             input_item_t *p_child )
218
{
219 220 221
    vlc_mutex_lock( &p_parent->lock );

    for( int i = 0 ; i< p_parent->i_options; i++ )
222
    {
223
        if( !strcmp( p_parent->ppsz_options[i], "meta-file" ) )
224
            continue;
225

226 227 228
        input_item_AddOption( p_child,
                              p_parent->ppsz_options[i],
                              p_parent->optflagv[i] );
229 230
    }

231
    vlc_mutex_unlock( &p_parent->lock );
232 233 234 235 236 237
}

/* This won't hold the item, but can tell to interested third parties
 * Like the playlist, that there is a new sub item. With this design
 * It is not the input item's responsability to keep all the ref of
 * the input item children. */
238
void input_item_AddSubItem( input_item_t *p_parent, input_item_t *p_child )
239
{
240
    vlc_mutex_lock( &p_parent->lock );
241 242 243

    p_parent->i_type = ITEM_TYPE_PLAYLIST;

244 245
    vlc_mutex_unlock( &p_parent->lock );

246
    /* Notify interested third parties */
247 248
    vlc_event_t event;

249 250 251 252 253
    event.type = vlc_InputItemSubItemAdded;
    event.u.input_item_subitem_added.p_new_child = p_child;
    vlc_event_send( &p_parent->event_manager, &event );
}

254
bool input_item_HasErrorWhenReading( input_item_t *p_item )
255
{
256 257 258 259 260 261 262
    vlc_mutex_lock( &p_item->lock );

    bool b_error = p_item->b_error_when_reading;

    vlc_mutex_unlock( &p_item->lock );

    return b_error;
263 264
}

265 266
bool input_item_MetaMatch( input_item_t *p_i,
                           vlc_meta_type_t meta_type, const char *psz )
267 268
{
    vlc_mutex_lock( &p_i->lock );
269

270 271 272 273 274
    if( !p_i->p_meta )
    {
        vlc_mutex_unlock( &p_i->lock );
        return false;
    }
275 276 277
    const char *psz_meta = vlc_meta_Get( p_i->p_meta, meta_type );
    bool b_ret = psz_meta && strcasestr( psz_meta, psz );

278 279
    vlc_mutex_unlock( &p_i->lock );

280
    return b_ret;
281 282
}

283
char *input_item_GetMeta( input_item_t *p_i, vlc_meta_type_t meta_type )
284 285 286 287 288 289 290 291 292
{
    vlc_mutex_lock( &p_i->lock );

    if( !p_i->p_meta )
    {
        vlc_mutex_unlock( &p_i->lock );
        return NULL;
    }

293
    char *psz = NULL;
294 295 296 297 298 299 300
    if( vlc_meta_Get( p_i->p_meta, meta_type ) )
        psz = strdup( vlc_meta_Get( p_i->p_meta, meta_type ) );

    vlc_mutex_unlock( &p_i->lock );
    return psz;
}

301
char *input_item_GetName( input_item_t *p_item )
302
{
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
    vlc_mutex_lock( &p_item->lock );

    char *psz_name = p_item->psz_name ? strdup( p_item->psz_name ) : NULL;

    vlc_mutex_unlock( &p_item->lock );
    return psz_name;
}
void input_item_SetName( input_item_t *p_item, const char *psz_name )
{
    vlc_mutex_lock( &p_item->lock );

    free( p_item->psz_name );
    p_item->psz_name = strdup( psz_name );

    vlc_mutex_unlock( &p_item->lock );
318 319
}

320
char *input_item_GetURI( input_item_t *p_i )
321 322
{
    vlc_mutex_lock( &p_i->lock );
323

324
    char *psz_s = p_i->psz_uri ? strdup( p_i->psz_uri ) : NULL;
325

326 327 328
    vlc_mutex_unlock( &p_i->lock );
    return psz_s;
}
329
void input_item_SetURI( input_item_t *p_i, const char *psz_uri )
330 331
{
    vlc_mutex_lock( &p_i->lock );
332

333 334
    free( p_i->psz_uri );
    p_i->psz_uri = strdup( psz_uri );
335

336
    GuessType( p_i );
337

338 339 340 341 342 343 344 345 346 347 348 349
    if( !p_i->psz_name && p_i->i_type == ITEM_TYPE_FILE )
    {
        const char *psz_filename = strrchr( p_i->psz_uri, DIR_SEP_CHAR );
        if( psz_filename && *psz_filename == DIR_SEP_CHAR )
            psz_filename++;
        if( psz_filename && *psz_filename )
            p_i->psz_name = strdup( psz_filename );
    }

    if( !p_i->psz_name )
        p_i->psz_name = strdup( p_i->psz_uri );

350 351 352
    vlc_mutex_unlock( &p_i->lock );
}

353
mtime_t input_item_GetDuration( input_item_t *p_i )
354 355
{
    vlc_mutex_lock( &p_i->lock );
356

357
    mtime_t i_duration = p_i->i_duration;
358

359 360 361 362
    vlc_mutex_unlock( &p_i->lock );
    return i_duration;
}

363
void input_item_SetDuration( input_item_t *p_i, mtime_t i_duration )
364
{
365
    bool b_send_event = false;
366 367 368 369 370

    vlc_mutex_lock( &p_i->lock );
    if( p_i->i_duration != i_duration )
    {
        p_i->i_duration = i_duration;
371
        b_send_event = true;
372 373 374
    }
    vlc_mutex_unlock( &p_i->lock );

375
    if( b_send_event )
376 377
    {
        vlc_event_t event;
378

379 380 381 382 383 384 385
        event.type = vlc_InputItemDurationChanged;
        event.u.input_item_duration_changed.new_duration = i_duration;
        vlc_event_send( &p_i->event_manager, &event );
    }
}


386
bool input_item_IsPreparsed( input_item_t *p_item )
387
{
388 389 390
    vlc_mutex_lock( &p_item->lock );
    bool b_preparsed = p_item->p_meta ? ( p_item->p_meta->i_status & ITEM_PREPARSED ) != 0 : false;
    vlc_mutex_unlock( &p_item->lock );
391

392
    return b_preparsed;
393 394
}

395
bool input_item_IsArtFetched( input_item_t *p_item )
396
{
397 398 399
    vlc_mutex_lock( &p_item->lock );
    bool b_fetched = p_item->p_meta ? ( p_item->p_meta->i_status & ITEM_ART_FETCHED ) != 0 : false;
    vlc_mutex_unlock( &p_item->lock );
400

401
    return b_fetched;
402 403
}

404 405 406 407 408 409 410 411 412 413
/**
 * Get a info item from a given category in a given input item.
 *
 * \param p_i The input item to get info from
 * \param psz_cat String representing the category for the info
 * \param psz_name String representing the name of the desired info
 * \return A pointer to the string with the given info if found, or an
 *         empty string otherwise. The caller should free the returned
 *         pointer.
 */
414
char *input_item_GetInfo( input_item_t *p_i,
415 416
                          const char *psz_cat,
                          const char *psz_name )
417 418 419
{
    vlc_mutex_lock( &p_i->lock );

420
    for( int i = 0; i< p_i->i_categories; i++ )
421
    {
422
        const info_category_t *p_cat = p_i->pp_categories[i];
423 424 425 426

        if( !psz_cat || strcmp( p_cat->psz_name, psz_cat ) )
            continue;

427
        for( int j = 0; j < p_cat->i_infos; j++ )
428 429 430 431 432 433 434 435 436 437 438 439 440
        {
            if( !strcmp( p_cat->pp_infos[j]->psz_name, psz_name ) )
            {
                char *psz_ret = strdup( p_cat->pp_infos[j]->psz_value );
                vlc_mutex_unlock( &p_i->lock );
                return psz_ret;
            }
        }
    }
    vlc_mutex_unlock( &p_i->lock );
    return strdup( "" );
}

441
static void input_item_Destroy ( gc_object_t *p_gc )
442
{
443
    input_item_t *p_item = vlc_priv( p_gc, input_item_t );
444

445 446
    input_item_Clean( p_item );
    free( p_item );
447 448
}

449 450
int input_item_AddOption( input_item_t *p_input, const char *psz_option,
                          unsigned flags )
451
{
452 453
    int err = VLC_SUCCESS;

454
    if( psz_option == NULL )
455
        return VLC_EGENERIC;
456 457

    vlc_mutex_lock( &p_input->lock );
458
    if (flags & VLC_INPUT_OPTION_UNIQUE)
459
    {
460 461 462
        for (int i = 0 ; i < p_input->i_options; i++)
            if( !strcmp( p_input->ppsz_options[i], psz_option ) )
                goto out;
463 464
    }

465 466 467 468 469 470 471 472 473
    uint8_t *flagv = realloc (p_input->optflagv, p_input->optflagc + 1);
    if (flagv == NULL)
    {
        err = VLC_ENOMEM;
        goto out;
    }
    p_input->optflagv = flagv;
    flagv[p_input->optflagc++] = flags;

474 475 476 477
    INSERT_ELEM( p_input->ppsz_options, p_input->i_options,
                 p_input->i_options, strdup( psz_option ) );
out:
    vlc_mutex_unlock( &p_input->lock );
478
    return err;
479
}
480

481
int input_item_AddInfo( input_item_t *p_i,
482 483 484
                        const char *psz_cat,
                        const char *psz_name,
                        const char *psz_format, ... )
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
{
    va_list args;
    int i;
    info_t *p_info = NULL;
    info_category_t *p_cat = NULL ;

    vlc_mutex_lock( &p_i->lock );

    for( i = 0 ; i < p_i->i_categories ; i ++ )
    {
        if( !strcmp( p_i->pp_categories[i]->psz_name, psz_cat ) )
        {
            p_cat = p_i->pp_categories[i];
            break;
        }
    }
    if( !p_cat )
    {
        if( !(p_cat = (info_category_t *)malloc( sizeof(info_category_t) )) )
        {
            vlc_mutex_unlock( &p_i->lock );
506
            return VLC_ENOMEM;
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
        }
        p_cat->psz_name = strdup( psz_cat );
        p_cat->i_infos = 0;
        p_cat->pp_infos = 0;
        INSERT_ELEM( p_i->pp_categories, p_i->i_categories, p_i->i_categories,
                     p_cat );
    }

    for( i = 0; i< p_cat->i_infos; i++ )
    {
        if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
        {
            p_info = p_cat->pp_infos[i];
            break;
        }
    }

    if( !p_info )
    {
        if( ( p_info = (info_t *)malloc( sizeof( info_t ) ) ) == NULL )
        {
            vlc_mutex_unlock( &p_i->lock );
529
            return VLC_ENOMEM;
530 531 532 533 534 535
        }
        INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos, p_cat->i_infos, p_info );
        p_info->psz_name = strdup( psz_name );
    }
    else
    {
536
        free( p_info->psz_value );
537 538 539
    }

    va_start( args, psz_format );
540
    if( vasprintf( &p_info->psz_value, psz_format, args) == -1 )
541
        p_info->psz_value = NULL;
542 543 544 545
    va_end( args );

    vlc_mutex_unlock( &p_i->lock );

546 547 548 549 550 551 552
    if( p_info->psz_value )
    {
        vlc_event_t event;

        event.type = vlc_InputItemInfoChanged;
        vlc_event_send( &p_i->event_manager, &event );
    }
553
    return p_info->psz_value ? VLC_SUCCESS : VLC_ENOMEM;
554
}
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
int input_item_DelInfo( input_item_t *p_i,
                        const char *psz_cat,
                        const char *psz_name )
{
    info_category_t *p_cat = NULL;
    int i_cat;
    int i;

    vlc_mutex_lock( &p_i->lock );
    for( i_cat = 0; i_cat < p_i->i_categories; i_cat++ )
    {
        if( !strcmp( p_i->pp_categories[i_cat]->psz_name,
                     psz_cat ) )
        {
            p_cat = p_i->pp_categories[i_cat];
            break;
        }
    }
    if( p_cat == NULL )
    {
        vlc_mutex_unlock( &p_i->lock );
        return VLC_EGENERIC;
    }

    if( psz_name )
    {
        /* Remove a specific info */
        for( i = 0; i < p_cat->i_infos; i++ )
        {
            if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
            {
                free( p_cat->pp_infos[i]->psz_name );
587
                free( p_cat->pp_infos[i]->psz_value );
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
                free( p_cat->pp_infos[i] );
                REMOVE_ELEM( p_cat->pp_infos, p_cat->i_infos, i );
                break;
            }
        }
        if( i >= p_cat->i_infos )
        {
            vlc_mutex_unlock( &p_i->lock );
            return VLC_EGENERIC;
        }
    }
    else
    {
        /* Remove the complete categorie */
        for( i = 0; i < p_cat->i_infos; i++ )
        {
            free( p_cat->pp_infos[i]->psz_name );
605
            free( p_cat->pp_infos[i]->psz_value );
606 607
            free( p_cat->pp_infos[i] );
        }
608
        free( p_cat->pp_infos );
609 610
        REMOVE_ELEM( p_i->pp_categories, p_i->i_categories, i_cat );
    }
611 612 613 614

    // Free the category
    free( p_cat->psz_name );
    free( p_cat );
615 616 617 618 619 620 621 622 623 624
    vlc_mutex_unlock( &p_i->lock );


    vlc_event_t event;
    event.type = vlc_InputItemInfoChanged;
    vlc_event_send( &p_i->event_manager, &event );

    return VLC_SUCCESS;
}

625

626
input_item_t *__input_item_NewExt( vlc_object_t *p_obj, const char *psz_uri,
627 628 629
                                  const char *psz_name,
                                  int i_options,
                                  const char *const *ppsz_options,
630
                                  unsigned i_option_flags,
631
                                  mtime_t i_duration )
632
{
633
    return input_item_NewWithType( p_obj, psz_uri, psz_name,
634
                                  i_options, ppsz_options, i_option_flags,
635 636 637 638
                                  i_duration, ITEM_TYPE_UNKNOWN );
}


639
input_item_t *input_item_NewWithType( vlc_object_t *p_obj, const char *psz_uri,
640 641 642
                                const char *psz_name,
                                int i_options,
                                const char *const *ppsz_options,
643
                                unsigned i_option_flags,
644
                                mtime_t i_duration,
645 646
                                int i_type )
{
647 648
    libvlc_priv_t *priv = libvlc_priv (p_obj->p_libvlc);

649 650 651
    input_item_t* p_input = malloc( sizeof(input_item_t ) );
    if( !p_input )
        return NULL;
652

653
    input_item_Init( p_obj, p_input );
654
    vlc_gc_init( p_input, input_item_Destroy );
655

656 657 658 659
    vlc_object_lock( p_obj->p_libvlc );
    p_input->i_id = ++priv->i_last_input_id;
    vlc_object_unlock( p_obj->p_libvlc );

660
    p_input->b_fixed_name = false;
661 662

    p_input->i_type = i_type;
663
    p_input->b_prefers_tree = false;
664

665 666
    if( psz_uri )
        input_item_SetURI( p_input, psz_uri );
667

668 669 670 671 672
    if( i_type != ITEM_TYPE_UNKNOWN )
        p_input->i_type = i_type;

    if( psz_name )
        input_item_SetName( p_input, psz_name );
673

674 675
    p_input->i_duration = i_duration;

676
    for( int i = 0; i < i_options; i++ )
677
        input_item_AddOption( p_input, ppsz_options[i], i_option_flags );
678 679 680 681 682 683 684
    return p_input;
}

/* Guess the type of the item using the beginning of the mrl */
static void GuessType( input_item_t *p_item)
{
    int i;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
685
    static struct { const char *psz_search; int i_type; }  types_array[] =
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
    {
        { "http", ITEM_TYPE_NET },
        { "dvd", ITEM_TYPE_DISC },
        { "cdda", ITEM_TYPE_CDDA },
        { "mms", ITEM_TYPE_NET },
        { "rtsp", ITEM_TYPE_NET },
        { "udp", ITEM_TYPE_NET },
        { "rtp", ITEM_TYPE_NET },
        { "vcd", ITEM_TYPE_DISC },
        { "v4l", ITEM_TYPE_CARD },
        { "dshow", ITEM_TYPE_CARD },
        { "pvr", ITEM_TYPE_CARD },
        { "dvb", ITEM_TYPE_CARD },
        { "qpsk", ITEM_TYPE_CARD },
        { "sdp", ITEM_TYPE_NET },
        { NULL, 0 }
    };

704 705 706 707 708 709
    if( !p_item->psz_uri )
    {
        p_item->i_type = ITEM_TYPE_FILE;
        return;
    }

710 711 712 713 714 715 716 717 718
    for( i = 0; types_array[i].psz_search != NULL; i++ )
    {
        if( !strncmp( p_item->psz_uri, types_array[i].psz_search,
                      strlen( types_array[i].psz_search ) ) )
        {
            p_item->i_type = types_array[i].i_type;
            return;
        }
    }
719
    p_item->i_type = ITEM_TYPE_FILE;
720
}