+
+ vcdinfo_close( p_vcdplayer->vcd );
+
+ if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input );
+
+ FREENULL( p_vcdplayer->p_entries );
+ FREENULL( p_vcdplayer->p_segments );
+ FREENULL( p_vcdplayer->psz_source );
+ FREENULL( p_vcdplayer->track );
+ FREENULL( p_vcdplayer->segment );
+ FREENULL( p_vcdplayer->entry );
+ FREENULL( p_access->psz_demux );
+ FREENULL( p_vcdplayer );
+ p_vcd_access = NULL;
+}
+
+/*****************************************************************************
+ * Control: The front-end or vlc engine calls here to ether get
+ * information such as meta information or plugin capabilities or to
+ * issue miscellaneous "set" requests.
+ *****************************************************************************/
+static int VCDControl( access_t *p_access, int i_query, va_list args )
+{
+ vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
+ int *pi_int;
+ int i;
+
+ dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
+ "query %d", i_query );
+
+ switch( i_query )
+ {
+ /* Pass back a copy of meta information that was gathered when we
+ during the Open/Initialize call.
+ */
+ case ACCESS_GET_META:
+ {
+ vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
+
+ dbg_print( INPUT_DBG_EVENT, "get meta info" );
+#if 0
+ if( p_vcdplayer->p_meta )
+ {
+ *pp_meta = vlc_meta_Duplicate( p_vcdplayer->p_meta );
+ dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
+ }
+ else
+#endif
+ msg_Warn( p_access, "tried to copy NULL meta info" );
+
+ return VLC_SUCCESS;
+ }
+ return VLC_EGENERIC;
+
+ case ACCESS_CAN_SEEK:
+ case ACCESS_CAN_FASTSEEK:
+ case ACCESS_CAN_PAUSE:
+ case ACCESS_CAN_CONTROL_PACE:
+ {
+ vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
+
+ dbg_print( INPUT_DBG_EVENT,
+ "seek/fastseek/pause/can_control_pace" );
+ *pb_bool = VLC_TRUE;
+ return VLC_SUCCESS;
+ break;
+ }
+
+ /* */
+ case ACCESS_GET_MTU:
+ pi_int = (int*)va_arg( args, int * );
+ *pi_int = (p_vcdplayer->i_blocks_per_read * M2F2_SECTOR_SIZE);
+ dbg_print( INPUT_DBG_EVENT, "GET MTU: %d", *pi_int );
+ break;
+
+ case ACCESS_GET_PTS_DELAY:
+ {
+ int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
+ *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
+ * MILLISECONDS_PER_SEC;
+ dbg_print( INPUT_DBG_EVENT, "GET PTS DELAY" );
+ return VLC_SUCCESS;
+ break;
+ }
+
+ /* */
+ case ACCESS_SET_PAUSE_STATE:
+ dbg_print( INPUT_DBG_EVENT, "SET PAUSE STATE" );
+ return VLC_SUCCESS;
+ break;
+
+ case ACCESS_GET_TITLE_INFO:
+ {
+ unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX)
+ + strlen(p_vcdplayer->psz_source) + sizeof("@E999")+3;
+ input_title_t ***ppp_title
+ = (input_title_t***)va_arg( args, input_title_t*** );
+ char *psz_mrl = malloc( psz_mrl_max );
+ unsigned int i;
+
+ pi_int = (int*)va_arg( args, int* );
+
+ dbg_print( INPUT_DBG_EVENT, "GET TITLE: i_titles %d",
+ p_vcdplayer->i_titles );
+
+ if( psz_mrl == NULL ) {
+ msg_Warn( p_access, "out of memory" );
+ } else {
+ snprintf(psz_mrl, psz_mrl_max, "%s%s",
+ VCD_MRL_PREFIX, p_vcdplayer->psz_source);
+ VCDMetaInfo( p_access, psz_mrl );
+ free(psz_mrl);
+ }
+
+ /* Duplicate title info */
+ if( p_vcdplayer->i_titles == 0 )
+ {
+ *pi_int = 0; ppp_title = NULL;
+ return VLC_SUCCESS;
+ }
+ *pi_int = p_vcdplayer->i_titles;
+ *ppp_title = malloc( sizeof( input_title_t **)
+ * p_vcdplayer->i_titles );
+
+ if (!*ppp_title) return VLC_ENOMEM;
+
+ for( i = 0; i < p_vcdplayer->i_titles; i++ )
+ {
+ if ( p_vcdplayer->p_title[i] )
+ (*ppp_title)[i] =
+ vlc_input_title_Duplicate( p_vcdplayer->p_title[i] );
+ }
+ }
+ break;
+
+ case ACCESS_SET_TITLE:
+ i = (int)va_arg( args, int );
+
+ dbg_print( INPUT_DBG_EVENT, "set title %d" , i);
+ if( i != p_access->info.i_title )
+ {
+ vcdinfo_itemid_t itemid;
+ track_t i_track = i+1;
+ unsigned int i_entry =
+ vcdinfo_track_get_entry( p_vcdplayer->vcd, i_track);