Example #1
0
/*****************************************************************************
 * Control input stream
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    input_title_t ***ppp_title;
    int i;
    int64_t *pi64;
    vlc_meta_t *p_meta;

    switch( i_query )
    {
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            *va_arg( args, bool* ) = true;
            break;

        case ACCESS_GET_SIZE:
            *va_arg( args, uint64_t* ) = p_sys->size;
            break;

        case ACCESS_GET_PTS_DELAY:
            pi64 = va_arg( args, int64_t * );
            *pi64 = INT64_C(1000)
                  * var_InheritInteger( p_access, "file-caching" );
            break;

        case ACCESS_SET_PAUSE_STATE:
            /* nothing to do */
            break;

        case ACCESS_GET_TITLE_INFO:
            /* return a copy of our seek points */
            if( !p_sys->p_marks )
                return VLC_EGENERIC;
            ppp_title = va_arg( args, input_title_t*** );
            *va_arg( args, int* ) = 1;
            *ppp_title = malloc( sizeof( **ppp_title ) );
            if( !*ppp_title )
                return VLC_ENOMEM;
            **ppp_title = vlc_input_title_Duplicate( p_sys->p_marks );
            break;

        case ACCESS_GET_TITLE:
            *va_arg( args, unsigned * ) = 0;
            break;

        case ACCESS_GET_SEEKPOINT:
            *va_arg( args, unsigned * ) = p_sys->cur_seekpoint;
            break;

        case ACCESS_GET_CONTENT_TYPE:
            *va_arg( args, char ** ) =
                strdup( p_sys->b_ts_format ? "video/MP2T" : "video/MP2P" );
            break;

        case ACCESS_SET_TITLE:
            /* ignore - only one title */
            break;

        case ACCESS_SET_SEEKPOINT:
            i = va_arg( args, int );
            return Seek( p_access, p_sys->offsets[i] );

        case ACCESS_GET_META:
            p_meta = va_arg( args, vlc_meta_t* );
            vlc_meta_Merge( p_meta, p_sys->p_meta );
            break;

        default:
            return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}
