/**
 * Moves an item
 *
 * This function must be entered with the playlist lock
 *
 * \param p_playlist the playlist
 * \param p_item the item to move
 * \param p_node the new parent of the item
 * \param i_newpos the new position under this new parent
 * \return VLC_SUCCESS or an error
 */
int playlist_TreeMove( playlist_t * p_playlist, playlist_item_t *p_item,
                       playlist_item_t *p_node, int i_newpos )
{
    PL_ASSERT_LOCKED;

    if( p_node->i_children == -1 ) return VLC_EGENERIC;

    playlist_item_t *p_detach = p_item->p_parent;
    int i_index = ItemIndex( p_item );

    REMOVE_ELEM( p_detach->pp_children, p_detach->i_children, i_index );

    if( p_detach == p_node && i_index < i_newpos )
        i_newpos--;

    INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item );
    p_item->p_parent = p_node;

    pl_priv( p_playlist )->b_reset_currently_playing = true;
    vlc_cond_signal( &pl_priv( p_playlist )->signal );
    return VLC_SUCCESS;
}
Exemple #2
0
void input_item_MergeInfos( input_item_t *p_item, info_category_t *p_cat )
{
    vlc_mutex_lock( &p_item->lock );
    info_category_t *p_old = InputItemFindCat( p_item, NULL, p_cat->psz_name );
    if( p_old )
    {
        for( int i = 0; i < p_cat->i_infos; i++ )
            info_category_ReplaceInfo( p_old, p_cat->pp_infos[i] );
        TAB_CLEAN( p_cat->i_infos, p_cat->pp_infos );
        info_category_Delete( p_cat );
    }
    else
    {
        INSERT_ELEM( p_item->pp_categories, p_item->i_categories, p_item->i_categories,
                     p_cat );
    }
    vlc_mutex_unlock( &p_item->lock );


    vlc_event_t event;
    event.type = vlc_InputItemInfoChanged;
    vlc_event_send( &p_item->event_manager, &event );
}
Exemple #3
0
void playlist_preparser_Push( playlist_preparser_t *p_preparser, input_item_t *p_item,
                              input_item_meta_request_option_t i_options )
{
    preparser_entry_t *p_entry = malloc( sizeof(preparser_entry_t) );

    if ( !p_entry )
        return;
    p_entry->p_item = p_item;
    p_entry->i_options = i_options;
    vlc_gc_incref( p_entry->p_item );

    vlc_mutex_lock( &p_preparser->lock );
    INSERT_ELEM( p_preparser->pp_waiting, p_preparser->i_waiting,
                 p_preparser->i_waiting, p_entry );
    if( !p_preparser->b_live )
    {
        if( vlc_clone_detach( NULL, Thread, p_preparser,
                              VLC_THREAD_PRIORITY_LOW ) )
            msg_Warn( p_preparser->object, "cannot spawn pre-parser thread" );
        else
            p_preparser->b_live = true;
    }
    vlc_mutex_unlock( &p_preparser->lock );
}
Exemple #4
0
/**
 * Register a callback in a variable
 *
 * We store a function pointer that will be called upon variable
 * modification.
 *
 * \param p_this The object that holds the variable
 * \param psz_name The name of the variable
 * \param pf_callback The function pointer
 * \param p_data A generic pointer that will be passed as the last
 *               argument to the callback function.
 *
 * \warning The callback function is run in the thread that calls var_Set on
 *          the variable. Use proper locking. This thread may not have much
 *          time to spare, so keep callback functions short.
 */
int var_AddCallback( vlc_object_t *p_this, const char *psz_name,
                     vlc_callback_t pf_callback, void *p_data )
{
    variable_t *p_var;
    callback_entry_t entry;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    entry.pf_callback = pf_callback;
    entry.p_data = p_data;

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
#ifndef NDEBUG
        msg_Warn( p_this, "Failed to add a callback to the non-existing "
                          "variable '%s'", psz_name );
#endif
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_ENOVAR;
    }

    WaitUnused( p_this, p_var );
    INSERT_ELEM( p_var->p_entries,
                 p_var->i_entries,
                 p_var->i_entries,
                 entry );

    vlc_mutex_unlock( &p_priv->var_lock );

    return VLC_SUCCESS;
}
Exemple #5
0
/** RTSP requests handler
 * @param id selected track for non-aggregate URLs,
 *           NULL for aggregate URLs
 */
static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
                        httpd_client_t *cl,
                        httpd_message_t *answer,
                        const httpd_message_t *query )
{
    sout_stream_t *p_stream = rtsp->owner;
    char psz_sesbuf[17];
    const char *psz_session = NULL, *psz;
    char control[sizeof("rtsp://[]:12345") + NI_MAXNUMERICHOST
                  + strlen( rtsp->psz_path )];
    time_t now;

    time (&now);

    if( answer == NULL || query == NULL || cl == NULL )
        return VLC_SUCCESS;
    else
    {
        /* Build self-referential control URL */
        char ip[NI_MAXNUMERICHOST], *ptr;

        httpd_ServerIP( cl, ip );
        ptr = strchr( ip, '%' );
        if( ptr != NULL )
            *ptr = '\0';

        if( strchr( ip, ':' ) != NULL )
            sprintf( control, "rtsp://[%s]:%u%s", ip, rtsp->port,
                     rtsp->psz_path );
        else
            sprintf( control, "rtsp://%s:%u%s", ip, rtsp->port,
                     rtsp->psz_path );
    }

    /* */
    answer->i_proto = HTTPD_PROTO_RTSP;
    answer->i_version= 0;
    answer->i_type   = HTTPD_MSG_ANSWER;
    answer->i_body = 0;
    answer->p_body = NULL;

    httpd_MsgAdd( answer, "Server", "%s", PACKAGE_STRING );

    /* Date: is always allowed, and sometimes mandatory with RTSP/2.0. */
    struct tm ut;
    if (gmtime_r (&now, &ut) != NULL)
    {   /* RFC1123 format, GMT is mandatory */
        static const char wdays[7][4] = {
            "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
        static const char mons[12][4] = {
            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
        httpd_MsgAdd (answer, "Date", "%s, %02u %s %04u %02u:%02u:%02u GMT",
                      wdays[ut.tm_wday], ut.tm_mday, mons[ut.tm_mon],
                      1900 + ut.tm_year, ut.tm_hour, ut.tm_min, ut.tm_sec);
    }

    if( query->i_proto != HTTPD_PROTO_RTSP )
    {
        answer->i_status = 505;
    }
    else
    if( httpd_MsgGet( query, "Require" ) != NULL )
    {
        answer->i_status = 551;
        httpd_MsgAdd( answer, "Unsupported", "%s",
                      httpd_MsgGet( query, "Require" ) );
    }
    else
    switch( query->i_type )
    {
        case HTTPD_MSG_DESCRIBE:
        {   /* Aggregate-only */
            if( id != NULL )
            {
                answer->i_status = 460;
                break;
            }

            answer->i_status = 200;
            httpd_MsgAdd( answer, "Content-Type",  "%s", "application/sdp" );
            httpd_MsgAdd( answer, "Content-Base",  "%s", control );
            answer->p_body = (uint8_t *)SDPGenerate( rtsp->owner, control );
            if( answer->p_body != NULL )
                answer->i_body = strlen( (char *)answer->p_body );
            else
                answer->i_status = 500;
            break;
        }

        case HTTPD_MSG_SETUP:
            /* Non-aggregate-only */
            if( id == NULL )
            {
                answer->i_status = 459;
                break;
            }

            psz_session = httpd_MsgGet( query, "Session" );
            answer->i_status = 461;

            for( const char *tpt = httpd_MsgGet( query, "Transport" );
                 tpt != NULL;
                 tpt = transport_next( tpt ) )
            {
                bool b_multicast = true, b_unsupp = false;
                unsigned loport = 5004, hiport = 5005; /* from RFC3551 */

                /* Check transport protocol. */
                /* Currently, we only support RTP/AVP over UDP */
                if( strncmp( tpt, "RTP/AVP", 7 ) )
                    continue;
                tpt += 7;
                if( strncmp( tpt, "/UDP", 4 ) == 0 )
                    tpt += 4;
                if( strchr( ";,", *tpt ) == NULL )
                    continue;

                /* Parse transport options */
                for( const char *opt = parameter_next( tpt );
                     opt != NULL;
                     opt = parameter_next( opt ) )
                {
                    if( strncmp( opt, "multicast", 9 ) == 0)
                        b_multicast = true;
                    else
                    if( strncmp( opt, "unicast", 7 ) == 0 )
                        b_multicast = false;
                    else
                    if( sscanf( opt, "client_port=%u-%u", &loport, &hiport )
                                == 2 )
                        ;
                    else
                    if( strncmp( opt, "mode=", 5 ) == 0 )
                    {
                        if( strncasecmp( opt + 5, "play", 4 )
                         && strncasecmp( opt + 5, "\"PLAY\"", 6 ) )
                        {
                            /* Not playing?! */
                            b_unsupp = true;
                            break;
                        }
                    }
                    else
                    if( strncmp( opt,"destination=", 12 ) == 0 )
                    {
                        answer->i_status = 403;
                        b_unsupp = true;
                    }
                    else
                    {
                    /*
                     * Every other option is unsupported:
                     *
                     * "source" and "append" are invalid (server-only);
                     * "ssrc" also (as clarified per RFC2326bis).
                     *
                     * For multicast, "port", "layers", "ttl" are set by the
                     * stream output configuration.
                     *
                     * For unicast, we want to decide "server_port" values.
                     *
                     * "interleaved" is not implemented.
                     */
                        b_unsupp = true;
                        break;
                    }
                }

                if( b_unsupp )
                    continue;

                if( b_multicast )
                {
                    const char *dst = id->dst;
                    if( dst == NULL )
                        continue;

                    if( psz_session == NULL )
                    {
                        /* Create a dummy session ID */
                        snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%d",
                                  rand() );
                        psz_session = psz_sesbuf;
                    }
                    answer->i_status = 200;

                    httpd_MsgAdd( answer, "Transport",
                                  "RTP/AVP/UDP;destination=%s;port=%u-%u;"
                                  "ttl=%d;mode=play",
                                  dst, id->loport, id->hiport,
                                  ( id->ttl > 0 ) ? id->ttl : 1 );
                }
                else
                {
                    char ip[NI_MAXNUMERICHOST], src[NI_MAXNUMERICHOST];
                    rtsp_session_t *ses = NULL;
                    rtsp_strack_t track = { id->sout_id, -1, false };
                    int sport;

                    if( httpd_ClientIP( cl, ip ) == NULL )
                    {
                        answer->i_status = 500;
                        continue;
                    }

                    track.fd = net_ConnectDgram( p_stream, ip, loport, -1,
                                                 IPPROTO_UDP );
                    if( track.fd == -1 )
                    {
                        msg_Err( p_stream,
                                 "cannot create RTP socket for %s port %u",
                                 ip, loport );
                        answer->i_status = 500;
                        continue;
                    }

                    net_GetSockAddress( track.fd, src, &sport );

                    vlc_mutex_lock( &rtsp->lock );
                    if( psz_session == NULL )
                    {
                        ses = RtspClientNew( rtsp );
                        snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%"PRIx64,
                                  ses->id );
                        psz_session = psz_sesbuf;
                    }
                    else
                    {
                        /* FIXME: we probably need to remove an access out,
                         * if there is already one for the same ID */
                        ses = RtspClientGet( rtsp, psz_session );
                        if( ses == NULL )
                        {
                            answer->i_status = 454;
                            vlc_mutex_unlock( &rtsp->lock );
                            continue;
                        }
                    }

                    INSERT_ELEM( ses->trackv, ses->trackc, ses->trackc,
                                 track );
                    vlc_mutex_unlock( &rtsp->lock );

                    httpd_ServerIP( cl, ip );

                    if( strcmp( src, ip ) )
                    {
                        /* Specify source IP if it is different from the RTSP
                         * control connection server address */
                        char *ptr = strchr( src, '%' );
                        if( ptr != NULL ) *ptr = '\0'; /* remove scope ID */

                        httpd_MsgAdd( answer, "Transport",
                                      "RTP/AVP/UDP;unicast;source=%s;"
                                      "client_port=%u-%u;server_port=%u-%u;"
                                      "ssrc=%08X;mode=play",
                                      src, loport, loport + 1, sport,
                                      sport + 1, id->ssrc );
                    }
                    else
                    {
                        httpd_MsgAdd( answer, "Transport",
                                      "RTP/AVP/UDP;unicast;"
                                      "client_port=%u-%u;server_port=%u-%u;"
                                      "ssrc=%08X;mode=play",
                                      loport, loport + 1, sport, sport + 1,
                                      id->ssrc );
                    }

                    answer->i_status = 200;
                }
                break;
            }
            break;

        case HTTPD_MSG_PLAY:
        {
            rtsp_session_t *ses;
            answer->i_status = 200;

            psz_session = httpd_MsgGet( query, "Session" );
            const char *range = httpd_MsgGet (query, "Range");
            if (range && strncmp (range, "npt=", 4))
            {
                answer->i_status = 501;
                break;
            }

            vlc_mutex_lock( &rtsp->lock );
            ses = RtspClientGet( rtsp, psz_session );
            if( ses != NULL )
            {
                /* FIXME: we really need to limit the number of tracks... */
                char info[ses->trackc * ( strlen( control )
                              + sizeof("url=/trackID=123;seq=65535, ") ) + 1];
                size_t infolen = 0;

                for( int i = 0; i < ses->trackc; i++ )
                {
                    rtsp_strack_t *tr = ses->trackv + i;
                    if( ( id == NULL ) || ( tr->id == id->sout_id ) )
                    {
                        if( !tr->playing )
                        {
                            tr->playing = true;
                            rtp_add_sink( tr->id, tr->fd, false );
                        }
                        infolen += sprintf( info + infolen,
                                            "url=%s/trackID=%u;seq=%u, ",
                                            control,
                                            rtp_get_num( tr->id ),
                                            rtp_get_seq( tr->id ) );
                    }
                }
                if( infolen > 0 )
                {
                    info[infolen - 2] = '\0'; /* remove trailing ", " */
                    httpd_MsgAdd( answer, "RTP-Info", "%s", info );
                }
            }
            vlc_mutex_unlock( &rtsp->lock );

            if( httpd_MsgGet( query, "Scale" ) != NULL )
                httpd_MsgAdd( answer, "Scale", "1." );
            break;
        }

        case HTTPD_MSG_PAUSE:
            answer->i_status = 405;
            httpd_MsgAdd( answer, "Allow",
                          "%s, TEARDOWN, PLAY, GET_PARAMETER",
                          ( id != NULL ) ? "SETUP" : "DESCRIBE" );
            break;

        case HTTPD_MSG_GETPARAMETER:
            if( query->i_body > 0 )
            {
                answer->i_status = 451;
                break;
            }

            psz_session = httpd_MsgGet( query, "Session" );
            answer->i_status = 200;
            break;

        case HTTPD_MSG_TEARDOWN:
        {
            rtsp_session_t *ses;

            answer->i_status = 200;

            psz_session = httpd_MsgGet( query, "Session" );

            vlc_mutex_lock( &rtsp->lock );
            ses = RtspClientGet( rtsp, psz_session );
            if( ses != NULL )
            {
                if( id == NULL ) /* Delete the entire session */
                    RtspClientDel( rtsp, ses );
                else /* Delete one track from the session */
                for( int i = 0; i < ses->trackc; i++ )
                {
                    if( ses->trackv[i].id == id->sout_id )
                    {
                        rtp_del_sink( id->sout_id, ses->trackv[i].fd );
                        REMOVE_ELEM( ses->trackv, ses->trackc, i );
                    }
                }
            }
            vlc_mutex_unlock( &rtsp->lock );
            break;
        }

        default:
            return VLC_EGENERIC;
    }

    if( psz_session )
        httpd_MsgAdd( answer, "Session", "%s"/*;timeout=5*/, psz_session );

    httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
    httpd_MsgAdd( answer, "Cache-Control", "no-cache" );

    psz = httpd_MsgGet( query, "Cseq" );
    if( psz != NULL )
        httpd_MsgAdd( answer, "Cseq", "%s", psz );
    psz = httpd_MsgGet( query, "Timestamp" );
    if( psz != NULL )
        httpd_MsgAdd( answer, "Timestamp", "%s", psz );

    return VLC_SUCCESS;
}
Exemple #6
0
/**
 * Add a playlist item into a playlist
 *
 * \param p_playlist the playlist to insert into
 * \param p_item the playlist item to insert
 * \param i_mode the mode used when adding
 * \param i_pos the possition in the playlist where to add. If this is
 *        PLAYLIST_END the item will be added at the end of the playlist
 *        regardless of it's size
 * \return The id of the playlist item
 */
