/***************************************************************************** * 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; }
/***************************************************************************** * 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; }
/***************************************************************************** * 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; }
/***************************************************************************** * 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; }
/***************************************************************************** * 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; } }
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; }
/***************************************************************************** * 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; }