Example #2
0
File: vcd.c Project: Ackhuman/vlc
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    input_title_t ***ppp_title;
    int i;

    switch( i_query )
    {
        /* */
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            *va_arg( args, bool* ) = true;
            break;

        /* */
        case ACCESS_GET_PTS_DELAY:
            *va_arg( args, int64_t * ) = INT64_C(1000)
                * var_InheritInteger(p_access, "disc-caching");
            break;

        /* */
        case ACCESS_SET_PAUSE_STATE:
            break;

        case ACCESS_GET_TITLE_INFO:
            ppp_title = va_arg( args, input_title_t*** );
            *va_arg( args, int* ) = p_sys->i_titles;

            /* Duplicate title infos */
            *ppp_title = malloc( sizeof(input_title_t **) * p_sys->i_titles );
            for( i = 0; i < p_sys->i_titles; i++ )
            {
                (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->title[i] );
            }
            break;

        case ACCESS_SET_TITLE:
            i = va_arg( args, int );
            if( i != p_access->info.i_title )
            {
                /* Update info */
                p_access->info.i_update |=
                  INPUT_UPDATE_TITLE|INPUT_UPDATE_SEEKPOINT|INPUT_UPDATE_SIZE;
                p_access->info.i_title = i;
                p_access->info.i_seekpoint = 0;
                p_access->info.i_size = p_sys->title[i]->i_size;
                p_access->info.i_pos  = 0;

                /* Next sector to read */
                p_sys->i_sector = p_sys->p_sectors[1+i];
            }
            break;

        case ACCESS_SET_SEEKPOINT:
        {
            input_title_t *t = p_sys->title[p_access->info.i_title];
            i = va_arg( args, int );
            if( t->i_seekpoint > 0 )
            {
                p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
                p_access->info.i_seekpoint = i;

                p_sys->i_sector = p_sys->p_sectors[1+p_access->info.i_title] +
                    t->seekpoint[i]->i_byte_offset / VCD_DATA_SIZE;

                p_access->info.i_pos = (uint64_t)(p_sys->i_sector -
                    p_sys->p_sectors[1+p_access->info.i_title]) *VCD_DATA_SIZE;
            }
            return VLC_SUCCESS;
        }

        case ACCESS_SET_PRIVATE_ID_STATE:
        case ACCESS_GET_CONTENT_TYPE:
            return VLC_EGENERIC;

        default:
            msg_Warn( p_access, "unimplemented query in control" );
            return VLC_EGENERIC;

    }
    return VLC_SUCCESS;
}
Example #3
0
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( demux_t *p_demux, int i_query, va_list args )
{
    demux_sys_t        *p_sys = p_demux->p_sys;
    int64_t     *pi64, i64;
    double      *pf, f;
    int         i_skp;
    size_t      i_idx;
    bool            b;

    vlc_meta_t *p_meta;
    input_attachment_t ***ppp_attach;
    int *pi_int;

    switch( i_query )
    {
        case DEMUX_CAN_SEEK:
            return vlc_stream_vaControl( p_demux->s, i_query, args );

        case DEMUX_GET_ATTACHMENTS:
            ppp_attach = va_arg( args, input_attachment_t*** );
            pi_int = va_arg( args, int * );

            if( p_sys->stored_attachments.size() <= 0 )
                return VLC_EGENERIC;

            *pi_int = p_sys->stored_attachments.size();
            *ppp_attach = static_cast<input_attachment_t**>( malloc( sizeof(input_attachment_t*) *
                                                        p_sys->stored_attachments.size() ) );
            if( !(*ppp_attach) )
                return VLC_ENOMEM;
            for( size_t i = 0; i < p_sys->stored_attachments.size(); i++ )
            {
                attachment_c *a = p_sys->stored_attachments[i];
                (*ppp_attach)[i] = vlc_input_attachment_New( a->fileName(), a->mimeType(), NULL,
                                                             a->p_data, a->size() );
                if( !(*ppp_attach)[i] )
                {
                    free(*ppp_attach);
                    return VLC_ENOMEM;
                }
            }
            return VLC_SUCCESS;

        case DEMUX_GET_META:
            p_meta = va_arg( args, vlc_meta_t* );
            vlc_meta_Merge( p_meta, p_sys->meta );
            return VLC_SUCCESS;

        case DEMUX_GET_LENGTH:
            pi64 = va_arg( args, int64_t * );
            if( p_sys->f_duration > 0.0 )
            {
                *pi64 = static_cast<int64_t>( p_sys->f_duration * 1000 );
                return VLC_SUCCESS;
            }
            return VLC_EGENERIC;

        case DEMUX_GET_POSITION:
            pf = va_arg( args, double * );
            if ( p_sys->f_duration > 0.0 )
                *pf = static_cast<double> (p_sys->i_pcr >= p_sys->i_start_pts ? p_sys->i_pcr : p_sys->i_start_pts ) / (1000.0 * p_sys->f_duration);
            return VLC_SUCCESS;

        case DEMUX_SET_POSITION:
            if( p_sys->f_duration > 0.0 )
            {
                f = va_arg( args, double );
                b = va_arg( args, int ); /* precise? */
                Seek( p_demux, -1, f, NULL, b );
                return VLC_SUCCESS;
            }
            return VLC_EGENERIC;

        case DEMUX_GET_TIME:
            pi64 = va_arg( args, int64_t * );
            *pi64 = p_sys->i_pcr;
            return VLC_SUCCESS;

        case DEMUX_GET_TITLE_INFO:
            if( p_sys->titles.size() > 1 || ( p_sys->titles.size() == 1 && p_sys->titles[0]->i_seekpoint > 0 ) )
            {
                input_title_t ***ppp_title = va_arg( args, input_title_t*** );
                int *pi_int = va_arg( args, int* );

                *pi_int = p_sys->titles.size();
                *ppp_title = static_cast<input_title_t**>( malloc( sizeof( input_title_t* ) * p_sys->titles.size() ) );

                for( size_t i = 0; i < p_sys->titles.size(); i++ )
                    (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->titles[i] );
                return VLC_SUCCESS;
            }
Example #4
0
File: vdr.c Project: Flameeyes/vlc
/*****************************************************************************
 * Control input stream
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    input_title_t ***ppp_title;
    int i;
    int64_t *pi64;
    vlc_meta_t *p_meta;

    switch( i_query )
    {
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            *va_arg( args, bool* ) = true;
            break;

        case ACCESS_GET_PTS_DELAY:
            pi64 = va_arg( args, int64_t * );
            *pi64 = INT64_C(1000)
                  * var_InheritInteger( p_access, "file-caching" );
            break;

        case ACCESS_SET_PAUSE_STATE:
            /* nothing to do */
            break;

        case ACCESS_GET_TITLE_INFO:
            /* return a copy of our seek points */
            if( !p_sys->p_marks )
                return VLC_EGENERIC;
            ppp_title = va_arg( args, input_title_t*** );
            *va_arg( args, int* ) = 1;
            *ppp_title = malloc( sizeof( input_title_t** ) );
            if( !*ppp_title )
                return VLC_ENOMEM;
            **ppp_title = vlc_input_title_Duplicate( p_sys->p_marks );
            break;

        case ACCESS_SET_TITLE:
            /* ignore - only one title */
            break;

        case ACCESS_SET_SEEKPOINT:
            i = va_arg( args, int );
            /* Seek updates p_access->info */
            return Seek( p_access, p_sys->p_marks->seekpoint[i]->i_byte_offset );

        case ACCESS_GET_META:
            if( !p_sys->p_meta )
                return VLC_EGENERIC;
            p_meta = va_arg( args, vlc_meta_t* );
            vlc_meta_Merge( p_meta, p_sys->p_meta );
            break;

        case ACCESS_SET_PRIVATE_ID_STATE:
        case ACCESS_GET_CONTENT_TYPE:
            return VLC_EGENERIC;

        default:
            msg_Warn( p_access, "unimplemented query in control" );
            return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}
Example #5
0
File: demux.c Project: mstorsjo/vlc
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( demux_t *p_demux, int i_query, va_list args )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    const int64_t i_start_time = p_sys->ic->start_time != AV_NOPTS_VALUE ? p_sys->ic->start_time : 0;
    double f, *pf;
    int64_t i64;

    switch( i_query )
    {
        case DEMUX_CAN_SEEK:
            *va_arg( args, bool * ) = true;
            return VLC_SUCCESS;

        case DEMUX_GET_POSITION:
            pf = va_arg( args, double * ); *pf = 0.0;
            i64 = stream_Size( p_demux->s );
            if( i64 > 0 )
            {
                double current = vlc_stream_Tell( p_demux->s );
                *pf = current / (double)i64;
            }

            if( (p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE) && (p_sys->i_pcr > 0) )
            {
                *pf = (double)p_sys->i_pcr / (double)p_sys->ic->duration;
            }

            return VLC_SUCCESS;

        case DEMUX_SET_POSITION:
        {
            f = va_arg( args, double );
            bool precise = va_arg( args, int );
            i64 = p_sys->ic->duration * f + i_start_time;

            msg_Warn( p_demux, "DEMUX_SET_POSITION: %"PRId64, i64 );

            /* If we have a duration, we prefer to seek by time
               but if we don't, or if the seek fails, try BYTE seeking */
            if( p_sys->ic->duration == (int64_t)AV_NOPTS_VALUE ||
                (av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0) )
            {
                int64_t i_size = stream_Size( p_demux->s );
                i64 = (i_size * f);

                msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
                if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
                    return VLC_EGENERIC;

                ResetTime( p_demux, -1 );
            }
            else
            {
                if( precise )
                    ResetTime( p_demux, i64 - i_start_time );
                else
                    ResetTime( p_demux, -1 );
            }
            return VLC_SUCCESS;
        }

        case DEMUX_GET_LENGTH:
            if( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE )
                *va_arg( args, vlc_tick_t * ) = FROM_AV_TS(p_sys->ic->duration);
            else
                *va_arg( args, vlc_tick_t * ) = 0;
            return VLC_SUCCESS;

        case DEMUX_GET_TIME:
            *va_arg( args, vlc_tick_t * ) = p_sys->i_pcr;
            return VLC_SUCCESS;

        case DEMUX_SET_TIME:
        {
            i64 = TO_AV_TS(va_arg( args, vlc_tick_t ));
            bool precise = va_arg( args, int );

            msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );

            if( av_seek_frame( p_sys->ic, -1, i64 + i_start_time, AVSEEK_FLAG_BACKWARD ) < 0 )
            {
                return VLC_EGENERIC;
            }
            if( precise )
                ResetTime( p_demux, i64 - i_start_time );
            else
                ResetTime( p_demux, -1 );
            return VLC_SUCCESS;
        }

        case DEMUX_HAS_UNSUPPORTED_META:
        {
            bool *pb_bool = va_arg( args, bool* );
            *pb_bool = true;
            return VLC_SUCCESS;
        }


        case DEMUX_GET_META:
        {
            static const char names[][10] = {
                [vlc_meta_Title] = "title",
                [vlc_meta_Artist] = "artist",
                [vlc_meta_Genre] = "genre",
                [vlc_meta_Copyright] = "copyright",
                [vlc_meta_Album] = "album",
                //[vlc_meta_TrackNumber] -- TODO: parse number/total value
                [vlc_meta_Description] = "comment",
                //[vlc_meta_Rating]
                [vlc_meta_Date] = "date",
                [vlc_meta_Setting] = "encoder",
                //[vlc_meta_URL]
                [vlc_meta_Language] = "language",
                //[vlc_meta_NowPlaying]
                [vlc_meta_Publisher] = "publisher",
                [vlc_meta_EncodedBy] = "encoded_by",
                //[vlc_meta_ArtworkURL]
                //[vlc_meta_TrackID]
                //[vlc_meta_TrackTotal]
            };
            vlc_meta_t *p_meta = va_arg( args, vlc_meta_t * );
            AVDictionary *dict = p_sys->ic->metadata;

            for( unsigned i = 0; i < sizeof(names) / sizeof(*names); i++)
            {
                if( !names[i][0] )
                    continue;

                AVDictionaryEntry *e = av_dict_get( dict, names[i], NULL, 0 );
                if( e != NULL && e->value != NULL && IsUTF8(e->value) )
                    vlc_meta_Set( p_meta, i, e->value );
            }
            return VLC_SUCCESS;
        }

        case DEMUX_GET_ATTACHMENTS:
        {
            input_attachment_t ***ppp_attach =
                va_arg( args, input_attachment_t*** );
            int *pi_int = va_arg( args, int * );
            int i;

            if( p_sys->i_attachments <= 0 )
                return VLC_EGENERIC;

            *ppp_attach = vlc_alloc( p_sys->i_attachments, sizeof(input_attachment_t*) );
            if( *ppp_attach == NULL )
                return VLC_EGENERIC;

            for( i = 0; i < p_sys->i_attachments; i++ )
            {
                (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
                if((*ppp_attach)[i] == NULL)
                    break;
            }
            *pi_int = i;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_TITLE_INFO:
        {
            input_title_t ***ppp_title = va_arg( args, input_title_t *** );
            int *pi_int = va_arg( args, int * );
            int *pi_title_offset = va_arg( args, int * );
            int *pi_seekpoint_offset = va_arg( args, int * );

            if( !p_sys->p_title )
                return VLC_EGENERIC;

            *ppp_title = malloc( sizeof( input_title_t*) );
            if( *ppp_title == NULL )
                return VLC_EGENERIC;
            (*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );
            *pi_int = (*ppp_title)[0] ? 1 : 0;
            *pi_title_offset = 0;
            *pi_seekpoint_offset = 0;
            return VLC_SUCCESS;
        }
        case DEMUX_SET_TITLE:
        {
            const int i_title = va_arg( args, int );
            if( !p_sys->p_title || i_title != 0 )
                return VLC_EGENERIC;
            return VLC_SUCCESS;
        }
        case DEMUX_SET_SEEKPOINT:
        {
            const int i_seekpoint = va_arg( args, int );
            if( !p_sys->p_title )
                return VLC_EGENERIC;

            i64 = TO_AV_TS(p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset) +
                  i_start_time;

            msg_Warn( p_demux, "DEMUX_SET_SEEKPOINT: %"PRId64, i64 );

            if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0 )
            {
                return VLC_EGENERIC;
            }
            ResetTime( p_demux, i64 - i_start_time );
            return VLC_SUCCESS;
        }
        case DEMUX_TEST_AND_CLEAR_FLAGS:
        {
            unsigned *restrict flags = va_arg(args, unsigned *);
            *flags &= p_sys->i_update;
            p_sys->i_update &= ~*flags;
            return VLC_SUCCESS;
        }
        case DEMUX_GET_TITLE:
            if( p_sys->p_title == NULL )
                return VLC_EGENERIC;
            *va_arg( args, int * ) = 0;
            return VLC_SUCCESS;
        case DEMUX_GET_SEEKPOINT:
            if( p_sys->p_title == NULL )
                return VLC_EGENERIC;
            *va_arg( args, int * ) = p_sys->i_seekpoint;
            return VLC_SUCCESS;
        case DEMUX_CAN_PAUSE:
        case DEMUX_SET_PAUSE_STATE:
        case DEMUX_CAN_CONTROL_PACE:
        case DEMUX_GET_PTS_DELAY:
            return demux_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args );
        default:
            return VLC_EGENERIC;
    }
}
Example #6
0
File: gme.c Project: 0xheart0/vlc
static int Control (demux_t *demux, int query, va_list args)
{
    demux_sys_t *sys = demux->p_sys;

    switch (query)
    {
        case DEMUX_CAN_SEEK:
            *va_arg (args, bool *) = true;
            return VLC_SUCCESS;

        case DEMUX_GET_POSITION:
        {
            double *pos = va_arg (args, double *);

            if (unlikely(sys->track_id >= sys->titlec)
             || (sys->titlev[sys->track_id]->i_length == 0))
                *pos = 0.;
            else
            {
                int offset = gme_tell (sys->emu);

                *pos = (double)offset
                    / (double)(sys->titlev[sys->track_id]->i_length / 1000);
            }
            return VLC_SUCCESS;
        }

        case DEMUX_SET_POSITION:
        {
            double pos = va_arg (args, double);

            if (unlikely(sys->track_id >= sys->titlec)
             || (sys->titlev[sys->track_id]->i_length == 0))
                break;

            int seek = (sys->titlev[sys->track_id]->i_length / 1000) * pos;
            if (gme_seek (sys->emu, seek))
                break;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_LENGTH:
        {
            int64_t *v = va_arg (args, int64_t *);

            if (unlikely(sys->track_id >= sys->titlec)
             || (sys->titlev[sys->track_id]->i_length == 0))
                break;
            *v = sys->titlev[sys->track_id]->i_length;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_TIME:
        {
            int64_t *v = va_arg (args, int64_t *);
            *v = gme_tell (sys->emu) * INT64_C(1000);
            return VLC_SUCCESS;
        }

        case DEMUX_SET_TIME:
        {
            int64_t v = va_arg (args, int64_t) / 1000;
            if (v > INT_MAX || gme_seek (sys->emu, v))
                break;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_TITLE_INFO:
        {
            input_title_t ***titlev = va_arg (args, input_title_t ***);
            int *titlec = va_arg (args, int *);
            *(va_arg (args, int *)) = 0; /* Title offset */
            *(va_arg (args, int *)) = 0; /* Chapter offset */

            unsigned n = sys->titlec;
            *titlev = malloc (sizeof (**titlev) * n);
            if (unlikely(*titlev == NULL))
                n = 0;
            *titlec = n;
            for (unsigned i = 0; i < n; i++)
                (*titlev)[i] = vlc_input_title_Duplicate (sys->titlev[i]);
            return VLC_SUCCESS;
        }

        case DEMUX_SET_TITLE:
        {
            int track_id = va_arg (args, int);
            if (track_id >= gme_track_count (sys->emu))
                break;
            gme_start_track (sys->emu, track_id);
            demux->info.i_update |= INPUT_UPDATE_TITLE;
            demux->info.i_title = track_id;
            sys->track_id = track_id;
            return VLC_SUCCESS;
        }
    }

    return VLC_EGENERIC;
}
Example #7
0
File: vcd.c Project: spike008t/vlc
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    input_title_t ***ppp_title;

    switch( i_query )
    {
        /* */
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            *va_arg( args, bool* ) = true;
            break;

        case ACCESS_GET_SIZE:
            *va_arg( args, uint64_t * ) =
                p_sys->title[p_sys->i_current_title]->i_size;
            break;

        /* */
        case ACCESS_GET_PTS_DELAY:
            *va_arg( args, int64_t * ) = INT64_C(1000)
                * var_InheritInteger(p_access, "disc-caching");
            break;

        /* */
        case ACCESS_SET_PAUSE_STATE:
            break;

        case ACCESS_GET_TITLE_INFO:
            ppp_title = va_arg( args, input_title_t*** );
            *va_arg( args, int* ) = p_sys->i_titles;

            /* Duplicate title infos */
            *ppp_title = malloc( sizeof(input_title_t *) * p_sys->i_titles );
            for( int i = 0; i < p_sys->i_titles; i++ )
                (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->title[i] );
            break;

        case ACCESS_GET_TITLE:
            *va_arg( args, unsigned * ) = p_sys->i_current_title;
            break;

        case ACCESS_GET_SEEKPOINT:
            *va_arg( args, unsigned * ) = p_sys->i_current_seekpoint;
            break;

        case ACCESS_GET_CONTENT_TYPE:
            *va_arg( args, char ** ) = strdup("video/MP2P");
            break;

        case ACCESS_SET_TITLE:
        {
            int i = va_arg( args, int );
            if( i != p_sys->i_current_title )
            {
                /* Update info */
                p_sys->offset = 0;
                p_sys->i_current_title = i;
                p_sys->i_current_seekpoint = 0;

                /* Next sector to read */
                p_sys->i_sector = p_sys->p_sectors[1+i];
            }
            break;
        }

        case ACCESS_SET_SEEKPOINT:
        {
            int i = va_arg( args, int );
            unsigned i_title = p_sys->i_current_title;
            input_title_t *t = p_sys->title[i_title];

            if( t->i_seekpoint > 0 )
            {
                p_sys->i_current_seekpoint = i;

                p_sys->i_sector = p_sys->p_sectors[1 + i_title] +
                    t->seekpoint[i]->i_byte_offset / VCD_DATA_SIZE;

                p_sys->offset = (uint64_t)(p_sys->i_sector -
                    p_sys->p_sectors[1 + i_title]) * VCD_DATA_SIZE;
            }
            break;
        }

        default:
            return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}