int playlist_AddItem( playlist_t *p_playlist, playlist_item_t *p_item,
                      int i_mode, int i_pos)
{
    vlc_value_t val;

    vlc_mutex_lock( &p_playlist->object_lock );

    /*
     * CHECK_INSERT : checks if the item is already enqued before
     * enqueing it
     */
    if ( i_mode & PLAYLIST_CHECK_INSERT )
    {
         int j;

         if ( p_playlist->pp_items )
         {
             for ( j = 0; j < p_playlist->i_size; j++ )
             {
                 if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri,
                               p_item->input.psz_uri ) )
                 {
                      if ( p_item->input.psz_name )
                      {
                          free( p_item->input.psz_name );
                      }
                      if ( p_item->input.psz_uri )
                      {
                          free ( p_item->input.psz_uri );
                      }
                      free( p_item );
                      vlc_mutex_unlock( &p_playlist->object_lock );
                      return -1;
                 }
             }
         }
         i_mode &= ~PLAYLIST_CHECK_INSERT;
         i_mode |= PLAYLIST_APPEND;
    }

    msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )",
             p_item->input.psz_name, p_item->input.psz_uri );

    p_item->i_id = ++p_playlist->i_last_id;

    /* Do a few boundary checks and allocate space for the item */
    if( i_pos == PLAYLIST_END )
    {
        if( i_mode & PLAYLIST_INSERT )
        {
            i_mode &= ~PLAYLIST_INSERT;
            i_mode |= PLAYLIST_APPEND;
        }

        i_pos = p_playlist->i_size - 1;
    }

    if( !(i_mode & PLAYLIST_REPLACE)
         || i_pos < 0 || i_pos >= p_playlist->i_size )
    {
        /* Additional boundary checks */
        if( i_mode & PLAYLIST_APPEND )
        {
            i_pos++;
        }

        if( i_pos < 0 )
        {
            i_pos = 0;
        }
        else if( i_pos > p_playlist->i_size )
        {
            i_pos = p_playlist->i_size;
        }

        INSERT_ELEM( p_playlist->pp_items, p_playlist->i_size, i_pos, p_item );
        p_playlist->i_enabled ++;

        if( p_playlist->i_index >= i_pos )
        {
            p_playlist->i_index++;
        }
    }
    else
    {
        /* i_mode == PLAYLIST_REPLACE and 0 <= i_pos < p_playlist->i_size */
        if( p_playlist->pp_items[i_pos]->input.psz_name )
        {
            free( p_playlist->pp_items[i_pos]->input.psz_name );
        }
        if( p_playlist->pp_items[i_pos]->input.psz_uri )
        {
            free( p_playlist->pp_items[i_pos]->input.psz_uri );
        }
        /* XXX: what if the item is still in use? */
        free( p_playlist->pp_items[i_pos] );
        p_playlist->pp_items[i_pos] = p_item;
    }

    if( i_mode & PLAYLIST_GO )
    {
        p_playlist->i_index = i_pos;
        if( p_playlist->p_input )
        {
            input_StopThread( p_playlist->p_input );
        }
        p_playlist->i_status = PLAYLIST_RUNNING;
    }

    vlc_mutex_unlock( &p_playlist->object_lock );

    val.b_bool = VLC_TRUE;
    var_Set( p_playlist, "intf-change", val );

    return p_item->i_id;
}
Exemple #7
0
/**
 * Add a playlist item into a playlist
 *
 * \param p_playlist the playlist to insert into
 * \param p_item the playlist item to insert
 * \param i_mode the mode used when adding
 * \param i_pos the possition in the playlist where to add. If this is
 *        PLAYLIST_END the item will be added at the end of the playlist
 *        regardless of it's size
 * \return The id of the playlist item
 */
int playlist_AddItem( playlist_t *p_playlist, playlist_item_t *p_item,
                      int i_mode, int i_pos)
{
    vlc_value_t val;
    vlc_bool_t b_end = VLC_FALSE;
    playlist_view_t *p_view = NULL;

    playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));

    vlc_mutex_lock( &p_playlist->object_lock );

    /*
     * CHECK_INSERT : checks if the item is already enqued before
     * enqueing it
     */

    /* That should not change */
    if ( i_mode & PLAYLIST_CHECK_INSERT )
    {
         int j;

        if ( p_playlist->pp_items )
        {
            for ( j = 0; j < p_playlist->i_size; j++ )
            {
                if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri,
                               p_item->input.psz_uri ) )
                {
                    playlist_ItemDelete( p_item );
                    vlc_mutex_unlock( &p_playlist->object_lock );
                    return -1;
                }
             }
         }
         i_mode &= ~PLAYLIST_CHECK_INSERT;
         i_mode |= PLAYLIST_APPEND;
    }

    msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )",
             p_item->input.psz_name, p_item->input.psz_uri );

    p_item->input.i_id = ++p_playlist->i_last_id;

    /* Do a few boundary checks and allocate space for the item */
    if( i_pos == PLAYLIST_END )
    {
        b_end = VLC_TRUE;
        if( i_mode & PLAYLIST_INSERT )
        {
            i_mode &= ~PLAYLIST_INSERT;
            i_mode |= PLAYLIST_APPEND;
        }

        i_pos = p_playlist->i_size - 1;
    }

    if( !(i_mode & PLAYLIST_REPLACE)
         || i_pos < 0 || i_pos >= p_playlist->i_size )
    {
        /* Additional boundary checks */
        if( i_mode & PLAYLIST_APPEND )
        {
            i_pos++;
        }

        if( i_pos < 0 )
        {
            i_pos = 0;
        }
        else if( i_pos > p_playlist->i_size )
        {
            i_pos = p_playlist->i_size;
        }

        INSERT_ELEM( p_playlist->pp_items, p_playlist->i_size, i_pos, p_item );
        INSERT_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size,
                     p_playlist->i_all_size, p_item );
        p_playlist->i_enabled ++;

        /* We update the ALL view directly */
        playlist_ViewUpdate( p_playlist, VIEW_ALL );

        /* Add the item to the General category */
        if( b_end == VLC_TRUE )
        {
            playlist_NodeAppend( p_playlist, VIEW_CATEGORY, p_item,
                                 p_playlist->p_general );
            p_add->i_item = p_item->input.i_id;
            p_add->i_node = p_playlist->p_general->input.i_id;
            p_add->i_view = VIEW_CATEGORY;
            val.p_address = p_add;
            var_Set( p_playlist, "item-append", val );
        }
        else
        {
            playlist_NodeInsert( p_playlist, VIEW_CATEGORY, p_item,
                                 p_playlist->p_general, i_pos );
        }


        p_view = playlist_ViewFind( p_playlist, VIEW_ALL );
        playlist_ItemAddParent( p_item, VIEW_ALL, p_view->p_root );

        /* FIXME : Update sorted views */

        if( p_playlist->i_index >= i_pos )
        {
            p_playlist->i_index++;
        }
    }
    else
    {
        msg_Err( p_playlist, "Insert mode not implemented" );
    }

    if( (i_mode & PLAYLIST_GO ) && p_view )
    {
        p_playlist->request.b_request = VLC_TRUE;
        /* FIXME ... */
        p_playlist->request.i_view = VIEW_CATEGORY;
        p_playlist->request.p_node = p_view->p_root;
        p_playlist->request.p_item = p_item;

        if( p_playlist->p_input )
        {
            input_StopThread( p_playlist->p_input );
        }
        p_playlist->status.i_status = PLAYLIST_RUNNING;
    }

    if( i_mode & PLAYLIST_PREPARSE &&
        var_CreateGetBool( p_playlist, "auto-preparse" ) )
    {
        playlist_PreparseEnqueue( p_playlist, &p_item->input );
    }

    vlc_mutex_unlock( &p_playlist->object_lock );

    if( b_end == VLC_FALSE )
    {
        val.b_bool = VLC_TRUE;
        var_Set( p_playlist, "intf-change", val );
    }

    free( p_add );

    return p_item->input.i_id;
}
Exemple #8
0
/**
 * Add a playlist item to a given node (in the category view )
 *
 * \param p_playlist the playlist to insert into
 * \param p_item the playlist item to insert
 * \param i_view the view for which to add or TODO: ALL_VIEWS
 * \param p_parent the parent node
 * \param i_mode the mode used when adding
 * \param i_pos the possition in the node where to add. If this is
 *        PLAYLIST_END the item will be added at the end of the node
 ** \return The id of the playlist item
 */
int playlist_NodeAddItem( playlist_t *p_playlist, playlist_item_t *p_item,
                          int i_view,playlist_item_t *p_parent,
                          int i_mode, int i_pos)
{
    vlc_value_t val;
    int i_position;
    playlist_view_t *p_view;

    playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));

    vlc_mutex_lock( &p_playlist->object_lock );

    if ( i_pos == PLAYLIST_END ) i_pos = -1;

    /* Sanity checks */
    if( !p_parent || p_parent->i_children == -1 )
    {
        msg_Err( p_playlist, "invalid node" );
    }

    /*
     * CHECK_INSERT : checks if the item is already enqued before
     * enqueing it
     */
    if ( i_mode & PLAYLIST_CHECK_INSERT )
    {
         int j;

        if ( p_playlist->pp_items )
        {
            for ( j = 0; j < p_playlist->i_size; j++ )
            {
                if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri,
                              p_item->input.psz_uri ) )
                {
                    playlist_ItemDelete( p_item );
                    vlc_mutex_unlock( &p_playlist->object_lock );
                    free( p_add );
                    return -1;
                }
            }
        }
        i_mode &= ~PLAYLIST_CHECK_INSERT;
        i_mode |= PLAYLIST_APPEND;
    }

    msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )",
             p_item->input.psz_name, p_item->input.psz_uri );

    p_item->input.i_id = ++p_playlist->i_last_id;

    /* First, add the item at the right position in the item bank */
    /* WHY THAT ? */
     //i_position = p_playlist->i_index == -1 ? 0 : p_playlist->i_index;
    i_position = p_playlist->i_size ;

    INSERT_ELEM( p_playlist->pp_items,
                 p_playlist->i_size,
                 i_position,
                 p_item );
    INSERT_ELEM( p_playlist->pp_all_items,
                 p_playlist->i_all_size,
                 p_playlist->i_all_size,
                 p_item );
    p_playlist->i_enabled ++;

    /* TODO: Handle modes */
    playlist_NodeInsert( p_playlist, i_view, p_item, p_parent, i_pos );

    p_add->i_item = p_item->input.i_id;
    p_add->i_node = p_parent->input.i_id;
    p_add->i_view = i_view;
    val.p_address = p_add;
    var_Set( p_playlist, "item-append", val );

    /* We update the ALL view directly */
    p_view = playlist_ViewFind( p_playlist, VIEW_ALL );
    playlist_ItemAddParent( p_item, VIEW_ALL, p_view->p_root );
    playlist_ViewUpdate( p_playlist, VIEW_ALL );

    /* TODO : Update sorted views*/

    if( i_mode & PLAYLIST_GO )
    {
        p_playlist->request.b_request = VLC_TRUE;
        p_playlist->request.i_view = VIEW_CATEGORY;
        p_playlist->request.p_node = p_parent;
        p_playlist->request.p_item = p_item;
        if( p_playlist->p_input )
        {
            input_StopThread( p_playlist->p_input );
        }
        p_playlist->status.i_status = PLAYLIST_RUNNING;
    }
    if( i_mode & PLAYLIST_PREPARSE &&
        var_CreateGetBool( p_playlist, "auto-preparse" ) )
    {
        playlist_PreparseEnqueue( p_playlist, &p_item->input );
    }

    vlc_mutex_unlock( &p_playlist->object_lock );

    val.b_bool = VLC_TRUE;
//    var_Set( p_playlist, "intf-change", val );
//
    free( p_add );

    return p_item->input.i_id;
}
Exemple #9
0
static int Demux( demux_t *p_demux )
{
    char       *psz_line;
    char       *psz_name = NULL;
    char       *psz_artist = NULL;
    int        i_parsed_duration = 0;
    mtime_t    i_duration = -1;
    const char**ppsz_options = NULL;
    char *    (*pf_dup) (const char *) = p_demux->p_sys->pf_dup;
    int        i_options = 0;
    bool b_cleanup = false;
    input_item_t *p_input;

    input_item_t *p_current_input = GetCurrentItem(p_demux);

    psz_line = stream_ReadLine( p_demux->s );
    while( psz_line )
    {
        char *psz_parse = psz_line;

        /* Skip leading tabs and spaces */
        while( *psz_parse == ' ' || *psz_parse == '\t' ||
               *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++;

        if( *psz_parse == '#' )
        {
            /* Parse extra info */

            /* Skip leading tabs and spaces */
            while( *psz_parse == ' ' || *psz_parse == '\t' ||
                   *psz_parse == '\n' || *psz_parse == '\r' ||
                   *psz_parse == '#' ) psz_parse++;

            if( !*psz_parse ) goto error;

            if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) )
            {
                /* Extended info */
                psz_parse += sizeof("EXTINF:") - 1;
                parseEXTINF( psz_parse, &psz_artist, &psz_name, &i_parsed_duration );
                if( i_parsed_duration >= 0 )
                    i_duration = i_parsed_duration * INT64_C(1000000);
                if( psz_name )
                    psz_name = pf_dup( psz_name );
                if( psz_artist )
                    psz_artist = pf_dup( psz_artist );
            }
            else if( !strncasecmp( psz_parse, "EXTVLCOPT:",
                                   sizeof("EXTVLCOPT:") -1 ) )
            {
                /* VLC Option */
                char *psz_option;
                psz_parse += sizeof("EXTVLCOPT:") -1;
                if( !*psz_parse ) goto error;

                psz_option = pf_dup( psz_parse );
                if( psz_option )
                    INSERT_ELEM( ppsz_options, i_options, i_options,
                                 psz_option );
            }
        }
        else if( !strncasecmp( psz_parse, "RTSPtext", sizeof("RTSPtext") -1 ) )
        {
            ;/* special case to handle QuickTime RTSPtext redirect files */
        }
        else if( *psz_parse )
        {
            char *psz_mrl;

            psz_parse = pf_dup( psz_parse );
            if( !psz_name && psz_parse )
                /* Use filename as name for relative entries */
                psz_name = strdup( psz_parse );

            psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix );

            b_cleanup = true;
            if( !psz_mrl ) goto error;

            p_input = input_item_NewExt( p_demux, psz_mrl, psz_name,
                                        i_options, ppsz_options, 0, i_duration );

            LocaleFree( psz_parse );
            free( psz_mrl );

            if ( psz_artist && *psz_artist )
                input_item_SetArtist( p_input, psz_artist );
            if( psz_name ) input_item_SetTitle( p_input, psz_name );

            input_item_AddSubItem( p_current_input, p_input );
            vlc_gc_decref( p_input );
        }

 error:

        /* Fetch another line */
        free( psz_line );
        psz_line = stream_ReadLine( p_demux->s );
        if( !psz_line ) b_cleanup = true;

        if( b_cleanup )
        {
            /* Cleanup state */
            while( i_options-- ) free( (char*)ppsz_options[i_options] );
            free( ppsz_options );
            ppsz_options = NULL; i_options = 0;
            free( psz_name );
            psz_name = NULL;
            free( psz_artist );
            psz_artist = NULL;
            i_parsed_duration = 0;
            i_duration = -1;

            b_cleanup = false;
        }
    }
    vlc_gc_decref(p_current_input);
    var_Destroy( p_demux, "m3u-extvlcopt" );
    return 0; /* Needed for correct operation of go back */
}
Exemple #10
0
/**
 * Initialize a vlc object
 *
 * This function allocates memory for a vlc object and initializes it. If
 * i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and
 * so on, vlc_object_create will use its value for the object size.
 */
void * __vlc_object_create( vlc_object_t *p_this, int i_type )
{
    vlc_object_t * p_new;
    char *         psz_type;
    size_t         i_size;

    switch( i_type )
    {
        case VLC_OBJECT_ROOT:
            i_size = sizeof(libvlc_t);
            psz_type = "root";
            break;
        case VLC_OBJECT_VLC:
            i_size = sizeof(vlc_t);
            psz_type = "vlc";
            break;
        case VLC_OBJECT_MODULE:
            i_size = sizeof(module_t);
            psz_type = "module";
            break;
        case VLC_OBJECT_INTF:
            i_size = sizeof(intf_thread_t);
            psz_type = "interface";
            break;
        case VLC_OBJECT_DIALOGS:
            i_size = sizeof(intf_thread_t);
            psz_type = "dialogs provider";
            break;
        case VLC_OBJECT_PLAYLIST:
            i_size = sizeof(playlist_t);
            psz_type = "playlist";
            break;
        case VLC_OBJECT_INPUT:
            i_size = sizeof(input_thread_t);
            psz_type = "input";
            break;
        case VLC_OBJECT_DEMUX:
            i_size = sizeof(demux_t);
            psz_type = "demux";
            break;
        case VLC_OBJECT_STREAM:
            i_size = sizeof(stream_t);
            psz_type = "stream";
            break;
        case VLC_OBJECT_ACCESS:
            i_size = sizeof(access_t);
            psz_type = "access";
            break;
        case VLC_OBJECT_DECODER:
            i_size = sizeof(decoder_t);
            psz_type = "decoder";
            break;
        case VLC_OBJECT_PACKETIZER:
            i_size = sizeof(decoder_t);
            psz_type = "packetizer";
            break;
        case VLC_OBJECT_ENCODER:
            i_size = sizeof(encoder_t);
            psz_type = "encoder";
            break;
        case VLC_OBJECT_FILTER:
            i_size = sizeof(filter_t);
            psz_type = "filter";
            break;
        case VLC_OBJECT_VOUT:
            i_size = sizeof(vout_thread_t);
            psz_type = "video output";
            break;
        case VLC_OBJECT_SPU:
            i_size = sizeof(spu_t);
            psz_type = "subpicture unit";
            break;
        case VLC_OBJECT_AOUT:
            i_size = sizeof(aout_instance_t);
            psz_type = "audio output";
            break;
        case VLC_OBJECT_SOUT:
            i_size = sizeof(sout_instance_t);
            psz_type = "stream output";
            break;
        case VLC_OBJECT_HTTPD:
            i_size = sizeof( httpd_t );
            psz_type = "http daemon";
            break;
        case VLC_OBJECT_VLM:
            i_size = sizeof( vlm_t );
            psz_type = "vlm dameon";
            break;
        case VLC_OBJECT_VOD:
            i_size = sizeof( vod_t );
            psz_type = "vod server";
            break;
        case VLC_OBJECT_TLS:
            i_size = sizeof( tls_t );
            psz_type = "tls";
            break;
        case VLC_OBJECT_OPENGL:
            i_size = sizeof( vout_thread_t );
            psz_type = "opengl provider";
            break;
        case VLC_OBJECT_ANNOUNCE:
            i_size = sizeof( announce_handler_t );
            psz_type = "announce handler";
            break;
        default:
            i_size = i_type > 0
                      ? i_type > (int)sizeof(vlc_object_t)
                         ? i_type : (int)sizeof(vlc_object_t)
                      : (int)sizeof(vlc_object_t);
            i_type = VLC_OBJECT_GENERIC;
            psz_type = "generic";
            break;
    }

    if( i_type == VLC_OBJECT_ROOT )
    {
        p_new = p_this;
    }
    else
    {
        p_new = malloc( i_size );
        if( !p_new ) return NULL;
        memset( p_new, 0, i_size );
    }

    p_new->i_object_type = i_type;
    p_new->psz_object_type = psz_type;

    p_new->psz_object_name = NULL;

    p_new->b_die = VLC_FALSE;
    p_new->b_error = VLC_FALSE;
    p_new->b_dead = VLC_FALSE;
    p_new->b_attached = VLC_FALSE;
    p_new->b_force = VLC_FALSE;

    p_new->i_vars = 0;
    p_new->p_vars = (variable_t *)malloc( 16 * sizeof( variable_t ) );

    if( !p_new->p_vars )
    {
        free( p_new );
        return NULL;
    }

    if( i_type == VLC_OBJECT_ROOT )
    {
        /* If i_type is root, then p_new is actually p_libvlc */
        p_new->p_libvlc = (libvlc_t*)p_new;
        p_new->p_vlc = NULL;

        p_new->p_libvlc->i_counter = 0;
        p_new->i_object_id = 0;

        p_new->p_libvlc->i_objects = 1;
        p_new->p_libvlc->pp_objects = malloc( sizeof(vlc_object_t *) );
        p_new->p_libvlc->pp_objects[0] = p_new;
        p_new->b_attached = VLC_TRUE;
    }
    else
    {
        p_new->p_libvlc = p_this->p_libvlc;
        p_new->p_vlc = ( i_type == VLC_OBJECT_VLC ) ? (vlc_t*)p_new
                                                    : p_this->p_vlc;

        vlc_mutex_lock( &structure_lock );

        p_new->p_libvlc->i_counter++;
        p_new->i_object_id = p_new->p_libvlc->i_counter;

        /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
         * useless to try and recover anything if pp_objects gets smashed. */
        INSERT_ELEM( p_new->p_libvlc->pp_objects,
                     p_new->p_libvlc->i_objects,
                     p_new->p_libvlc->i_objects,
                     p_new );

        vlc_mutex_unlock( &structure_lock );
    }

    p_new->i_refcount = 0;
    p_new->p_parent = NULL;
    p_new->pp_children = NULL;
    p_new->i_children = 0;

    p_new->p_private = NULL;

    /* Initialize mutexes and condvars */
    vlc_mutex_init( p_new, &p_new->object_lock );
    vlc_cond_init( p_new, &p_new->object_wait );
    vlc_mutex_init( p_new, &p_new->var_lock );

    if( i_type == VLC_OBJECT_ROOT )
    {
        vlc_mutex_init( p_new, &structure_lock );

        var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
        var_AddCallback( p_new, "list", DumpCommand, NULL );
        var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
        var_AddCallback( p_new, "tree", DumpCommand, NULL );
    }

    return p_new;
}
Exemple #11
0
/**
 * Detect subtitle files.
 *
 * When called this function will split up the psz_name string into a
 * directory, filename and extension. It then opens the directory
 * in which the file resides and tries to find possible matches of
 * subtitles files.
 *
 * \ingroup Demux
 * \param p_this the calling \ref input_thread_t
 * \param psz_path a list of subdirectories (separated by a ',') to look in.
 * \param psz_name_org the complete filename to base the search on.
 * \param pp_slaves an initialized input item slave list to append detected subtitles to
 * \param p_slaves pointer to the size of the slave list
 * \return VLC_SUCCESS if ok
 */
int subtitles_Detect( input_thread_t *p_this, char *psz_path, const char *psz_name_org,
                      input_item_slave_t ***ppp_slaves, int *p_slaves )
{
    int i_fuzzy = var_GetInteger( p_this, "sub-autodetect-fuzzy" );
    if ( i_fuzzy == 0 )
        return VLC_EGENERIC;
    int j, i_fname_len;
    input_item_slave_t **pp_slaves = *ppp_slaves;
    int i_slaves = *p_slaves;
    char *f_fname_noext = NULL, *f_fname_trim = NULL;
    char **subdirs; /* list of subdirectories to look in */

    if( !psz_name_org )
        return VLC_EGENERIC;

    char *psz_fname = vlc_uri2path( psz_name_org );
    if( !psz_fname )
        return VLC_EGENERIC;

    /* extract filename & dirname from psz_fname */
    char *f_dir = strdup( psz_fname );
    if( f_dir == 0 )
    {
        free( psz_fname );
        return VLC_ENOMEM;
    }

    const char *f_fname = strrchr( psz_fname, DIR_SEP_CHAR );
    if( !f_fname )
    {
        free( f_dir );
        free( psz_fname );
        return VLC_EGENERIC;
    }
    f_fname++; /* Skip the '/' */
    f_dir[f_fname - psz_fname] = 0; /* keep dir separator in f_dir */

    i_fname_len = strlen( f_fname );

    f_fname_noext = malloc(i_fname_len + 1);
    f_fname_trim = malloc(i_fname_len + 1 );
    if( !f_fname_noext || !f_fname_trim )
    {
        free( f_dir );
        free( f_fname_noext );
        free( f_fname_trim );
        free( psz_fname );
        return VLC_ENOMEM;
    }

    strcpy_strip_ext( f_fname_noext, f_fname );
    strcpy_trim( f_fname_trim, f_fname_noext );

    subdirs = paths_to_list( f_dir, psz_path );
    for( j = -1; (j == -1) || ( j >= 0 && subdirs != NULL && subdirs[j] != NULL ); j++ )
    {
        const char *psz_dir = (j < 0) ? f_dir : subdirs[j];
        if( psz_dir == NULL || ( j >= 0 && !strcmp( psz_dir, f_dir ) ) )
            continue;

        /* parse psz_src dir */
        DIR *dir = vlc_opendir( psz_dir );
        if( dir == NULL )
            continue;

        msg_Dbg( p_this, "looking for a subtitle file in %s", psz_dir );

        const char *psz_name;
        while( (psz_name = vlc_readdir( dir )) )
        {
            if( psz_name[0] == '.' || !subtitles_Filter( psz_name ) )
                continue;

            char tmp_fname_noext[strlen( psz_name ) + 1];
            char tmp_fname_trim[strlen( psz_name ) + 1];
            char tmp_fname_ext[strlen( psz_name ) + 1];
            const char *tmp;
            int i_prio = 0;

            /* retrieve various parts of the filename */
            strcpy_strip_ext( tmp_fname_noext, psz_name );
            strcpy_get_ext( tmp_fname_ext, psz_name );
            strcpy_trim( tmp_fname_trim, tmp_fname_noext );

            if( !strcmp( tmp_fname_trim, f_fname_trim ) )
            {
                /* matches the movie name exactly */
                i_prio = SLAVE_PRIORITY_MATCH_ALL;
            }
            else if( (tmp = strstr( tmp_fname_trim, f_fname_trim )) )
            {
                /* contains the movie name */
                tmp += strlen( f_fname_trim );
                if( whiteonly( tmp ) )
                {
                    /* chars in front of the movie name */
                    i_prio = SLAVE_PRIORITY_MATCH_RIGHT;
                }
                else
                {
                    /* chars after (and possibly in front of)
                     * the movie name */
                    i_prio = SLAVE_PRIORITY_MATCH_LEFT;
                }
            }
            else if( j == -1 )
            {
                /* doesn't contain the movie name, prefer files in f_dir over subdirs */
                i_prio = SLAVE_PRIORITY_MATCH_NONE;
            }
            if( i_prio >= i_fuzzy )
            {
                struct stat st;
                char *path;

                size_t i_len = strlen( psz_dir );
                const char *psz_format;
                if ( i_len == 0 )
                    continue;
                if( psz_dir[i_len - 1] == DIR_SEP_CHAR )
                    psz_format = "%s%s";
                else
                    psz_format = "%s"DIR_SEP"%s";

                if( asprintf( &path, psz_format, psz_dir, psz_name ) < 0 )
                    continue;

                if( strcmp( path, psz_fname )
                 && vlc_stat( path, &st ) == 0
                 && S_ISREG( st.st_mode ) )
                {
                    msg_Dbg( p_this,
                            "autodetected subtitle: %s with priority %d",
                            path, i_prio );
                    char *psz_uri = vlc_path2uri( path, NULL );
                    input_item_slave_t *p_sub = psz_uri != NULL ?
                        input_item_slave_New( psz_uri, SLAVE_TYPE_SPU, i_prio )
                        : NULL;
                    if( p_sub )
                    {
                        p_sub->b_forced = true;
                        INSERT_ELEM( pp_slaves, i_slaves, i_slaves, p_sub );
                    }
                    free( psz_uri );
                }
                free( path );
            }
        }
        closedir( dir );
    }
    if( subdirs )
    {
        for( j = 0; subdirs[j]; j++ )
            free( subdirs[j] );
        free( subdirs );
    }
    free( f_dir );
    free( f_fname_trim );
    free( f_fname_noext );
    free( psz_fname );

    for( int i = 0; i < i_slaves; i++ )
    {
        input_item_slave_t *p_sub = pp_slaves[i];

        bool b_reject = false;
        char *psz_ext = strrchr( p_sub->psz_uri, '.' );
        if( !psz_ext )
            continue;
        psz_ext++;

        if( !strcasecmp( psz_ext, "sub" ) )
        {
            for( int j = 0; j < i_slaves; j++ )
            {
                input_item_slave_t *p_sub_inner = pp_slaves[j];

                /* A slave can be null if it's already rejected */
                if( p_sub_inner == NULL )
                    continue;

                /* check that the filenames without extension match */
                if( strncasecmp( p_sub->psz_uri, p_sub_inner->psz_uri,
                    strlen( p_sub->psz_uri ) - 3 ) )
                    continue;

                char *psz_ext_inner = strrchr( p_sub_inner->psz_uri, '.' );
                if( !psz_ext_inner )
                    continue;
                psz_ext_inner++;

                /* check that we have an idx file */
                if( !strcasecmp( psz_ext_inner, "idx" ) )
                {
                    b_reject = true;
                    break;
                }
            }
        }
        else if( !strcasecmp( psz_ext, "cdg" ) )
        {
            if( p_sub->i_priority < SLAVE_PRIORITY_MATCH_ALL )
                b_reject = true;
        }
        if( b_reject )
        {
            pp_slaves[i] = NULL;
            input_item_slave_Delete( p_sub );
        }
    }

    /* Sort alphabetically */
    if( i_slaves > 0 )
        qsort( pp_slaves, i_slaves, sizeof (input_item_slave_t*), slave_strcmp );

    *ppp_slaves = pp_slaves; /* in case of realloc */
    *p_slaves = i_slaves;
    return VLC_SUCCESS;
}
Exemple #12
0
static int ParseLine( char *psz_line, char **ppsz_name,
                      char ***pppsz_options, int *pi_options )
{
    char *psz_name = 0, *psz_parse = psz_line;
    int i_count = 0, i_program = 0, i_frequency = 0;
    vlc_bool_t b_valid = VLC_FALSE;

    if( pppsz_options ) *pppsz_options = 0;
    if( pi_options ) *pi_options = 0;
    if( ppsz_name ) *ppsz_name = 0;

    /* Skip leading tabs and spaces */
    while( *psz_parse == ' ' || *psz_parse == '\t' ||
           *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++;

    /* Ignore comments */
    if( *psz_parse == '#' ) return VLC_FALSE;

    while( psz_parse )
    {
        char *psz_option = 0;
        char *psz_end = strchr( psz_parse, ':' );
        if( psz_end ) { *psz_end = 0; psz_end++; }

        if( i_count == 0 )
        {
            /* Channel name */
            psz_name = psz_parse;
        }
        else if( i_count == 1 )
        {
            /* Frequency */
            char *psz_end;
            long i_value;

            i_value = strtol( psz_parse, &psz_end, 10 );
            if( psz_end == psz_parse ||
                i_value == LONG_MAX || i_value == LONG_MIN ) break;

            i_frequency = i_value;
        }
        else
        {
            int i;

            /* Check option name with our list */
            for( i = 0; dvb_options[i].psz_name; i++ )
            {
                if( !strcmp( psz_parse, dvb_options[i].psz_name ) )
                {
                    psz_option = dvb_options[i].psz_option;

                    /* If we recognize one of the strings, then we are sure
                     * the data is really valid (ie. a channels file). */
                    b_valid = VLC_TRUE;
                    break;
                }
            }

            if( !psz_option )
            {
                /* Option not recognized, test if it is a number */
                char *psz_end;
                long i_value;

                i_value = strtol( psz_parse, &psz_end, 10 );
                if( psz_end != psz_parse &&
                    i_value != LONG_MAX && i_value != LONG_MIN )
                {
                    i_program = i_value;
                }
            }
        }

        if( psz_option && pppsz_options && pi_options )
        {
            psz_option = strdup( psz_option );
            INSERT_ELEM( *pppsz_options, (*pi_options), (*pi_options),
                         psz_option );
        }

        psz_parse = psz_end;
        i_count++;
    }

    if( !b_valid && pppsz_options && pi_options )
    {
        /* This isn't a valid channels file, cleanup everything */
        while( (*pi_options)-- ) free( (*pppsz_options)[*pi_options] );
        if( *pppsz_options ) free( *pppsz_options );
        *pppsz_options = 0; *pi_options = 0;
    }

    if( i_program && pppsz_options && pi_options )
    {
        char *psz_option;

        asprintf( &psz_option, "program=%i", i_program );
        INSERT_ELEM( *pppsz_options, (*pi_options), (*pi_options),
                     psz_option );
    }
    if( i_frequency && pppsz_options && pi_options )
    {
        char *psz_option;

        asprintf( &psz_option, "dvb-frequency=%i", i_frequency );
        INSERT_ELEM( *pppsz_options, (*pi_options), (*pi_options),
                     psz_option );
    }
    if( ppsz_name && psz_name ) *ppsz_name = strdup( psz_name );

    return b_valid;
}
Exemple #13
0
/**
 * Initialize a vlc variable
 *
 * We hash the given string and insert it into the sorted list. The insertion
 * may require slow memory copies, but think about what we gain in the log(n)
 * lookup phase when setting/getting the variable value!
 *
 * \param p_this The object in which to create the variable
 * \param psz_name The name of the variable
 * \param i_type The variables type. Must be one of \ref var_type combined with
 *               zero or more \ref var_flags
 */
int var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
{
    assert( p_this );

    variable_t *p_var = calloc( 1, sizeof( *p_var ) );
    if( p_var == NULL )
        return VLC_ENOMEM;

    p_var->psz_name = strdup( psz_name );
    p_var->psz_text = NULL;

    p_var->i_type = i_type & ~VLC_VAR_DOINHERIT;

    p_var->i_usage = 1;

    p_var->i_default = -1;
    p_var->choices.i_count = 0;
    p_var->choices.p_values = NULL;
    p_var->choices_text.i_count = 0;
    p_var->choices_text.p_values = NULL;

    p_var->b_incallback = false;
    p_var->i_entries = 0;
    p_var->p_entries = NULL;

    /* Always initialize the variable, even if it is a list variable; this
     * will lead to errors if the variable is not initialized, but it will
     * not cause crashes in the variable handling. */
    switch( i_type & VLC_VAR_CLASS )
    {
        case VLC_VAR_BOOL:
            p_var->ops = &bool_ops;
            p_var->val.b_bool = false;
            break;
        case VLC_VAR_INTEGER:
            p_var->ops = &int_ops;
            p_var->val.i_int = 0;
            break;
        case VLC_VAR_STRING:
            p_var->ops = &string_ops;
            p_var->val.psz_string = NULL;
            break;
        case VLC_VAR_FLOAT:
            p_var->ops = &float_ops;
            p_var->val.f_float = 0.0;
            break;
        case VLC_VAR_TIME:
            p_var->ops = &time_ops;
            p_var->val.i_time = 0;
            break;
        case VLC_VAR_COORDS:
            p_var->ops = &coords_ops;
            p_var->val.coords.x = p_var->val.coords.y = 0;
            break;
        case VLC_VAR_ADDRESS:
            p_var->ops = &addr_ops;
            p_var->val.p_address = NULL;
            break;
        default:
            p_var->ops = &void_ops;
#ifndef NDEBUG
            if( (i_type & VLC_VAR_CLASS) != VLC_VAR_VOID )
                msg_Err( p_this, "Creating the variable '%s' without a type",
                          psz_name );
#endif
    }

    if( i_type & VLC_VAR_DOINHERIT )
    {
        if( var_Inherit( p_this, psz_name, i_type, &p_var->val ) )
            msg_Err( p_this, "cannot inherit value for %s", psz_name );
        else if( i_type & VLC_VAR_HASCHOICE )
        {
            /* We must add the inherited value to our choice list */
            p_var->i_default = 0;

            INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
                         0, p_var->val );
            INSERT_ELEM( p_var->choices_text.p_values,
                         p_var->choices_text.i_count, 0, p_var->val );
            p_var->ops->pf_dup( &p_var->choices.p_values[0] );
            p_var->choices_text.p_values[0].psz_string = NULL;
        }
    }

    vlc_object_internals_t *p_priv = vlc_internals( p_this );
    variable_t **pp_var, *p_oldvar;
    int ret = VLC_SUCCESS;

    vlc_mutex_lock( &p_priv->var_lock );

    pp_var = tsearch( p_var, &p_priv->var_root, varcmp );
    if( unlikely(pp_var == NULL) )
        ret = VLC_ENOMEM;
    else if( (p_oldvar = *pp_var) == p_var )
        p_var = NULL;
    else if( unlikely((i_type ^ p_oldvar->i_type) & VLC_VAR_CLASS) )
    {    /* If the types differ, variable creation failed. */
         msg_Err( p_this, "Variable '%s' (0x%04x) already exist "
                  "but with a different type (0x%04x)",
                  psz_name, p_oldvar->i_type, i_type );
         ret = VLC_EBADVAR;
    }
    else
    {
        p_oldvar->i_usage++;
        p_oldvar->i_type |= i_type & (VLC_VAR_ISCOMMAND|VLC_VAR_HASCHOICE);
    }
    vlc_mutex_unlock( &p_priv->var_lock );

    /* If we did not need to create a new variable, free everything... */
    if( p_var != NULL )
        Destroy( p_var );
    return ret;
}
Exemple #14
0
/* Add a SAP announce */
static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
                             session_descriptor_t *p_session,
                             announce_method_t *p_method )
{
    int i;
    char *psz_type = "application/sdp";
    int i_header_size;
    char *psz_head;
    vlc_bool_t b_found = VLC_FALSE;
    sap_session_t *p_sap_session;
    mtime_t i_hash;

    vlc_mutex_lock( &p_sap->object_lock );

    /* If needed, build the SDP */
    if( !p_session->psz_sdp )
    {
        if ( SDPGenerate( p_sap, p_session ) != VLC_SUCCESS )
        {
            vlc_mutex_unlock( &p_sap->object_lock );
            return VLC_EGENERIC;
        }
    }

    if( !p_method->psz_address )
    {
        if( p_method->i_ip_version == 6 )
        {
            char sz_scope;
            if( p_method->psz_ipv6_scope != NULL )
            {
                sz_scope = *p_method->psz_ipv6_scope;
            }
            else
            {
                sz_scope = DEFAULT_IPV6_SCOPE;
            }
            p_method->psz_address = (char*)malloc( 30*sizeof(char ));
            sprintf( p_method->psz_address, "%s%c%s",
                            SAP_IPV6_ADDR_1, sz_scope, SAP_IPV6_ADDR_2 );
        }
        else
        {
            /* IPv4 */
            p_method->psz_address = (char*)malloc( 15*sizeof(char) );
            snprintf(p_method->psz_address, 15, SAP_IPV4_ADDR );
        }
    }
    msg_Dbg( p_sap, "using SAP address: %s",p_method->psz_address);

    /* XXX: Check for dupes */
    p_sap_session = (sap_session_t*)malloc(sizeof(sap_session_t));

    p_sap_session->psz_sdp = strdup( p_session->psz_sdp );
    p_sap_session->i_last = 0;

    /* Add the address to the buffer */
    for( i = 0; i< p_sap->i_addresses; i++)
    {
        if( !strcmp( p_method->psz_address,
             p_sap->pp_addresses[i]->psz_address ) )
        {
            p_sap_session->p_address = p_sap->pp_addresses[i];
            b_found = VLC_TRUE;
            break;
        }
    }
    if( b_found == VLC_FALSE )
    {
        sap_address_t *p_address = (sap_address_t *)
                                    malloc( sizeof(sap_address_t) );
        if( !p_address )
        {
            msg_Err( p_sap, "out of memory" );
            return VLC_ENOMEM;
        }
        p_address->psz_address = strdup( p_method->psz_address );
        p_address->i_ip_version = p_method->i_ip_version;
        p_address->i_port  =  9875;
        p_address->i_wfd = net_OpenUDP( p_sap, "", 0,
                                        p_address->psz_address,
                                        p_address->i_port );

        if( p_sap->b_control == VLC_TRUE )
        {
            p_address->i_rfd = net_OpenUDP( p_sap, p_method->psz_address,
                                            p_address->i_port,
                                            "", 0 );
            p_address->i_buff = 0;
            p_address->b_enabled = VLC_TRUE;
            p_address->b_ready = VLC_FALSE;
            p_address->i_limit = 10000; /* 10000 bps */
            p_address->t1 = 0;
        }
        else
        {
            p_address->b_enabled = VLC_TRUE;
            p_address->b_ready = VLC_TRUE;
            p_address->i_interval = config_GetInt( p_sap,"sap-interval");
        }

        if( p_address->i_wfd == -1 || (p_address->i_rfd == -1
                                        && p_sap->b_control ) )
        {
            msg_Warn( p_sap, "disabling address" );
            p_address->b_enabled = VLC_FALSE;
        }

        INSERT_ELEM( p_sap->pp_addresses,
                     p_sap->i_addresses,
                     p_sap->i_addresses,
                     p_address );
        p_sap_session->p_address = p_address;
    }

    /* Build the SAP Headers */
    i_header_size = ( p_method->i_ip_version == 6 ? 20 : 8 ) + strlen( psz_type ) + 1;
    psz_head = (char *) malloc( i_header_size * sizeof( char ) );
    if( ! psz_head )
    {
        msg_Err( p_sap, "out of memory" );
        return VLC_ENOMEM;
    }

    psz_head[0] = 0x20; /* Means SAPv1, IPv4, not encrypted, not compressed */
    psz_head[1] = 0x00; /* No authentification length */

    i_hash = mdate();
    psz_head[2] = (i_hash & 0xFF00) >> 8; /* Msg id hash */
    psz_head[3] = (i_hash & 0xFF);        /* Msg id hash 2 */

    if( p_method->i_ip_version == 6 )
    {
        /* in_addr_t ip_server = inet_addr( ip ); */
        psz_head[0] |= 0x10; /* Set IPv6 */

        psz_head[4] = 0x01; /* Source IP  FIXME: we should get the real address */
        psz_head[5] = 0x02; /* idem */
        psz_head[6] = 0x03; /* idem */
        psz_head[7] = 0x04; /* idem */

        psz_head[8] = 0x01; /* Source IP  FIXME: we should get the real address */
        psz_head[9] = 0x02; /* idem */
        psz_head[10] = 0x03; /* idem */
        psz_head[11] = 0x04; /* idem */

        psz_head[12] = 0x01; /* Source IP  FIXME: we should get the real address */
        psz_head[13] = 0x02; /* idem */
        psz_head[14] = 0x03; /* idem */
        psz_head[15] = 0x04; /* idem */

        psz_head[16] = 0x01; /* Source IP  FIXME: we should get the real address */
        psz_head[17] = 0x02; /* idem */
        psz_head[18] = 0x03; /* idem */
        psz_head[19] = 0x04; /* idem */

        strncpy( psz_head + 20, psz_type, 15 );
    }
    else
    {
        /* in_addr_t ip_server = inet_addr( ip) */
        /* Source IP  FIXME: we should get the real address */
        psz_head[4] = 0x01; /* ip_server */
        psz_head[5] = 0x02; /* ip_server>>8 */
        psz_head[6] = 0x03; /* ip_server>>16 */
        psz_head[7] = 0x04; /* ip_server>>24 */

        strncpy( psz_head + 8, psz_type, 15 );
    }

    psz_head[ i_header_size-1 ] = '\0';
    p_sap_session->i_length = i_header_size + strlen( p_sap_session->psz_sdp);

    p_sap_session->psz_data = (char *)malloc( sizeof(char)*
                                              p_sap_session->i_length );

    /* Build the final message */
    memcpy( p_sap_session->psz_data, psz_head, i_header_size );
    memcpy( p_sap_session->psz_data+i_header_size, p_sap_session->psz_sdp,
            strlen( p_sap_session->psz_sdp) );

    free( psz_head );

    /* Enqueue the announce */
    INSERT_ELEM( p_sap->pp_sessions,
                 p_sap->i_sessions,
                 p_sap->i_sessions,
                 p_sap_session );
    msg_Dbg( p_sap,"Addresses: %i  Sessions: %i",
                   p_sap->i_addresses,p_sap->i_sessions);

    /* Remember the SAP session for later deletion */
    p_session->p_sap = p_sap_session;

    vlc_mutex_unlock( &p_sap->object_lock );

    return VLC_SUCCESS;
}
Exemple #15
0
/** Parse a stringified option
 * This function parse a string option and create the associated object
 * variable
 * The option must be of the form "[no[-]]foo[=bar]" where foo is the
 * option name and bar is the value of the option.
 * \param p_obj the object in which the variable must be created
 * \param psz_option the option to parse
 * \return nothing
 */
void __var_OptionParse( vlc_object_t *p_obj, const char *psz_option )
{
    char *psz_name, *psz_value = strchr( psz_option, '=' );
    int  i_name_len, i_type;
    vlc_bool_t b_isno = VLC_FALSE;
    vlc_value_t val;

    if( psz_value ) i_name_len = psz_value - psz_option;
    else i_name_len = strlen( psz_option );

    /* It's too much of an hassle to remove the ':' when we parse
     * the cmd line :) */
    if( i_name_len && *psz_option == ':' )
    {
        psz_option++;
        i_name_len--;
    }

    if( i_name_len == 0 ) return;

    psz_name = strndup( psz_option, i_name_len );
    if( psz_value ) psz_value++;

    /* FIXME: :programs should be handled generically */
    if( !strcmp( psz_name, "programs" ) )
        i_type = VLC_VAR_LIST;
    else
        i_type = config_GetType( p_obj, psz_name );

    if( !i_type && !psz_value )
    {
        /* check for "no-foo" or "nofoo" */
        if( !strncmp( psz_name, "no-", 3 ) )
        {
            memmove( psz_name, psz_name + 3, strlen(psz_name) + 1 - 3 );
        }
        else if( !strncmp( psz_name, "no", 2 ) )
        {
            memmove( psz_name, psz_name + 2, strlen(psz_name) + 1 - 2 );
        }
        else goto cleanup;           /* Option doesn't exist */

        b_isno = VLC_TRUE;
        i_type = config_GetType( p_obj, psz_name );

        if( !i_type ) goto cleanup;  /* Option doesn't exist */
    }
    else if( !i_type ) goto cleanup; /* Option doesn't exist */

    if( ( i_type != VLC_VAR_BOOL ) &&
        ( !psz_value || !*psz_value ) ) goto cleanup; /* Invalid value */

    /* Create the variable in the input object.
     * Children of the input object will be able to retreive this value
     * thanks to the inheritance property of the object variables. */
    var_Create( p_obj, psz_name, i_type );

    switch( i_type )
    {
    case VLC_VAR_BOOL:
        val.b_bool = !b_isno;
        break;

    case VLC_VAR_INTEGER:
        val.i_int = strtol( psz_value, NULL, 0 );
        break;

    case VLC_VAR_FLOAT:
        val.f_float = atof( psz_value );
        break;

    case VLC_VAR_STRING:
    case VLC_VAR_MODULE:
    case VLC_VAR_FILE:
    case VLC_VAR_DIRECTORY:
        val.psz_string = psz_value;
        break;

    case VLC_VAR_LIST:
    {
        char *psz_orig, *psz_var;
        vlc_list_t *p_list = malloc(sizeof(vlc_list_t));
        val.p_list = p_list;
        p_list->i_count = 0;

        psz_var = psz_orig = strdup(psz_value);
        while( psz_var && *psz_var )
        {
            char *psz_item = psz_var;
            vlc_value_t val2;
            while( *psz_var && *psz_var != ',' ) psz_var++;
            if( *psz_var == ',' )
            {
                *psz_var = '\0';
                psz_var++;
            }
            val2.i_int = strtol( psz_item, NULL, 0 );
            INSERT_ELEM( p_list->p_values, p_list->i_count,
                         p_list->i_count, val2 );
            /* p_list->i_count is incremented twice by INSERT_ELEM */
            p_list->i_count--;
            INSERT_ELEM( p_list->pi_types, p_list->i_count,
                         p_list->i_count, VLC_VAR_INTEGER );
        }
        if( psz_orig ) free( psz_orig );
        break;
    }

    default:
        goto cleanup;
        break;
    }

    var_Set( p_obj, psz_name, val );

  cleanup:
    if( psz_name ) free( psz_name );
    return;
}
Exemple #16
0
/**
 * Perform an action on a variable
 *
 * \param p_this The object that holds the variable
 * \param psz_name The name of the variable
 * \param i_action The action to perform. Must be one of \ref var_action
 * \param p_val First action parameter
 * \param p_val2 Second action parameter
 */
int __var_Change( vlc_object_t *p_this, const char *psz_name,
                  int i_action, vlc_value_t *p_val, vlc_value_t *p_val2 )
{
    int i_var, i;
    variable_t *p_var;
    vlc_value_t oldval;

    vlc_mutex_lock( &p_this->var_lock );

    i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );

    if( i_var < 0 )
    {
        vlc_mutex_unlock( &p_this->var_lock );
        return VLC_ENOVAR;
    }

    p_var = &p_this->p_vars[i_var];

    switch( i_action )
    {
        case VLC_VAR_SETMIN:
            if( p_var->i_type & VLC_VAR_HASMIN )
            {
                p_var->pf_free( &p_var->min );
            }
            p_var->i_type |= VLC_VAR_HASMIN;
            p_var->min = *p_val;
            p_var->pf_dup( &p_var->min );
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_SETMAX:
            if( p_var->i_type & VLC_VAR_HASMAX )
            {
                p_var->pf_free( &p_var->max );
            }
            p_var->i_type |= VLC_VAR_HASMAX;
            p_var->max = *p_val;
            p_var->pf_dup( &p_var->max );
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_SETSTEP:
            if( p_var->i_type & VLC_VAR_HASSTEP )
            {
                p_var->pf_free( &p_var->step );
            }
            p_var->i_type |= VLC_VAR_HASSTEP;
            p_var->step = *p_val;
            p_var->pf_dup( &p_var->step );
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_ADDCHOICE:
            /* FIXME: the list is sorted, dude. Use something cleverer. */
            for( i = p_var->choices.i_count ; i-- ; )
            {
                if( p_var->pf_cmp( p_var->choices.p_values[i], *p_val ) < 0 )
                {
                    break;
                }
            }

            /* The new place is i+1 */
            i++;

            if( p_var->i_default >= i )
            {
                p_var->i_default++;
            }

            INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
                         i, *p_val );
            INSERT_ELEM( p_var->choices_text.p_values,
                         p_var->choices_text.i_count, i, *p_val );
            p_var->pf_dup( &p_var->choices.p_values[i] );
            p_var->choices_text.p_values[i].psz_string =
                ( p_val2 && p_val2->psz_string ) ?
                strdup( p_val2->psz_string ) : NULL;

            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_DELCHOICE:
            /* FIXME: the list is sorted, dude. Use something cleverer. */
            for( i = 0 ; i < p_var->choices.i_count ; i++ )
            {
                if( p_var->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 )
                {
                    break;
                }
            }

            if( i == p_var->choices.i_count )
            {
                /* Not found */
                vlc_mutex_unlock( &p_this->var_lock );
                return VLC_EGENERIC;
            }

            if( p_var->i_default > i )
            {
                p_var->i_default--;
            }
            else if( p_var->i_default == i )
            {
                p_var->i_default = -1;
            }

            p_var->pf_free( &p_var->choices.p_values[i] );
            if( p_var->choices_text.p_values[i].psz_string )
                free( p_var->choices_text.p_values[i].psz_string );
            REMOVE_ELEM( p_var->choices.p_values, p_var->choices.i_count, i );
            REMOVE_ELEM( p_var->choices_text.p_values,
                         p_var->choices_text.i_count, i );

            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_CHOICESCOUNT:
            p_val->i_int = p_var->choices.i_count;
            break;
        case VLC_VAR_CLEARCHOICES:
            for( i = 0 ; i < p_var->choices.i_count ; i++ )
            {
                p_var->pf_free( &p_var->choices.p_values[i] );
            }
            for( i = 0 ; i < p_var->choices_text.i_count ; i++ )
            {
                if( p_var->choices_text.p_values[i].psz_string )
                    free( p_var->choices_text.p_values[i].psz_string );
            }
            if( p_var->choices.i_count ) free( p_var->choices.p_values );
            if( p_var->choices_text.i_count ) free( p_var->choices_text.p_values );

            p_var->choices.i_count = 0;
            p_var->choices.p_values = NULL;
            p_var->choices_text.i_count = 0;
            p_var->choices_text.p_values = NULL;
            p_var->i_default = -1;
            break;
        case VLC_VAR_SETDEFAULT:
            /* FIXME: the list is sorted, dude. Use something cleverer. */
            for( i = 0 ; i < p_var->choices.i_count ; i++ )
            {
                if( p_var->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 )
                {
                    break;
                }
            }

            if( i == p_var->choices.i_count )
            {
                /* Not found */
                break;
            }

            p_var->i_default = i;
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_SETVALUE:
            /* Duplicate data if needed */
            p_var->pf_dup( p_val );
            /* Backup needed stuff */
            oldval = p_var->val;
            /* Check boundaries and list */
            CheckValue( p_var, p_val );
            /* Set the variable */
            p_var->val = *p_val;
            /* Free data if needed */
            p_var->pf_free( &oldval );
            break;
        case VLC_VAR_GETCHOICES:
        case VLC_VAR_GETLIST:
            p_val->p_list = malloc( sizeof(vlc_list_t) );
            if( p_val2 ) p_val2->p_list = malloc( sizeof(vlc_list_t) );
            if( p_var->choices.i_count )
            {
                p_val->p_list->p_values = malloc( p_var->choices.i_count
                                                  * sizeof(vlc_value_t) );
                p_val->p_list->pi_types = malloc( p_var->choices.i_count
                                                  * sizeof(int) );
                if( p_val2 )
                {
                    p_val2->p_list->p_values =
                        malloc( p_var->choices.i_count * sizeof(vlc_value_t) );
                    p_val2->p_list->pi_types =
                        malloc( p_var->choices.i_count * sizeof(int) );
                }
            }
            p_val->p_list->i_count = p_var->choices.i_count;
            if( p_val2 ) p_val2->p_list->i_count = p_var->choices.i_count;
            for( i = 0 ; i < p_var->choices.i_count ; i++ )
            {
                p_val->p_list->p_values[i] = p_var->choices.p_values[i];
                p_val->p_list->pi_types[i] = p_var->i_type;
                p_var->pf_dup( &p_val->p_list->p_values[i] );
                if( p_val2 )
                {
                    p_val2->p_list->p_values[i].psz_string =
                        p_var->choices_text.p_values[i].psz_string ?
                    strdup(p_var->choices_text.p_values[i].psz_string) : NULL;
                    p_val2->p_list->pi_types[i] = VLC_VAR_STRING;
                }
            }
            break;
        case VLC_VAR_FREELIST:
            FreeList( p_val );
            if( p_val2 && p_val2->p_list )
            {
                for( i = 0; i < p_val2->p_list->i_count; i++ )
                    if( p_val2->p_list->p_values[i].psz_string )
                        free( p_val2->p_list->p_values[i].psz_string );
                if( p_val2->p_list->i_count )
                {
                    free( p_val2->p_list->p_values );
                    free( p_val2->p_list->pi_types );
                }
                free( p_val2->p_list );
            }
            break;
        case VLC_VAR_SETTEXT:
            if( p_var->psz_text ) free( p_var->psz_text );
            if( p_val && p_val->psz_string )
                p_var->psz_text = strdup( p_val->psz_string );
            break;
        case VLC_VAR_GETTEXT:
            p_val->psz_string = NULL;
            if( p_var->psz_text )
            {
                p_val->psz_string = strdup( p_var->psz_text );
            }
            break;
        case VLC_VAR_INHERITVALUE:
            {
                vlc_value_t val;

                if( InheritValue( p_this, psz_name, &val, p_var->i_type )
                    == VLC_SUCCESS )
                {
                    /* Duplicate already done */

                    /* Backup needed stuff */
                    oldval = p_var->val;
                    /* Check boundaries and list */
                    CheckValue( p_var, &val );
                    /* Set the variable */
                    p_var->val = val;
                    /* Free data if needed */
                    p_var->pf_free( &oldval );
                }

                if( p_val )
                {
                    *p_val = p_var->val;
                    p_var->pf_dup( p_val );
                }
            }
            break;
        case VLC_VAR_TRIGGER_CALLBACKS:
            {
                /* Deal with callbacks. Tell we're in a callback, release the lock,
                 * call stored functions, retake the lock. */
                if( p_var->i_entries )
                {
                    int i_var;
                    int i_entries = p_var->i_entries;
                    callback_entry_t *p_entries = p_var->p_entries;

                    p_var->b_incallback = VLC_TRUE;
                    vlc_mutex_unlock( &p_this->var_lock );

                    /* The real calls */
                    for( ; i_entries-- ; )
                    {
                        p_entries[i_entries].pf_callback( p_this, psz_name, p_var->val, p_var->val,
                                                          p_entries[i_entries].p_data );
                    }

                    vlc_mutex_lock( &p_this->var_lock );

                    i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );
                    if( i_var < 0 )
                    {
                        msg_Err( p_this, "variable %s has disappeared", psz_name );
                        vlc_mutex_unlock( &p_this->var_lock );
                        return VLC_ENOVAR;
                    }

                    p_var = &p_this->p_vars[i_var];
                    p_var->b_incallback = VLC_FALSE;
                }
            }
            break;

        default:
            break;
    }

    vlc_mutex_unlock( &p_this->var_lock );

    return VLC_SUCCESS;
}
Exemple #17
0
/**
 * Initialize a vlc variable
 *
 * We hash the given string and insert it into the sorted list. The insertion
 * may require slow memory copies, but think about what we gain in the log(n)
 * lookup phase when setting/getting the variable value!
 *
 * \param p_this The object in which to create the variable
 * \param psz_name The name of the variable
 * \param i_type The variables type. Must be one of \ref var_type combined with
 *               zero or more \ref var_flags
 */
int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
{
    int i_new;
    variable_t *p_var;
    static vlc_list_t dummy_null_list = {0, NULL, NULL};

    vlc_mutex_lock( &p_this->var_lock );

    /* FIXME: if the variable already exists, we don't duplicate it. But we
     * duplicate the lookups. It's not that serious, but if anyone finds some
     * time to rework Insert() so that only one lookup has to be done, feel
     * free to do so. */
    i_new = Lookup( p_this->p_vars, p_this->i_vars, psz_name );

    if( i_new >= 0 )
    {
        /* If the types differ, variable creation failed. */
        if( (i_type & ~VLC_VAR_DOINHERIT) != p_this->p_vars[i_new].i_type )
        {
            vlc_mutex_unlock( &p_this->var_lock );
            return VLC_EBADVAR;
        }

        p_this->p_vars[i_new].i_usage++;
        vlc_mutex_unlock( &p_this->var_lock );
        return VLC_SUCCESS;
    }

    i_new = Insert( p_this->p_vars, p_this->i_vars, psz_name );

    if( (p_this->i_vars & 15) == 15 )
    {
        p_this->p_vars = realloc( p_this->p_vars,
                                  (p_this->i_vars+17) * sizeof(variable_t) );
    }

    memmove( p_this->p_vars + i_new + 1,
             p_this->p_vars + i_new,
             (p_this->i_vars - i_new) * sizeof(variable_t) );

    p_this->i_vars++;

    p_var = &p_this->p_vars[i_new];
    memset( p_var, 0, sizeof(*p_var) );

    p_var->i_hash = HashString( psz_name );
    p_var->psz_name = strdup( psz_name );
    p_var->psz_text = NULL;

    p_var->i_type = i_type & ~VLC_VAR_DOINHERIT;
    memset( &p_var->val, 0, sizeof(vlc_value_t) );

    p_var->pf_dup = DupDummy;
    p_var->pf_free = FreeDummy;

    p_var->i_usage = 1;

    p_var->i_default = -1;
    p_var->choices.i_count = 0;
    p_var->choices.p_values = NULL;
    p_var->choices_text.i_count = 0;
    p_var->choices_text.p_values = NULL;

    p_var->b_incallback = VLC_FALSE;
    p_var->i_entries = 0;
    p_var->p_entries = NULL;

    /* Always initialize the variable, even if it is a list variable; this
     * will lead to errors if the variable is not initialized, but it will
     * not cause crashes in the variable handling. */
    switch( i_type & VLC_VAR_TYPE )
    {
        case VLC_VAR_BOOL:
            p_var->pf_cmp = CmpBool;
            p_var->val.b_bool = VLC_FALSE;
            break;
        case VLC_VAR_INTEGER:
        case VLC_VAR_HOTKEY:
            p_var->pf_cmp = CmpInt;
            p_var->val.i_int = 0;
            break;
        case VLC_VAR_STRING:
        case VLC_VAR_MODULE:
        case VLC_VAR_FILE:
        case VLC_VAR_DIRECTORY:
        case VLC_VAR_VARIABLE:
            p_var->pf_cmp = CmpString;
            p_var->pf_dup = DupString;
            p_var->pf_free = FreeString;
            p_var->val.psz_string = "";
            break;
        case VLC_VAR_FLOAT:
            p_var->pf_cmp = CmpFloat;
            p_var->val.f_float = 0.0;
            break;
        case VLC_VAR_TIME:
            p_var->pf_cmp = CmpTime;
            p_var->val.i_time = 0;
            break;
        case VLC_VAR_ADDRESS:
            p_var->pf_cmp = CmpAddress;
            p_var->val.p_address = NULL;
            break;
        case VLC_VAR_MUTEX:
            p_var->pf_cmp = CmpAddress;
            p_var->pf_free = FreeMutex;
            p_var->val.p_address = malloc( sizeof(vlc_mutex_t) );
            vlc_mutex_init( p_this, (vlc_mutex_t*)p_var->val.p_address );
            break;
        case VLC_VAR_LIST:
            p_var->pf_cmp = CmpAddress;
            p_var->pf_dup = DupList;
            p_var->pf_free = FreeList;
            p_var->val.p_list = &dummy_null_list;
            break;
    }

    /* Duplicate the default data we stored. */
    p_var->pf_dup( &p_var->val );

    if( i_type & VLC_VAR_DOINHERIT )
    {
        vlc_value_t val;

        if( InheritValue( p_this, psz_name, &val, p_var->i_type )
            == VLC_SUCCESS )
        {
            /* Free data if needed */
            p_var->pf_free( &p_var->val );
            /* Set the variable */
            p_var->val = val;

            if( i_type & VLC_VAR_HASCHOICE )
            {
                /* We must add the inherited value to our choice list */
                p_var->i_default = 0;

                INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
                             0, val );
                INSERT_ELEM( p_var->choices_text.p_values,
                             p_var->choices_text.i_count, 0, val );
                p_var->pf_dup( &p_var->choices.p_values[0] );
                p_var->choices_text.p_values[0].psz_string = NULL;
            }
        }
    }

    vlc_mutex_unlock( &p_this->var_lock );

    return VLC_SUCCESS;
}
Exemple #18
0
/*****************************************************************************
 * InheritValue: try to inherit the value of this variable from the same one
 *               in our closest parent.
 *****************************************************************************/
static int InheritValue( vlc_object_t *p_this, const char *psz_name,
                         vlc_value_t *p_val, int i_type )
{
    int i_var;
    variable_t *p_var;

    /* No need to take the structure lock,
     * we are only looking for our parents */

    if( !p_this->p_parent )
    {
        switch( i_type & VLC_VAR_TYPE )
        {
        case VLC_VAR_FILE:
        case VLC_VAR_DIRECTORY:
        case VLC_VAR_STRING:
        case VLC_VAR_MODULE:
            p_val->psz_string = config_GetPsz( p_this, psz_name );
            if( !p_val->psz_string ) p_val->psz_string = strdup("");
            break;
        case VLC_VAR_FLOAT:
            p_val->f_float = config_GetFloat( p_this, psz_name );
            break;
        case VLC_VAR_INTEGER:
        case VLC_VAR_HOTKEY:
            p_val->i_int = config_GetInt( p_this, psz_name );
            break;
        case VLC_VAR_BOOL:
            p_val->b_bool = config_GetInt( p_this, psz_name );
            break;
        case VLC_VAR_LIST:
        {
            char *psz_orig, *psz_var;
            vlc_list_t *p_list = malloc(sizeof(vlc_list_t));
            p_val->p_list = p_list;
            p_list->i_count = 0;

            psz_var = psz_orig = config_GetPsz( p_this, psz_name );
            while( psz_var && *psz_var )
            {
                char *psz_item = psz_var;
                vlc_value_t val;
                while( *psz_var && *psz_var != ',' ) psz_var++;
                if( *psz_var == ',' )
                {
                    *psz_var = '\0';
                    psz_var++;
                }
                val.i_int = strtol( psz_item, NULL, 0 );
                INSERT_ELEM( p_list->p_values, p_list->i_count,
                             p_list->i_count, val );
                /* p_list->i_count is incremented twice by INSERT_ELEM */
                p_list->i_count--;
                INSERT_ELEM( p_list->pi_types, p_list->i_count,
                             p_list->i_count, VLC_VAR_INTEGER );
            }
            if( psz_orig ) free( psz_orig );
            break;
        }
        default:
            return VLC_ENOOBJ;
            break;
        }

        return VLC_SUCCESS;
    }

    /* Look for the variable */
    vlc_mutex_lock( &p_this->p_parent->var_lock );

    i_var = Lookup( p_this->p_parent->p_vars, p_this->p_parent->i_vars,
                    psz_name );

    if( i_var >= 0 )
    {
        /* We found it! */
        p_var = &p_this->p_parent->p_vars[i_var];

        /* Really get the variable */
        *p_val = p_var->val;

        /* Duplicate value if needed */
        p_var->pf_dup( p_val );

        vlc_mutex_unlock( &p_this->p_parent->var_lock );
        return VLC_SUCCESS;
    }

    vlc_mutex_unlock( &p_this->p_parent->var_lock );

    /* We're still not there */

    return InheritValue( p_this->p_parent, psz_name, p_val, i_type );
}
Exemple #19
0
static int Demux( demux_t *p_demux )
{
    playlist_t *p_playlist;
    char       *psz_line;
    int        i_position;

    char *psz_name = NULL;
    mtime_t i_duration = -1;
    char **ppsz_options = NULL;
    int i_options = 0;

    vlc_bool_t b_cleanup = VLC_FALSE;

    p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
                                                 FIND_PARENT );
    if( !p_playlist )
    {
        msg_Err( p_demux, "can't find playlist" );
        return -1;
    }

    vlc_mutex_lock( &p_playlist->object_lock );
    p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
    i_position = p_playlist->i_index + 1;
    vlc_mutex_unlock( &p_playlist->object_lock );

    psz_line = stream_ReadLine( p_demux->s );
    while( psz_line )
    {
        char *psz_parse = psz_line;

        /* Skip leading tabs and spaces */
        while( *psz_parse == ' ' || *psz_parse == '\t' ||
               *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++;

        if( *psz_parse == '#' )
        {
            /* Parse extra info */

            /* Skip leading tabs and spaces */
            while( *psz_parse == ' ' || *psz_parse == '\t' || 
                   *psz_parse == '\n' || *psz_parse == '\r' ||
                   *psz_parse == '#' ) psz_parse++;

            if( !*psz_parse ) goto error;

            if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) )
            {
                /* Extended info */
                char *psz_duration;
                psz_parse += sizeof("EXTINF:") - 1;
                while( *psz_parse == '\t' || *psz_parse == ' ' ) psz_parse++;

                psz_duration = psz_parse;
                psz_parse = strchr( psz_parse, ',' );
                if( psz_parse )
                {
                    *psz_parse = '\0';
                    psz_parse++;
                    psz_name = strdup( psz_parse );
                    i_duration = atoi( psz_duration );
                    if( i_duration != -1 ) i_duration *= 1000000;
                }
            }
            else if( !strncasecmp( psz_parse, "EXTVLCOPT:",
                                   sizeof("EXTVLCOPT:") -1 ) )

            {
                /* VLC Option */
                char *psz_option;
                psz_parse += sizeof("EXTVLCOPT:") -1;
                if( !*psz_parse ) goto error;

                psz_option = strdup( psz_parse );
                if( psz_option )
                    INSERT_ELEM( ppsz_options, i_options, i_options,
                                 psz_option );
            }
        }
        else if( *psz_parse )
        {
            char *psz_mrl =
                ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix );

            b_cleanup = VLC_TRUE;
            if( !psz_mrl ) goto error;

            playlist_AddExt( p_playlist, psz_mrl, psz_name,
                             PLAYLIST_INSERT, i_position, i_duration,
                             (const char **)ppsz_options, i_options );

            i_position++;
            free( psz_mrl );
        }

 error:

        /* Fetch another line */
        free( psz_line );
        psz_line = stream_ReadLine( p_demux->s );
        if( !psz_line ) b_cleanup = VLC_TRUE;

        if( b_cleanup )
        {
            /* Cleanup state */
            while( i_options-- ) free( ppsz_options[i_options] );
            if( ppsz_options ) free( ppsz_options );
            ppsz_options = NULL; i_options = 0;
            if( psz_name ) free( psz_name );
            psz_name = NULL;
            i_duration = -1;

            b_cleanup = VLC_FALSE;
        }
    }

    vlc_object_release( p_playlist );
    return VLC_SUCCESS;
}
Exemple #20
0
static void ParseUrls( services_discovery_t *p_sd, char *psz_urls )
{
    services_discovery_sys_t *p_sys = p_sd->p_sys;
    int i_new_items = 0;
    input_item_t **pp_new_items = NULL;

    int i_new_urls = 0;
    char **ppsz_new_urls = NULL;

    int i, j;

    for( ;; )
    {
        if( !psz_urls ) break;

        char *psz_tok = strchr( psz_urls, '|' );
        if( psz_tok ) *psz_tok = '\0';

        for( i = 0; i < p_sys->i_urls; i++ )
            if( !strcmp( psz_urls, p_sys->ppsz_urls[i] ) )
                break;
        if( i == p_sys->i_urls )
        {
            INSERT_ELEM( ppsz_new_urls, i_new_urls, i_new_urls,
                         strdup( psz_urls ) );

            input_item_t *p_input;
            p_input = input_item_New( p_sd, psz_urls, psz_urls );
            input_item_AddOption( p_input, "demux=podcast", VLC_INPUT_OPTION_TRUSTED );

            INSERT_ELEM( pp_new_items, i_new_items, i_new_items, p_input );
            services_discovery_AddItem( p_sd, p_input, NULL /* no cat */ );

            INSERT_ELEM( p_sys->pp_input, p_sys->i_input, p_sys->i_input,
                         input_CreateAndStart( p_sd, p_input, NULL ) );
        }
        else
        {
            INSERT_ELEM( ppsz_new_urls, i_new_urls, i_new_urls,
                         strdup( p_sys->ppsz_urls[i]) );
            INSERT_ELEM( pp_new_items, i_new_items, i_new_items, p_sys->pp_items[i] );
        }
        if( psz_tok )  psz_urls = psz_tok+1;
        else break;
    }

    /* delete removed items and signal the removal */
    for( i = 0; i<p_sys->i_items; ++i )
    {
        for( j = 0; j < i_new_items; ++j )
            if( pp_new_items[j] == p_sys->pp_items[i] ) break;
        if( j == i_new_items )
        {
          services_discovery_RemoveItem( p_sd, p_sys->pp_items[i] );
          vlc_gc_decref( p_sys->pp_items[i] );
        }
    }
    free( p_sys->pp_items );
    for( int i = 0; i < p_sys->i_urls; i++ ) free( p_sys->ppsz_urls[i] );
    free( p_sys->ppsz_urls );

    p_sys->ppsz_urls = ppsz_new_urls;
    p_sys->i_urls = i_new_urls;
    p_sys->pp_items = pp_new_items;
    p_sys->i_items = i_new_items;
}
Exemple #21
0
/**
 * Initialize a vlc variable
 *
 * We hash the given string and insert it into the sorted list. The insertion
 * may require slow memory copies, but think about what we gain in the log(n)
 * lookup phase when setting/getting the variable value!
 *
 * \param p_this The object in which to create the variable
 * \param psz_name The name of the variable
 * \param i_type The variables type. Must be one of \ref var_type combined with
 *               zero or more \ref var_flags
 */
int var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
{
    assert( p_this );

    variable_t *p_var = calloc( 1, sizeof( *p_var ) );
    if( p_var == NULL )
        return VLC_ENOMEM;

    p_var->psz_name = strdup( psz_name );
    p_var->psz_text = NULL;

    p_var->i_type = i_type & ~VLC_VAR_DOINHERIT;

    p_var->i_usage = 1;

    p_var->i_default = -1;
    p_var->choices.i_count = 0;
    p_var->choices.p_values = NULL;
    p_var->choices_text.i_count = 0;
    p_var->choices_text.p_values = NULL;

    p_var->b_incallback = false;
    p_var->value_callbacks = (callback_table_t){ 0 };

    /* Always initialize the variable, even if it is a list variable; this
     * will lead to errors if the variable is not initialized, but it will
     * not cause crashes in the variable handling. */
    switch( i_type & VLC_VAR_CLASS )
    {
        case VLC_VAR_BOOL:
            p_var->ops = &bool_ops;
            p_var->val.b_bool = false;
            break;
        case VLC_VAR_INTEGER:
            p_var->ops = &int_ops;
            p_var->val.i_int = 0;
            break;
        case VLC_VAR_STRING:
            p_var->ops = &string_ops;
            p_var->val.psz_string = NULL;
            break;
        case VLC_VAR_FLOAT:
            p_var->ops = &float_ops;
            p_var->val.f_float = 0.0;
            break;
        case VLC_VAR_COORDS:
            p_var->ops = &coords_ops;
            p_var->val.coords.x = p_var->val.coords.y = 0;
            break;
        case VLC_VAR_ADDRESS:
            p_var->ops = &addr_ops;
            p_var->val.p_address = NULL;
            break;
        case VLC_VAR_VOID:
            p_var->ops = &void_ops;
            break;
        default:
            vlc_assert_unreachable ();
    }

    if( (i_type & VLC_VAR_DOINHERIT)
     && var_Inherit( p_this, psz_name, i_type, &p_var->val ) == 0 )
    {
        if( i_type & VLC_VAR_HASCHOICE )
        {
            /* We must add the inherited value to our choice list */
            p_var->i_default = 0;

            INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
                         0, p_var->val );
            INSERT_ELEM( p_var->choices_text.p_values,
                         p_var->choices_text.i_count, 0, p_var->val );
            p_var->ops->pf_dup( &p_var->choices.p_values[0] );
            p_var->choices_text.p_values[0].psz_string = NULL;
        }
    }

    vlc_object_internals_t *p_priv = vlc_internals( p_this );
    variable_t **pp_var, *p_oldvar;
    int ret = VLC_SUCCESS;

    vlc_mutex_lock( &p_priv->var_lock );

    pp_var = tsearch( p_var, &p_priv->var_root, varcmp );
    if( unlikely(pp_var == NULL) )
        ret = VLC_ENOMEM;
    else if( (p_oldvar = *pp_var) == p_var ) /* Variable create */
        p_var = NULL; /* Variable created */
    else /* Variable already exists */
    {
        assert (((i_type ^ p_oldvar->i_type) & VLC_VAR_CLASS) == 0);
        p_oldvar->i_usage++;
        p_oldvar->i_type |= i_type & (VLC_VAR_ISCOMMAND|VLC_VAR_HASCHOICE);
    }
    vlc_mutex_unlock( &p_priv->var_lock );

    /* If we did not need to create a new variable, free everything... */
    if( p_var != NULL )
        Destroy( p_var );
    return ret;
}
Exemple #22
0
/**
 * Main demux callback function
 * @param p_demux: this demux object
 */
static int Demux( demux_t *p_demux )
{
    char       *psz_line;
    char       *psz_artist = NULL, *psz_album = NULL, *psz_genre = NULL, *psz_year = NULL;
    char       *psz_author = NULL, *psz_title = NULL, *psz_copyright = NULL, *psz_cdnum = NULL, *psz_comments = NULL;
    mtime_t    i_duration = -1;
    const char **ppsz_options = NULL;
    int        i_options = 0, i_start = 0, i_stop = 0;
    bool b_cleanup = false;
    input_item_t *p_input;

    input_item_t *p_current_input = GetCurrentItem(p_demux);

    input_item_node_t *p_subitems = input_item_node_Create( p_current_input );

    psz_line = vlc_stream_ReadLine( p_demux->s );
    while( psz_line )
    {
        char *psz_parse = psz_line;

        /* Skip leading tabs and spaces */
        while( *psz_parse == ' ' || *psz_parse == '\t' ||
               *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++;

        if( *psz_parse == '#' )
        {
            /* Ignore comments */
        }
        else if( *psz_parse )
        {
            char *psz_mrl, *psz_option_next, *psz_option;
            char *psz_param, *psz_value;

            /* Get the MRL from the file. Note that this might contain parameters of form ?param1=value1&param2=value2 in a RAM file */
            psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix );

            b_cleanup = true;
            if ( !psz_mrl ) goto error;

            /* We have the MRL, now we have to check for options and parse them from MRL */
            psz_option = strchr( psz_mrl, '?' ); /* Look for start of options */
            if( psz_option )
            {
                /* Remove options from MRL
                   because VLC can't get the file otherwise */
                *psz_option = '\0';
                psz_option++;
                psz_option_next = psz_option;
                while( 1 ) /* Process each option */
                {
                    /* Look for end of first option which maybe a & or \0 */
                    psz_option = psz_option_next;
                    psz_option_next = strchr( psz_option, '&' );
                    if( psz_option_next )
                    {
                        *psz_option_next = '\0';
                        psz_option_next++;
                    }
                    else
                        psz_option_next = strchr( psz_option, '\0' );
                    /* Quit if options are over */
                    if( psz_option_next == psz_option )
                        break;

                    /* Parse out param and value */
                    psz_param = psz_option;
                    psz_value = strchr( psz_option, '=' );
                    if( psz_value == NULL )
                        break;
                    *psz_value = '\0';
                    psz_value++;

                    /* Take action based on parameter value in the below if else structure */
                    /* TODO: Remove any quotes surrounding values if required */
                    if( !strcmp( psz_param, "clipinfo" ) )
                    {
                        ParseClipInfo( psz_value, &psz_artist, &psz_title,
                           &psz_album, &psz_genre, &psz_year,
                           &psz_cdnum, &psz_comments ); /* clipinfo has various sub parameters, which is parsed by this function */
                    }
                    else if( !strcmp( psz_param, "author" ) )
                    {
                        psz_author = vlc_uri_decode_duplicate(psz_value);
                        EnsureUTF8( psz_author );
                    }
                    else if( !strcmp( psz_param, "start" )
                            && strncmp( psz_mrl, "rtsp", 4 ) /* Our rtsp-real or our real demuxer is wrong */  )
                    {
                        i_start = ParseTime( psz_value, strlen( psz_value ) );
                        char *temp;
                        if( i_start )
                        {
                            if( asprintf( &temp, ":start-time=%d", i_start ) != -1 )
                                INSERT_ELEM( ppsz_options, i_options, i_options, temp );
                        }
                    }
                    else if( !strcmp( psz_param, "end" ) )
                    {
                        i_stop = ParseTime( psz_value, strlen( psz_value ) );
                        char *temp;
                        if( i_stop )
                        {
                            if( asprintf( &temp, ":stop-time=%d", i_stop ) != -1 )
                                INSERT_ELEM( ppsz_options, i_options, i_options, temp );
                        }
                    }
                    else if( !strcmp( psz_param, "title" ) )
                    {
                        free( psz_title );
                        psz_title = vlc_uri_decode_duplicate(psz_value);
                        EnsureUTF8( psz_title );
                    }
                    else if( !strcmp( psz_param, "copyright" ) )
                    {
                        psz_copyright = vlc_uri_decode_duplicate(psz_value);
                        EnsureUTF8( psz_copyright );
                    }
                    else
                    {   /* TODO: insert option anyway? Currently ignores*/
                        /* INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); */
                    }
                }
            }

            /* Create the input item and pump in all the options into playlist item */
            p_input = input_item_NewExt( psz_mrl, psz_title, i_duration,
                                         ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN );
            if( !p_input )
            {
                free( psz_mrl );
                goto error;
            }
            input_item_AddOptions( p_input, i_options, ppsz_options, 0 );

            if( !EMPTY_STR( psz_artist ) ) input_item_SetArtist( p_input, psz_artist );
            if( !EMPTY_STR( psz_author ) ) input_item_SetPublisher( p_input, psz_author );
            if( !EMPTY_STR( psz_title ) ) input_item_SetTitle( p_input, psz_title );
            if( !EMPTY_STR( psz_copyright ) ) input_item_SetCopyright( p_input, psz_copyright );
            if( !EMPTY_STR( psz_album ) ) input_item_SetAlbum( p_input, psz_album );
            if( !EMPTY_STR( psz_genre ) ) input_item_SetGenre( p_input, psz_genre );
            if( !EMPTY_STR( psz_year ) ) input_item_SetDate( p_input, psz_year );
            if( !EMPTY_STR( psz_cdnum ) ) input_item_SetTrackNum( p_input, psz_cdnum );
            if( !EMPTY_STR( psz_comments ) ) input_item_SetDescription( p_input, psz_comments );

            input_item_node_AppendItem( p_subitems, p_input );
            vlc_gc_decref( p_input );
            free( psz_mrl );
        }

 error:
        /* Fetch another line */
        free( psz_line );
        psz_line = vlc_stream_ReadLine( p_demux->s );
        if( !psz_line ) b_cleanup = true;

        if( b_cleanup )
        {
            /* Cleanup state */
            while( i_options-- ) free( (char*)ppsz_options[i_options] );
            FREENULL( ppsz_options );
            FREENULL( psz_artist );
            FREENULL( psz_title );
            FREENULL( psz_author );
            FREENULL( psz_copyright );
            FREENULL( psz_album );
            FREENULL( psz_genre );
            FREENULL( psz_year );
            FREENULL( psz_cdnum );
            FREENULL( psz_comments );
            i_options = 0;
            i_duration = -1;
            i_start = 0;
            i_stop = 0;
            b_cleanup = false;
        }
    }
    input_item_node_PostAndDelete( p_subitems );
    vlc_gc_decref(p_current_input);
    var_Destroy( p_demux, "m3u-extvlcopt" );
    return 0; /* Needed for correct operation of go back */
}
Exemple #23
0
/**
 * Perform an action on a variable
 *
 * \param p_this The object that holds the variable
 * \param psz_name The name of the variable
 * \param i_action The action to perform. Must be one of \ref var_action
 * \param p_val First action parameter
 * \param p_val2 Second action parameter
 */
int var_Change( vlc_object_t *p_this, const char *psz_name,
                int i_action, vlc_value_t *p_val, vlc_value_t *p_val2 )
{
    int ret = VLC_SUCCESS;
    variable_t *p_var;
    vlc_value_t oldval;
    vlc_value_t newval;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_ENOVAR;
    }

    switch( i_action )
    {
        case VLC_VAR_SETMIN:
            if( p_var->i_type & VLC_VAR_HASMIN )
            {
                p_var->ops->pf_free( &p_var->min );
            }
            p_var->i_type |= VLC_VAR_HASMIN;
            p_var->min = *p_val;
            p_var->ops->pf_dup( &p_var->min );
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_GETMIN:
            if( p_var->i_type & VLC_VAR_HASMIN )
                *p_val = p_var->min;
            else
                ret = VLC_EGENERIC;
            break;
        case VLC_VAR_SETMAX:
            if( p_var->i_type & VLC_VAR_HASMAX )
            {
                p_var->ops->pf_free( &p_var->max );
            }
            p_var->i_type |= VLC_VAR_HASMAX;
            p_var->max = *p_val;
            p_var->ops->pf_dup( &p_var->max );
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_GETMAX:
            if( p_var->i_type & VLC_VAR_HASMAX )
                *p_val = p_var->max;
            else
                ret = VLC_EGENERIC;
            break;
        case VLC_VAR_SETSTEP:
            if( p_var->i_type & VLC_VAR_HASSTEP )
            {
                p_var->ops->pf_free( &p_var->step );
            }
            p_var->i_type |= VLC_VAR_HASSTEP;
            p_var->step = *p_val;
            p_var->ops->pf_dup( &p_var->step );
            CheckValue( p_var, &p_var->val );
            break;
        case VLC_VAR_GETSTEP:
            if( p_var->i_type & VLC_VAR_HASSTEP )
                *p_val = p_var->step;
            else
                ret = VLC_EGENERIC;
            break;
        case VLC_VAR_ADDCHOICE:
        {
            int i = p_var->choices.i_count;

            INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
                         i, *p_val );
            INSERT_ELEM( p_var->choices_text.p_values,
                         p_var->choices_text.i_count, i, *p_val );
            p_var->ops->pf_dup( &p_var->choices.p_values[i] );
            p_var->choices_text.p_values[i].psz_string =
                ( p_val2 && p_val2->psz_string ) ?
                strdup( p_val2->psz_string ) : NULL;

            CheckValue( p_var, &p_var->val );

            TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_ADDCHOICE, p_val);
            break;
        }
        case VLC_VAR_DELCHOICE:
        {
            int i;

            for( i = 0 ; i < p_var->choices.i_count ; i++ )
                if( p_var->ops->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 )
                    break;

            if( i == p_var->choices.i_count )
            {
                /* Not found */
                vlc_mutex_unlock( &p_priv->var_lock );
                return VLC_EGENERIC;
            }

            if( p_var->i_default > i )
                p_var->i_default--;
            else if( p_var->i_default == i )
                p_var->i_default = -1;

            p_var->ops->pf_free( &p_var->choices.p_values[i] );
            free( p_var->choices_text.p_values[i].psz_string );
            REMOVE_ELEM( p_var->choices.p_values, p_var->choices.i_count, i );
            REMOVE_ELEM( p_var->choices_text.p_values,
                         p_var->choices_text.i_count, i );

            CheckValue( p_var, &p_var->val );

            TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_DELCHOICE, p_val);
            break;
        }
        case VLC_VAR_CHOICESCOUNT:
            p_val->i_int = p_var->choices.i_count;
            break;
        case VLC_VAR_CLEARCHOICES:
            for( int i = 0 ; i < p_var->choices.i_count ; i++ )
                p_var->ops->pf_free( &p_var->choices.p_values[i] );
            for( int i = 0 ; i < p_var->choices_text.i_count ; i++ )
                free( p_var->choices_text.p_values[i].psz_string );

            if( p_var->choices.i_count ) free( p_var->choices.p_values );
            if( p_var->choices_text.i_count ) free( p_var->choices_text.p_values );

            p_var->choices.i_count = 0;
            p_var->choices.p_values = NULL;
            p_var->choices_text.i_count = 0;
            p_var->choices_text.p_values = NULL;
            p_var->i_default = -1;
            TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_CLEARCHOICES, NULL);
            break;
        case VLC_VAR_SETDEFAULT:
        {
            int i;
            /* FIXME: the list is sorted, dude. Use something cleverer. */
            for( i = 0 ; i < p_var->choices.i_count ; i++ )
                if( p_var->ops->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 )
                    break;

            if( i == p_var->choices.i_count )
                /* Not found */
                break;

            p_var->i_default = i;
            CheckValue( p_var, &p_var->val );
            break;
        }
        case VLC_VAR_SETVALUE:
            /* Duplicate data if needed */
            newval = *p_val;
            p_var->ops->pf_dup( &newval );
            /* Backup needed stuff */
            oldval = p_var->val;
            /* Check boundaries and list */
            CheckValue( p_var, &newval );
            /* Set the variable */
            p_var->val = newval;
            /* Free data if needed */
            p_var->ops->pf_free( &oldval );
            break;
        case VLC_VAR_GETCHOICES:
            p_val->p_list = xmalloc( sizeof(vlc_list_t) );
            p_val->p_list->p_values =
                xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) );
            p_val->p_list->i_type = p_var->i_type;
            p_val->p_list->i_count = p_var->choices.i_count;
            if( p_val2 )
            {
                p_val2->p_list = xmalloc( sizeof(vlc_list_t) );
                p_val2->p_list->p_values =
                    xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) );
                p_val2->p_list->i_type = VLC_VAR_STRING;
                p_val2->p_list->i_count = p_var->choices.i_count;
            }
            for( int i = 0 ; i < p_var->choices.i_count ; i++ )
            {
                p_val->p_list->p_values[i] = p_var->choices.p_values[i];
                p_var->ops->pf_dup( &p_val->p_list->p_values[i] );
                if( p_val2 )
                {
                    p_val2->p_list->p_values[i].psz_string =
                        p_var->choices_text.p_values[i].psz_string ?
                    strdup(p_var->choices_text.p_values[i].psz_string) : NULL;
                }
            }
            break;
        case VLC_VAR_SETTEXT:
            free( p_var->psz_text );
            if( p_val && p_val->psz_string )
                p_var->psz_text = strdup( p_val->psz_string );
            else
                p_var->psz_text = NULL;
            break;
        case VLC_VAR_GETTEXT:
            p_val->psz_string = p_var->psz_text ? strdup( p_var->psz_text )
                                                : NULL;
            break;
        default:
            break;
    }

    vlc_mutex_unlock( &p_priv->var_lock );

    return ret;
}
Exemple #24
0
Fichier : m3u.c Projet : etix/vlc
static int Demux( demux_t *p_demux )
{
    char       *psz_line;
    char       *psz_name = NULL;
    char       *psz_artist = NULL;
    char       *psz_album_art = NULL;
    int        i_parsed_duration = 0;
    mtime_t    i_duration = -1;
    const char**ppsz_options = NULL;
    char *    (*pf_dup) (const char *) = p_demux->p_sys->pf_dup;
    int        i_options = 0;
    bool b_cleanup = false;
    input_item_t *p_input;

    input_item_t *p_current_input = GetCurrentItem(p_demux);
    input_item_node_t *p_subitems = input_item_node_Create( p_current_input );

    psz_line = vlc_stream_ReadLine( p_demux->s );
    while( psz_line )
    {
        char *psz_parse = psz_line;

        /* Skip leading tabs and spaces */
        while( *psz_parse == ' ' || *psz_parse == '\t' ||
               *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++;

        if( *psz_parse == '#' )
        {
            /* Parse extra info */

            /* Skip leading tabs and spaces */
            while( *psz_parse == ' ' || *psz_parse == '\t' ||
                   *psz_parse == '\n' || *psz_parse == '\r' ||
                   *psz_parse == '#' ) psz_parse++;

            if( !*psz_parse ) goto error;

            if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) )
            {
                /* Extended info */
                psz_parse += sizeof("EXTINF:") - 1;
                FREENULL( psz_name );
                FREENULL( psz_artist );
                parseEXTINF( psz_parse, &psz_artist, &psz_name, &i_parsed_duration );
                if( i_parsed_duration >= 0 )
                    i_duration = i_parsed_duration * INT64_C(1000000);
                if( psz_name )
                    psz_name = pf_dup( psz_name );
                if( psz_artist )
                    psz_artist = pf_dup( psz_artist );
            }
            else if( !strncasecmp( psz_parse, "EXTVLCOPT:",
                                   sizeof("EXTVLCOPT:") -1 ) )
            {
                /* VLC Option */
                char *psz_option;
                psz_parse += sizeof("EXTVLCOPT:") -1;
                if( !*psz_parse ) goto error;

                psz_option = pf_dup( psz_parse );
                if( psz_option )
                    INSERT_ELEM( ppsz_options, i_options, i_options,
                                 psz_option );
            }
            /* Special case for jamendo which provide the albumart */
            else if( !strncasecmp( psz_parse, "EXTALBUMARTURL:",
                     sizeof( "EXTALBUMARTURL:" ) -1 ) )
            {
                psz_parse += sizeof( "EXTALBUMARTURL:" ) - 1;
                free( psz_album_art );
                psz_album_art = pf_dup( psz_parse );
            }
        }
        else if( !strncasecmp( psz_parse, "RTSPtext", sizeof("RTSPtext") -1 ) )
        {
            ;/* special case to handle QuickTime RTSPtext redirect files */
        }
        else if( *psz_parse )
        {
            char *psz_mrl;

            psz_parse = pf_dup( psz_parse );
            if( !psz_name && psz_parse )
                /* Use filename as name for relative entries */
                psz_name = strdup( psz_parse );

            psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix );

            b_cleanup = true;
            if( !psz_mrl )
            {
                free( psz_parse );
                goto error;
            }

            p_input = input_item_NewExt( psz_mrl, psz_name, i_duration,
                                         ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN );
            free( psz_parse );
            free( psz_mrl );

            if( !p_input )
                goto error;
            input_item_AddOptions( p_input, i_options, ppsz_options, 0 );
            input_item_CopyOptions( p_input, p_current_input );

            if( !EMPTY_STR(psz_artist) )
                input_item_SetArtist( p_input, psz_artist );
            if( psz_name ) input_item_SetTitle( p_input, psz_name );
            if( !EMPTY_STR(psz_album_art) )
                input_item_SetArtURL( p_input, psz_album_art );

            input_item_node_AppendItem( p_subitems, p_input );
            vlc_gc_decref( p_input );
        }

 error:

        /* Fetch another line */
        free( psz_line );
        psz_line = vlc_stream_ReadLine( p_demux->s );
        if( !psz_line ) b_cleanup = true;

        if( b_cleanup )
        {
            /* Cleanup state */
            while( i_options-- ) free( (char*)ppsz_options[i_options] );
            FREENULL( ppsz_options );
            i_options = 0;
            FREENULL( psz_name );
            FREENULL( psz_artist );
            FREENULL( psz_album_art );
            i_parsed_duration = 0;
            i_duration = -1;

            b_cleanup = false;
        }
    }
    input_item_node_PostAndDelete( p_subitems );
    vlc_gc_decref(p_current_input);
    var_Destroy( p_demux, "m3u-extvlcopt" );
    return 0; /* Needed for correct operation of go back */
}
Exemple #25
0
static void ParseRequest( services_discovery_t *p_sd )
{
    services_discovery_sys_t *p_sys = p_sd->p_sys;

    char *psz_request = p_sys->psz_request;

    int i;

    char *psz_tok = strchr( psz_request, ':' );
    if( !psz_tok ) return;
    *psz_tok = '\0';

    if ( ! p_sys->b_savedurls_loaded )
    {
        char *psz_urls = var_GetNonEmptyString( p_sd->p_parent,
                                                "podcast-urls" );
        ParseUrls( p_sd, psz_urls );
        free( psz_urls );
    }

    if( !strcmp( psz_request, "ADD" ) )
    {
        psz_request = psz_tok + 1;
        for( i = 0; i<p_sys->i_urls; i++ )
            if( !strcmp(p_sys->ppsz_urls[i],psz_request) )
              break;
        if( i == p_sys->i_urls )
        {
            INSERT_ELEM( p_sys->ppsz_urls, p_sys->i_urls, p_sys->i_urls,
              strdup( psz_request ) );

            input_item_t *p_input;
            p_input = input_item_New( psz_request, psz_request );
            input_item_AddOption( p_input, "demux=podcast", VLC_INPUT_OPTION_TRUSTED );

            INSERT_ELEM( p_sys->pp_items, p_sys->i_items, p_sys->i_items, p_input );
            services_discovery_AddItem( p_sd, p_input, NULL /* no cat */ );

            INSERT_ELEM( p_sys->pp_input, p_sys->i_input, p_sys->i_input,
                         input_CreateAndStart( p_sd, p_input, NULL ) );
            SaveUrls( p_sd );
        }
    }
    else if ( !strcmp( psz_request, "RM" ) )
    {
        psz_request = psz_tok + 1;
        for( i = 0; i<p_sys->i_urls; i++ )
          if( !strcmp(p_sys->ppsz_urls[i],psz_request) )
            break;
        if( i != p_sys->i_urls )
        {
            services_discovery_RemoveItem( p_sd, p_sys->pp_items[i] );
            vlc_gc_decref( p_sys->pp_items[i] );
            REMOVE_ELEM( p_sys->ppsz_urls, p_sys->i_urls, i );
            REMOVE_ELEM( p_sys->pp_items, p_sys->i_items, i );
        }
        SaveUrls( p_sd );
    }

    free( p_sys->psz_request );
    p_sys->psz_request = NULL;
}